summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/decorator.c15
-rw-r--r--src/events.c65
-rw-r--r--src/gtk-window-decorator.c29
-rw-r--r--src/gtk-window-decorator.h12
-rw-r--r--src/metacity.c22
-rw-r--r--src/switcher.c38
-rw-r--r--src/wnck.c73
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);
diff --git a/src/wnck.c b/src/wnck.c
index a42ccc1..b008c47 100644
--- a/src/wnck.c
+++ b/src/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",
@@ -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);