mirror of
https://github.com/brl/mutter.git
synced 2024-11-23 00:20:42 -05:00
x11: Integrate frames client into Mutter
Replace the in-process implementation of frames with the external frames client. When a client window is created and managed by Mutter, Mutter will determine whether it is a window that requires decorations and hint the creation of a frame for it by setting the _MUTTER_NEEDS_FRAME property on the client window. After the frames client created a window that has the _MUTTER_FRAME_FOR property, Mutter will proceed to reparent the client window on the frame window, and show them as a single unit. Rendering and event handling on the frame window will be performed by the external client, Mutter is still responsible for everything else, namely resizing client and frame window in synchronization, and managing updates on the MetaWindowActor. In order to let the frame be managed by the external client, Mutter needs to change the way some properties are forwarded to the client and/or frame windows. Some properties are necessary to keep propagating to the client window only, some others need to happen on the frame window now, and some others needs to be propagated on both so they are synchronized about the behavior. Also, some events that were previously totally unexpected in frame windows are now susceptible to happen, so must be allowed now. MetaFrame in src/core/frame.c now acts as the wrapper of foreign windows created by the frames client, from the Mutter side. Location, size, and lifetime are still largely in control of Mutter, some details like visible/invisible borders are obtained from the client instead (through the _MUTTER_FRAME_EXTENTS and _GTK_FRAME_EXTENTS properties, respectively). Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
This commit is contained in:
parent
3f8e4d515e
commit
3994297429
@ -2122,10 +2122,6 @@ meta_display_queue_retheme_all_windows (MetaDisplay *display)
|
||||
|
||||
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
|
||||
meta_window_frame_size_changed (window);
|
||||
if (window->frame)
|
||||
{
|
||||
meta_frame_queue_draw (window->frame);
|
||||
}
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
@ -469,27 +469,8 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
* trigger ::captured-event handlers along the way.
|
||||
*/
|
||||
bypass_clutter = !IS_GESTURE_EVENT (event);
|
||||
|
||||
/* When double clicking to un-maximize an X11 window under Wayland,
|
||||
* there is a race between X11 and Wayland protocols and the X11
|
||||
* XConfigureWindow may be processed by Xwayland before the button
|
||||
* press event is forwarded via the Wayland protocol.
|
||||
* As a result, the second click may reach another X11 window placed
|
||||
* immediately underneath in the X11 stack.
|
||||
* The following is to make sure we do not forward the button press
|
||||
* event to Wayland if it was handled by the frame UI.
|
||||
* See: https://gitlab.gnome.org/GNOME/mutter/issues/88
|
||||
*/
|
||||
if (meta_window_handle_ui_frame_event (window, event))
|
||||
{
|
||||
bypass_wayland = (event->type == CLUTTER_BUTTON_PRESS ||
|
||||
event->type == CLUTTER_TOUCH_BEGIN);
|
||||
}
|
||||
else
|
||||
{
|
||||
bypass_wayland = meta_window_has_modals (window);
|
||||
meta_window_handle_ungrabbed_event (window, event);
|
||||
}
|
||||
bypass_wayland = meta_window_has_modals (window);
|
||||
meta_window_handle_ungrabbed_event (window, event);
|
||||
|
||||
/* This might start a grab op. If it does, then filter out the
|
||||
* event, and if it doesn't, replay the event to release our
|
||||
|
301
src/core/frame.c
301
src/core/frame.c
@ -31,24 +31,42 @@
|
||||
#include "meta/meta-x11-errors.h"
|
||||
#include "x11/meta-x11-display-private.h"
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#define EVENT_MASK (SubstructureRedirectMask | \
|
||||
StructureNotifyMask | SubstructureNotifyMask | \
|
||||
ExposureMask | FocusChangeMask)
|
||||
PropertyChangeMask | FocusChangeMask)
|
||||
|
||||
void
|
||||
meta_window_ensure_frame (MetaWindow *window)
|
||||
{
|
||||
MetaFrame *frame;
|
||||
MetaX11Display *x11_display = window->display->x11_display;
|
||||
unsigned long data[1] = { 1 };
|
||||
|
||||
meta_x11_error_trap_push (x11_display);
|
||||
|
||||
XChangeProperty (x11_display->xdisplay,
|
||||
window->xwindow,
|
||||
x11_display->atom__MUTTER_NEEDS_FRAME,
|
||||
XA_CARDINAL,
|
||||
32, PropModeReplace, (guchar*) data, 1);
|
||||
|
||||
meta_x11_error_trap_pop (x11_display);
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_set_frame_xwindow (MetaWindow *window,
|
||||
Window xframe)
|
||||
{
|
||||
MetaX11Display *x11_display = window->display->x11_display;
|
||||
XSetWindowAttributes attrs;
|
||||
gulong create_serial;
|
||||
MetaX11Display *x11_display;
|
||||
gulong create_serial = 0;
|
||||
MetaFrame *frame;
|
||||
|
||||
if (window->frame)
|
||||
return;
|
||||
|
||||
x11_display = window->display->x11_display;
|
||||
|
||||
frame = g_new (MetaFrame, 1);
|
||||
frame = g_new0 (MetaFrame, 1);
|
||||
|
||||
frame->window = window;
|
||||
frame->xwindow = None;
|
||||
@ -58,24 +76,22 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
frame->child_y = 0;
|
||||
frame->bottom_height = 0;
|
||||
frame->right_width = 0;
|
||||
frame->current_cursor = 0;
|
||||
|
||||
frame->borders_cached = FALSE;
|
||||
|
||||
window->frame = frame;
|
||||
|
||||
meta_verbose ("Frame geometry %d,%d %dx%d",
|
||||
frame->rect.x, frame->rect.y,
|
||||
frame->rect.width, frame->rect.height);
|
||||
|
||||
frame->ui_frame = meta_ui_create_frame (x11_display->ui,
|
||||
x11_display->xdisplay,
|
||||
frame->window,
|
||||
window->xvisual,
|
||||
frame->rect.x,
|
||||
frame->rect.y,
|
||||
frame->rect.width,
|
||||
frame->rect.height,
|
||||
&create_serial);
|
||||
frame->xwindow = frame->ui_frame->xwindow;
|
||||
meta_verbose ("Setting frame 0x%lx for window %s, "
|
||||
"frame geometry %d,%d %dx%d",
|
||||
xframe, window->desc,
|
||||
frame->rect.x, frame->rect.y,
|
||||
frame->rect.width, frame->rect.height);
|
||||
|
||||
frame->xwindow = xframe;
|
||||
|
||||
meta_stack_tracker_record_add (window->display->stack_tracker,
|
||||
frame->xwindow,
|
||||
@ -120,43 +136,16 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
/* stick frame to the window */
|
||||
window->frame = frame;
|
||||
|
||||
/* Now that frame->xwindow is registered with window, we can set its
|
||||
* style and background.
|
||||
*/
|
||||
meta_frame_update_style (frame);
|
||||
meta_frame_update_title (frame);
|
||||
|
||||
meta_ui_map_frame (x11_display->ui, frame->xwindow);
|
||||
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
if (META_IS_BACKEND_X11 (backend))
|
||||
{
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
|
||||
|
||||
/* Since the backend selects for events on another connection,
|
||||
* make sure to sync the GTK+ connection to ensure that the
|
||||
* frame window has been created on the server at this point. */
|
||||
XSync (x11_display->xdisplay, False);
|
||||
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
|
||||
XISelectEvents (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
|
||||
frame->xwindow, &mask, 1);
|
||||
|
||||
XISetMask (mask.mask, XI_ButtonPress);
|
||||
XISetMask (mask.mask, XI_ButtonRelease);
|
||||
XISetMask (mask.mask, XI_Motion);
|
||||
XISetMask (mask.mask, XI_Enter);
|
||||
XISetMask (mask.mask, XI_Leave);
|
||||
|
||||
XISelectEvents (xdisplay, frame->xwindow, &mask, 1);
|
||||
}
|
||||
}
|
||||
XMapWindow (x11_display->xdisplay, frame->xwindow);
|
||||
|
||||
/* Move keybindings to frame instead of window */
|
||||
meta_window_grab_keys (window);
|
||||
|
||||
/* Even though the property was already set, notify
|
||||
* on it so other bits of the machinery catch up
|
||||
* on the new frame.
|
||||
*/
|
||||
g_object_notify (G_OBJECT (window), "decorated");
|
||||
}
|
||||
|
||||
void
|
||||
@ -215,8 +204,6 @@ meta_window_destroy_frame (MetaWindow *window)
|
||||
|
||||
meta_x11_error_trap_pop (x11_display);
|
||||
|
||||
meta_ui_frame_unmanage (frame->ui_frame);
|
||||
|
||||
/* Ensure focus is restored after the unmap/map events triggered
|
||||
* by XReparentWindow().
|
||||
*/
|
||||
@ -321,6 +308,80 @@ meta_frame_borders_clear (MetaFrameBorders *self)
|
||||
self->visible.right = self->invisible.right = self->total.right = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_frame_query_borders (MetaFrame *frame,
|
||||
MetaFrameBorders *borders)
|
||||
{
|
||||
MetaWindow *window = frame->window;
|
||||
MetaX11Display *x11_display = window->display->x11_display;
|
||||
int format, res;
|
||||
Atom type;
|
||||
unsigned long nitems, bytes_after;
|
||||
unsigned char *data;
|
||||
|
||||
if (!frame->xwindow)
|
||||
return;
|
||||
|
||||
meta_x11_error_trap_push (x11_display);
|
||||
|
||||
res = XGetWindowProperty (x11_display->xdisplay,
|
||||
frame->xwindow,
|
||||
x11_display->atom__GTK_FRAME_EXTENTS,
|
||||
0, 4,
|
||||
False, XA_CARDINAL,
|
||||
&type, &format,
|
||||
&nitems, &bytes_after,
|
||||
(unsigned char **) &data);
|
||||
|
||||
if (meta_x11_error_trap_pop_with_return (x11_display) != Success)
|
||||
return;
|
||||
|
||||
if (res == Success && nitems == 4)
|
||||
{
|
||||
borders->invisible = (GtkBorder) {
|
||||
((long *) data)[0],
|
||||
((long *) data)[1],
|
||||
((long *) data)[2],
|
||||
((long *) data)[3],
|
||||
};
|
||||
}
|
||||
|
||||
g_clear_pointer (&data, XFree);
|
||||
|
||||
meta_x11_error_trap_push (x11_display);
|
||||
|
||||
res = XGetWindowProperty (x11_display->xdisplay,
|
||||
frame->xwindow,
|
||||
x11_display->atom__MUTTER_FRAME_EXTENTS,
|
||||
0, 4,
|
||||
False, XA_CARDINAL,
|
||||
&type, &format,
|
||||
&nitems, &bytes_after,
|
||||
(unsigned char **) &data);
|
||||
|
||||
if (meta_x11_error_trap_pop_with_return (x11_display) != Success)
|
||||
return;
|
||||
|
||||
if (res == Success && nitems == 4)
|
||||
{
|
||||
borders->visible = (GtkBorder) {
|
||||
((long *) data)[0],
|
||||
((long *) data)[1],
|
||||
((long *) data)[2],
|
||||
((long *) data)[3],
|
||||
};
|
||||
}
|
||||
|
||||
g_clear_pointer (&data, XFree);
|
||||
|
||||
borders->total = (GtkBorder) {
|
||||
borders->invisible.left + frame->cached_borders.visible.left,
|
||||
borders->invisible.right + frame->cached_borders.visible.right,
|
||||
borders->invisible.top + frame->cached_borders.visible.top,
|
||||
borders->invisible.bottom + frame->cached_borders.visible.bottom,
|
||||
};
|
||||
}
|
||||
|
||||
void
|
||||
meta_frame_calc_borders (MetaFrame *frame,
|
||||
MetaFrameBorders *borders)
|
||||
@ -333,7 +394,7 @@ meta_frame_calc_borders (MetaFrame *frame,
|
||||
{
|
||||
if (!frame->borders_cached)
|
||||
{
|
||||
meta_ui_frame_get_borders (frame->ui_frame, &frame->cached_borders);
|
||||
meta_frame_query_borders (frame, &frame->cached_borders);
|
||||
frame->borders_cached = TRUE;
|
||||
}
|
||||
|
||||
@ -351,6 +412,9 @@ gboolean
|
||||
meta_frame_sync_to_window (MetaFrame *frame,
|
||||
gboolean need_resize)
|
||||
{
|
||||
MetaWindow *window = frame->window;
|
||||
MetaX11Display *x11_display = window->display->x11_display;
|
||||
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"Syncing frame geometry %d,%d %dx%d (SE: %d,%d)",
|
||||
frame->rect.x, frame->rect.y,
|
||||
@ -358,11 +422,16 @@ meta_frame_sync_to_window (MetaFrame *frame,
|
||||
frame->rect.x + frame->rect.width,
|
||||
frame->rect.y + frame->rect.height);
|
||||
|
||||
meta_ui_frame_move_resize (frame->ui_frame,
|
||||
frame->rect.x,
|
||||
frame->rect.y,
|
||||
frame->rect.width,
|
||||
frame->rect.height);
|
||||
meta_x11_error_trap_push (x11_display);
|
||||
|
||||
XMoveResizeWindow (x11_display->xdisplay,
|
||||
frame->xwindow,
|
||||
frame->rect.x,
|
||||
frame->rect.y,
|
||||
frame->rect.width,
|
||||
frame->rect.height);
|
||||
|
||||
meta_x11_error_trap_pop (x11_display);
|
||||
|
||||
return need_resize;
|
||||
}
|
||||
@ -370,7 +439,21 @@ meta_frame_sync_to_window (MetaFrame *frame,
|
||||
cairo_region_t *
|
||||
meta_frame_get_frame_bounds (MetaFrame *frame)
|
||||
{
|
||||
return meta_ui_frame_get_bounds (frame->ui_frame);
|
||||
MetaFrameBorders borders;
|
||||
cairo_region_t *bounds;
|
||||
|
||||
meta_frame_calc_borders (frame, &borders);
|
||||
/* FIXME: currently just the client area, should shape closer to
|
||||
* frame border, incl. rounded corners.
|
||||
*/
|
||||
bounds = cairo_region_create_rectangle (&(cairo_rectangle_int_t) {
|
||||
borders.total.left,
|
||||
borders.total.top,
|
||||
frame->rect.width - borders.total.left - borders.total.right,
|
||||
frame->rect.height - borders.total.top - borders.total.bottom,
|
||||
});
|
||||
|
||||
return bounds;
|
||||
}
|
||||
|
||||
void
|
||||
@ -378,36 +461,17 @@ meta_frame_get_mask (MetaFrame *frame,
|
||||
cairo_rectangle_int_t *frame_rect,
|
||||
cairo_t *cr)
|
||||
{
|
||||
meta_ui_frame_get_mask (frame->ui_frame, frame_rect, cr);
|
||||
}
|
||||
MetaFrameBorders borders;
|
||||
|
||||
void
|
||||
meta_frame_queue_draw (MetaFrame *frame)
|
||||
{
|
||||
meta_ui_frame_queue_draw (frame->ui_frame);
|
||||
}
|
||||
meta_frame_calc_borders (frame, &borders);
|
||||
|
||||
void
|
||||
meta_frame_set_screen_cursor (MetaFrame *frame,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
MetaX11Display *x11_display;
|
||||
Cursor xcursor;
|
||||
if (cursor == frame->current_cursor)
|
||||
return;
|
||||
|
||||
frame->current_cursor = cursor;
|
||||
x11_display = frame->window->display->x11_display;
|
||||
|
||||
if (cursor == META_CURSOR_DEFAULT)
|
||||
XUndefineCursor (x11_display->xdisplay, frame->xwindow);
|
||||
else
|
||||
{
|
||||
xcursor = meta_x11_display_create_x_cursor (x11_display, cursor);
|
||||
XDefineCursor (x11_display->xdisplay, frame->xwindow, xcursor);
|
||||
XFlush (x11_display->xdisplay);
|
||||
XFreeCursor (x11_display->xdisplay, xcursor);
|
||||
}
|
||||
cairo_rectangle (cr,
|
||||
borders.invisible.left,
|
||||
borders.invisible.top,
|
||||
frame_rect->width,
|
||||
frame_rect->height);
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
cairo_fill (cr);
|
||||
}
|
||||
|
||||
Window
|
||||
@ -416,15 +480,60 @@ meta_frame_get_xwindow (MetaFrame *frame)
|
||||
return frame->xwindow;
|
||||
}
|
||||
|
||||
void
|
||||
meta_frame_update_style (MetaFrame *frame)
|
||||
gboolean
|
||||
meta_frame_handle_xevent (MetaFrame *frame,
|
||||
XEvent *xevent)
|
||||
{
|
||||
meta_ui_frame_update_style (frame->ui_frame);
|
||||
MetaWindow *window = frame->window;
|
||||
MetaX11Display *x11_display = window->display->x11_display;
|
||||
|
||||
if (xevent->xany.type == PropertyNotify &&
|
||||
xevent->xproperty.state == PropertyNewValue &&
|
||||
(xevent->xproperty.atom == x11_display->atom__GTK_FRAME_EXTENTS ||
|
||||
xevent->xproperty.atom == x11_display->atom__MUTTER_FRAME_EXTENTS))
|
||||
{
|
||||
meta_window_frame_size_changed (window);
|
||||
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_frame_update_title (MetaFrame *frame)
|
||||
GSubprocess *
|
||||
meta_frame_launch_client (MetaX11Display *x11_display,
|
||||
const char *display_name)
|
||||
{
|
||||
if (frame->window->title)
|
||||
meta_ui_frame_set_title (frame->ui_frame, frame->window->title);
|
||||
g_autoptr(GSubprocessLauncher) launcher = NULL;
|
||||
g_autoptr (GError) error = NULL;
|
||||
GSubprocess *proc;
|
||||
const char *args[2];
|
||||
|
||||
args[0] = MUTTER_LIBEXECDIR "/mutter-x11-frames";
|
||||
args[1] = NULL;
|
||||
|
||||
launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
|
||||
g_subprocess_launcher_setenv (launcher, "DISPLAY", display_name, TRUE);
|
||||
|
||||
proc = g_subprocess_launcher_spawnv (launcher, args, &error);
|
||||
if (error)
|
||||
{
|
||||
if (g_error_matches (error, G_SPAWN_ERROR, G_SPAWN_ERROR_NOENT))
|
||||
{
|
||||
/* Fallback case for uninstalled tests, relies on CWD being
|
||||
* the builddir, as it is the case during "ninja test".
|
||||
*/
|
||||
g_clear_error (&error);
|
||||
args[0] = "./src/frames/mutter-x11-frames";
|
||||
proc = g_subprocess_launcher_spawnv (launcher, args, &error);
|
||||
}
|
||||
|
||||
if (error)
|
||||
{
|
||||
g_warning ("Could not launch X11 frames client: %s", error->message);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
@ -23,7 +23,6 @@
|
||||
#define META_FRAME_PRIVATE_H
|
||||
|
||||
#include "core/window-private.h"
|
||||
#include "ui/frames.h"
|
||||
|
||||
struct _MetaFrame
|
||||
{
|
||||
@ -33,8 +32,6 @@ struct _MetaFrame
|
||||
/* reparent window */
|
||||
Window xwindow;
|
||||
|
||||
MetaCursor current_cursor;
|
||||
|
||||
/* This rect is trusted info from where we put the
|
||||
* frame, not the result of ConfigureNotify
|
||||
*/
|
||||
@ -48,15 +45,11 @@ struct _MetaFrame
|
||||
int right_width;
|
||||
int bottom_height;
|
||||
|
||||
guint need_reapply_frame_shape : 1;
|
||||
guint borders_cached : 1;
|
||||
|
||||
MetaUIFrame *ui_frame;
|
||||
};
|
||||
|
||||
void meta_window_ensure_frame (MetaWindow *window);
|
||||
void meta_window_destroy_frame (MetaWindow *window);
|
||||
void meta_frame_queue_draw (MetaFrame *frame);
|
||||
|
||||
MetaFrameFlags meta_frame_get_flags (MetaFrame *frame);
|
||||
Window meta_frame_get_xwindow (MetaFrame *frame);
|
||||
@ -76,10 +69,10 @@ void meta_frame_get_mask (MetaFrame *frame,
|
||||
cairo_rectangle_int_t *frame_rect,
|
||||
cairo_t *cr);
|
||||
|
||||
void meta_frame_set_screen_cursor (MetaFrame *frame,
|
||||
MetaCursor cursor);
|
||||
gboolean meta_frame_handle_xevent (MetaFrame *frame,
|
||||
XEvent *event);
|
||||
|
||||
void meta_frame_update_style (MetaFrame *frame);
|
||||
void meta_frame_update_title (MetaFrame *frame);
|
||||
GSubprocess * meta_frame_launch_client (MetaX11Display *x11_display,
|
||||
const char *display_name);
|
||||
|
||||
#endif
|
||||
|
@ -821,9 +821,6 @@ void meta_window_handle_enter (MetaWindow *window,
|
||||
guint root_y);
|
||||
void meta_window_handle_leave (MetaWindow *window);
|
||||
|
||||
gboolean meta_window_handle_ui_frame_event (MetaWindow *window,
|
||||
const ClutterEvent *event);
|
||||
|
||||
void meta_window_handle_ungrabbed_event (MetaWindow *window,
|
||||
const ClutterEvent *event);
|
||||
|
||||
@ -907,4 +904,7 @@ gboolean meta_window_calculate_bounds (MetaWindow *window,
|
||||
int *bounds_width,
|
||||
int *bounds_height);
|
||||
|
||||
void meta_window_set_frame_xwindow (MetaWindow *window,
|
||||
Window xframe);
|
||||
|
||||
#endif
|
||||
|
@ -840,6 +840,10 @@ client_window_should_be_mapped (MetaWindow *window)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (window->client_type == META_WINDOW_CLIENT_TYPE_X11 &&
|
||||
window->decorated && !window->frame)
|
||||
return FALSE;
|
||||
|
||||
return !window->shaded;
|
||||
}
|
||||
|
||||
@ -1701,6 +1705,10 @@ meta_window_should_be_showing (MetaWindow *window)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (window->client_type == META_WINDOW_CLIENT_TYPE_X11 &&
|
||||
window->decorated && !window->frame)
|
||||
return FALSE;
|
||||
|
||||
/* Windows should be showing if they're located on the
|
||||
* active workspace and they're showing on their own workspace. */
|
||||
return (meta_window_located_on_workspace (window, workspace_manager->active_workspace) &&
|
||||
@ -2948,9 +2956,6 @@ meta_window_tile (MetaWindow *window,
|
||||
META_MOVE_RESIZE_CONSTRAIN),
|
||||
META_GRAVITY_NORTH_WEST,
|
||||
window->unconstrained_rect);
|
||||
|
||||
if (window->frame)
|
||||
meta_frame_queue_draw (window->frame);
|
||||
}
|
||||
|
||||
MetaTileMode
|
||||
@ -5098,9 +5103,6 @@ meta_window_update_appears_focused (MetaWindow *window)
|
||||
meta_window_frame_size_changed (window);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_APPEARS_FOCUSED]);
|
||||
|
||||
if (window->frame)
|
||||
meta_frame_queue_draw (window->frame);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -5191,9 +5193,6 @@ meta_window_set_focused_internal (MetaWindow *window,
|
||||
if (window->override_redirect)
|
||||
return;
|
||||
|
||||
if (window->frame)
|
||||
meta_frame_queue_draw (window->frame);
|
||||
|
||||
/* Ungrab click to focus button since the sync grab can interfere
|
||||
* with some things you might do inside the focused window, by
|
||||
* causing the client to get funky enter/leave events.
|
||||
@ -7871,9 +7870,6 @@ meta_window_set_title (MetaWindow *window,
|
||||
g_free (window->title);
|
||||
window->title = g_strdup (title);
|
||||
|
||||
if (window->frame)
|
||||
meta_frame_update_title (window->frame);
|
||||
|
||||
meta_window_update_desc (window);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_TITLE]);
|
||||
@ -8254,16 +8250,6 @@ meta_window_handle_leave (MetaWindow *window)
|
||||
meta_window_lower (window);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_window_handle_ui_frame_event (MetaWindow *window,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
if (!window->frame)
|
||||
return FALSE;
|
||||
|
||||
return meta_ui_frame_handle_event (window->frame->ui_frame, event);
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_handle_ungrabbed_event (MetaWindow *window,
|
||||
const ClutterEvent *event)
|
||||
|
@ -71,6 +71,9 @@ item(_MUTTER_TIMESTAMP_PING)
|
||||
item(_MUTTER_FOCUS_SET)
|
||||
item(_MUTTER_SENTINEL)
|
||||
item(_MUTTER_VERSION)
|
||||
item(_MUTTER_FRAME_FOR)
|
||||
item(_MUTTER_FRAME_EXTENTS)
|
||||
item(_MUTTER_NEEDS_FRAME)
|
||||
item(WM_CLIENT_MACHINE)
|
||||
item(MANAGER)
|
||||
item(TARGETS)
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "x11/meta-x11-selection-input-stream-private.h"
|
||||
#include "x11/meta-x11-selection-output-stream-private.h"
|
||||
#include "x11/window-x11.h"
|
||||
#include "x11/window-x11-private.h"
|
||||
#include "x11/xprops.h"
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
@ -965,10 +966,6 @@ handle_input_xevent (MetaX11Display *x11_display,
|
||||
meta_x11_display_lookup_x_window (x11_display, modified) :
|
||||
NULL;
|
||||
|
||||
/* If this is an event for a GTK+ widget, let GTK+ handle it. */
|
||||
if (meta_ui_window_is_widget (x11_display->ui, modified))
|
||||
return FALSE;
|
||||
|
||||
switch (input_event->evtype)
|
||||
{
|
||||
case XI_Enter:
|
||||
@ -1039,10 +1036,6 @@ handle_input_xevent (MetaX11Display *x11_display,
|
||||
break;
|
||||
}
|
||||
|
||||
/* Don't eat events for GTK frames (we need to update the :hover state on buttons) */
|
||||
if (window && window->frame && modified == window->frame->xwindow)
|
||||
return FALSE;
|
||||
|
||||
/* Don't pass these events through to Clutter / GTK+ */
|
||||
return TRUE;
|
||||
}
|
||||
@ -1359,7 +1352,7 @@ handle_other_xevent (MetaX11Display *x11_display,
|
||||
{
|
||||
bypass_gtk = TRUE; /* GTK doesn't want to see this really */
|
||||
|
||||
if (window && !frame_was_receiver)
|
||||
if (window)
|
||||
{
|
||||
XShapeEvent *sev = (XShapeEvent*) event;
|
||||
|
||||
@ -1371,9 +1364,8 @@ handle_other_xevent (MetaX11Display *x11_display,
|
||||
else
|
||||
{
|
||||
meta_topic (META_DEBUG_SHAPES,
|
||||
"ShapeNotify not on a client window (window %s frame_was_receiver = %d)",
|
||||
window ? window->desc : "(none)",
|
||||
frame_was_receiver);
|
||||
"ShapeNotify not on a client window (window 0x%lx)",
|
||||
modified);
|
||||
}
|
||||
|
||||
goto out;
|
||||
@ -1420,8 +1412,6 @@ handle_other_xevent (MetaX11Display *x11_display,
|
||||
|
||||
if (frame_was_receiver)
|
||||
{
|
||||
meta_warning ("Unexpected destruction of frame 0x%lx, not sure if this should silently fail or be considered a bug",
|
||||
window->frame->xwindow);
|
||||
meta_x11_error_trap_push (x11_display);
|
||||
meta_window_destroy_frame (window->frame->window);
|
||||
meta_x11_error_trap_pop (x11_display);
|
||||
@ -1492,6 +1482,38 @@ handle_other_xevent (MetaX11Display *x11_display,
|
||||
case MapRequest:
|
||||
if (window == NULL)
|
||||
{
|
||||
Atom type;
|
||||
int format;
|
||||
unsigned long nitems, bytes_after, *data;
|
||||
|
||||
/* Check whether the new window is a frame for another window */
|
||||
if (XGetWindowProperty (x11_display->xdisplay,
|
||||
event->xmaprequest.window,
|
||||
x11_display->atom__MUTTER_FRAME_FOR,
|
||||
0, 32, False, XA_WINDOW,
|
||||
&type, &format, &nitems, &bytes_after,
|
||||
(guchar **) &data) == Success &&
|
||||
nitems == 1)
|
||||
{
|
||||
Window client_window;
|
||||
|
||||
client_window = data[0];
|
||||
XFree (data);
|
||||
|
||||
window = meta_x11_display_lookup_x_window (x11_display,
|
||||
client_window);
|
||||
|
||||
if (window != NULL && window->decorated && !window->frame)
|
||||
{
|
||||
meta_window_set_frame_xwindow (window,
|
||||
event->xmaprequest.window);
|
||||
meta_window_x11_initialize_state (window);
|
||||
meta_window_update_visibility (window);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
window = meta_window_x11_new (display, event->xmaprequest.window,
|
||||
FALSE, META_COMP_EFFECT_CREATE);
|
||||
/* The window might have initial iconic state, but this is a
|
||||
@ -1501,7 +1523,6 @@ handle_other_xevent (MetaX11Display *x11_display,
|
||||
}
|
||||
else if (frame_was_receiver)
|
||||
{
|
||||
meta_warning ("Map requests on the frame window are unexpected");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1575,10 +1596,9 @@ handle_other_xevent (MetaX11Display *x11_display,
|
||||
xwcm, &xwc);
|
||||
meta_x11_error_trap_pop (x11_display);
|
||||
}
|
||||
else
|
||||
else if (!frame_was_receiver)
|
||||
{
|
||||
if (!frame_was_receiver)
|
||||
meta_window_x11_configure_request (window, event);
|
||||
meta_window_x11_configure_request (window, event);
|
||||
}
|
||||
break;
|
||||
case GravityNotify:
|
||||
@ -1597,6 +1617,8 @@ handle_other_xevent (MetaX11Display *x11_display,
|
||||
meta_window_x11_property_notify (window, event);
|
||||
else if (property_for_window && !frame_was_receiver)
|
||||
meta_window_x11_property_notify (property_for_window, event);
|
||||
else if (frame_was_receiver)
|
||||
meta_frame_handle_xevent (window->frame, event);
|
||||
|
||||
group = meta_x11_display_lookup_group (x11_display,
|
||||
event->xproperty.window);
|
||||
@ -1650,7 +1672,6 @@ handle_other_xevent (MetaX11Display *x11_display,
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (!frame_was_receiver)
|
||||
meta_window_x11_client_message (window, event);
|
||||
}
|
||||
else
|
||||
|
@ -130,6 +130,9 @@ struct _MetaX11Display
|
||||
|
||||
MetaUI *ui;
|
||||
|
||||
GSubprocess *frames_client;
|
||||
GCancellable *frames_client_cancellable;
|
||||
|
||||
struct {
|
||||
Window xwindow;
|
||||
guint timeout_id;
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "x11/meta-x11-display-private.h"
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
@ -92,6 +93,8 @@ static void unset_wm_check_hint (MetaX11Display *x11_display);
|
||||
static void prefs_changed_callback (MetaPreference pref,
|
||||
void *data);
|
||||
|
||||
static void meta_x11_display_init_frames_client (MetaX11Display *x11_display);
|
||||
|
||||
static void
|
||||
meta_x11_display_unmanage_windows (MetaX11Display *x11_display)
|
||||
{
|
||||
@ -122,6 +125,18 @@ meta_x11_display_dispose (GObject *object)
|
||||
|
||||
g_clear_pointer (&x11_display->alarm_filters, g_ptr_array_unref);
|
||||
|
||||
if (x11_display->frames_client_cancellable)
|
||||
{
|
||||
g_cancellable_cancel (x11_display->frames_client_cancellable);
|
||||
g_clear_object (&x11_display->frames_client_cancellable);
|
||||
}
|
||||
|
||||
if (x11_display->frames_client)
|
||||
{
|
||||
g_subprocess_send_signal (x11_display->frames_client, SIGTERM);
|
||||
g_clear_object (&x11_display->frames_client);
|
||||
}
|
||||
|
||||
if (x11_display->empty_region != None)
|
||||
{
|
||||
XFixesDestroyRegion (x11_display->xdisplay,
|
||||
@ -140,12 +155,6 @@ meta_x11_display_dispose (GObject *object)
|
||||
meta_x11_selection_shutdown (x11_display);
|
||||
meta_x11_display_unmanage_windows (x11_display);
|
||||
|
||||
if (x11_display->ui)
|
||||
{
|
||||
meta_ui_free (x11_display->ui);
|
||||
x11_display->ui = NULL;
|
||||
}
|
||||
|
||||
if (x11_display->no_focus_window != None)
|
||||
{
|
||||
XUnmapWindow (x11_display->xdisplay, x11_display->no_focus_window);
|
||||
@ -1112,6 +1121,52 @@ on_window_visibility_updated (MetaDisplay *display,
|
||||
meta_x11_display_increment_focus_sentinel (x11_display);
|
||||
}
|
||||
|
||||
static void
|
||||
on_frames_client_died (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaX11Display *x11_display = user_data;
|
||||
GSubprocess *proc = G_SUBPROCESS (source);
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
if (!g_subprocess_wait_finish (proc, result, &error))
|
||||
{
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
g_warning ("Error obtaining frames client exit status: %s\n", error->message);
|
||||
}
|
||||
|
||||
g_clear_object (&x11_display->frames_client_cancellable);
|
||||
g_clear_object (&x11_display->frames_client);
|
||||
|
||||
if (g_subprocess_get_if_signaled (proc))
|
||||
{
|
||||
int signum;
|
||||
|
||||
signum = g_subprocess_get_term_sig (proc);
|
||||
|
||||
/* Bring it up again, unless it was forcibly closed */
|
||||
if (signum != SIGTERM && signum != SIGKILL)
|
||||
meta_x11_display_init_frames_client (x11_display);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_x11_display_init_frames_client (MetaX11Display *x11_display)
|
||||
{
|
||||
const char *display_name;
|
||||
|
||||
display_name = get_display_name (x11_display->display);
|
||||
x11_display->frames_client_cancellable = g_cancellable_new ();
|
||||
x11_display->frames_client = meta_frame_launch_client (x11_display,
|
||||
display_name);
|
||||
g_subprocess_wait_async (x11_display->frames_client,
|
||||
x11_display->frames_client_cancellable,
|
||||
on_frames_client_died, x11_display);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_x11_display_new:
|
||||
*
|
||||
@ -1258,7 +1313,6 @@ meta_x11_display_new (MetaDisplay *display,
|
||||
meta_unsigned_long_equal);
|
||||
|
||||
x11_display->groups_by_leader = NULL;
|
||||
x11_display->ui = NULL;
|
||||
x11_display->composite_overlay_window = None;
|
||||
x11_display->guard_window = None;
|
||||
x11_display->leader_window = None;
|
||||
@ -1324,7 +1378,6 @@ meta_x11_display_new (MetaDisplay *display,
|
||||
set_desktop_viewport_hint (x11_display);
|
||||
set_desktop_geometry_hint (x11_display);
|
||||
|
||||
x11_display->ui = meta_ui_new (x11_display);
|
||||
x11_display->x11_stack = meta_x11_stack_new (x11_display);
|
||||
|
||||
x11_display->keys_grabbed = FALSE;
|
||||
@ -1408,6 +1461,8 @@ meta_x11_display_new (MetaDisplay *display,
|
||||
|
||||
init_event_masks (x11_display);
|
||||
|
||||
meta_x11_display_init_frames_client (x11_display);
|
||||
|
||||
return g_steal_pointer (&x11_display);
|
||||
}
|
||||
|
||||
|
@ -211,7 +211,4 @@ meta_x11_wm_set_screen_cursor (MetaX11Display *x11_display,
|
||||
Window frame_on_screen,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
MetaWindow *window = window_from_frame (x11_display, frame_on_screen);
|
||||
|
||||
meta_frame_set_screen_cursor (window->frame, cursor);
|
||||
}
|
||||
|
@ -1815,9 +1815,6 @@ reload_gtk_theme_variant (MetaWindow *window,
|
||||
g_free (current_variant);
|
||||
|
||||
window->gtk_theme_variant = g_strdup (requested_variant);
|
||||
|
||||
if (window->frame)
|
||||
meta_frame_update_style (window->frame);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,6 +95,8 @@ void meta_window_x11_set_bypass_compositor_hint (MetaWindowX11 *windo
|
||||
|
||||
void meta_window_x11_queue_update_icon (MetaWindowX11 *window_x11);
|
||||
|
||||
void meta_window_x11_initialize_state (MetaWindow *window);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
|
@ -560,6 +560,15 @@ meta_window_x11_manage (MetaWindow *window)
|
||||
|
||||
if (window->decorated)
|
||||
meta_window_ensure_frame (window);
|
||||
else
|
||||
meta_window_x11_initialize_state (window);
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_x11_initialize_state (MetaWindow *window)
|
||||
{
|
||||
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
|
||||
MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
|
||||
|
||||
/* Now try applying saved stuff from the session */
|
||||
{
|
||||
@ -1223,7 +1232,7 @@ update_gtk_edge_constraints (MetaWindow *window)
|
||||
|
||||
meta_x11_error_trap_push (x11_display);
|
||||
XChangeProperty (x11_display->xdisplay,
|
||||
window->xwindow,
|
||||
window->frame ? window->frame->xwindow : window->xwindow,
|
||||
x11_display->atom__GTK_EDGE_CONSTRAINTS,
|
||||
XA_CARDINAL, 32, PropModeReplace,
|
||||
(guchar*) data, 1);
|
||||
@ -1737,9 +1746,6 @@ meta_window_x11_update_icon (MetaWindowX11 *window_x11,
|
||||
g_object_notify (G_OBJECT (window), "icon");
|
||||
g_object_notify (G_OBJECT (window), "mini-icon");
|
||||
g_object_thaw_notify (G_OBJECT (window));
|
||||
|
||||
if (window->frame)
|
||||
meta_frame_queue_draw (window->frame);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2303,6 +2309,16 @@ meta_window_x11_set_net_wm_state (MetaWindow *window)
|
||||
x11_display->atom__NET_WM_STATE,
|
||||
XA_ATOM,
|
||||
32, PropModeReplace, (guchar*) data, i);
|
||||
|
||||
if (window->frame)
|
||||
{
|
||||
XChangeProperty (x11_display->xdisplay,
|
||||
window->frame->xwindow,
|
||||
x11_display->atom__NET_WM_STATE,
|
||||
XA_ATOM,
|
||||
32, PropModeReplace, (guchar*) data, i);
|
||||
}
|
||||
|
||||
meta_x11_error_trap_pop (x11_display);
|
||||
|
||||
if (window->fullscreen)
|
||||
@ -4070,10 +4086,21 @@ meta_window_x11_set_allowed_actions_hint (MetaWindow *window)
|
||||
meta_verbose ("Setting _NET_WM_ALLOWED_ACTIONS with %d atoms", i);
|
||||
|
||||
meta_x11_error_trap_push (x11_display);
|
||||
XChangeProperty (x11_display->xdisplay, window->xwindow,
|
||||
XChangeProperty (x11_display->xdisplay,
|
||||
window->xwindow,
|
||||
x11_display->atom__NET_WM_ALLOWED_ACTIONS,
|
||||
XA_ATOM,
|
||||
32, PropModeReplace, (guchar*) data, i);
|
||||
|
||||
if (window->frame)
|
||||
{
|
||||
XChangeProperty (x11_display->xdisplay,
|
||||
window->frame->xwindow,
|
||||
x11_display->atom__NET_WM_ALLOWED_ACTIONS,
|
||||
XA_ATOM,
|
||||
32, PropModeReplace, (guchar*) data, i);
|
||||
}
|
||||
|
||||
meta_x11_error_trap_pop (x11_display);
|
||||
#undef MAX_N_ACTIONS
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user