static Eina_Bool _e_border_vkbd_hide_prepare_timeout(void *data);
static void _e_border_vkbd_show(E_Border *bd);
static void _e_border_vkbd_hide(E_Border *bd);
+static Eina_Bool _e_border_rotation_set_internal(E_Border *bd, int rotation, Eina_Bool *pending);
#endif
static void _e_border_move_resize_internal(E_Border *bd,
int x,
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if (bd->visible) return;
#ifdef _F_ZONE_WINDOW_ROTATION_
+ // newly created window that has to be rotated will be show after rotation done.
+ // so, skip at this time. it will be called again after GETTING ROT_DONE.
+#if 0
if ((bd->new_client) &&
(bd->client.e.state.rot.changes != -1))
{
- // newly created window that has to be rotated will be show after rotation done.
- // so, skip at this time. it will be called again after GETTING ROT_DONE.
+ // if this window is in withdrawn state, show this window right now.
+ // that's because the window in withdrawn state can't render its canvas.
+ // eventually, this window will not send the message of rotation done,
+ // even if e17 request to rotation this window.
+ if (bd->client.icccm.state != ECORE_X_WINDOW_STATE_HINT_NORMAL)
+ e_hints_window_visible_set(bd);
+
bd->client.e.state.rot.pending_show = 1;
return;
}
+#endif
if ((e_config->wm_win_rotation) &&
(rot.vkbd_ctrl_win) && (rot.vkbd) &&
(bd == rot.vkbd) &&
_e_border_move_resize_internal(bd, 0, 0, w, h, 0, 0);
}
+#ifdef _F_ZONE_WINDOW_ROTATION_
+EAPI Eina_Bool
+e_border_rotation_set(E_Border *bd, int rotation)
+{
+ return _e_border_rotation_set_internal(bd, rotation, NULL);
+}
+#endif
+
/**
* Resize window to values that do not account border decorations yet.
*
}
static void
-_e_border_deiconify_approve_send(E_Border *bd, E_Border *bd_ancestor)
+_e_border_deiconify_approve_send_pending_end(void *data)
+{
+ E_Border *bd = (E_Border *)data;
+
+ if (e_config->deiconify_approve)
+ {
+ if (!e_object_is_del(E_OBJECT(bd)))
+ {
+ bd->client.e.state.deiconify_approve.pending_job = NULL;
+
+ ELBF(ELBT_BD, 0, bd->client.win,
+ "SEND DEICONIFY_APPROVE. (PENDING_END) ancestor:%x",
+ bd->client.win);
+
+ ecore_x_client_message32_send(bd->client.win,
+ ECORE_X_ATOM_E_DEICONIFY_APPROVE,
+ ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
+ bd->client.win, 0, 0, 0, 0);
+
+ bd->client.e.state.deiconify_approve.wait_timer = ecore_timer_add(e_config->deiconify_timeout, _e_border_uniconify_timeout, bd);
+ }
+ }
+}
+
+static void
+_e_border_deiconify_approve_send(E_Border *bd, E_Border *bd_ancestor, Eina_Bool pending_ancestor)
{
if (!bd || !bd_ancestor) return;
Eina_List *list = _e_border_sub_borders_new(bd);
EINA_LIST_FOREACH(list, l, child)
{
+ Eina_Bool pending = EINA_FALSE;
+ Eina_Bool p = EINA_FALSE;
+
#ifdef _F_ZONE_WINDOW_ROTATION_
if ((e_config->wm_win_rotation) &&
((child->client.e.state.rot.support) ||
{
ELB(ELBT_ROT, "CHECK_DEICONIFY CHILD", child->client.win);
int rotation = _e_border_rotation_angle_get(bd);
- if (rotation != -1) e_border_rotation_set(bd, rotation);
+ if (rotation != -1) _e_border_rotation_set_internal(bd, rotation, &pending);
}
#endif
- _e_border_deiconify_approve_send(child, bd_ancestor);
+ if ((pending_ancestor) || (pending)) p = EINA_TRUE;
+
+ _e_border_deiconify_approve_send(child, bd_ancestor, p);
if (child->client.e.state.deiconify_approve.support)
{
- ELBF(ELBT_BD, 0, child->client.win,
- "SEND DEICONIFY_APPROVE. ancestor:%x", bd_ancestor->client.win);
-
- ecore_x_client_message32_send(child->client.win,
- ECORE_X_ATOM_E_DEICONIFY_APPROVE,
- ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
- child->client.win, 0, 0, 0, 0);
- child->client.e.state.deiconify_approve.ancestor = bd_ancestor;
- bd_ancestor->client.e.state.deiconify_approve.req_list = eina_list_append(bd_ancestor->client.e.state.deiconify_approve.req_list, child);
+ if (p)
+ {
+ ELBF(ELBT_BD, 0, child->client.win,
+ "SEND DEICONIFY_APPROVE. ancestor:%x pending(%d,%d)",
+ bd_ancestor->client.win,
+ pending_ancestor, pending);
+
+ ecore_x_client_message32_send(child->client.win,
+ ECORE_X_ATOM_E_DEICONIFY_APPROVE,
+ ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
+ child->client.win, 0, 0, 0, 0);
+ child->client.e.state.deiconify_approve.ancestor = bd_ancestor;
+ bd_ancestor->client.e.state.deiconify_approve.req_list = eina_list_append(bd_ancestor->client.e.state.deiconify_approve.req_list, child);
+ }
+ else
+ {
+ /* queue a deiconify send job to give the chance to other jobs */
+ ELBF(ELBT_BD, 0, child->client.win,
+ "SEND DEICONIFY_APPROVE. (PENDING) ancestor:%x",
+ bd_ancestor->client.win);
+ child->client.e.state.deiconify_approve.pending_job = ecore_job_add(_e_border_deiconify_approve_send_pending_end, child);
+ }
}
}
eina_list_free(list);
static void
_e_border_deiconify_approve_send_all_transient(E_Border *bd)
{
- E_Border *bd_ancestor;
- bd_ancestor = bd;
+ Eina_Bool pending = EINA_FALSE;
if (e_config->deiconify_approve)
{
{
ELB(ELBT_ROT, "CHECK_DEICONIFY", bd->client.win);
int rotation = _e_border_rotation_angle_get(bd);
- if (rotation != -1) e_border_rotation_set(bd, rotation);
+ if (rotation != -1) _e_border_rotation_set_internal(bd, rotation, &pending);
}
#endif
if (e_config->transient.iconify)
{
- _e_border_deiconify_approve_send(bd, bd_ancestor);
+ _e_border_deiconify_approve_send(bd, bd, pending);
}
if (bd->client.e.state.deiconify_approve.support)
{
- ELBF(ELBT_BD, 0, bd->client.win,
- "SEND DEICONIFY_APPROVE.. ancestor:%x", bd_ancestor->client.win);
-
- ecore_x_client_message32_send(bd->client.win,
- ECORE_X_ATOM_E_DEICONIFY_APPROVE,
- ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
- bd->client.win, 0, 0, 0, 0);
- bd->client.e.state.deiconify_approve.wait_timer = ecore_timer_add(e_config->deiconify_timeout, _e_border_uniconify_timeout, bd);
+ if (!pending)
+ {
+ ELBF(ELBT_BD, 0, bd->client.win, "SEND DEICONIFY_APPROVE.");
+ ecore_x_client_message32_send(bd->client.win,
+ ECORE_X_ATOM_E_DEICONIFY_APPROVE,
+ ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
+ bd->client.win, 0, 0, 0, 0);
+ bd->client.e.state.deiconify_approve.wait_timer = ecore_timer_add(e_config->deiconify_timeout, _e_border_uniconify_timeout, bd);
+ }
+ else
+ {
+ /* queue a deiconify send job to give the chance to other jobs */
+ ELBF(ELBT_BD, 0, bd->client.win, "SEND DEICONIFY_APPROVE. (PENDING)");
+ bd->client.e.state.deiconify_approve.pending_job = ecore_job_add(_e_border_deiconify_approve_send_pending_end, bd);
+ }
}
}
}
rot.vkbd_prediction = NULL;
}
#endif
+#ifdef _F_DEICONIFY_APPROVE_
+ if (bd->client.e.state.deiconify_approve.pending_job)
+ {
+ ecore_job_del(bd->client.e.state.deiconify_approve.pending_job);
+ bd->client.e.state.deiconify_approve.pending_job = NULL;
+ }
+#endif
evas_object_del(bd->bg_object);
e_canvas_del(bd->bg_ecore_evas);
ecore_evas_free(bd->bg_ecore_evas);
if ((int)e->data.l[1] == bd->client.e.state.rot.curr)
{
_e_border_rotation_list_remove(bd);
+#if 0
if (bd->client.e.state.rot.pending_show)
{
ELB(ELBT_BD, "SHOW_BD (PEND)", bd->client.win);
e_border_show(bd);
bd->client.e.state.rot.pending_show = 0;
}
+#endif
}
}
}
if (rot.done_timer)
ecore_timer_del(rot.done_timer);
ELB(ELBT_ROT, "ADD TIMEOUT ROT_DONE", zone->id);
- rot.done_timer = ecore_timer_add(4.0f,
+ rot.done_timer = ecore_timer_add(5.0f,
_e_border_rotation_change_done_timeout,
NULL);
}
ELB(ELBT_ROT, "CHECK ROT", bd->client.win);
- if (bd->parent) will_ang = bd->parent->client.e.state.rot.curr;
+ // the window with "ECORE_X_WINDOW_TYPE_NORMAL" type
+ // should follow the state of rotation of zone.
+ if ((bd->parent) &&
+ (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_NORMAL))
+ will_ang = bd->parent->client.e.state.rot.curr;
else will_ang = zone->rot.curr;
if (bd->client.vkbd.win_type != E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE)
{
if (!bd) continue;
- // if this window have parent,
+ // if this window has parent and window type isn't "ECORE_X_WINDOW_TYPE_NORMAL",
// it will be rotated when parent do rotate itself.
// so skip here.
- if (bd->parent) continue;
+ if ((bd->parent) &&
+ (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_NORMAL)) continue;
- // this type is set by illume.
+ // default type is "E_BORDER_ROTATION_TYPE_NORMAL",
+ // but it can be changed to "E_BORDER_ROTATION_TYPE_DEPENDENT" by illume according to its policy.
// if it's not normal type window, will be rotated by illume.
// so skip here.
if (bd->client.e.state.rot.type != E_BORDER_ROTATION_TYPE_NORMAL) continue;
return ret;
}
-EAPI Eina_Bool
-e_border_rotation_set(E_Border *bd, int rotation)
+static Eina_Bool
+_e_border_rotation_set_internal(E_Border *bd, int rotation, Eina_Bool *pending)
{
E_Zone *zone = bd->zone;
E_Border_Rotation_Info *info = NULL;
E_Border *child;
if (rotation < 0) return EINA_FALSE;
+ if (pending) *pending = EINA_FALSE;
/* step 1. check if rotation */
if (!_e_border_rotatable_check(bd, rotation)) return EINA_FALSE;
e_manager_comp_screen_lock(e_manager_current_get());
}
+ if (pending) *pending = EINA_TRUE;
+
/* step 3. search rotatable window in this window's child */
list = _e_border_sub_borders_new(bd);
EINA_LIST_FOREACH(list, l, child)
{
+ // the window which type is "ECORE_X_WINDOW_TYPE_NORMAL" will be rotated itself.
+ // it shouldn't be rotated by rotation state of parent window.
+ if (child->client.netwm.type == ECORE_X_WINDOW_TYPE_NORMAL) continue;
if (_e_border_rotatable_check(child, rotation))
{
ELBF(ELBT_ROT, 0, child->client.win, "ROT_SET(child) curr:%d != TOBE:%d",
if ((rot.vkbd_ctrl_win) &&
(rot.vkbd == bd) &&
(!e_object_is_del(E_OBJECT(rot.vkbd))) &&
- (rot.vkbd->visible) &&
(rot.vkbd->zone == bd->zone) &&
(E_INTERSECTS(bd->zone->x, bd->zone->y,
bd->zone->w, bd->zone->h,
return EINA_FALSE;
}
+static Eina_Bool
+_e_border_rotation_change_floating_pos(E_Border *bd, int *x, int *y)
+{
+ int new_x, new_y;
+ int min_title_width=96;
+
+ if (!bd) return EINA_FALSE;
+ if (!x || !y) return EINA_FALSE;
+
+ new_x = bd->x;
+ new_y = bd->y;
+
+ // Portrait -> Landscape, x= pre_x*2, y=pre_y/2
+ // Landscape -> Portrait, x= pre_x/2, y=pre_y*2
+ // guaranteeing the minimum size of titlebar shown, min_title_width
+ // so user can initiate drag&drop action after rotation changed.
+ if (bd->client.e.state.rot.curr == 0)
+ {
+ if (bd->client.e.state.rot.prev == 90)
+ {
+ new_x = (bd->zone->h - bd->h - bd->y) / 2;
+ new_y = 2 * bd->x;
+ }
+ else if (bd->client.e.state.rot.prev == 270)
+ {
+ new_x = bd->y / 2;
+ new_y = (bd->zone->w - bd->w - bd->x) * 2;
+ }
+ else if (bd->client.e.state.rot.prev == 180)
+ {
+ new_x = bd->zone->w - bd->x - bd->w;
+ new_y = bd->zone->h - bd->y - bd->h;
+ }
+
+ if(new_x + bd->w < min_title_width)
+ {
+ new_x = min_title_width - bd->w;
+ }
+ else if(new_x > bd->zone->w - min_title_width)
+ {
+ new_x = bd->zone->w - min_title_width;
+ }
+ }
+ else if (bd->client.e.state.rot.curr == 90)
+ {
+ if (bd->client.e.state.rot.prev == 0)
+ {
+ new_x = bd->y / 2;
+ new_y = bd->zone->h - (2 * bd->x) - bd->w;
+ }
+ else if (bd->client.e.state.rot.prev == 270)
+ {
+ new_x = bd->zone->w - bd->x - bd->w;
+ new_y = bd->zone->h - bd->y - bd->h;
+ }
+ else if (bd->client.e.state.rot.prev == 180)
+ {
+ new_x = (bd->zone->h - bd->y - bd->h) / 2;
+ new_y = bd->zone->h - (2 * (bd->zone->w - bd->x - bd->w)) - bd->w;
+ }
+
+ if(new_y > bd->zone->h - min_title_width)
+ {
+ new_y = bd->zone->h - min_title_width;
+ }
+ else if(new_y < min_title_width - bd->w)
+ {
+ new_y = min_title_width - bd->w;
+ }
+ }
+ else if (bd->client.e.state.rot.curr == 270)
+ {
+ if (bd->client.e.state.rot.prev == 0)
+ {
+ new_x = bd->zone->w - bd->h - (bd->y / 2);
+ new_y = bd->x * 2;
+ }
+ else if (bd->client.e.state.rot.prev == 90)
+ {
+ new_x = bd->zone->w - bd->x - bd->w;
+ new_y = bd->zone->h - bd->y - bd->h;
+ }
+ else if (bd->client.e.state.rot.prev == 180)
+ {
+ new_x = bd->zone->w - bd->x - bd->w;
+ new_y = bd->zone->h - bd->y - bd->h;
+
+ new_x = bd->zone->w - bd->h - ((bd->zone->h - bd->y - bd->h) / 2);
+ new_y = (bd->zone->w - bd->x - bd->w) * 2;
+ }
+
+ if(new_y > bd->zone->h - min_title_width)
+ {
+ new_y = bd->zone->h - min_title_width;
+ }
+ else if( new_y + bd->w < min_title_width)
+ {
+ new_y = min_title_width - bd->w ;
+ }
+ }
+ else if (bd->client.e.state.rot.curr == 180)
+ {
+ if (bd->client.e.state.rot.prev == 0)
+ {
+ new_x = bd->zone->w - bd->x - bd->w;
+ new_y = bd->zone->h - bd->y - bd->h;
+ }
+ else if (bd->client.e.state.rot.prev == 90)
+ {
+ new_x = bd->zone->w - ((bd->zone->h - bd->h - bd->y) / 2) - bd->h;
+ new_y = bd->zone->h - (2 * bd->x) - bd->w;
+ }
+ else if (bd->client.e.state.rot.prev == 270)
+ {
+ new_x = bd->zone->w - (bd->y / 2) - bd->h;
+ new_y = bd->zone->h - ((bd->zone->w - bd->w - bd->x) * 2) - bd->w;
+ }
+
+ if(new_x + bd->w < min_title_width)
+ {
+ new_x = min_title_width - bd->w;
+ }
+ else if(new_x > bd->zone->w - min_title_width)
+ {
+ new_x = bd->zone->w - min_title_width;
+ }
+ }
+
+ ELBF(ELBT_ROT, 0, bd->client.win,
+ "Floating Mode. ANGLE (%d->%d), POS (%d,%d) -> (%d,%d)",
+ bd->client.e.state.rot.prev, bd->client.e.state.rot.curr,
+ bd->x, bd->y, new_x, new_y);
+
+ if ((new_x == *x) &&
+ (new_y == *y))
+ {
+ return EINA_FALSE;
+ }
+
+ *x = new_x;
+ *y = new_y;
+
+ return EINA_TRUE;
+}
+
#define SIZE_EQUAL_TO_ZONE(a, z) \
((((a)->w) == ((z)->w)) && \
(((a)->h) == ((z)->h)))
_x = bd->x; _y = bd->y;
_w = bd->w; _h = bd->h;
+ if (bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)
+ move = _e_border_rotation_change_floating_pos(bd, &_x, &_y);
+ else
+ move = EINA_FALSE;
+
rot_dif = bd->client.e.state.rot.prev - rotation;
if (rot_dif < 0) rot_dif = -rot_dif;
if (rot_dif != 180)
}
}
+
+ if (!resize && move)
+ _e_border_move_internal(bd, _x, _y, EINA_TRUE);
}
if (resize)
{
if (need_rotation_set)
{
- ELB(ELBT_ROT, "NEED ROT", bd->client.win);
- bd->client.e.state.rot.changes = _e_border_rotation_angle_get(bd);
- if (bd->client.e.state.rot.changes != -1) bd->changed = 1;
- }
-
- if (bd->new_client)
- {
Eina_Bool hint = EINA_FALSE;
int ang = 0;
int x, y, w, h, move;
- if (bd->client.e.state.rot.changes != -1)
- ang = bd->client.e.state.rot.changes;
- else ang = bd->client.e.state.rot.curr;
+ ELB(ELBT_ROT, "NEED ROT", bd->client.win);
+ bd->client.e.state.rot.changes = _e_border_rotation_angle_get(bd);
- hint = _e_border_rotation_geom_get(bd, bd->zone, ang, &x, &y, &w, &h, &move);
- if (hint)
+ if (bd->client.e.state.rot.changes == -1)
{
- _e_border_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move);
- ELBF(ELBT_ROT, 0, bd->client.win, "RESIZE_BY_HINT name:%s (%d,%d) %dx%d",
- bd->client.icccm.name, x, y, w, h);
+ ang = bd->client.e.state.rot.curr;
+
+ hint = _e_border_rotation_geom_get(bd, bd->zone, ang, &x, &y, &w, &h, &move);
+ if (hint)
+ {
+ _e_border_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move);
+ ELBF(ELBT_ROT, 0, bd->client.win, "RESIZE_BY_HINT name:%s (%d,%d) %dx%d",
+ bd->client.icccm.name, x, y, w, h);
+ }
}
+ else bd->changed = 1;
}
-
}
#endif
static int
_e_border_resize_begin(E_Border *bd)
{
+ int ret;
+
if (!bd->lock_user_stacking)
{
if (e_config->border_raise_on_mouse_action)
(bd->fullscreen) || (bd->lock_user_size))
return 0;
- if (grabbed && !e_grabinput_get(bd->win, 0, bd->win))
+ if (bd->client.icccm.accepts_focus || bd->client.icccm.take_focus)
+ ret = e_grabinput_get(bd->win, 0, bd->win);
+ else
+ ret = e_grabinput_get(bd->win, 0, 0);
+
+ if (grabbed && !ret)
{
grabbed = 0;
return 0;
static int
_e_border_move_begin(E_Border *bd)
{
+ int ret;
if (!bd->lock_user_stacking)
{
if (e_config->border_raise_on_mouse_action)
if ((bd->fullscreen) || (bd->lock_user_location))
return 0;
- if (grabbed && !e_grabinput_get(bd->win, 0, bd->win))
+ if (bd->client.icccm.accepts_focus || bd->client.icccm.take_focus)
+ ret = e_grabinput_get(bd->win, 0, bd->win);
+ else
+ ret = e_grabinput_get(bd->win, 0, 0);
+
+ if (grabbed && !ret)
{
grabbed = 0;
return 0;