diff options
Diffstat (limited to 'libtopmenu-server/topmenu-widget.c')
-rw-r--r-- | libtopmenu-server/topmenu-widget.c | 92 |
1 files changed, 74 insertions, 18 deletions
diff --git a/libtopmenu-server/topmenu-widget.c b/libtopmenu-server/topmenu-widget.c index 9d80ff2..5d13a6a 100644 --- a/libtopmenu-server/topmenu-widget.c +++ b/libtopmenu-server/topmenu-widget.c @@ -42,10 +42,17 @@ #include <libmatewnck/libmatewnck.h> #endif +enum _TopMenuWidgetAtoms +{ + ATOM_WINDOW, + ATOM_BACKGROUND_CHANGE, + ATOM_TRANSIENT_FOR, + N_ATOMS +}; + struct _TopMenuWidgetPrivate { - Atom atom_window; - Atom atom_transient_for; + Atom atoms[N_ATOMS]; GQueue followed_windows; #ifdef HAVE_WNCK WnckScreen *wnck_screen; @@ -176,7 +183,8 @@ static Window topmenu_widget_get_any_app_window_with_menu(TopMenuWidget *self, W for (i = g_list_last(windows); i; i = g_list_previous(i)) { if (i->data != w && wnck_window_get_application(i->data) == app) { Window candidate = wnck_window_get_xid(i->data); - Window menu_window = read_window_property(dpy, candidate, self->priv->atom_window); + Window menu_window = read_window_property(dpy, candidate, + self->priv->atoms[ATOM_WINDOW]); if (menu_window) { return candidate; } @@ -198,7 +206,8 @@ static Window topmenu_widget_get_any_app_window_with_menu(TopMenuWidget *self, W for (i = g_list_last(windows); i; i = g_list_previous(i)) { if (i->data != w && matewnck_window_get_application(i->data) == app) { Window candidate = matewnck_window_get_xid(i->data); - Window menu_window = read_window_property(dpy, candidate, self->priv->atom_window); + Window menu_window = read_window_property(dpy, candidate, + self->priv->atoms[ATOM_WINDOW]); if (menu_window) { return candidate; } @@ -208,6 +217,37 @@ static Window topmenu_widget_get_any_app_window_with_menu(TopMenuWidget *self, W return None; } +static Window topmenu_widget_get_current_topmenu_window(TopMenuWidget *self) +{ + g_return_val_if_fail(self->socket, None); + GdkWindow *cur = gtk_socket_get_plug_window(self->socket); + if (cur) { + return GDK_WINDOW_XID(cur); + } else { + return None; + } +} + +static void topmenu_widget_send_background(TopMenuWidget *self, Window window) +{ + Display *dpy = topmenu_widget_get_display(self); + g_return_if_fail(dpy); + + XEvent e; + XClientMessageEvent *msg = &e.xclient; + msg->type = ClientMessage; + msg->display = dpy; + msg->window = window; + msg->message_type = self->priv->atoms[ATOM_BACKGROUND_CHANGE]; + topmenu_background_fill_client_message(self->background, msg); + + g_debug("sending current background to window 0x%lx", window); + + if (XSendEvent(dpy, window, False, 0, &e) == 0) { + g_warning("sending background message failed"); + } +} + static void topmenu_widget_embed_topmenu_window(TopMenuWidget *self, Window window) { g_return_if_fail(self->socket); @@ -244,6 +284,7 @@ static void topmenu_widget_embed_topmenu_window(TopMenuWidget *self, Window wind if (window) { g_debug("Embedding window 0x%lx", window); + topmenu_widget_send_background(self, window); gtk_socket_add_id(self->socket, window); } } @@ -254,7 +295,8 @@ static gboolean topmenu_widget_try_window(TopMenuWidget *self, Window window) g_return_val_if_fail(dpy, FALSE); g_return_val_if_fail(window, FALSE); - Window menu_window = read_window_property(dpy, window, self->priv->atom_window); + Window menu_window = read_window_property(dpy, window, + self->priv->atoms[ATOM_WINDOW]); if (menu_window) { topmenu_widget_embed_topmenu_window(self, menu_window); return TRUE; @@ -335,11 +377,16 @@ static void topmenu_widget_set_followed_window(TopMenuWidget *self, Window windo if (window) { // Initialize atoms now - if (self->priv->atom_window == None) { - self->priv->atom_window = XInternAtom(dpy, ATOM_TOPMENU_WINDOW, False); - } - if (self->priv->atom_transient_for) { - self->priv->atom_transient_for = XInternAtom(dpy, "WM_TRANSIENT_FOR", False); + if (self->priv->atoms[0] == None) { + static const char *atom_names[] = { + ATOM_TOPMENU_WINDOW, + ATOM_TOPMENU_BACKGROUND_CHANGE, + "WM_TRANSIENT_FOR", + NULL + }; + if (!XInternAtoms(dpy, (char**) atom_names, N_ATOMS, False, self->priv->atoms)) { + g_warning("Could not intern all atoms"); + } } // Start by checking the active window @@ -360,9 +407,7 @@ static void topmenu_widget_set_followed_window(TopMenuWidget *self, Window windo static void handle_socket_realize(GtkSocket *socket, TopMenuWidget *self) { - // Workaround a "bug workaround" where GtkSocket will not select ButtonPress - // events - g_warn_if_fail(gtk_widget_get_realized(GTK_WIDGET(socket))); + // GtkSocket does not select ButtonPress events gtk_widget_add_events(GTK_WIDGET(socket), GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); } @@ -374,6 +419,16 @@ static gboolean handle_socket_plug_removed(GtkSocket *socket, TopMenuWidget *sel return TRUE; // Do not destroy the socket } +static void handle_background_changed(TopMenuBackground *background, TopMenuWidget *self) +{ + g_debug("background has changed"); + topmenu_background_apply(background, GTK_WIDGET(self->socket)); + Window cur = topmenu_widget_get_current_topmenu_window(self); + if (cur != None) { + topmenu_widget_send_background(self, cur); + } +} + #ifdef HAVE_WNCK static void handle_active_wnck_window_changed(WnckScreen *screen, WnckWindow *prev_window, TopMenuWidget *self) { @@ -410,8 +465,8 @@ static GdkFilterReturn handle_gdk_event(GdkXEvent *xevent, GdkEvent *event, gpoi XEvent *e = (XEvent*) xevent; if (e->type == PropertyNotify && - (e->xproperty.atom == self->priv->atom_transient_for || - e->xproperty.atom == self->priv->atom_window)) { + (e->xproperty.atom == self->priv->atoms[ATOM_TRANSIENT_FOR] || + e->xproperty.atom == self->priv->atoms[ATOM_WINDOW])) { // One of the properties we are interested in changed. // See if it's one of the windows we're following. if (g_queue_find(&self->priv->followed_windows, @@ -480,7 +535,7 @@ static void topmenu_widget_size_request(GtkWidget *widget, GtkRequisition *requi if (self->socket) { gtk_widget_size_request(GTK_WIDGET(self->socket), requisition); } -} +} #endif static void topmenu_widget_dispose(GObject *obj) @@ -534,8 +589,9 @@ static void topmenu_widget_init(TopMenuWidget *self) G_CALLBACK(handle_socket_realize), self); g_signal_connect(self->socket, "plug-removed", G_CALLBACK(handle_socket_plug_removed), self); - self->priv->atom_window = None; - self->priv->atom_transient_for = None; + self->background = topmenu_background_new(); + g_signal_connect(self->background, "changed", + G_CALLBACK(handle_background_changed), self); g_queue_init(&self->priv->followed_windows); #ifdef HAVE_WNCK self->priv->wnck_screen = wnck_screen_get_default(); |