x11/window: Implement _NET_RESTACK_WINDOW and XConfigureRequestEvent sibling

Implement _NET_RESTACK_WINDOW, based on metacity commit 0b5a50c8.

Also respect "above" field (sibling) of XConfigureRequestEvent. When it is
set, perform a stack operation relative to that sibling.

https://bugzilla.gnome.org/show_bug.cgi?id=786363
https://bugzilla.gnome.org/show_bug.cgi?id=786365
This commit is contained in:
Vasilis Liaskovitis 2017-09-29 16:57:22 +02:00 committed by Rui Matos
parent 2c85bb4178
commit e3d59832c5
4 changed files with 99 additions and 15 deletions

View File

@ -682,6 +682,9 @@ void meta_window_frame_size_changed (MetaWindow *window);
void meta_window_stack_just_below (MetaWindow *window, void meta_window_stack_just_below (MetaWindow *window,
MetaWindow *below_this_one); MetaWindow *below_this_one);
void meta_window_stack_just_above (MetaWindow *window,
MetaWindow *above_this_one);
void meta_window_set_user_time (MetaWindow *window, void meta_window_set_user_time (MetaWindow *window,
guint32 timestamp); guint32 timestamp);

View File

@ -6728,6 +6728,30 @@ meta_window_stack_just_below (MetaWindow *window,
} }
} }
void
meta_window_stack_just_above (MetaWindow *window,
MetaWindow *above_this_one)
{
g_return_if_fail (window != NULL);
g_return_if_fail (above_this_one != NULL);
if (window->stack_position < above_this_one->stack_position)
{
meta_topic (META_DEBUG_STACK,
"Setting stack position of window %s to %d (making it above window %s).\n",
window->desc,
above_this_one->stack_position,
above_this_one->desc);
meta_window_set_stack_position (window, above_this_one->stack_position);
}
else
{
meta_topic (META_DEBUG_STACK,
"Window %s was already above window %s.\n",
window->desc, above_this_one->desc);
}
}
/** /**
* meta_window_get_user_time: * meta_window_get_user_time:
* @window: a #MetaWindow * @window: a #MetaWindow

View File

@ -176,6 +176,7 @@ item(_NET_WM_OPAQUE_REGION)
item(_NET_WM_FRAME_DRAWN) item(_NET_WM_FRAME_DRAWN)
item(_NET_WM_FRAME_TIMINGS) item(_NET_WM_FRAME_TIMINGS)
item(_NET_WM_WINDOW_OPACITY) item(_NET_WM_WINDOW_OPACITY)
item(_NET_RESTACK_WINDOW)
/* eof atomnames.h */ /* eof atomnames.h */

View File

@ -2092,6 +2092,32 @@ meta_window_move_resize_request (MetaWindow *window,
} }
} }
static void
restack_window (MetaWindow *window,
MetaWindow *sibling,
int direction)
{
switch (direction)
{
case Above:
if (sibling)
meta_window_stack_just_above (window, sibling);
else
meta_window_raise (window);
break;
case Below:
if (sibling)
meta_window_stack_just_below (window, sibling);
else
meta_window_lower (window);
break;
case TopIf:
case BottomIf:
case Opposite:
break;
}
}
gboolean gboolean
meta_window_x11_configure_request (MetaWindow *window, meta_window_x11_configure_request (MetaWindow *window,
XEvent *event) XEvent *event)
@ -2125,10 +2151,7 @@ meta_window_x11_configure_request (MetaWindow *window,
* the stack looks). * the stack looks).
* *
* I'm pretty sure no interesting client uses TopIf, BottomIf, or * I'm pretty sure no interesting client uses TopIf, BottomIf, or
* Opposite anyway, so the only possible missing thing is * Opposite anyway.
* Above/Below with a sibling set. For now we just pretend there's
* never a sibling set and always do the full raise/lower instead of
* the raise-just-above/below-sibling.
*/ */
if (event->xconfigurerequest.value_mask & CWStackMode) if (event->xconfigurerequest.value_mask & CWStackMode)
{ {
@ -2160,19 +2183,23 @@ meta_window_x11_configure_request (MetaWindow *window,
} }
else else
{ {
switch (event->xconfigurerequest.detail) MetaWindow *sibling = NULL;
/* Handle Above/Below with a sibling set */
if (event->xconfigurerequest.above != None)
{ {
case Above: MetaDisplay *display;
meta_window_raise (window);
break; display = meta_window_get_display (window);
case Below: sibling = meta_display_lookup_x_window (display,
meta_window_lower (window); event->xconfigurerequest.above);
break; if (sibling == NULL)
case TopIf: return TRUE;
case BottomIf:
case Opposite: meta_topic (META_DEBUG_STACK,
break; "xconfigure stacking request from window %s sibling %s stackmode %d\n",
window->desc, sibling->desc, event->xconfigurerequest.detail);
} }
restack_window (window, sibling, event->xconfigurerequest.detail);
} }
} }
@ -2245,6 +2272,30 @@ query_pressed_buttons (MetaWindow *window)
return button; return button;
} }
static void
handle_net_restack_window (MetaDisplay *display,
XEvent *event)
{
MetaWindow *window, *sibling = NULL;
/* Ignore if this does not come from a pager, see the WM spec
*/
if (event->xclient.data.l[0] != 2)
return;
window = meta_display_lookup_x_window (display,
event->xclient.window);
if (window)
{
if (event->xclient.data.l[1])
sibling = meta_display_lookup_x_window (display,
event->xclient.data.l[1]);
restack_window (window, sibling, event->xclient.data.l[2]);
}
}
gboolean gboolean
meta_window_x11_client_message (MetaWindow *window, meta_window_x11_client_message (MetaWindow *window,
XEvent *event) XEvent *event)
@ -2728,6 +2779,11 @@ meta_window_x11_client_message (MetaWindow *window,
meta_window_show_menu (window, META_WINDOW_MENU_WM, x, y); meta_window_show_menu (window, META_WINDOW_MENU_WM, x, y);
} }
else if (event->xclient.message_type ==
display->atom__NET_RESTACK_WINDOW)
{
handle_net_restack_window (display, event);
}
return FALSE; return FALSE;
} }