Commit 8905bd22 authored by Jasper St. Pierre's avatar Jasper St. Pierre
Browse files

window-x11: Move meta_window_new to window-x11.c and rename

parent b09e1399
......@@ -2817,14 +2817,14 @@ handle_other_xevent (MetaDisplay *display,
if (display->compositor && window == NULL
&& meta_display_screen_for_root (display, event->xmap.event))
{
window = meta_window_new (display, event->xmap.window,
window = meta_window_x11_new (display, event->xmap.window,
FALSE, META_COMP_EFFECT_CREATE);
}
break;
case MapRequest:
if (window == NULL)
{
window = meta_window_new (display, event->xmaprequest.window,
window = meta_window_x11_new (display, event->xmaprequest.window,
FALSE, META_COMP_EFFECT_CREATE);
}
/* if frame was receiver it's some malicious send event or something */
......
......@@ -896,7 +896,7 @@ meta_screen_manage_all_windows (MetaScreen *screen)
for (i = 0; i < n_children; ++i)
{
meta_window_new (screen->display, children[i].x11.xwindow, TRUE,
meta_window_x11_new (screen->display, children[i].x11.xwindow, TRUE,
META_COMP_EFFECT_NONE);
}
......
......@@ -506,12 +506,22 @@ struct _MetaWindowClass
#define META_WINDOW_ALLOWS_HORIZONTAL_RESIZE(w) (META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS (w) && (w)->size_hints.min_width < (w)->size_hints.max_width)
#define META_WINDOW_ALLOWS_VERTICAL_RESIZE(w) (META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS (w) && (w)->size_hints.min_height < (w)->size_hints.max_height)
MetaWindow* meta_window_new (MetaDisplay *display,
MetaWindow * _meta_window_shared_new (MetaDisplay *display,
MetaScreen *screen,
MetaWindowClientType client_type,
MetaWaylandSurface *surface,
Window xwindow,
gulong existing_wm_state,
MetaCompEffect effect,
XWindowAttributes *attrs);
MetaWindow * meta_window_x11_new (MetaDisplay *display,
Window xwindow,
gboolean must_be_viewable,
MetaCompEffect effect);
MetaWindow *meta_window_new_for_wayland (MetaDisplay *display,
MetaWindow * meta_window_wayland_new (MetaDisplay *display,
MetaWaylandSurface *surface);
void meta_window_unmanage (MetaWindow *window,
guint32 timestamp);
void meta_window_calc_showing (MetaWindow *window);
......
......@@ -846,7 +846,7 @@ reload_mwm_hints (MetaWindow *window,
meta_window_recalc_features (window);
/* We do all this anyhow at the end of meta_window_new() */
/* We do all this anyhow at the end of meta_window_x11_new() */
if (!window->constructing)
{
if (window->decorated)
......
......@@ -32,6 +32,9 @@
#include <X11/extensions/shape.h>
#endif
#include <X11/extensions/Xcomposite.h>
#include "core.h"
#include <meta/common.h>
#include <meta/errors.h>
#include <meta/prefs.h>
......@@ -1146,3 +1149,343 @@ meta_window_x11_client_message (MetaWindow *window,
return FALSE;
}
static void
set_wm_state_on_xwindow (MetaDisplay *display,
Window xwindow,
int state)
{
unsigned long data[2];
/* Mutter doesn't use icon windows, so data[1] should be None
* according to the ICCCM 2.0 Section 4.1.3.1.
*/
data[0] = state;
data[1] = None;
meta_error_trap_push (display);
XChangeProperty (display->xdisplay, xwindow,
display->atom_WM_STATE,
display->atom_WM_STATE,
32, PropModeReplace, (guchar*) data, 2);
meta_error_trap_pop (display);
}
void
meta_window_x11_set_wm_state (MetaWindow *window)
{
int state;
if (window->withdrawn)
state = WithdrawnState;
else if (window->iconic)
state = IconicState;
else
state = NormalState;
set_wm_state_on_xwindow (window->display, window->xwindow, state);
}
/* The MUTTER_WM_CLASS_FILTER environment variable is designed for
* performance and regression testing environments where we want to do
* tests with only a limited set of windows and ignore all other windows
*
* When it is set to a comma separated list of WM_CLASS class names, all
* windows not matching the list will be ignored.
*
* Returns TRUE if window has been filtered out and should be ignored.
*/
static gboolean
maybe_filter_xwindow (MetaDisplay *display,
Window xwindow,
gboolean must_be_viewable,
XWindowAttributes *attrs)
{
static char **filter_wm_classes = NULL;
static gboolean initialized = FALSE;
XClassHint class_hint;
gboolean filtered;
Status success;
int i;
if (!initialized)
{
const char *filter_string = g_getenv ("MUTTER_WM_CLASS_FILTER");
if (filter_string)
filter_wm_classes = g_strsplit (filter_string, ",", -1);
initialized = TRUE;
}
if (!filter_wm_classes || !filter_wm_classes[0])
return FALSE;
filtered = TRUE;
meta_error_trap_push (display);
success = XGetClassHint (display->xdisplay, xwindow, &class_hint);
if (success)
{
for (i = 0; filter_wm_classes[i]; i++)
{
if (strcmp (class_hint.res_class, filter_wm_classes[i]) == 0)
{
filtered = FALSE;
break;
}
}
XFree (class_hint.res_name);
XFree (class_hint.res_class);
}
if (filtered)
{
/* We want to try and get the window managed by the next WM that come along,
* so we need to make sure that windows that are requested to be mapped while
* Mutter is running (!must_be_viewable), or windows already viewable at startup
* get a non-withdrawn WM_STATE property. Previously unmapped windows are left
* with whatever WM_STATE property they had.
*/
if (!must_be_viewable || attrs->map_state == IsViewable)
{
gulong old_state;
if (!meta_prop_get_cardinal_with_atom_type (display, xwindow,
display->atom_WM_STATE,
display->atom_WM_STATE,
&old_state))
old_state = WithdrawnState;
if (old_state == WithdrawnState)
set_wm_state_on_xwindow (display, xwindow, NormalState);
}
/* Make sure filtered windows are hidden from view */
XUnmapWindow (display->xdisplay, xwindow);
}
meta_error_trap_pop (display);
return filtered;
}
static gboolean
is_our_xwindow (MetaDisplay *display,
MetaScreen *screen,
Window xwindow,
XWindowAttributes *attrs)
{
if (xwindow == screen->no_focus_window)
return TRUE;
if (xwindow == screen->flash_window)
return TRUE;
if (xwindow == screen->wm_sn_selection_window)
return TRUE;
if (xwindow == screen->wm_cm_selection_window)
return TRUE;
if (xwindow == screen->guard_window)
return TRUE;
if (display->compositor && xwindow == XCompositeGetOverlayWindow (display->xdisplay, screen->xroot))
return TRUE;
/* Any windows created via meta_create_offscreen_window */
if (attrs->override_redirect && attrs->x == -100 && attrs->height == -100 && attrs->width == 1 && attrs->height == 1)
return TRUE;
return FALSE;
}
#ifdef WITH_VERBOSE_MODE
static const char*
wm_state_to_string (int state)
{
switch (state)
{
case NormalState:
return "NormalState";
case IconicState:
return "IconicState";
case WithdrawnState:
return "WithdrawnState";
}
return "Unknown";
}
#endif
MetaWindow *
meta_window_x11_new (MetaDisplay *display,
Window xwindow,
gboolean must_be_viewable,
MetaCompEffect effect)
{
XWindowAttributes attrs;
MetaScreen *screen = NULL;
GSList *tmp;
gulong existing_wm_state;
MetaWindow *window = NULL;
gulong event_mask;
meta_verbose ("Attempting to manage 0x%lx\n", xwindow);
if (meta_display_xwindow_is_a_no_focus_window (display, xwindow))
{
meta_verbose ("Not managing no_focus_window 0x%lx\n",
xwindow);
return NULL;
}
meta_error_trap_push (display); /* Push a trap over all of window
* creation, to reduce XSync() calls
*/
/*
* This function executes without any server grabs held. This means that
* the window could have already gone away, or could go away at any point,
* so we must be careful with X error handling.
*/
if (!XGetWindowAttributes (display->xdisplay, xwindow, &attrs))
{
meta_verbose ("Failed to get attributes for window 0x%lx\n",
xwindow);
goto error;
}
for (tmp = display->screens; tmp != NULL; tmp = tmp->next)
{
MetaScreen *scr = tmp->data;
if (scr->xroot == attrs.root)
{
screen = tmp->data;
break;
}
}
g_assert (screen);
if (is_our_xwindow (display, screen, xwindow, &attrs))
{
meta_verbose ("Not managing our own windows\n");
goto error;
}
if (maybe_filter_xwindow (display, xwindow, must_be_viewable, &attrs))
{
meta_verbose ("Not managing filtered window\n");
goto error;
}
existing_wm_state = WithdrawnState;
if (must_be_viewable && attrs.map_state != IsViewable)
{
/* Only manage if WM_STATE is IconicState or NormalState */
gulong state;
/* WM_STATE isn't a cardinal, it's type WM_STATE, but is an int */
if (!(meta_prop_get_cardinal_with_atom_type (display, xwindow,
display->atom_WM_STATE,
display->atom_WM_STATE,
&state) &&
(state == IconicState || state == NormalState)))
{
meta_verbose ("Deciding not to manage unmapped or unviewable window 0x%lx\n", xwindow);
goto error;
}
existing_wm_state = state;
meta_verbose ("WM_STATE of %lx = %s\n", xwindow,
wm_state_to_string (existing_wm_state));
}
meta_error_trap_push_with_return (display);
/*
* XAddToSaveSet can only be called on windows created by a different
* client. with Mutter we want to be able to create manageable windows
* from within the process (such as a dummy desktop window). As we do not
* want this call failing to prevent the window from being managed, we
* call this before creating the return-checked error trap.
*/
XAddToSaveSet (display->xdisplay, xwindow);
meta_error_trap_push_with_return (display);
event_mask = PropertyChangeMask | ColormapChangeMask;
if (attrs.override_redirect)
event_mask |= StructureNotifyMask;
/* If the window is from this client (a menu, say) we need to augment
* the event mask, not replace it. For windows from other clients,
* attrs.your_event_mask will be empty at this point.
*/
XSelectInput (display->xdisplay, xwindow, attrs.your_event_mask | event_mask);
{
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
meta_core_add_old_event_mask (display->xdisplay, xwindow, &mask);
XISetMask (mask.mask, XI_Enter);
XISetMask (mask.mask, XI_Leave);
XISetMask (mask.mask, XI_FocusIn);
XISetMask (mask.mask, XI_FocusOut);
XISelectEvents (display->xdisplay, xwindow, &mask, 1);
}
/* Get rid of any borders */
if (attrs.border_width != 0)
XSetWindowBorderWidth (display->xdisplay, xwindow, 0);
/* Get rid of weird gravities */
if (attrs.win_gravity != NorthWestGravity)
{
XSetWindowAttributes set_attrs;
set_attrs.win_gravity = NorthWestGravity;
XChangeWindowAttributes (display->xdisplay,
xwindow,
CWWinGravity,
&set_attrs);
}
if (meta_error_trap_pop_with_return (display) != Success)
{
meta_verbose ("Window 0x%lx disappeared just as we tried to manage it\n",
xwindow);
goto error;
}
window = _meta_window_shared_new (display,
screen,
META_WINDOW_CLIENT_TYPE_X11,
NULL,
xwindow,
existing_wm_state,
effect,
&attrs);
/* When running as an X compositor, we can simply show the window now.
*
* When running as a Wayland compositor, we need to wait until we see
* the Wayland surface appear. We will later call meta_window_set_surface_mapped()
* to show the window in our in our set_surface_id implementation */
if (!meta_is_wayland_compositor ())
meta_window_set_surface_mapped (window, TRUE);
meta_error_trap_pop (display); /* pop the XSync()-reducing trap */
return window;
error:
meta_error_trap_pop (display);
return NULL;
}
......@@ -27,6 +27,7 @@
#include <X11/Xlib.h>
void meta_window_x11_set_net_wm_state (MetaWindow *window);
void meta_window_x11_set_wm_state (MetaWindow *window);
void meta_window_x11_update_role (MetaWindow *window);
void meta_window_x11_update_net_wm_type (MetaWindow *window);
......
......@@ -58,8 +58,6 @@
#include <X11/extensions/shape.h>
#endif
#include <X11/extensions/Xcomposite.h>
#include "meta-wayland-private.h"
#include "meta/compositor-mutter.h"
......@@ -95,9 +93,6 @@ static void ping_data_free (MetaPingData *ping_data);
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_on_xwindow (MetaDisplay *display,
Window xwindow,
int state);
static void set_wm_state (MetaWindow *window);
static void set_net_wm_state (MetaWindow *window);
static void meta_window_set_above (MetaWindow *window,
......@@ -622,24 +617,6 @@ meta_window_init (MetaWindow *self)
meta_prefs_add_listener (prefs_changed_callback, self);
}
#ifdef WITH_VERBOSE_MODE
static const char*
wm_state_to_string (int state)
{
switch (state)
{
case NormalState:
return "NormalState";
case IconicState:
return "IconicState";
case WithdrawnState:
return "WithdrawnState";
}
return "Unknown";
}
#endif
static gboolean
is_desktop_or_dock_foreach (MetaWindow *window,
void *data)
......@@ -686,121 +663,6 @@ maybe_leave_show_desktop_mode (MetaWindow *window)
}
}
/* The MUTTER_WM_CLASS_FILTER environment variable is designed for
* performance and regression testing environments where we want to do
* tests with only a limited set of windows and ignore all other windows
*
* When it is set to a comma separated list of WM_CLASS class names, all
* windows not matching the list will be ignored.
*
* Returns TRUE if window has been filtered out and should be ignored.
*/
static gboolean
maybe_filter_xwindow (MetaDisplay *display,
Window xwindow,
gboolean must_be_viewable,
XWindowAttributes *attrs)
{
static char **filter_wm_classes = NULL;
static gboolean initialized = FALSE;
XClassHint class_hint;
gboolean filtered;
Status success;
int i;
if (!initialized)
{
const char *filter_string = g_getenv ("MUTTER_WM_CLASS_FILTER");
if (filter_string)
filter_wm_classes = g_strsplit (filter_string, ",", -1);
initialized = TRUE;
}
if (!filter_wm_classes || !filter_wm_classes[0])
return FALSE;
filtered = TRUE;
meta_error_trap_push (display);
success = XGetClassHint (display->xdisplay, xwindow, &class_hint);
if (success)
{
for (i = 0; filter_wm_classes[i]; i++)
{
if (strcmp (class_hint.res_class, filter_wm_classes[i]) == 0)
{
filtered = FALSE;
break;
}
}
XFree (class_hint.res_name);
XFree (class_hint.res_class);
}
if (filtered)
{
/* We want to try and get the window managed by the next WM that come along,
* so we need to make sure that windows that are requested to be mapped while
* Mutter is running (!must_be_viewable), or windows already viewable at startup
* get a non-withdrawn WM_STATE property. Previously unmapped windows are left
* with whatever WM_STATE property they had.
*/
if (!must_be_viewable || attrs->map_state == IsViewable)
{
gulong old_state;
if (!meta_prop_get_cardinal_with_atom_type (display, xwindow,
display->atom_WM_STATE,
display->atom_WM_STATE,
&old_state))
old_state = WithdrawnState;
if (old_state == WithdrawnState)
set_wm_state_on_xwindow (display, xwindow, NormalState);
}
/* Make sure filtered windows are hidden from view */
XUnmapWindow (display->xdisplay, xwindow);
}
meta_error_trap_pop (display);
return filtered;
}
static gboolean
is_our_xwindow (MetaDisplay *display,
MetaScreen *screen,
Window xwindow,
XWindowAttributes *attrs)
{
if (xwindow == screen->no_focus_window)
return TRUE;
if (xwindow == screen->flash_window)
return TRUE;
if (xwindow == screen->wm_sn_selection_window)
return TRUE;
if (xwindow == screen->wm_cm_selection_window)
return TRUE;
if (xwindow == screen->guard_window)
return TRUE;
if (display->compositor && xwindow == XCompositeGetOverlayWindow (display->xdisplay, screen->xroot))
return TRUE;
/* Any windows created via meta_create_offscreen_window */
if (attrs->override_redirect && attrs->x == -100 && attrs->height == -100 && attrs->width == 1 && attrs->height == 1)
return TRUE;
return FALSE;
}
gboolean
meta_window_should_attach_to_parent (MetaWindow *window)
{
......@@ -826,8 +688,8 @@ meta_window_should_attach_to_parent (MetaWindow *window)
}
}
static MetaWindow*
meta_window_new_shared (MetaDisplay *display,
MetaWindow *
_meta_window_shared_new (MetaDisplay *display,
MetaScreen *screen,
MetaWindowClientType client_type,
MetaWaylandSurface *surface,
......@@ -1365,7 +1227,7 @@ meta_window_new_shared (MetaDisplay *display,
}
MetaWindow *
meta_window_new_for_wayland (MetaDisplay *display,
meta_window_wayland_new (MetaDisplay *display,
MetaWaylandSurface *surface)
{
XWindowAttributes attrs;
......@@ -1406,7 +1268,7 @@ meta_window_new_for_wayland (MetaDisplay *display,
* creation, to reduce XSync() calls
*/
window = meta_window_new_shared (display,
window = _meta_window_shared_new (display,
scr,
META_WINDOW_CLIENT_TYPE_WAYLAND,
surface,
......@@ -1426,179 +1288,6 @@ meta_window_new_for_wayland (MetaDisplay *display,
return window;
}
MetaWindow*
meta_window_new (MetaDisplay *display,
Window xwindow,
gboolean