Commit 6849735e authored by Robert Bragg's avatar Robert Bragg
Browse files

Adds support in src/core for tracking override redirect windows.

The metacity core is now directly aware of override redirect windows.
- They get MetaWindows like normal windows, so mutter no longer need to special
  case them. The net wm types applicable to override redirects are also
  recognised.
- The original positioning/stacking semantics of metacity with respect to OR
  windows are maintained, but now it's easier to synchronize the stacking
  between the core and mutter.
- mutter no longer needs to manualy track UnmapNotify, MapNotify,
  ReparentNotify, CreateNotify and DestroyNotify events; instead map, unmap,
  add and remove events can now be consistently delivered via the
  MetaCompositor callbacks.
parent 13badba1
......@@ -33,11 +33,9 @@ struct _MetaCompositor
void (*unmanage_screen) (MetaCompositor *compositor,
MetaScreen *screen);
void (*add_window) (MetaCompositor *compositor,
MetaWindow *window,
Window xwindow,
XWindowAttributes *attrs);
MetaWindow *window);
void (*remove_window) (MetaCompositor *compositor,
Window xwindow);
MetaWindow *window);
void (*set_updates) (MetaCompositor *compositor,
MetaWindow *window,
gboolean update);
......@@ -49,40 +47,34 @@ struct _MetaCompositor
void (*set_active_window) (MetaCompositor *compositor,
MetaScreen *screen,
MetaWindow *window);
/* local additions */
void (*destroy_window) (MetaCompositor *compositor,
MetaWindow *window);
void (*map_window) (MetaCompositor *compositor,
MetaWindow *window);
void (*unmap_window) (MetaCompositor *compositor,
MetaWindow *window);
void (*minimize_window) (MetaCompositor *compositor,
MetaWindow *window);
MetaWindow *window,
MetaRectangle *window_rect,
MetaRectangle *icon_rect);
void (*unminimize_window) (MetaCompositor *compositor,
MetaWindow *window,
MetaRectangle *window_rect,
MetaRectangle *icon_rect);
void (*maximize_window) (MetaCompositor *compositor,
MetaWindow *window,
int x,
int y,
int width,
int height);
MetaRectangle *window_rect);
void (*unmaximize_window) (MetaCompositor *compositor,
MetaWindow *window,
int x,
int y,
int width,
int height);
MetaRectangle *window_rect);
void (*update_workspace_geometry) (MetaCompositor *compositor,
MetaWorkspace *workspace);
void (*switch_workspace) (MetaCompositor *compositor,
MetaScreen *screen,
MetaWorkspace *from,
MetaWorkspace *to,
MetaMotionDirection direction);
void (*sync_stack) (MetaCompositor *compositor,
MetaScreen *screen,
GList *stack);
void (*set_window_hidden) (MetaCompositor *compositor,
MetaScreen *screen,
MetaWindow *window,
......
......@@ -911,7 +911,7 @@ window_has_shadow (MetaCompWindow *cw)
}
if (cw->type == META_COMP_WINDOW_MENU ||
cw->type == META_COMP_WINDOW_DROP_DOWN_MENU) {
cw->type == META_COMP_WINDOW_DROPDOWN_MENU) {
meta_verbose ("Window has shadow as it is a menu\n");
return TRUE;
}
......@@ -1776,7 +1776,7 @@ get_window_type (MetaDisplay *display,
else if (type_atom == compositor->atom_net_wm_window_type_menu)
cw->type = META_COMP_WINDOW_MENU;
else if (type_atom == compositor->atom_net_wm_window_type_dropdown_menu)
cw->type = META_COMP_WINDOW_DROP_DOWN_MENU;
cw->type = META_COMP_WINDOW_DROPDOWN_MENU;
else if (type_atom == compositor->atom_net_wm_window_type_tooltip)
cw->type = META_COMP_WINDOW_TOOLTIP;
else
......
......@@ -57,23 +57,21 @@ meta_compositor_destroy (MetaCompositor *compositor)
void
meta_compositor_add_window (MetaCompositor *compositor,
MetaWindow *window,
Window xwindow,
XWindowAttributes *attrs)
MetaWindow *window)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
if (compositor && compositor->add_window)
compositor->add_window (compositor, window, xwindow, attrs);
compositor->add_window (compositor, window);
#endif
}
void
meta_compositor_remove_window (MetaCompositor *compositor,
Window xwindow)
MetaWindow *window)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
if (compositor && compositor->remove_window)
compositor->remove_window (compositor, xwindow);
compositor->remove_window (compositor, window);
#endif
}
......@@ -165,57 +163,69 @@ void meta_compositor_end_move (MetaCompositor *compositor,
{
}
void meta_compositor_free_window (MetaCompositor *compositor,
MetaWindow *window)
void
meta_compositor_map_window (MetaCompositor *compositor,
MetaWindow *window)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
if (compositor && compositor->map_window)
compositor->map_window (compositor, window);
#endif
}
void
meta_compositor_destroy_window (MetaCompositor *compositor,
MetaWindow *window)
meta_compositor_unmap_window (MetaCompositor *compositor,
MetaWindow *window)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
if (compositor && compositor->destroy_window)
compositor->destroy_window (compositor, window);
if (compositor && compositor->unmap_window)
compositor->unmap_window (compositor, window);
#endif
}
void
meta_compositor_minimize_window (MetaCompositor *compositor,
MetaWindow *window)
MetaWindow *window,
MetaRectangle *window_rect,
MetaRectangle *icon_rect)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
if (compositor && compositor->minimize_window)
compositor->minimize_window (compositor, window);
compositor->minimize_window (compositor, window, window_rect, icon_rect);
#endif
}
void
meta_compositor_unminimize_window (MetaCompositor *compositor,
MetaWindow *window,
MetaRectangle *window_rect,
MetaRectangle *icon_rect)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
if (compositor && compositor->unminimize_window)
compositor->unminimize_window (compositor, window, window_rect, icon_rect);
#endif
}
void
meta_compositor_maximize_window (MetaCompositor *compositor,
MetaWindow *window,
int x,
int y,
int width,
int height)
MetaRectangle *window_rect)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
if (compositor && compositor->maximize_window)
compositor->maximize_window (compositor, window, x, y, width, height);
compositor->maximize_window (compositor, window, window_rect);
#endif
}
void
meta_compositor_unmaximize_window (MetaCompositor *compositor,
MetaWindow *window,
int x,
int y,
int width,
int height)
MetaRectangle *window_rect)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
if (compositor && compositor->unmaximize_window)
compositor->unmaximize_window (compositor, window, x, y, width, height);
compositor->unmaximize_window (compositor, window, window_rect);
#endif
}
......
This diff is collapsed.
......@@ -145,6 +145,13 @@ meta_core_get (Display *xdisplay,
case META_WINDOW_DOCK:
case META_WINDOW_TOOLBAR:
case META_WINDOW_SPLASHSCREEN:
case META_WINDOW_DROPDOWN_MENU:
case META_WINDOW_POPUP_MENU:
case META_WINDOW_TOOLTIP:
case META_WINDOW_NOTIFICATION:
case META_WINDOW_COMBO:
case META_WINDOW_DND:
case META_WINDOW_OVERRIDE_OTHER:
/* No frame */
base_type = META_FRAME_TYPE_LAST;
break;
......
......@@ -2020,7 +2020,8 @@ event_callback (XEvent *event,
"Window %s withdrawn\n",
window->desc);
meta_effect_run_close (window, NULL, NULL);
if (!window->override_redirect)
meta_effect_run_close (window, NULL, NULL);
/* Unmanage withdrawn window */
window->withdrawn = TRUE;
......@@ -2045,6 +2046,15 @@ event_callback (XEvent *event,
}
break;
case MapNotify:
/* NB: override redirect windows wont cause a map request so we
* watch out for map notifies against any root windows too if a
* compositor is enabled: */
if (display->compositor && window == NULL
&& meta_display_screen_for_root (display, event->xmap.event))
{
window = meta_window_new (display, event->xmap.window,
FALSE);
}
break;
case MapRequest:
if (window == NULL)
......@@ -2073,29 +2083,32 @@ event_callback (XEvent *event,
case ReparentNotify:
break;
case ConfigureNotify:
/* Handle screen resize */
{
MetaScreen *screen;
if (window && window->override_redirect)
meta_window_configure_notify (window, &event->xconfigure);
else
/* Handle screen resize */
{
MetaScreen *screen;
screen = meta_display_screen_for_root (display,
event->xconfigure.window);
screen = meta_display_screen_for_root (display,
event->xconfigure.window);
if (screen != NULL)
{
if (screen != NULL)
{
#ifdef HAVE_RANDR
/* do the resize the official way */
XRRUpdateConfiguration (event);
/* do the resize the official way */
XRRUpdateConfiguration (event);
#else
/* poke around in Xlib */
screen->xscreen->width = event->xconfigure.width;
screen->xscreen->height = event->xconfigure.height;
/* poke around in Xlib */
screen->xscreen->width = event->xconfigure.width;
screen->xscreen->height = event->xconfigure.height;
#endif
meta_screen_resize (screen,
event->xconfigure.width,
event->xconfigure.height);
}
}
meta_screen_resize (screen,
event->xconfigure.width,
event->xconfigure.height);
}
}
break;
case ConfigureRequest:
/* This comment and code is found in both twm and fvwm */
......
......@@ -862,7 +862,8 @@ meta_window_grab_keys (MetaWindow *window)
if (window->all_keys_grabbed)
return;
if (window->type == META_WINDOW_DOCK)
if (window->type == META_WINDOW_DOCK
|| window->override_redirect)
{
if (window->keys_grabbed)
ungrab_all_keys (window->display, window->xwindow);
......
......@@ -394,6 +394,14 @@ rectangle_overlaps_some_window (MetaRectangle *rect,
case META_WINDOW_DESKTOP:
case META_WINDOW_DIALOG:
case META_WINDOW_MODAL_DIALOG:
/* override redirect window types: */
case META_WINDOW_DROPDOWN_MENU:
case META_WINDOW_POPUP_MENU:
case META_WINDOW_TOOLTIP:
case META_WINDOW_NOTIFICATION:
case META_WINDOW_COMBO:
case META_WINDOW_DND:
case META_WINDOW_OVERRIDE_OTHER:
break;
case META_WINDOW_NORMAL:
......@@ -680,6 +688,14 @@ meta_window_place (MetaWindow *window,
case META_WINDOW_TOOLBAR:
case META_WINDOW_MENU:
case META_WINDOW_UTILITY:
/* override redirect window types: */
case META_WINDOW_DROPDOWN_MENU:
case META_WINDOW_POPUP_MENU:
case META_WINDOW_TOOLTIP:
case META_WINDOW_NOTIFICATION:
case META_WINDOW_COMBO:
case META_WINDOW_DND:
case META_WINDOW_OVERRIDE_OTHER:
goto done_no_constraints;
}
......@@ -713,6 +729,14 @@ meta_window_place (MetaWindow *window,
case META_WINDOW_TOOLBAR:
case META_WINDOW_MENU:
case META_WINDOW_UTILITY:
/* override redirect window types: */
case META_WINDOW_DROPDOWN_MENU:
case META_WINDOW_POPUP_MENU:
case META_WINDOW_TOOLTIP:
case META_WINDOW_NOTIFICATION:
case META_WINDOW_COMBO:
case META_WINDOW_DND:
case META_WINDOW_OVERRIDE_OTHER:
if (window->size_hints.flags & PPosition)
{
meta_topic (META_DEBUG_PLACEMENT,
......
......@@ -790,20 +790,6 @@ meta_screen_manage_all_windows (MetaScreen *screen)
window = meta_window_new_with_attrs (screen->display, info->xwindow, TRUE,
&info->attrs);
if (info->xwindow == screen->no_focus_window ||
info->xwindow == screen->flash_window ||
#ifdef HAVE_COMPOSITE_EXTENSIONS
info->xwindow == screen->wm_cm_selection_window ||
info->xwindow == screen->guard_window ||
#endif
info->xwindow == screen->wm_sn_selection_window) {
meta_verbose ("Not managing our own windows\n");
continue;
}
if (screen->display->compositor)
meta_compositor_add_window (screen->display->compositor, window,
info->xwindow, &info->attrs);
}
meta_stack_thaw (screen->stack);
......@@ -818,38 +804,20 @@ meta_screen_composite_all_windows (MetaScreen *screen)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
MetaDisplay *display;
GList *windows, *list;
GSList *windows, *tmp;
display = screen->display;
if (!display->compositor)
return;
windows = list_windows (screen);
windows = meta_display_list_windows (display);
for (tmp = windows; tmp != NULL; tmp = tmp->next)
meta_compositor_add_window (display->compositor, tmp->data);
g_slist_free (windows);
/* trigger a stack_sync_to_server: */
meta_stack_freeze (screen->stack);
for (list = windows; list != NULL; list = list->next)
{
WindowInfo *info = list->data;
if (info->xwindow == screen->no_focus_window ||
info->xwindow == screen->flash_window ||
info->xwindow == screen->wm_sn_selection_window ||
info->xwindow == screen->wm_cm_selection_window) {
meta_verbose ("Not managing our own windows\n");
continue;
}
meta_compositor_add_window (display->compositor,
meta_display_lookup_x_window (display,
info->xwindow),
info->xwindow, &info->attrs);
}
meta_stack_thaw (screen->stack);
g_list_foreach (windows, (GFunc)g_free, NULL);
g_list_free (windows);
#endif
}
......
......@@ -698,6 +698,20 @@ window_type_to_string (MetaWindowType type)
return "splashscreen";
case META_WINDOW_UTILITY:
return "utility";
case META_WINDOW_DROPDOWN_MENU:
return "dropdown_menu";
case META_WINDOW_POPUP_MENU:
return "popup_menu";
case META_WINDOW_TOOLTIP:
return "tooltip";
case META_WINDOW_NOTIFICATION:
return "notification";
case META_WINDOW_COMBO:
return "combo";
case META_WINDOW_DND:
return "dnd";
case META_WINDOW_OVERRIDE_OTHER:
return "override_redirect";
}
return "";
......
......@@ -265,6 +265,14 @@ get_standalone_layer (MetaWindow *window)
layer = META_LAYER_DOCK;
break;
case META_WINDOW_DROPDOWN_MENU:
case META_WINDOW_POPUP_MENU:
case META_WINDOW_TOOLTIP:
case META_WINDOW_NOTIFICATION:
case META_WINDOW_COMBO:
case META_WINDOW_OVERRIDE_OTHER:
layer = META_LAYER_OVERRIDE_REDIRECT;
break;
default:
meta_window_foreach_transient (window,
is_focused_foreach,
......@@ -1062,6 +1070,7 @@ stack_sync_to_server (MetaStack *stack)
GArray *root_children_stacked;
GList *tmp;
GArray *all_hidden;
int n_override_redirect = 0;
/* Bail out if frozen */
if (stack->freeze_count > 0)
......@@ -1100,7 +1109,10 @@ stack_sync_to_server (MetaStack *stack)
w->layer, w->stack_position, w->desc);
/* remember, stacked is in reverse order (bottom to top) */
g_array_prepend_val (stacked, w->xwindow);
if (w->override_redirect)
n_override_redirect++;
else
g_array_prepend_val (stacked, w->xwindow);
if (w->frame)
top_level_window = w->frame->xwindow;
......@@ -1124,7 +1136,7 @@ stack_sync_to_server (MetaStack *stack)
meta_pop_no_msg_prefix ();
/* All windows should be in some stacking order */
if (stacked->len != stack->windows->len)
if (stacked->len != stack->windows->len - n_override_redirect)
meta_bug ("%u windows stacked, %u windows exist in stack\n",
stacked->len, stack->windows->len);
......
......@@ -49,14 +49,15 @@
*/
typedef enum
{
META_LAYER_DESKTOP = 0,
META_LAYER_BOTTOM = 1,
META_LAYER_NORMAL = 2,
META_LAYER_TOP = 4, /* Same as DOCK; see EWMH and bug 330717 */
META_LAYER_DOCK = 4,
META_LAYER_FULLSCREEN = 5,
META_LAYER_FOCUSED_WINDOW = 6,
META_LAYER_LAST = 7
META_LAYER_DESKTOP = 0,
META_LAYER_BOTTOM = 1,
META_LAYER_NORMAL = 2,
META_LAYER_TOP = 4, /* Same as DOCK; see EWMH and bug 330717 */
META_LAYER_DOCK = 4,
META_LAYER_FULLSCREEN = 5,
META_LAYER_FOCUSED_WINDOW = 6,
META_LAYER_OVERRIDE_REDIRECT = 7,
META_LAYER_LAST = 8
} MetaStackLayer;
/**
......
......@@ -110,6 +110,9 @@ struct _MetaWindow
/* Initial timestamp property */
guint32 initial_timestamp;
/* Whether this is an override redirect window or not */
guint override_redirect : 1;
/* Whether we're maximized */
guint maximized_horizontally : 1;
guint maximized_vertically : 1;
......
......@@ -53,6 +53,10 @@
#include <X11/extensions/shape.h>
#endif
#ifdef HAVE_COMPOSITE_EXTENSIONS
#include <X11/extensions/Xcomposite.h>
#endif
static int destroying_windows_disallowed = 0;
......@@ -253,6 +257,7 @@ meta_window_new_with_attrs (MetaDisplay *display,
Atom initial_props[N_INITIAL_PROPS];
int i;
gboolean has_shape;
MetaScreen *screen;
g_assert (attrs != NULL);
g_assert (N_INITIAL_PROPS == (int) G_N_ELEMENTS (initial_props));
......@@ -266,12 +271,43 @@ meta_window_new_with_attrs (MetaDisplay *display,
return NULL;
}
if (attrs->override_redirect)
screen = NULL;
for (tmp = display->screens; tmp != NULL; tmp = tmp->next)
{
meta_verbose ("Deciding not to manage override_redirect window 0x%lx\n", xwindow);
return NULL;
MetaScreen *scr = tmp->data;
if (scr->xroot == attrs->root)
{
screen = tmp->data;
break;
}
}
g_assert (screen);
/* A black list of override redirect windows that we don't need to manage: */
if (attrs->override_redirect &&
(xwindow == screen->no_focus_window ||
xwindow == screen->flash_window ||
xwindow == screen->wm_sn_selection_window ||
attrs->class == InputOnly ||
/* any windows created via meta_create_offscreen_window: */
(attrs->x == -100 && attrs->y == -100
&& attrs->width == 1 && attrs->height == 1) ||
#ifdef HAVE_COMPOSITE_EXTENSIONS
xwindow == screen->wm_cm_selection_window ||
xwindow == screen->guard_window ||
(display->compositor &&
xwindow == XCompositeGetOverlayWindow (display->xdisplay,
screen->xroot)
)
#endif
)
) {
meta_verbose ("Not managing our own windows\n");
return NULL;
}
/* Grab server */
meta_display_grab (display);
meta_error_trap_push (display); /* Push a trap over all of window
......@@ -330,6 +366,8 @@ meta_window_new_with_attrs (MetaDisplay *display,
event_mask =
PropertyChangeMask | EnterWindowMask | LeaveWindowMask |
FocusChangeMask | ColormapChangeMask;
if (attrs->override_redirect)
event_mask |= StructureNotifyMask;
XSelectInput (display->xdisplay, xwindow, event_mask);
......@@ -384,8 +422,6 @@ meta_window_new_with_attrs (MetaDisplay *display,
return NULL;
}
g_assert (!attrs->override_redirect);
window = g_new (MetaWindow, 1);
window->constructing = TRUE;
......@@ -408,25 +444,12 @@ meta_window_new_with_attrs (MetaDisplay *display,
window->sync_request_time.tv_usec = 0;
#endif
window->screen = NULL;
tmp = display->screens;
while (tmp != NULL)
{