summaryrefslogtreecommitdiff
path: root/gtk
diff options
context:
space:
mode:
authorSam Spilsbury <sam.spilsbury@canonical.com>2011-02-10 20:26:12 +0800
committerSam Spilsbury <sam.spilsbury@canonical.com>2011-02-10 20:26:12 +0800
commit73499a21c1ec450eb70de8129185e0289f86d56f (patch)
tree53d4efe429ab403a205b0e5e3942cbefca362216 /gtk
parent561d030ab63f3888d1b7698a3c2a8c7ba8985b79 (diff)
downloadcompiz-with-glib-mainloop-73499a21c1ec450eb70de8129185e0289f86d56f.tar.gz
compiz-with-glib-mainloop-73499a21c1ec450eb70de8129185e0289f86d56f.tar.bz2
Make the switcher window being override redirect.
Previously the switcher window was a normal managed window (which the switcher plugin actually lied about, see SwitchWindow::managed), such that the decorators could pick it up and draw the switcher decoration. However now with reparenting, this means that whenever we actually manage and unmanage the switcher window (eg with map and unmap) it means we must also reparent the window, which floods the server with requests and makes the switcher slow. Since we don't interact with the switcher window, it makes no sense to manage it like this, so make it override redirect
Diffstat (limited to 'gtk')
-rw-r--r--gtk/window-decorator/decorator.c15
-rw-r--r--gtk/window-decorator/events.c44
-rw-r--r--gtk/window-decorator/gtk-window-decorator.c41
-rw-r--r--gtk/window-decorator/gtk-window-decorator.h12
-rw-r--r--gtk/window-decorator/settings.c4
-rw-r--r--gtk/window-decorator/switcher.c39
-rw-r--r--gtk/window-decorator/wnck.c27
7 files changed, 131 insertions, 51 deletions
diff --git a/gtk/window-decorator/decorator.c b/gtk/window-decorator/decorator.c
index 3bcaddd..b4fe58b 100644
--- a/gtk/window-decorator/decorator.c
+++ b/gtk/window-decorator/decorator.c
@@ -653,21 +653,6 @@ update_window_decoration (WnckWindow *win)
update_window_decoration_size (win);
update_event_windows (win);
}
- else
- {
- Window xid = wnck_window_get_xid (win);
- Window select;
-
- if (get_window_prop (xid, select_window_atom, &select))
- {
- /* force size update */
- d->context = NULL;
- d->width = d->height = 0;
- switcher_width = switcher_height = 0;
-
- update_switcher_window (win, select);
- }
- }
}
void
diff --git a/gtk/window-decorator/events.c b/gtk/window-decorator/events.c
index 6c3af32..1faec8b 100644
--- a/gtk/window-decorator/events.c
+++ b/gtk/window-decorator/events.c
@@ -859,11 +859,33 @@ event_filter_func (GdkXEvent *gdkxevent,
GdkDisplay *gdkdisplay;
XEvent *xevent = gdkxevent;
gulong xid = 0;
+ Window select = 0;
gdkdisplay = gdk_display_get_default ();
xdisplay = GDK_DISPLAY_XDISPLAY (gdkdisplay);
switch (xevent->type) {
+ case CreateNotify:
+ {
+ if (!wnck_window_get (xevent->xcreatewindow.window))
+ {
+ GdkWindow *toplevel = gdk_window_foreign_new_for_display (gdkdisplay,
+ xevent->xcreatewindow.window);
+
+ if (toplevel)
+ {
+ gdk_window_set_events (toplevel,
+ gdk_window_get_events (toplevel) |
+ GDK_PROPERTY_CHANGE_MASK);
+
+ /* check if the window is a switcher and update accordingly */
+
+ if (get_window_prop (xevent->xcreatewindow.window, select_window_atom, &select))
+ update_switcher_window (xevent->xcreatewindow.window, select);
+ }
+ }
+ }
+ break;
case ButtonPress:
case ButtonRelease:
xid = (gulong)
@@ -891,9 +913,9 @@ event_filter_func (GdkXEvent *gdkxevent,
win = wnck_window_get (xid);
if (win)
{
- Window frame, window;
+ Window frame;
- if (!get_window_prop (xid, select_window_atom, &window))
+ if (!get_window_prop (xid, select_window_atom, &select))
{
if (get_window_prop (xid, frame_input_window_atom, &frame))
add_frame_window (win, frame, FALSE);
@@ -911,9 +933,9 @@ event_filter_func (GdkXEvent *gdkxevent,
win = wnck_window_get (xid);
if (win)
{
- Window frame, window;
+ Window frame;
- if (!get_window_prop (xid, select_window_atom, &window))
+ if (!get_window_prop (xid, select_window_atom, &select))
{
if (get_window_prop (xid, frame_output_window_atom, &frame))
add_frame_window (win, frame, TRUE);
@@ -974,18 +996,10 @@ event_filter_func (GdkXEvent *gdkxevent,
}
else if (xevent->xproperty.atom == select_window_atom)
{
- WnckWindow *win;
+ Window select;
- xid = xevent->xproperty.window;
-
- win = wnck_window_get (xid);
- if (win)
- {
- Window select;
-
- if (get_window_prop (xid, select_window_atom, &select))
- update_switcher_window (win, select);
- }
+ if (get_window_prop (xevent->xproperty.window, select_window_atom, &select))
+ update_switcher_window (xevent->xproperty.window, select);
}
break;
case DestroyNotify:
diff --git a/gtk/window-decorator/gtk-window-decorator.c b/gtk/window-decorator/gtk-window-decorator.c
index bde881a..93e38db 100644
--- a/gtk/window-decorator/gtk-window-decorator.c
+++ b/gtk/window-decorator/gtk-window-decorator.c
@@ -172,6 +172,7 @@ GdkPixmap *switcher_buffer_pixmap = NULL;
gint switcher_width;
gint switcher_height;
Window switcher_selected_window = None;
+decor_t *switcher_window = NULL;
XRenderPictFormat *xformat_rgba;
XRenderPictFormat *xformat_rgb;
@@ -185,6 +186,9 @@ main (int argc, char *argv[])
WnckScreen *screen;
gint i, j, status;
gboolean replace = FALSE;
+ unsigned int nchildren;
+ Window root_ret, parent_ret;
+ Window *children = NULL;
#ifdef USE_METACITY
char *meta_theme = NULL;
@@ -380,13 +384,38 @@ main (int argc, char *argv[])
selection_event_filter_func,
NULL);
- if (!minimal)
- {
- gdk_window_add_filter (NULL,
- event_filter_func,
- NULL);
+ if (!minimal)
+ {
+ GdkWindow *root = gdk_window_foreign_new_for_display (gdkdisplay,
+ gdk_x11_get_default_root_xwindow ());
+
+ gdk_window_add_filter (NULL,
+ event_filter_func,
+ NULL);
+
+ XQueryTree (xdisplay, gdk_x11_get_default_root_xwindow (),
+ &root_ret, &parent_ret, &children, &nchildren);
+
+ for (i = 0; i < nchildren; i++)
+ {
+ GdkWindow *toplevel = gdk_window_foreign_new_for_display (gdkdisplay,
+ children[i]);
+
+ /* Need property notify on all windows */
+
+ gdk_window_set_events (toplevel,
+ gdk_window_get_events (toplevel) |
+ GDK_PROPERTY_CHANGE_MASK);
+ }
- connect_screen (screen);
+ /* Need MapNotify on new windows */
+ gdk_window_set_events (root, gdk_window_get_events (root) |
+ GDK_STRUCTURE_MASK |
+ GDK_PROPERTY_CHANGE_MASK |
+ GDK_VISIBILITY_NOTIFY_MASK |
+ GDK_SUBSTRUCTURE_MASK);
+
+ connect_screen (screen);
}
if (!init_settings (screen))
diff --git a/gtk/window-decorator/gtk-window-decorator.h b/gtk/window-decorator/gtk-window-decorator.h
index 861cba2..2bd8669 100644
--- a/gtk/window-decorator/gtk-window-decorator.h
+++ b/gtk/window-decorator/gtk-window-decorator.h
@@ -450,6 +450,7 @@ extern GdkPixmap *switcher_buffer_pixmap;
extern gint switcher_width;
extern gint switcher_height;
extern Window switcher_selected_window;
+extern decor_t *switcher_window;
extern XRenderPictFormat *xformat_rgba;
extern XRenderPictFormat *xformat_rgb;
@@ -532,6 +533,9 @@ void
restack_window (WnckWindow *win,
int stack_mode);
+void
+connect_window (WnckWindow *win);
+
/* blur.c */
@@ -718,9 +722,15 @@ void
draw_switcher_decoration (decor_t *d);
gboolean
-update_switcher_window (WnckWindow *win,
+update_switcher_window (Window popup,
Window selected);
+decor_t *
+switcher_window_opened (Window popup, Window selected);
+
+void
+switcher_window_closed ();
+
/* events.c */
void
diff --git a/gtk/window-decorator/settings.c b/gtk/window-decorator/settings.c
index f158636..31cc3e9 100644
--- a/gtk/window-decorator/settings.c
+++ b/gtk/window-decorator/settings.c
@@ -54,7 +54,7 @@ shadow_property_changed (WnckScreen *s)
result = XGetTextProperty (xdisplay, root, &shadow_color_xtp,
compiz_shadow_color_atom);
-
+
if (shadow_color_xtp.value)
{
int ret_count = 0;
@@ -84,7 +84,7 @@ shadow_property_changed (WnckScreen *s)
if (changed)
decorations_changed (s);
}
-
+
#ifdef USE_GCONF
static gboolean
blur_settings_changed (GConfClient *client)
diff --git a/gtk/window-decorator/switcher.c b/gtk/window-decorator/switcher.c
index 046ea0a..6da0475 100644
--- a/gtk/window-decorator/switcher.c
+++ b/gtk/window-decorator/switcher.c
@@ -257,20 +257,49 @@ draw_switcher_decoration (decor_t *d)
draw_switcher_foreground (d);
}
+void
+switcher_window_closed ()
+{
+ g_free (switcher_window);
+ switcher_window = NULL;
+}
+
+/* Switcher is override-redirect now, we need to track
+ * it separately */
+decor_t *
+switcher_window_opened (Window popup, Window window)
+{
+ decor_t *d;
+
+ d = switcher_window = calloc (1, sizeof (decor_t));
+ if (!d)
+ return NULL;
+
+ return d;
+}
+
+
gboolean
-update_switcher_window (WnckWindow *win,
+update_switcher_window (Window popup,
Window selected)
{
- decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ decor_t *d = switcher_window;
GdkPixmap *pixmap, *buffer_pixmap = NULL;
- gint height, width = 0;
+ unsigned int height, width = 0, border, depth;
+ int x, y;
+ Window root_return;
WnckWindow *selected_win;
Display *xdisplay;
XRenderPictFormat *format;
+ if (!d)
+ d = switcher_window_opened (popup, selected);
+
xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
- wnck_window_get_client_window_geometry (win, NULL, NULL, &width, NULL);
+ /* FIXME: Thats a round-trip */
+ XGetGeometry (gdk_x11_get_default_xdisplay (), popup, &root_return,
+ &x, &y, &width, &height, &border, &depth);
decor_get_default_layout (&switcher_context, width, 1, &d->border_layout);
@@ -419,7 +448,7 @@ update_switcher_window (WnckWindow *win,
d->width = width;
d->height = height;
- d->prop_xid = wnck_window_get_xid (win);
+ d->prop_xid = popup;
queue_decor_draw (d);
diff --git a/gtk/window-decorator/wnck.c b/gtk/window-decorator/wnck.c
index a4794e5..fc5fd14 100644
--- a/gtk/window-decorator/wnck.c
+++ b/gtk/window-decorator/wnck.c
@@ -83,6 +83,7 @@ decorations_changed (WnckScreen *screen)
GdkDisplay *gdkdisplay;
GdkScreen *gdkscreen;
GList *windows;
+ Window select;
gdkdisplay = gdk_display_get_default ();
gdkscreen = gdk_display_get_default_screen (gdkdisplay);
@@ -96,6 +97,8 @@ decorations_changed (WnckScreen *screen)
if (minimal)
return;
+ /* Update all normal windows */
+
windows = wnck_screen_get_windows (screen);
while (windows != NULL)
{
@@ -115,6 +118,21 @@ decorations_changed (WnckScreen *screen)
update_window_decoration (WNCK_WINDOW (windows->data));
windows = windows->next;
}
+
+ /* Update switcher window */
+
+ if (switcher_window &&
+ get_window_prop (switcher_window->prop_xid,
+ select_window_atom, &select))
+ {
+ decor_t *d = switcher_window;
+ /* force size update */
+ d->context = NULL;
+ d->width = d->height = 0;
+ switcher_width = switcher_height = 0;
+
+ update_switcher_window (d->prop_xid, select);
+ }
}
void
@@ -438,7 +456,7 @@ remove_frame_window (WnckWindow *win)
draw_list = g_slist_remove (draw_list, d);
}
-static void
+void
connect_window (WnckWindow *win)
{
g_signal_connect_object (win, "name_changed",
@@ -543,12 +561,7 @@ window_opened (WnckScreen *screen,
xid = wnck_window_get_xid (win);
- if (get_window_prop (xid, select_window_atom, &window))
- {
- d->prop_xid = wnck_window_get_xid (win);
- update_switcher_window (win, window);
- }
- else if (get_window_prop (xid, frame_input_window_atom, &window))
+ if (get_window_prop (xid, frame_input_window_atom, &window))
{
add_frame_window (win, window, FALSE);
}