diff --git a/src/core/display.c b/src/core/display.c index ba78fe04a..e4eb81529 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -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; } diff --git a/src/core/events.c b/src/core/events.c index aaf6f49ae..ecb87a9c2 100644 --- a/src/core/events.c +++ b/src/core/events.c @@ -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 diff --git a/src/core/frame.c b/src/core/frame.c index f995ca2c3..1e09c260f 100644 --- a/src/core/frame.c +++ b/src/core/frame.c @@ -31,24 +31,42 @@ #include "meta/meta-x11-errors.h" #include "x11/meta-x11-display-private.h" +#include + #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; } diff --git a/src/core/frame.h b/src/core/frame.h index 61a5ca725..fb72d6388 100644 --- a/src/core/frame.h +++ b/src/core/frame.h @@ -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 diff --git a/src/core/window-private.h b/src/core/window-private.h index e5d5a280f..509862aca 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -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 diff --git a/src/core/window.c b/src/core/window.c index 883f83691..a5d203a5c 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -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) diff --git a/src/x11/atomnames.h b/src/x11/atomnames.h index b806e6e9d..4e2939edb 100644 --- a/src/x11/atomnames.h +++ b/src/x11/atomnames.h @@ -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) diff --git a/src/x11/events.c b/src/x11/events.c index 9ac9bf527..ef1301c1a 100644 --- a/src/x11/events.c +++ b/src/x11/events.c @@ -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 diff --git a/src/x11/meta-x11-display-private.h b/src/x11/meta-x11-display-private.h index a81113132..f9a9f6203 100644 --- a/src/x11/meta-x11-display-private.h +++ b/src/x11/meta-x11-display-private.h @@ -130,6 +130,9 @@ struct _MetaX11Display MetaUI *ui; + GSubprocess *frames_client; + GCancellable *frames_client_cancellable; + struct { Window xwindow; guint timeout_id; diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c index a38f64361..69f9f901d 100644 --- a/src/x11/meta-x11-display.c +++ b/src/x11/meta-x11-display.c @@ -34,6 +34,7 @@ #include "x11/meta-x11-display-private.h" #include +#include #include #include #include @@ -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); } diff --git a/src/x11/meta-x11-window-control.c b/src/x11/meta-x11-window-control.c index 4754be549..778855086 100644 --- a/src/x11/meta-x11-window-control.c +++ b/src/x11/meta-x11-window-control.c @@ -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); } diff --git a/src/x11/window-props.c b/src/x11/window-props.c index a0a30b39a..1eb3c990a 100644 --- a/src/x11/window-props.c +++ b/src/x11/window-props.c @@ -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); } } diff --git a/src/x11/window-x11-private.h b/src/x11/window-x11-private.h index 255c73f1b..5c738a83f 100644 --- a/src/x11/window-x11-private.h +++ b/src/x11/window-x11-private.h @@ -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 diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c index 0538beb13..58409609a 100644 --- a/src/x11/window-x11.c +++ b/src/x11/window-x11.c @@ -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 }