#include "e.h" #include "e_mod_main.h" #include "e_mod_config.h" #include "e_mod_layout.h" #include "e_mod_layout_illume.h" #include "e_kbd.h" /* local function prototypes */ static void _border_resize_fx(E_Border *bd, int bx, int by, int bw, int bh); static void _border_add(E_Border *bd); static void _border_del(E_Border *bd); static void _border_focus_in(E_Border *bd); static void _border_focus_out(E_Border *bd); static void _border_activate(E_Border *bd); static void _drag_start(E_Border *bd); static void _drag_end(E_Border *bd); static void _zone_layout(E_Zone *z); static void _zone_layout_single(E_Border *bd); static void _zone_layout_dual(E_Border *bd); static void _zone_layout_dual_top(E_Border *bd); static void _zone_layout_dual_top_custom(E_Border *bd); static void _zone_layout_dual_left(E_Border *bd); static void _zone_move_resize(E_Zone *z); static int _cb_mouse_up(void *data, int type, void *event); static int _cb_mouse_move(void *data, int type, void *event); /* local variables */ static int shelfsize = 0; static int kbdsize = 0; static int panelsize = 0; const Illume_Layout_Mode laymode = { "illume", "Illume", _border_add, _border_del, _border_focus_in, _border_focus_out, _zone_layout, _zone_move_resize, _border_activate, _drag_start, _drag_end }; /* public functions */ void illume_layout_illume_init(void) { illume_layout_mode_register(&laymode); } void illume_layout_illume_shutdown(void) { illume_layout_mode_unregister(&laymode); } /* local functions */ static void _border_resize_fx(E_Border *bd, int bx, int by, int bw, int bh) { /* CONVENIENCE FUNCTION TO REMOVE DUPLICATED CODE */ if ((bd->need_fullscreen) || (bd->fullscreen)) { if ((bd->w != bw) || (bd->h != bh)) { bd->w = bw; bd->h = bh; bd->client.w = bw; bd->client.h = bh; bd->changes.size = 1; } if ((bd->x != bx) || (bd->y != by)) { bd->x = bx; bd->y = by; bd->changes.pos = 1; } } else { if ((bd->w != bw) || (bd->h != bh)) e_border_resize(bd, bw, bh); if ((bd->x != bx) || (bd->y != by)) e_border_fx_offset(bd, bx, by); } } static void _border_add(E_Border *bd) { /* HANDLE A BORDER BEING ADDED */ int conform; /* skip new clients and invisible borders */ if ((bd->new_client) || (!bd->visible)) return; /* check if this border is conformant */ conform = illume_border_is_conformant(bd); /* is this a fullscreen border ? */ if ((bd->need_fullscreen) || (bd->fullscreen)) { E_Border *b; if (bd->layer != 115) e_border_layer_set(bd, 115); /* we lock stacking so that the keyboard does not get put * under the window (if it's needed) */ bd->lock_user_stacking = 1; /* conformant fullscreen borders just hide bottom panel */ b = illume_border_bottom_panel_get(); if (b) e_border_fx_offset(b, 0, -panelsize); /* for non-conformant fullscreen borders, * we hide top shelf and bottom panel in all cases */ if (!conform) { b = illume_border_top_shelf_get(); if (b) e_border_fx_offset(b, 0, -shelfsize); } } if (conform) { if (bd->layer != 110) e_border_layer_set(bd, 110); } /* we lock stacking so that the keyboard does not get put * under the window (if it's needed) */ if (conform) bd->lock_user_stacking = 1; /* only set focus if border accepts it and it's not locked out */ if ((bd->client.icccm.accepts_focus) && (bd->client.icccm.take_focus) && (!bd->lock_focus_out)) e_border_focus_set(bd, 1, 1); if (bd == illume_border_top_shelf_get()) { Ecore_X_Window xwin; Ecore_X_Illume_Mode mode; xwin = ecore_x_window_root_first_get(); mode = ecore_x_e_illume_mode_get(xwin); ecore_x_e_illume_mode_send(xwin, mode); } } static void _border_del(E_Border *bd) { /* HANDLE A BORDER BEING DELETED */ if ((bd->need_fullscreen) || (bd->fullscreen)) { E_Border *b; /* conformant fullscreen borders just get bottom panel shown */ b = illume_border_bottom_panel_get(); if (b) e_border_fx_offset(b, 0, 0); /* for non-conformant fullscreen borders, * we show top shelf and bottom panel in all cases */ if (!illume_border_is_conformant(bd)) { b = illume_border_top_shelf_get(); if (b) e_border_fx_offset(b, 0, 0); } } } static void _border_focus_in(E_Border *bd) { /* do something if focus enters a window */ } static void _border_focus_out(E_Border *bd) { /* do something if focus exits a window */ } static void _border_activate(E_Border *bd) { /* HANDLE A BORDER BEING ACTIVATED */ /* only set focus if border accepts it and it's not locked out */ if (((!bd->client.icccm.accepts_focus) && (!bd->client.icccm.take_focus)) || (bd->lock_focus_out)) return; /* if the border is not focused, check focus settings */ if ((bd) && (!bd->focused)) { if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) || ((bd->parent) && ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) || ((bd->parent->focused) && (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED))))) { if (bd->iconic) { /* if it's iconic, then uniconify */ if (!bd->lock_user_iconify) e_border_uniconify(bd); } /* if we can, raise the border */ if (!bd->lock_user_stacking) e_border_raise(bd); /* if we can, focus the border */ if (!bd->lock_focus_out) e_border_focus_set(bd, 1, 1); } } } static void _drag_start(E_Border *bd) { /* HANDLE A BORDER DRAG BEING STARTED */ ecore_x_e_illume_drag_set(bd->client.win, 1); } static void _drag_end(E_Border *bd) { /* HANDLE A BORDER DRAG BEING ENDED */ ecore_x_e_illume_drag_set(bd->client.win, 0); } static void _zone_layout(E_Zone *z) { Eina_List *l, *borders; E_Border *bd; /* ACTUALLY APPLY THE SIZING, POSITIONING AND LAYERING */ /* grab list of borders */ borders = e_border_client_list(); EINA_LIST_FOREACH(borders, l, bd) { int mh; /* skip border if: zone not the same, a new client, or invisible */ if ((bd->zone != z) || (bd->new_client) || (!bd->visible)) continue; /* check for special windows to get their size(s) */ illume_border_min_get(bd, NULL, &mh); if (illume_border_is_top_shelf(bd)) { if (shelfsize < mh) shelfsize = mh; } else if (illume_border_is_bottom_panel(bd)) { if (panelsize < mh) panelsize = mh; } else if (illume_border_is_keyboard(bd)) { if (kbdsize < mh) kbdsize = mh; } } /* grab list of borders */ borders = e_border_client_list(); EINA_LIST_FOREACH(borders, l, bd) { /* skip border if: zone not the same, a new client, or invisible */ if ((bd->zone != z) || (bd->new_client) || (!bd->visible)) continue; /* trap 'special' windows as they need special treatment */ if (illume_border_is_top_shelf(bd)) { /* make sure we are not dragging the shelf */ if (!ecore_x_e_illume_drag_get(bd->client.win)) { /* if we are not in dual mode, then set shelf to top */ if (!il_cfg->policy.mode.dual) _border_resize_fx(bd, z->x, z->y, z->w, shelfsize); else { /* make sure we are in landscape mode */ if (il_cfg->policy.mode.side == 0) _border_resize_fx(bd, z->x, bd->y, z->w, shelfsize); else _border_resize_fx(bd, z->x, z->y, z->w, shelfsize); } } e_border_stick(bd); if (bd->layer != 100) e_border_layer_set(bd, 100); } else if (illume_border_is_bottom_panel(bd)) { /* make sure we are not dragging the shelf */ if (!ecore_x_e_illume_drag_get(bd->client.win)) { _border_resize_fx(bd, z->x, (z->y + z->h - panelsize), z->w, panelsize); } e_border_stick(bd); if (bd->layer != 100) e_border_layer_set(bd, 100); } else if (illume_border_is_keyboard(bd)) { _border_resize_fx(bd, z->x, (z->y + z->h - kbdsize), z->w, kbdsize); e_border_stick(bd); if (bd->layer != 150) e_border_layer_set(bd, 150); } else if (illume_border_is_dialog(bd)) { int mw, mh; illume_border_min_get(bd, &mw, &mh); if (mw > z->w) mw = z->w; if (mh > z->h) mh = z->h; _border_resize_fx(bd, (z->x + ((z->w - mw) / 2)), (z->y + ((z->h - mh) / 2)), mw, mh); if (bd->layer != 160) e_border_layer_set(bd, 160); } else { if (illume_border_is_conformant(bd)) { /* make conformant windows under the indicator bar */ if (bd->layer != 90) e_border_layer_set(bd, 90); } /* normal border, handle layout based on policy mode */ if (il_cfg->policy.mode.dual) _zone_layout_dual(bd); else _zone_layout_single(bd); } } } static void _zone_layout_single(E_Border *bd) { int kx, ky, kw, kh, ss, ps; /* grab the 'safe' region. Safe region is space not occupied by keyboard */ e_kbd_safe_app_region_get(bd->zone, &kx, &ky, &kw, &kh); if (!illume_border_is_conformant(bd)) { if (!((bd->need_fullscreen) || (bd->fullscreen))) { if (kh >= bd->zone->h) ps = panelsize; ss = shelfsize; } } else kh = bd->zone->h; _border_resize_fx(bd, kx, (ky + ss), kw, (kh - ss - ps)); } static void _zone_layout_dual(E_Border *bd) { if (il_cfg->policy.mode.side == 0) { int ty; illume_border_top_shelf_pos_get(NULL, &ty); if (ty <= bd->zone->y) _zone_layout_dual_top(bd); else _zone_layout_dual_top_custom(bd); } else if (il_cfg->policy.mode.side == 1) _zone_layout_dual_left(bd); } static void _zone_layout_dual_top(E_Border *bd) { int kx, ky, kw, kh, ss, ps; int count, conform; /* get count of valid borders */ count = illume_border_valid_count_get(); /* fetch if this border is conformant */ conform = illume_border_is_conformant(bd); /* grab the 'safe' region. Safe region is space not occupied by keyboard */ e_kbd_safe_app_region_get(bd->zone, &kx, &ky, &kw, &kh); if (!conform) { /* if the border is not conformant and doesn't need fullscreen, then * we account for shelf & panel sizes */ if (!((bd->need_fullscreen) || (bd->fullscreen))) { if (kh >= bd->zone->h) ps = panelsize; ss = shelfsize; } } /* if there are no other borders, than give this one all available space */ if (count < 2) _border_resize_fx(bd, kx, (ky + ss), kw, (kh - ss - ps)); else { E_Border *b; int bx, by, bw, bh; /* more than one valid border */ bx = kx; by = (ky + ss); bw = kw; bh = (kh - ss - ps); /* grab the border at this location */ b = illume_border_at_xy_get(kx, shelfsize); if ((b) && (bd != b)) { /* we have a border there, and it's not the current one */ if (!illume_border_is_conformant(b)) { /* border in this location is not conformant */ bh = ((kh - ss - ps) / 2); by = (b->fx.y + b->h); } else { /* border there is conformant */ if (conform) { /* if current border is conformant, divide zone in half */ bh = ((bd->zone->h - ss) / 2); by = by + bh; } else { /* current border is not conformant */ by = (b->fx.y + b->h); bh = (kh - by - ps); } } } else if (b) { /* border at this location and it's the current border */ by = bd->fx.y; bh = ((kh - ss - ps) / 2); } else { /* no border at this location */ b = illume_border_valid_border_get(); by = ky + ss; bh = (ky - b->h); } _border_resize_fx(bd, bx, by, bw, bh); } } static void _zone_layout_dual_top_custom(E_Border *bd) { int kx, kw; int count, conform; int ax, ay, aw, ah; int zx, zy, zw, zh; /* get count of valid borders */ count = illume_border_valid_count_get(); /* fetch if this border is conformant */ conform = illume_border_is_conformant(bd); /* grab the 'safe' region. Safe region is space not occupied by keyboard */ e_kbd_safe_app_region_get(bd->zone, &kx, NULL, &kw, NULL); illume_border_app1_safe_region_get(bd->zone, &ax, &ay, &aw, &ah); illume_border_app2_safe_region_get(bd->zone, &zx, &zy, &zw, &zh); /* if there are no other borders, than give this one all available space */ if (count < 2) { if (ah >= zh) { zx = ax; zy = ax; zw = aw; zh = ah; } if ((bd->w != zw) || (bd->h != zh)) e_border_resize(bd, zw, zh); if ((bd->x != zx) || (bd->y != zy) || (bd->fx.y != zy)) e_border_fx_offset(bd, zx, zy); } else { E_Border *bt, *bb; int bh, by; /* more than one valid border */ if (ecore_x_e_virtual_keyboard_state_get(bd->client.win) > ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF) { bh = ah; by = ay; } else { /* grab the border at this location */ bt = illume_border_at_xy_get(kx, ay); if ((bt) && (bd != bt)) { /* is there a border in the bottom section */ bb = illume_border_at_xy_get(kx, zy); if (!bb) { bh = zh; by = zy; } else if ((bb) && (bd != bb)) { if (bt == e_border_focused_get()) { if (ecore_x_e_virtual_keyboard_state_get(bd->client.win) <= ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF) { bh = zh; by = zy; } else { bh = ah; by = ay; } } else if (bb = e_border_focused_get()) { if (ecore_x_e_virtual_keyboard_state_get(bd->client.win) <= ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF) { bh = ah; by = ay; } } } else if (bb) { bh = zh; by = zy; } } else { bh = ah; by = ay; } } if ((bd->w != kw) || (bd->h != bh)) e_border_resize(bd, kw, bh); if ((bd->x != kx) || (bd->y != by) || (bd->fx.y != by)) e_border_fx_offset(bd, kx, by); } } static void _zone_layout_dual_left(E_Border *bd) { int kx, ky, kw, kh, ss, ps; int count, conform; /* get count of valid borders */ count = illume_border_valid_count_get(); /* fetch if this border is conformant */ conform = illume_border_is_conformant(bd); /* grab the 'safe' region. Safe region is space not occupied by keyboard */ e_kbd_safe_app_region_get(bd->zone, &kx, &ky, &kw, &kh); if (!conform) { /* if the border is not conformant and doesn't need fullscreen, then * we account for shelf & panel sizes */ if (!((bd->need_fullscreen) || (bd->fullscreen))) { if (kh >= bd->zone->h) ps = panelsize; ss = shelfsize; } } /* if there are no other borders, than give this one all available space */ if (count < 2) _border_resize_fx(bd, kx, (ky + ss), kw, (kh - ss - ps)); else { E_Border *b; int bx, by, bw, bh; /* more than one valid border */ bx = kx; by = (ky + ss); bw = kw; bh = (kh - ss - ps); /* grab the border at this location */ b = illume_border_at_xy_get(kx, shelfsize); if ((b) && (bd != b)) { /* we have a border there, and it's not the current one */ if (!illume_border_is_conformant(b)) { /* border in this location is not conformant */ bw = (kw / 2); bx = (b->fx.x + b->w); } else { /* border there is conformant */ if (conform) { /* if current border is conformant, divide zone in half */ bw = (bd->zone->w / 2); bx = bx + bw; } else { /* current border is not conformant */ bx = (b->fx.x + b->w); bw = (kw - bx); } } } else if (b) { /* border at this location and it's the current border */ bx = bd->fx.x; bw = (kw / 2); } else { /* no border at this location */ b = illume_border_valid_border_get(); bx = kx; bw = (kw - b->w); } _border_resize_fx(bd, bx, by, bw, bh); } } static void _zone_move_resize(E_Zone *z) { /* the zone was moved or resized - re-configure all windows in this zone */ _zone_layout(z); }