diff options
author | Sam Spilsbury <sam.spilsbury@canonical.com> | 2011-02-24 15:58:35 +0800 |
---|---|---|
committer | Sam Spilsbury <sam.spilsbury@canonical.com> | 2011-02-24 15:58:35 +0800 |
commit | 84264628af48f6235ab2a4c0349cc06a518ec39e (patch) | |
tree | a033da18a97306bd09a914f6c96f4e37cfb6ead5 | |
parent | 5489aaa5c76a4bdb0ee65664c8b0b7604f8e33ba (diff) | |
parent | 08615b56f6b8796193962a6cbeba3d93132b6c00 (diff) | |
download | unity-window-decorator-master.tar.gz unity-window-decorator-master.tar.bz2 |
Merge branch 'master' of git+ssh://git.compiz.org/git/users/smspillaz/unity-window-decoratorHEADmaster
-rw-r--r-- | src/decorator.c | 15 | ||||
-rw-r--r-- | src/events.c | 65 | ||||
-rw-r--r-- | src/gtk-window-decorator.c | 29 | ||||
-rw-r--r-- | src/gtk-window-decorator.h | 12 | ||||
-rw-r--r-- | src/metacity.c | 22 | ||||
-rw-r--r-- | src/switcher.c | 38 | ||||
-rw-r--r-- | src/wnck.c | 73 |
7 files changed, 215 insertions, 39 deletions
diff --git a/src/decorator.c b/src/decorator.c index dc562a6..a18737f 100644 --- a/src/decorator.c +++ b/src/decorator.c @@ -654,21 +654,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/src/events.c b/src/events.c index 0b2099b..b007bdb 100644 --- a/src/events.c +++ b/src/events.c @@ -856,11 +856,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) @@ -888,9 +910,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); @@ -908,9 +930,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); @@ -971,24 +993,45 @@ event_filter_func (GdkXEvent *gdkxevent, } else if (xevent->xproperty.atom == select_window_atom) { - WnckWindow *win; + Window select; - xid = xevent->xproperty.window; + if (get_window_prop (xevent->xproperty.window, select_window_atom, &select)) + update_switcher_window (xevent->xproperty.window, select); + } + else if (xevent->xproperty.atom == XA_WM_TRANSIENT_FOR) + { + WnckWindow *win = wnck_window_get (xevent->xproperty.window); - win = wnck_window_get (xid); - if (win) + if (win && + wnck_window_get_window_type (win) == WNCK_WINDOW_DIALOG) { - Window select; + Window parent; + + if (get_window_prop (xevent->xproperty.window, XA_WM_TRANSIENT_FOR, &parent)) + { + WnckWindow *p = wnck_window_get (parent); + decor_t *d = g_object_get_data (G_OBJECT (p), "decor"); + decor_t *d_transient = g_object_get_data (G_OBJECT (p), "decor"); + + if (g_slist_find (d->transient_windows, p)) + break; - if (get_window_prop (xid, select_window_atom, &select)) - update_switcher_window (win, select); + if (d) + { + d->transient_windows = g_slist_append (d->transient_windows, win); + d_transient->transient_parent = p; + } + } } } break; case DestroyNotify: + { g_hash_table_remove (frame_table, GINT_TO_POINTER (xevent->xproperty.window)); + break; + } case ClientMessage: if (xevent->xclient.message_type == toolkit_action_atom) { diff --git a/src/gtk-window-decorator.c b/src/gtk-window-decorator.c index 53a1293..9f895d9 100644 --- a/src/gtk-window-decorator.c +++ b/src/gtk-window-decorator.c @@ -181,6 +181,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; @@ -193,6 +194,9 @@ main (int argc, char *argv[]) GdkScreen *gdkscreen; WnckScreen *screen; gint i, j, status; + unsigned int nchildren; + Window root_ret, parent_ret; + Window *children = NULL; gboolean replace = FALSE; #ifdef USE_METACITY @@ -389,9 +393,34 @@ main (int argc, char *argv[]) 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); + } + + /* 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); } diff --git a/src/gtk-window-decorator.h b/src/gtk-window-decorator.h index 9b262c8..db611d9 100644 --- a/src/gtk-window-decorator.h +++ b/src/gtk-window-decorator.h @@ -396,6 +396,8 @@ typedef struct _decor { WnckWindowActions actions; XID prop_xid; GtkWidget *force_quit_dialog; + GSList *transient_windows; + WnckWindow *transient_parent; Bool created; void (*draw) (struct _decor *d); } decor_t; @@ -462,6 +464,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; @@ -552,6 +555,7 @@ void restack_window (WnckWindow *win, int stack_mode); +void connect_window (WnckWindow *win); /* blur.c */ @@ -751,9 +755,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/src/metacity.c b/src/metacity.c index dd8d6c1..2095619 100644 --- a/src/metacity.c +++ b/src/metacity.c @@ -484,6 +484,28 @@ meta_get_decoration_geometry (decor_t *d, if (d->active) *flags |= (MetaFrameFlags ) META_FRAME_HAS_FOCUS; + else if (g_slist_length (d->transient_windows) > 1) + { + GSList *transient_windows = d->transient_windows; + + for (; transient_windows; + transient_windows = transient_windows->next) + { + if (!transient_windows->data) + continue; + + decor_t *d_transient = g_object_get_data (transient_windows->data, "decor"); + + if (d_transient) + { + if (d_transient->active) + { + *flags |= (MetaFrameFlags ) META_FRAME_HAS_FOCUS; + break; + } + } + } + } if ((d->state & META_MAXIMIZED) == META_MAXIMIZED) *flags |= (MetaFrameFlags ) META_FRAME_MAXIMIZED; diff --git a/src/switcher.c b/src/switcher.c index 046ea0a..ef603c5 100644 --- a/src/switcher.c +++ b/src/switcher.c @@ -257,20 +257,48 @@ 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); + /* 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 +447,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); @@ -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", @@ -521,6 +539,16 @@ active_window_changed (WnckScreen *screen) * since the image would have changed */ if (!update_window_decoration_size (d->win)) queue_decor_draw (d); + + /* Also update any parents of this window + * since they won't get a notification here + */ + if (d->transient_parent) + { + decor_t *d_parent = g_object_get_data (d->transient_parent, "decor"); + queue_decor_draw (d_parent); + } + } } @@ -581,6 +609,15 @@ active_window_changed (WnckScreen *screen) * since the image would have changed */ if (!update_window_decoration_size (d->win)) queue_decor_draw (d); + + /* Also update any parents of this window + * since they won't get a notification here + */ + if (d->transient_parent) + { + decor_t *d_parent = g_object_get_data (d->transient_parent, "decor"); + queue_decor_draw (d_parent); + } } } } @@ -634,6 +671,7 @@ window_opened (WnckScreen *screen, d->cr = NULL; d->buffer_pixmap = NULL; d->picture = None; + d->transient_windows = g_slist_alloc (); connect_window (win); @@ -641,12 +679,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); } @@ -654,6 +687,24 @@ window_opened (WnckScreen *screen, { add_frame_window (win, window, TRUE); } + + if (wnck_window_get_window_type (win) == WNCK_WINDOW_DIALOG) + { + Window parent; + + if (get_window_prop (xid, XA_WM_TRANSIENT_FOR, &parent)) + { + WnckWindow *p = wnck_window_get (parent); + decor_t *d = g_object_get_data (G_OBJECT (p), "decor"); + decor_t *d_transient = g_object_get_data (G_OBJECT (win), "decor"); + + if (d) + { + d->transient_windows = g_slist_append (d->transient_windows, win); + d_transient->transient_parent = p; + } + } + } } static void @@ -662,6 +713,14 @@ window_closed (WnckScreen *screen, { Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); + WnckWindow *parent = d->transient_parent; + + if (parent) + { + decor_t *d_parent = g_object_get_data (G_OBJECT (parent), "decor"); + + d_parent->transient_windows = g_slist_remove (d_parent->transient_windows, win); + } remove_frame_window (win); |