window: Move client-type-specific managing / unmanaging to a vfunc
This commit is contained in:
parent
74a1e00e30
commit
a377a1a110
@ -454,6 +454,8 @@ struct _MetaWindowClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (*manage) (MetaWindow *window);
|
||||
void (*unmanage) (MetaWindow *window);
|
||||
void (*get_default_skip_hints) (MetaWindow *window,
|
||||
gboolean *skip_taskbar_out,
|
||||
gboolean *skip_pager_out);
|
||||
|
@ -73,7 +73,6 @@
|
||||
static int destroying_windows_disallowed = 0;
|
||||
|
||||
|
||||
static void update_sm_hints (MetaWindow *window);
|
||||
static void update_net_frame_extents (MetaWindow *window);
|
||||
static void invalidate_work_areas (MetaWindow *window);
|
||||
static void set_wm_state (MetaWindow *window);
|
||||
@ -971,25 +970,9 @@ _meta_window_shared_new (MetaDisplay *display,
|
||||
*/
|
||||
window->stable_sequence = ++display->window_sequence_counter;
|
||||
|
||||
if (client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
{
|
||||
meta_display_register_x_window (display, &window->xwindow, window);
|
||||
meta_window_x11_update_shape_region (window);
|
||||
meta_window_x11_update_input_region (window);
|
||||
}
|
||||
else
|
||||
meta_display_register_wayland_window (display, window);
|
||||
|
||||
window->opacity = 0xFF;
|
||||
|
||||
/* assign the window to its group, or create a new group if needed
|
||||
*/
|
||||
window->group = NULL;
|
||||
window->xgroup_leader = None;
|
||||
meta_window_compute_group (window);
|
||||
|
||||
if (client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
meta_window_load_initial_properties (window);
|
||||
META_WINDOW_GET_CLASS (window)->manage (window);
|
||||
|
||||
if (window->override_redirect)
|
||||
{
|
||||
@ -1001,13 +984,6 @@ _meta_window_shared_new (MetaDisplay *display,
|
||||
window->has_resize_func = FALSE;
|
||||
}
|
||||
|
||||
if (!window->override_redirect &&
|
||||
client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
update_sm_hints (window); /* must come after transient_for */
|
||||
|
||||
if (client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
meta_window_x11_update_net_wm_type (window);
|
||||
|
||||
if (!window->override_redirect)
|
||||
meta_window_update_icon_now (window);
|
||||
|
||||
@ -1068,16 +1044,6 @@ _meta_window_shared_new (MetaDisplay *display,
|
||||
if (window->decorated)
|
||||
meta_window_ensure_frame (window);
|
||||
|
||||
if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
|
||||
{
|
||||
MetaStackWindow stack_window;
|
||||
stack_window.any.type = META_WINDOW_CLIENT_TYPE_WAYLAND;
|
||||
stack_window.wayland.meta_window = window;
|
||||
meta_stack_tracker_record_add (window->screen->stack_tracker,
|
||||
&stack_window,
|
||||
0);
|
||||
}
|
||||
|
||||
meta_window_grab_keys (window);
|
||||
if (window->type != META_WINDOW_DOCK && !window->override_redirect)
|
||||
{
|
||||
@ -1502,19 +1468,11 @@ meta_window_unmanage (MetaWindow *window,
|
||||
|
||||
meta_verbose ("Unmanaging 0x%lx\n", window->xwindow);
|
||||
|
||||
/* This needs to happen for both Wayland and XWayland clients,
|
||||
* so it can't be in MetaWindowWayland. */
|
||||
if (window->surface)
|
||||
meta_wayland_surface_window_unmanaged (window->surface);
|
||||
|
||||
if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
|
||||
{
|
||||
MetaStackWindow stack_window;
|
||||
stack_window.any.type = META_WINDOW_CLIENT_TYPE_WAYLAND;
|
||||
stack_window.wayland.meta_window = window;
|
||||
meta_stack_tracker_record_remove (window->screen->stack_tracker,
|
||||
&stack_window,
|
||||
0);
|
||||
}
|
||||
|
||||
if (window->visible_to_compositor)
|
||||
meta_compositor_hide_window (window->display->compositor, window,
|
||||
META_COMP_EFFECT_DESTROY);
|
||||
@ -1670,105 +1628,15 @@ meta_window_unmanage (MetaWindow *window,
|
||||
*/
|
||||
meta_stack_tracker_queue_sync_stack (window->screen->stack_tracker);
|
||||
|
||||
if (window->withdrawn)
|
||||
{
|
||||
/* We need to clean off the window's state so it
|
||||
* won't be restored if the app maps it again.
|
||||
*/
|
||||
meta_error_trap_push (window->display);
|
||||
meta_verbose ("Cleaning state from window %s\n", window->desc);
|
||||
XDeleteProperty (window->display->xdisplay,
|
||||
window->xwindow,
|
||||
window->display->atom__NET_WM_DESKTOP);
|
||||
XDeleteProperty (window->display->xdisplay,
|
||||
window->xwindow,
|
||||
window->display->atom__NET_WM_STATE);
|
||||
XDeleteProperty (window->display->xdisplay,
|
||||
window->xwindow,
|
||||
window->display->atom__NET_WM_FULLSCREEN_MONITORS);
|
||||
set_wm_state (window);
|
||||
meta_error_trap_pop (window->display);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We need to put WM_STATE so that others will understand it on
|
||||
* restart.
|
||||
*/
|
||||
if (!window->minimized)
|
||||
{
|
||||
meta_error_trap_push (window->display);
|
||||
set_wm_state (window);
|
||||
meta_error_trap_pop (window->display);
|
||||
}
|
||||
|
||||
/* If we're unmanaging a window that is not withdrawn, then
|
||||
* either (a) mutter is exiting, in which case we need to map
|
||||
* the window so the next WM will know that it's not Withdrawn,
|
||||
* or (b) we want to create a new MetaWindow to replace the
|
||||
* current one, which will happen automatically if we re-map
|
||||
* the X Window.
|
||||
*/
|
||||
meta_error_trap_push (window->display);
|
||||
XMapWindow (window->display->xdisplay,
|
||||
window->xwindow);
|
||||
meta_error_trap_pop (window->display);
|
||||
}
|
||||
|
||||
meta_window_ungrab_keys (window);
|
||||
meta_display_ungrab_window_buttons (window->display, window->xwindow);
|
||||
meta_display_ungrab_focus_window_button (window->display, window);
|
||||
if (window->display->autoraise_window == window)
|
||||
meta_display_remove_autoraise_callback (window->display);
|
||||
|
||||
if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
{
|
||||
meta_display_unregister_x_window (window->display, window->xwindow);
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
|
||||
/* Put back anything we messed up */
|
||||
if (window->border_width != 0)
|
||||
XSetWindowBorderWidth (window->display->xdisplay,
|
||||
window->xwindow,
|
||||
window->border_width);
|
||||
|
||||
/* No save set */
|
||||
XRemoveFromSaveSet (window->display->xdisplay,
|
||||
window->xwindow);
|
||||
|
||||
/* Even though the window is now unmanaged, we can't unselect events. This
|
||||
* window might be a window from this process, like a GdkMenu, in
|
||||
* which case it will have pointer events and so forth selected
|
||||
* for it by GDK. There's no way to disentangle those events from the events
|
||||
* we've selected. Even for a window from a different X client,
|
||||
* GDK could also have selected events for it for IPC purposes, so we
|
||||
* can't unselect in that case either.
|
||||
*
|
||||
* Similarly, we can't unselected for events on window->user_time_window.
|
||||
* It might be our own GDK focus window, or it might be a window that a
|
||||
* different client is using for multiple different things:
|
||||
* _NET_WM_USER_TIME_WINDOW and IPC, perhaps.
|
||||
*/
|
||||
|
||||
if (window->user_time_window != None)
|
||||
{
|
||||
meta_display_unregister_x_window (window->display,
|
||||
window->user_time_window);
|
||||
window->user_time_window = None;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
if (META_DISPLAY_HAS_SHAPE (window->display))
|
||||
XShapeSelectInput (window->display->xdisplay, window->xwindow, NoEventMask);
|
||||
#endif
|
||||
|
||||
meta_error_trap_pop (window->display);
|
||||
}
|
||||
else
|
||||
meta_display_unregister_wayland_window (window->display, window);
|
||||
META_WINDOW_GET_CLASS (window)->unmanage (window);
|
||||
|
||||
meta_prefs_remove_listener (prefs_changed_callback, window);
|
||||
|
||||
meta_screen_queue_check_fullscreen (window->screen);
|
||||
|
||||
g_signal_emit (window, window_signals[UNMANAGED], 0);
|
||||
@ -6541,106 +6409,6 @@ meta_window_set_icon_geometry (MetaWindow *window,
|
||||
}
|
||||
}
|
||||
|
||||
static Window
|
||||
read_client_leader (MetaDisplay *display,
|
||||
Window xwindow)
|
||||
{
|
||||
Window retval = None;
|
||||
|
||||
meta_prop_get_window (display, xwindow,
|
||||
display->atom_WM_CLIENT_LEADER,
|
||||
&retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Window leader;
|
||||
} ClientLeaderData;
|
||||
|
||||
static gboolean
|
||||
find_client_leader_func (MetaWindow *ancestor,
|
||||
void *data)
|
||||
{
|
||||
ClientLeaderData *d;
|
||||
|
||||
d = data;
|
||||
|
||||
d->leader = read_client_leader (ancestor->display,
|
||||
ancestor->xwindow);
|
||||
|
||||
/* keep going if no client leader found */
|
||||
return d->leader == None;
|
||||
}
|
||||
|
||||
static void
|
||||
update_sm_hints (MetaWindow *window)
|
||||
{
|
||||
Window leader;
|
||||
|
||||
window->xclient_leader = None;
|
||||
window->sm_client_id = NULL;
|
||||
|
||||
/* If not on the current window, we can get the client
|
||||
* leader from transient parents. If we find a client
|
||||
* leader, we read the SM_CLIENT_ID from it.
|
||||
*/
|
||||
leader = read_client_leader (window->display, window->xwindow);
|
||||
if (leader == None)
|
||||
{
|
||||
ClientLeaderData d;
|
||||
d.leader = None;
|
||||
meta_window_foreach_ancestor (window, find_client_leader_func,
|
||||
&d);
|
||||
leader = d.leader;
|
||||
}
|
||||
|
||||
if (leader != None)
|
||||
{
|
||||
char *str;
|
||||
|
||||
window->xclient_leader = leader;
|
||||
|
||||
if (meta_prop_get_latin1_string (window->display, leader,
|
||||
window->display->atom_SM_CLIENT_ID,
|
||||
&str))
|
||||
{
|
||||
window->sm_client_id = g_strdup (str);
|
||||
meta_XFree (str);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_verbose ("Didn't find a client leader for %s\n", window->desc);
|
||||
|
||||
if (!meta_prefs_get_disable_workarounds ())
|
||||
{
|
||||
/* Some broken apps (kdelibs fault?) set SM_CLIENT_ID on the app
|
||||
* instead of the client leader
|
||||
*/
|
||||
char *str;
|
||||
|
||||
str = NULL;
|
||||
if (meta_prop_get_latin1_string (window->display, window->xwindow,
|
||||
window->display->atom_SM_CLIENT_ID,
|
||||
&str))
|
||||
{
|
||||
if (window->sm_client_id == NULL) /* first time through */
|
||||
meta_warning ("Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER window as specified in the ICCCM.\n",
|
||||
window->desc);
|
||||
|
||||
window->sm_client_id = g_strdup (str);
|
||||
meta_XFree (str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
meta_verbose ("Window %s client leader: 0x%lx SM_CLIENT_ID: '%s'\n",
|
||||
window->desc, window->xclient_leader,
|
||||
window->sm_client_id ? window->sm_client_id : "none");
|
||||
}
|
||||
|
||||
static void
|
||||
redraw_icon (MetaWindow *window)
|
||||
{
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include "window-wayland.h"
|
||||
|
||||
#include "window-private.h"
|
||||
#include "stack-tracker.h"
|
||||
#include "meta-wayland-surface.h"
|
||||
|
||||
struct _MetaWindowWayland
|
||||
{
|
||||
@ -40,6 +42,38 @@ struct _MetaWindowWaylandClass
|
||||
|
||||
G_DEFINE_TYPE (MetaWindowWayland, meta_window_wayland, META_TYPE_WINDOW)
|
||||
|
||||
static void
|
||||
meta_window_wayland_manage (MetaWindow *window)
|
||||
{
|
||||
MetaDisplay *display = window->display;
|
||||
|
||||
meta_display_register_wayland_window (display, window);
|
||||
|
||||
{
|
||||
MetaStackWindow stack_window;
|
||||
stack_window.any.type = META_WINDOW_CLIENT_TYPE_WAYLAND;
|
||||
stack_window.wayland.meta_window = window;
|
||||
meta_stack_tracker_record_add (window->screen->stack_tracker,
|
||||
&stack_window,
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_wayland_unmanage (MetaWindow *window)
|
||||
{
|
||||
{
|
||||
MetaStackWindow stack_window;
|
||||
stack_window.any.type = META_WINDOW_CLIENT_TYPE_WAYLAND;
|
||||
stack_window.wayland.meta_window = window;
|
||||
meta_stack_tracker_record_remove (window->screen->stack_tracker,
|
||||
&stack_window,
|
||||
0);
|
||||
}
|
||||
|
||||
meta_display_unregister_wayland_window (window->display, window);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_wayland_init (MetaWindowWayland *window_wayland)
|
||||
{
|
||||
@ -48,4 +82,8 @@ meta_window_wayland_init (MetaWindowWayland *window_wayland)
|
||||
static void
|
||||
meta_window_wayland_class_init (MetaWindowWaylandClass *klass)
|
||||
{
|
||||
MetaWindowClass *window_class = META_WINDOW_CLASS (klass);
|
||||
|
||||
window_class->manage = meta_window_wayland_manage;
|
||||
window_class->unmanage = meta_window_wayland_unmanage;
|
||||
}
|
||||
|
@ -58,6 +58,210 @@ meta_window_x11_init (MetaWindowX11 *window_x11)
|
||||
window_x11->priv = meta_window_x11_get_instance_private (window_x11);
|
||||
}
|
||||
|
||||
static Window
|
||||
read_client_leader (MetaDisplay *display,
|
||||
Window xwindow)
|
||||
{
|
||||
Window retval = None;
|
||||
|
||||
meta_prop_get_window (display, xwindow,
|
||||
display->atom_WM_CLIENT_LEADER,
|
||||
&retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Window leader;
|
||||
} ClientLeaderData;
|
||||
|
||||
static gboolean
|
||||
find_client_leader_func (MetaWindow *ancestor,
|
||||
void *data)
|
||||
{
|
||||
ClientLeaderData *d;
|
||||
|
||||
d = data;
|
||||
|
||||
d->leader = read_client_leader (ancestor->display,
|
||||
ancestor->xwindow);
|
||||
|
||||
/* keep going if no client leader found */
|
||||
return d->leader == None;
|
||||
}
|
||||
|
||||
static void
|
||||
update_sm_hints (MetaWindow *window)
|
||||
{
|
||||
Window leader;
|
||||
|
||||
window->xclient_leader = None;
|
||||
window->sm_client_id = NULL;
|
||||
|
||||
/* If not on the current window, we can get the client
|
||||
* leader from transient parents. If we find a client
|
||||
* leader, we read the SM_CLIENT_ID from it.
|
||||
*/
|
||||
leader = read_client_leader (window->display, window->xwindow);
|
||||
if (leader == None)
|
||||
{
|
||||
ClientLeaderData d;
|
||||
d.leader = None;
|
||||
meta_window_foreach_ancestor (window, find_client_leader_func,
|
||||
&d);
|
||||
leader = d.leader;
|
||||
}
|
||||
|
||||
if (leader != None)
|
||||
{
|
||||
char *str;
|
||||
|
||||
window->xclient_leader = leader;
|
||||
|
||||
if (meta_prop_get_latin1_string (window->display, leader,
|
||||
window->display->atom_SM_CLIENT_ID,
|
||||
&str))
|
||||
{
|
||||
window->sm_client_id = g_strdup (str);
|
||||
meta_XFree (str);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_verbose ("Didn't find a client leader for %s\n", window->desc);
|
||||
|
||||
if (!meta_prefs_get_disable_workarounds ())
|
||||
{
|
||||
/* Some broken apps (kdelibs fault?) set SM_CLIENT_ID on the app
|
||||
* instead of the client leader
|
||||
*/
|
||||
char *str;
|
||||
|
||||
str = NULL;
|
||||
if (meta_prop_get_latin1_string (window->display, window->xwindow,
|
||||
window->display->atom_SM_CLIENT_ID,
|
||||
&str))
|
||||
{
|
||||
if (window->sm_client_id == NULL) /* first time through */
|
||||
meta_warning ("Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER window as specified in the ICCCM.\n",
|
||||
window->desc);
|
||||
|
||||
window->sm_client_id = g_strdup (str);
|
||||
meta_XFree (str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
meta_verbose ("Window %s client leader: 0x%lx SM_CLIENT_ID: '%s'\n",
|
||||
window->desc, window->xclient_leader,
|
||||
window->sm_client_id ? window->sm_client_id : "none");
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_x11_manage (MetaWindow *window)
|
||||
{
|
||||
MetaDisplay *display = window->display;
|
||||
|
||||
meta_display_register_x_window (display, &window->xwindow, window);
|
||||
meta_window_x11_update_shape_region (window);
|
||||
meta_window_x11_update_input_region (window);
|
||||
|
||||
/* assign the window to its group, or create a new group if needed */
|
||||
window->group = NULL;
|
||||
window->xgroup_leader = None;
|
||||
meta_window_compute_group (window);
|
||||
|
||||
meta_window_load_initial_properties (window);
|
||||
|
||||
if (!window->override_redirect)
|
||||
update_sm_hints (window); /* must come after transient_for */
|
||||
|
||||
meta_window_x11_update_net_wm_type (window);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_x11_unmanage (MetaWindow *window)
|
||||
{
|
||||
meta_error_trap_push (window->display);
|
||||
|
||||
if (window->withdrawn)
|
||||
{
|
||||
/* We need to clean off the window's state so it
|
||||
* won't be restored if the app maps it again.
|
||||
*/
|
||||
meta_verbose ("Cleaning state from window %s\n", window->desc);
|
||||
XDeleteProperty (window->display->xdisplay,
|
||||
window->xwindow,
|
||||
window->display->atom__NET_WM_DESKTOP);
|
||||
XDeleteProperty (window->display->xdisplay,
|
||||
window->xwindow,
|
||||
window->display->atom__NET_WM_STATE);
|
||||
XDeleteProperty (window->display->xdisplay,
|
||||
window->xwindow,
|
||||
window->display->atom__NET_WM_FULLSCREEN_MONITORS);
|
||||
meta_window_x11_set_wm_state (window);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We need to put WM_STATE so that others will understand it on
|
||||
* restart.
|
||||
*/
|
||||
if (!window->minimized)
|
||||
meta_window_x11_set_wm_state (window);
|
||||
|
||||
/* If we're unmanaging a window that is not withdrawn, then
|
||||
* either (a) mutter is exiting, in which case we need to map
|
||||
* the window so the next WM will know that it's not Withdrawn,
|
||||
* or (b) we want to create a new MetaWindow to replace the
|
||||
* current one, which will happen automatically if we re-map
|
||||
* the X Window.
|
||||
*/
|
||||
XMapWindow (window->display->xdisplay,
|
||||
window->xwindow);
|
||||
}
|
||||
|
||||
meta_display_unregister_x_window (window->display, window->xwindow);
|
||||
|
||||
/* Put back anything we messed up */
|
||||
if (window->border_width != 0)
|
||||
XSetWindowBorderWidth (window->display->xdisplay,
|
||||
window->xwindow,
|
||||
window->border_width);
|
||||
|
||||
/* No save set */
|
||||
XRemoveFromSaveSet (window->display->xdisplay,
|
||||
window->xwindow);
|
||||
|
||||
/* Even though the window is now unmanaged, we can't unselect events. This
|
||||
* window might be a window from this process, like a GdkMenu, in
|
||||
* which case it will have pointer events and so forth selected
|
||||
* for it by GDK. There's no way to disentangle those events from the events
|
||||
* we've selected. Even for a window from a different X client,
|
||||
* GDK could also have selected events for it for IPC purposes, so we
|
||||
* can't unselect in that case either.
|
||||
*
|
||||
* Similarly, we can't unselected for events on window->user_time_window.
|
||||
* It might be our own GDK focus window, or it might be a window that a
|
||||
* different client is using for multiple different things:
|
||||
* _NET_WM_USER_TIME_WINDOW and IPC, perhaps.
|
||||
*/
|
||||
|
||||
if (window->user_time_window != None)
|
||||
{
|
||||
meta_display_unregister_x_window (window->display,
|
||||
window->user_time_window);
|
||||
window->user_time_window = None;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
if (META_DISPLAY_HAS_SHAPE (window->display))
|
||||
XShapeSelectInput (window->display->xdisplay, window->xwindow, NoEventMask);
|
||||
#endif
|
||||
|
||||
meta_error_trap_pop (window->display);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_x11_get_default_skip_hints (MetaWindow *window,
|
||||
gboolean *skip_taskbar_out,
|
||||
@ -75,6 +279,8 @@ meta_window_x11_class_init (MetaWindowX11Class *klass)
|
||||
{
|
||||
MetaWindowClass *window_class = META_WINDOW_CLASS (klass);
|
||||
|
||||
window_class->manage = meta_window_x11_manage;
|
||||
window_class->unmanage = meta_window_x11_unmanage;
|
||||
window_class->get_default_skip_hints = meta_window_x11_get_default_skip_hints;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user