#include #include "e_mod_main.h" #include "e_mod_layout.h" #include "e_kbd.h" #include "e_cfg.h" /* FIXME: THIS CODE IS UGLY. MUST FIX!!!!! */ #define POST_NONE 0 #define POST_HIDE 1 #define POST_CLOSE 2 typedef struct _Effect Effect; struct _Effect { E_Border *border; Ecore_Animator *animator; double time_start, in; int direction; int post; }; /* internal calls */ static int _e_mod_layout_cb_effect_animator(void *data); static void _e_mod_layout_effect_slide_out(E_Border *bd, double in, int post); static void _e_mod_layout_effect_slide_in(E_Border *bd, double in, int post); static void _e_mod_layout_cb_hook_post_fetch(void *data, E_Border *bd); static void _e_mod_layout_cb_hook_post_border_assign(void *data, E_Border *bd); static void _e_mod_layout_cb_hook_end(void *data, E_Border *bd); static int _cb_event_border_add(void *data, int type, void *event); static int _cb_event_border_remove(void *data, int type, void *event); static int _cb_event_border_focus_in(void *data, int type, void *event); static int _cb_event_border_focus_out(void *data, int type, void *event); static int _cb_event_border_show(void *data, int type, void *event); static int _cb_event_border_hide(void *data, int type, void *event); static int _cb_event_zone_move_resize(void *data, int type, void *event); /* state */ static E_Border_Hook *hook1 = NULL; static E_Border_Hook *hook2 = NULL; static E_Border_Hook *hook3 = NULL; static Evas_List *handlers = NULL; static Evas_List *effects = NULL; /* mainwin is the main big window currently focused/visible */ static E_Border *mainwin = NULL; static E_Border *focuswin = NULL; static E_Border *dockwin = NULL; static int dockwin_use = 0; /* called from the module core */ void _e_mod_layout_init(E_Module *m) { hook1 = e_border_hook_add(E_BORDER_HOOK_EVAL_POST_FETCH, _e_mod_layout_cb_hook_post_fetch, NULL); hook2 = e_border_hook_add(E_BORDER_HOOK_EVAL_POST_BORDER_ASSIGN, _e_mod_layout_cb_hook_post_border_assign, NULL); hook3 = e_border_hook_add(E_BORDER_HOOK_EVAL_END, _e_mod_layout_cb_hook_end, NULL); handlers = evas_list_append (handlers, ecore_event_handler_add (E_EVENT_BORDER_ADD, _cb_event_border_add, NULL)); handlers = evas_list_append (handlers, ecore_event_handler_add (E_EVENT_BORDER_REMOVE, _cb_event_border_remove, NULL)); handlers = evas_list_append (handlers, ecore_event_handler_add (E_EVENT_BORDER_FOCUS_IN, _cb_event_border_focus_in, NULL)); handlers = evas_list_append (handlers, ecore_event_handler_add (E_EVENT_BORDER_FOCUS_OUT, _cb_event_border_focus_out, NULL)); handlers = evas_list_append (handlers, ecore_event_handler_add (E_EVENT_BORDER_SHOW, _cb_event_border_show, NULL)); handlers = evas_list_append (handlers, ecore_event_handler_add (E_EVENT_BORDER_HIDE, _cb_event_border_hide, NULL)); handlers = evas_list_append (handlers, ecore_event_handler_add (E_EVENT_ZONE_MOVE_RESIZE, _cb_event_zone_move_resize, NULL)); { E_Zone *zone; unsigned int area[4]; int wx = 0, wy = 0, ww = 0, wh = 0; int wx2 = 0, wy2 = 0, ww2 = 0, wh2 = 0; Ecore_X_Atom *supported, *supported_new; int i, supported_num; zone = e_util_zone_current_get(e_manager_current_get()); e_slipshelf_safe_app_region_get(zone, &wx, &wy, &ww, &wh); e_kbd_safe_app_region_get(zone, &wx2, &wy2, &ww2, &wh2); E_RECTS_CLIP_TO_RECT(wx, wy, ww, wh, wx2, wy2, ww2, wh2); area[0] = wx; area[1] = wy; area[2] = ww; area[3] = wh; ecore_x_netwm_desk_workareas_set(zone->container->manager->root, area, 1); if (ecore_x_netwm_supported_get(zone->container->manager->root, &supported, &supported_num)) { int have_it = 0; for (i = 0; i < supported_num; i++) { if (supported[i] == ECORE_X_ATOM_NET_WORKAREA) { have_it = 1; break; } } if (!have_it) { supported_new = malloc(sizeof(Ecore_X_Atom) * (supported_num + 1)); if (supported_new) { memcpy(supported_new, supported, sizeof(Ecore_X_Atom) * supported_num); supported_new[supported_num] = ECORE_X_ATOM_NET_WORKAREA; supported_num++; ecore_x_netwm_supported_set(zone->container->manager->root, supported_new, supported_num); free(supported_new); } } free(supported); } else { Ecore_X_Atom atom; atom = ECORE_X_ATOM_NET_WORKAREA; ecore_x_netwm_supported_set(zone->container->manager->root, &atom, 1); } } } void _e_mod_layout_shutdown(void) { if (hook1) { e_border_hook_del(hook1); hook1 = NULL; } if (hook2) { e_border_hook_del(hook2); hook2 = NULL; } if (hook3) { e_border_hook_del(hook3); hook3 = NULL; } } void _e_mod_layout_border_hide(E_Border *bd) { _e_mod_layout_effect_slide_out(bd, (double)illume_cfg->sliding.layout.duration / 1000.0, POST_HIDE); } void _e_mod_layout_border_close(E_Border *bd) { _e_mod_layout_effect_slide_out(bd, (double)illume_cfg->sliding.layout.duration / 1000.0, POST_CLOSE); } void _e_mod_layout_border_show(E_Border *bd) { _e_mod_layout_effect_slide_in(bd, (double)illume_cfg->sliding.layout.duration / 1000.0, POST_NONE); e_border_uniconify(bd); e_border_show(bd); e_border_raise(bd); } void _e_mod_layout_apply_all(void) { Evas_List *l, *borders; borders = e_border_client_list(); for (l = borders; l; l = l->next) { E_Border *bd; bd = l->data; if (e_object_is_del(E_OBJECT(bd))) continue; _e_mod_layout_cb_hook_post_border_assign(NULL, bd); } } /* internal calls */ static int _e_mod_layout_cb_effect_animator(void *data) { Effect *ef; double t, p; ef = data; t = ecore_time_get() - ef->time_start; if (ef->in > 0.0) { t /= ef->in; if (t > 1.0) t = 1.0; } else { t = 1.0; } p = 1.0 - t; p = 1.0 - (p * p * p * p); if (ef->direction == 1) e_border_fx_offset(ef->border, 0, (-ef->border->zone->h * (1.0 - p))); else e_border_fx_offset(ef->border, 0, (-ef->border->zone->h * p)); if (t >= 1.0) { if (ef->post == POST_HIDE) { e_border_iconify(ef->border); // e_border_focus_set(ef->border, 0, 1); // printf("hide - focus out\n"); } else if (ef->post == POST_CLOSE) { // e_border_focus_set(ef->border, 0, 1); // printf("close - focus out\n"); // e_border_iconify(ef->border); e_border_act_close_begin(ef->border); } else { // printf("show - focus in\n"); // e_border_focus_set(ef->border, 1, 1); } e_border_fx_offset(ef->border, 0, 0); effects = evas_list_remove(effects, ef); free(ef); return 0; } return 1; } static void _e_mod_layout_effect_slide_out(E_Border *bd, double in, int post) { Effect *ef; ef = E_NEW(Effect, 1); ef->border = bd; ef->animator = ecore_animator_add(_e_mod_layout_cb_effect_animator, ef); ef->time_start = ecore_time_get(); ef->in = in; ef->direction = 0; ef->post = post; effects = evas_list_append(effects, ef); e_border_fx_offset(ef->border, 0, 0); if (in <= 0.0) { ef->animator = ecore_animator_del(ef->animator); ef->animator = NULL; _e_mod_layout_cb_effect_animator(ef); return; } } static void _e_mod_layout_effect_slide_in(E_Border *bd, double in, int post) { Effect *ef; ef = E_NEW(Effect, 1); ef->border = bd; ef->animator = ecore_animator_add(_e_mod_layout_cb_effect_animator, ef); ef->time_start = ecore_time_get(); ef->in = in; ef->direction = 1; ef->post = post; effects = evas_list_append(effects, ef); if (ef->border->iconic) e_border_uniconify(ef->border); e_border_focus_set(bd, 1, 1); e_border_fx_offset(ef->border, 0, -ef->border->zone->h); if (in <= 0.0) { ef->animator = ecore_animator_del(ef->animator); ef->animator = NULL; _e_mod_layout_cb_effect_animator(ef); return; } } static int _is_dialog(E_Border *bd) { int isdialog = 0, i; if (bd->client.icccm.transient_for != 0) isdialog = 1; printf("basic type = %i\n", bd->client.netwm.type); if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG) { isdialog = 1; printf("dialog! = %i\n", bd->client.netwm.type); if (bd->client.netwm.extra_types) { for (i = 0; i < bd->client.netwm.extra_types_num; i++) { if (bd->client.netwm.extra_types[i] == ECORE_X_WINDOW_TYPE_UNKNOWN) continue; printf("type %i\n", bd->client.netwm.extra_types[i]); if ((bd->client.netwm.extra_types[i] != ECORE_X_WINDOW_TYPE_DIALOG) && (bd->client.netwm.extra_types[i] != ECORE_X_WINDOW_TYPE_SPLASH)) { printf("bd %p dialog = %i\n", bd, 0); return 0; } } } } printf("%p dialog = %i\n", bd, isdialog); return isdialog; } static void _e_mod_layout_cb_hook_post_fetch(void *data, E_Border *bd) { if (bd->stolen) return; if (bd->new_client) { if (bd->remember) { if (bd->bordername) { evas_stringshare_del(bd->bordername); bd->bordername = NULL; bd->client.border.changed = 1; } e_remember_unuse(bd->remember); bd->remember = NULL; } if (!_is_dialog(bd)) { printf("set to borderless\n"); if (bd->bordername) evas_stringshare_del(bd->bordername); bd->bordername = evas_stringshare_add("borderless"); bd->client.border.changed = 1; } } } static void _e_mod_layout_cb_hook_post_border_assign(void *data, E_Border *bd) { int wx = 0, wy = 0, ww = 0, wh = 0; int wx2 = 0, wy2 = 0, ww2 = 0, wh2 = 0; int center = 0; int isdialog = 0; int pbx, pby, pbw, pbh; if (bd->stolen) return; /* FIXME: make some modification based on policy */ printf("----->\n"); if (bd->new_client) { printf("Window Prop:\n" " Title: [%s][%s]\n" " Class: %s::%s\n" " Geometry: %ix%i+%i+%i\n" " New: %i\n" " Remember: %p\n" " NETWMType: %i\n" , bd->client.icccm.title, bd->client.netwm.name , bd->client.icccm.name, bd->client.icccm.class , bd->w, bd->h, bd->x, bd->y , bd->new_client , bd->remember , bd->client.netwm.type ); } pbx = bd->x; pby = bd->y; pbw = bd->w; pbh = bd->h; isdialog = _is_dialog(bd); e_slipshelf_safe_app_region_get(bd->zone, &wx, &wy, &ww, &wh); e_kbd_safe_app_region_get(bd->zone, &wx2, &wy2, &ww2, &wh2); E_RECTS_CLIP_TO_RECT(wx, wy, ww, wh, wx2, wy2, ww2, wh2); if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DOCK) { printf("dock...\n"); { unsigned int area[4]; if (dockwin) { /* FIXME: delete dockwin if set */ } dockwin = bd; area[0] = wx; area[1] = wy; area[2] = ww; area[3] = wh - bd->h; ecore_x_netwm_desk_workareas_set(bd->zone->container->manager->root, area, 1); wy = wy + wh - bd->h; wh = bd->h; if (bd->new_client) { dockwin_use = 0; } } } else if (isdialog) { printf("dialog...\n"); if (dockwin) { wh -= dockwin->h; } printf("min: %i %i | base: %i %i | size: %i %i\n", bd->client.icccm.min_w, bd->client.icccm.min_h, bd->client.icccm.base_w, bd->client.icccm.base_h, bd->w, bd->h); // if (ww > (bd->client.icccm.min_w + bd->client_inset.l + bd->client_inset.r)) // ww = bd->client.icccm.min_w + bd->client_inset.l + bd->client_inset.r; bd->w = ww; if (bd->h > wh) bd->h = wh; bd->client.w = bd->w - bd->client_inset.l - bd->client_inset.r; bd->client.h = bd->h - bd->client_inset.t - bd->client_inset.b; bd->changes.size = 1; if (bd->client.icccm.max_w < bd->client.w) bd->client.icccm.max_w = bd->client.w; if (bd->client.icccm.base_w > bd->client.w) bd->client.icccm.base_w = bd->client.w; if (bd->client.icccm.base_h > (wh - bd->client_inset.t - bd->client_inset.b)) bd->client.icccm.base_h = wh - bd->client_inset.t - bd->client_inset.b; if (bd->client.icccm.min_w > bd->client.w) bd->client.icccm.min_w = bd->client.w; if (bd->client.icccm.min_h > (wh - bd->client_inset.t - bd->client_inset.b)) bd->client.icccm.min_h = wh - bd->client_inset.t - bd->client_inset.b; if (bd->new_client) { _e_mod_layout_effect_slide_in(bd, (double)illume_cfg->sliding.layout.duration / 1000.0, POST_NONE); } } else { printf("normal...\n"); if ((dockwin) && (dockwin->client.qtopia.soft_menu) && (bd->client.qtopia.soft_menus)) { wh -= dockwin->h; } if (bd->new_client) { _e_mod_layout_effect_slide_in(bd, (double)illume_cfg->sliding.layout.duration / 1000.0, POST_NONE); } } if (isdialog) { // if (bd->new_client) { bd->client.e.state.centered = 0; printf(" ... centered dialog\n"); bd->x = wx + ((ww - bd->w) / 2); bd->y = wy + ((wh - bd->h) / 2); if ((pbx != bd->x) || (pby != bd->y) || (pbw != bd->w) || (pbh != bd->h)) { printf("@ %i %i | %ix%i\n", bd->x, bd->y, bd->w, bd->h); if (bd->internal_ecore_evas) ecore_evas_managed_move(bd->internal_ecore_evas, bd->x + bd->fx.x + bd->client_inset.l, bd->y + bd->fx.y + bd->client_inset.t); ecore_x_icccm_move_resize_send(bd->client.win, bd->x + bd->fx.x + bd->client_inset.l, bd->y + bd->fx.y + bd->client_inset.t, bd->client.w, bd->client.h); bd->changed = 1; bd->changes.pos = 1; } if (bd->remember) { e_remember_unuse(bd->remember); bd->remember = NULL; } } bd->placed = 1; bd->lock_border = 1; bd->lock_client_location = 1; bd->lock_client_size = 1; bd->lock_client_desk = 1; bd->lock_client_sticky = 1; bd->lock_client_shade = 1; bd->lock_client_maximize = 1; bd->lock_user_location = 1; bd->lock_user_size = 1; bd->lock_user_desk = 1; bd->lock_user_sticky = 1; bd->lock_user_shade = 1; bd->lock_user_maximize = 1; } else { printf(" ... normal\n"); bd->placed = 1; if (!((bd->need_fullscreen) || (bd->fullscreen))) { bd->x = wx; bd->y = wy; bd->w = ww; bd->h = wh; bd->client.w = bd->w; bd->client.h = bd->h; if ((pbx != bd->x) || (pby != bd->y) || (pbw != bd->w) || (pbh != bd->h)) { if (bd->internal_ecore_evas) ecore_evas_managed_move(bd->internal_ecore_evas, bd->x + bd->fx.x + bd->client_inset.l, bd->y + bd->fx.y + bd->client_inset.t); ecore_x_icccm_move_resize_send(bd->client.win, bd->x + bd->fx.x + bd->client_inset.l, bd->y + bd->fx.y + bd->client_inset.t, bd->client.w, bd->client.h); bd->changed = 1; bd->changes.pos = 1; bd->changes.size = 1; } } else { if ((pbx != bd->x) || (pby != bd->y) || (pbw != bd->w) || (pbh != bd->h)) { if (bd->internal_ecore_evas) ecore_evas_managed_move(bd->internal_ecore_evas, bd->x + bd->fx.x + bd->client_inset.l, bd->y + bd->fx.y + bd->client_inset.t); ecore_x_icccm_move_resize_send(bd->client.win, bd->x + bd->fx.x + bd->client_inset.l, bd->y + bd->fx.y + bd->client_inset.t, bd->client.w, bd->client.h); bd->changed = 1; bd->changes.pos = 1; bd->changes.size = 1; } } if (bd->remember) { e_remember_unuse(bd->remember); bd->remember = NULL; } bd->lock_border = 1; bd->lock_client_location = 1; bd->lock_client_size = 1; // bd->lock_client_stacking = 1; bd->lock_client_desk = 1; bd->lock_client_sticky = 1; bd->lock_client_shade = 1; bd->lock_client_maximize = 1; bd->lock_user_location = 1; bd->lock_user_size = 1; // bd->lock_user_stacking = 1; bd->lock_user_desk = 1; bd->lock_user_sticky = 1; bd->lock_user_shade = 1; bd->lock_user_maximize = 1; bd->client.icccm.base_w = 1; bd->client.icccm.base_h = 1; bd->client.icccm.min_w = 1; bd->client.icccm.min_h = 1; bd->client.icccm.max_w = 32767; bd->client.icccm.max_h = 32767; bd->client.icccm.min_aspect = 0.0; bd->client.icccm.max_aspect = 0.0; } printf("<-----\n"); } static void _e_mod_layout_cb_hook_end(void *data, E_Border *bd) { if (bd->stolen) return; if ((bd == dockwin) && (!dockwin_use) && (dockwin->visible)) e_border_hide(dockwin, 2); } static int _cb_event_border_add(void *data, int type, void *event) { E_Event_Border_Add *ev; ev = event; printf("bd add %p\n", ev->border); return 1; } static int _cb_event_border_remove(void *data, int type, void *event) { E_Event_Border_Remove *ev; Evas_List *l, *pl; ev = event; printf("bd del %p\n", ev->border); if (ev->border == dockwin) { unsigned int area[4]; int wx = 0, wy = 0, ww = 0, wh = 0; int wx2 = 0, wy2 = 0, ww2 = 0, wh2 = 0; printf("del dockwin\n"); dockwin = NULL; dockwin_use = 0; e_slipshelf_safe_app_region_get(ev->border->zone, &wx, &wy, &ww, &wh); e_kbd_safe_app_region_get(ev->border->zone, &wx2, &wy2, &ww2, &wh2); E_RECTS_CLIP_TO_RECT(wx, wy, ww, wh, wx2, wy2, ww2, wh2); area[0] = wx; area[1] = wy; area[2] = ww; area[3] = wh; ecore_x_netwm_desk_workareas_set(ev->border->zone->container->manager->root, area, 1); } for (l = effects; l;) { Effect *ef; ef = l->data; pl = l; l = l->next; if (ef->border == ev->border) { effects = evas_list_remove_list(effects, pl); ecore_animator_del(ef->animator); free(ef); } } return 1; } static int _cb_event_border_focus_in(void *data, int type, void *event) { E_Event_Border_Focus_In *ev; E_Border *bd; ev = event; printf("bd focus in %p\n", ev->border); bd = ev->border; if (bd != dockwin) { if (bd->client.qtopia.soft_menus) { if ((dockwin) && (!dockwin_use) && (dockwin->client.qtopia.soft_menu)) { dockwin_use = 1; printf("+ dockwin\n"); e_border_show(dockwin); } } else { if ((dockwin) && (dockwin_use) && (dockwin->client.qtopia.soft_menu)) { dockwin_use = 0; printf("- dockwin\n"); e_border_hide(dockwin, 2); // 1? } } } return 1; } static int _cb_event_border_focus_out(void *data, int type, void *event) { E_Event_Border_Focus_Out *ev; E_Border *bd; ev = event; printf("bd focus out %p\n", ev->border); bd = ev->border; if (bd != dockwin) { if (bd->client.qtopia.soft_menus) { if ((dockwin) && (dockwin_use) && (dockwin->client.qtopia.soft_menu)) { dockwin_use = 0; printf("- dockwin\n"); e_border_hide(dockwin, 2); // 1? } } } return 1; } static int _cb_event_border_show(void *data, int type, void *event) { E_Event_Border_Show *ev; ev = event; printf("bd show %p\n", ev->border); return 1; } static int _cb_event_border_hide(void *data, int type, void *event) { E_Event_Border_Hide *ev; ev = event; printf("bd hide %p\n", ev->border); return 1; } static int _cb_event_zone_move_resize(void *data, int type, void *event) { E_Event_Zone_Move_Resize *ev; ev = event; _e_mod_layout_apply_all(); return 1; }