diff --git a/gdk/x11/gdkscreen-x11.c b/gdk/x11/gdkscreen-x11.c index 6e551cbb78..5c3608f498 100644 --- a/gdk/x11/gdkscreen-x11.c +++ b/gdk/x11/gdkscreen-x11.c @@ -1609,104 +1609,6 @@ gdk_x11_screen_supports_net_wm_hint (GdkScreen *screen, return FALSE; } -static GdkFilterReturn -gdk_xsettings_client_event_filter (GdkXEvent *xevent, - GdkEvent *event, - gpointer data) -{ - GdkX11Screen *screen = data; - - if (xsettings_client_process_event (screen->xsettings_client, (XEvent *)xevent)) - return GDK_FILTER_REMOVE; - else - return GDK_FILTER_CONTINUE; -} - -static Bool -gdk_xsettings_watch_cb (Window window, - Bool is_start, - long mask, - void *cb_data) -{ - GdkWindow *gdkwin; - GdkScreen *screen = cb_data; - - gdkwin = gdk_x11_window_lookup_for_display (gdk_screen_get_display (screen), window); - - if (is_start) - { - if (gdkwin) - g_object_ref (gdkwin); - else - { - gdkwin = gdk_x11_window_foreign_new_for_display (gdk_screen_get_display (screen), window); - - /* gdk_window_foreign_new_for_display() can fail and return NULL if the - * window has already been destroyed. - */ - if (!gdkwin) - return False; - } - - gdk_window_add_filter (gdkwin, gdk_xsettings_client_event_filter, screen); - } - else - { - if (!gdkwin) - { - /* gdkwin should not be NULL here, since if starting the watch succeeded - * we have a reference on the window. It might mean that the caller didn't - * remove the watch when it got a DestroyNotify event. Or maybe the - * caller ignored the return value when starting the watch failed. - */ - g_warning ("gdk_xsettings_watch_cb(): Couldn't find window to unwatch"); - return False; - } - - gdk_window_remove_filter (gdkwin, gdk_xsettings_client_event_filter, screen); - g_object_unref (gdkwin); - } - - return True; -} - -static void -gdk_xsettings_notify_cb (const char *name, - XSettingsAction action, - XSettingsSetting *setting, - void *data) -{ - GdkEvent new_event; - GdkScreen *screen = data; - GdkX11Screen *x11_screen = data; - - if (x11_screen->xsettings_in_init) - return; - - new_event.type = GDK_SETTING; - new_event.setting.window = gdk_screen_get_root_window (screen); - new_event.setting.send_event = FALSE; - new_event.setting.name = (char*) gdk_from_xsettings_name (name); - - if (!new_event.setting.name) - return; - - switch (action) - { - case XSETTINGS_ACTION_NEW: - new_event.setting.action = GDK_SETTING_ACTION_NEW; - break; - case XSETTINGS_ACTION_CHANGED: - new_event.setting.action = GDK_SETTING_ACTION_CHANGED; - break; - case XSETTINGS_ACTION_DELETED: - new_event.setting.action = GDK_SETTING_ACTION_DELETED; - break; - } - - gdk_event_put (&new_event); -} - void _gdk_x11_screen_init_events (GdkScreen *screen) { @@ -1715,10 +1617,7 @@ _gdk_x11_screen_init_events (GdkScreen *screen) /* Keep a flag to avoid extra notifies that we don't need */ x11_screen->xsettings_in_init = TRUE; - x11_screen->xsettings_client = xsettings_client_new (screen, - gdk_xsettings_notify_cb, - gdk_xsettings_watch_cb, - screen); + x11_screen->xsettings_client = xsettings_client_new (screen); x11_screen->xsettings_in_init = FALSE; } diff --git a/gdk/x11/gdksettings.c b/gdk/x11/gdksettings.c index e2fdcf24d7..cfd2676027 100644 --- a/gdk/x11/gdksettings.c +++ b/gdk/x11/gdksettings.c @@ -79,7 +79,7 @@ static const struct { {"Gtk/RecentFilesEnabled", "gtk-recent-files-enabled"} }; -static const char * +static G_GNUC_UNUSED const char * gdk_from_xsettings_name (const char *xname) { static GHashTable *hash = NULL; @@ -97,7 +97,7 @@ gdk_from_xsettings_name (const char *xname) return g_hash_table_lookup (hash, xname); } -static const char * +static G_GNUC_UNUSED const char * gdk_to_xsettings_name (const char *gdkname) { static GHashTable *hash = NULL; diff --git a/gdk/x11/xsettings-client.c b/gdk/x11/xsettings-client.c index a27ef0bd04..7e7bc9d2ba 100644 --- a/gdk/x11/xsettings-client.c +++ b/gdk/x11/xsettings-client.c @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -36,6 +37,8 @@ #include #include /* For CARD16 */ +#include "gdksettings.c" + typedef struct _XSettingsBuffer XSettingsBuffer; struct _XSettingsBuffer @@ -50,9 +53,6 @@ struct _XSettingsClient { GdkScreen *screen; Display *display; - XSettingsNotifyFunc notify; - XSettingsWatchFunc watch; - void *cb_data; Window manager_window; Atom manager_atom; @@ -62,6 +62,42 @@ struct _XSettingsClient GHashTable *settings; /* string => XSettingsSetting */ }; +static void +gdk_xsettings_notify (const char *name, + XSettingsAction action, + XSettingsSetting *setting, + GdkScreen *screen) +{ + GdkEvent new_event; + GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen); + + if (x11_screen->xsettings_in_init) + return; + + new_event.type = GDK_SETTING; + new_event.setting.window = gdk_screen_get_root_window (screen); + new_event.setting.send_event = FALSE; + new_event.setting.name = (char*) gdk_from_xsettings_name (name); + + if (!new_event.setting.name) + return; + + switch (action) + { + case XSETTINGS_ACTION_NEW: + new_event.setting.action = GDK_SETTING_ACTION_NEW; + break; + case XSETTINGS_ACTION_CHANGED: + new_event.setting.action = GDK_SETTING_ACTION_CHANGED; + break; + case XSETTINGS_ACTION_DELETED: + new_event.setting.action = GDK_SETTING_ACTION_DELETED; + break; + } + + gdk_event_put (&new_event); +} + static void notify_changes (XSettingsClient *client, GHashTable *old_list) @@ -70,9 +106,6 @@ notify_changes (XSettingsClient *client, XSettingsSetting *setting, *old_setting; const char *name; - if (!client->notify) - return; - if (client->settings != NULL) { g_hash_table_iter_init (&iter, client->settings); @@ -81,9 +114,9 @@ notify_changes (XSettingsClient *client, old_setting = old_list ? g_hash_table_lookup (old_list, name) : NULL; if (old_setting == NULL) - client->notify (name, XSETTINGS_ACTION_NEW, setting, client->cb_data); + gdk_xsettings_notify (name, XSETTINGS_ACTION_NEW, setting, client->screen); else if (!xsettings_setting_equal (setting, old_setting)) - client->notify (name, XSETTINGS_ACTION_CHANGED, setting, client->cb_data); + gdk_xsettings_notify (name, XSETTINGS_ACTION_CHANGED, setting, client->screen); /* remove setting from old_list */ if (old_setting != NULL) @@ -96,7 +129,7 @@ notify_changes (XSettingsClient *client, /* old_list now contains only deleted settings */ g_hash_table_iter_init (&iter, old_list); while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer*) &old_setting)) - client->notify (name, XSETTINGS_ACTION_DELETED, NULL, client->cb_data); + gdk_xsettings_notify (name, XSETTINGS_ACTION_DELETED, NULL, client->screen); } } @@ -374,11 +407,17 @@ add_events (Display *display, XSelectInput (display, window, attr.your_event_mask | mask); } +static Bool +gdk_xsettings_watch (Window window, + Bool is_start, + long mask, + GdkScreen *screen); + static void check_manager_window (XSettingsClient *client) { - if (client->manager_window && client->watch) - client->watch (client->manager_window, False, 0, client->cb_data); + if (client->manager_window) + gdk_xsettings_watch (client->manager_window, False, 0, client->screen); gdk_x11_display_grab (gdk_screen_get_display (client->screen)); @@ -392,11 +431,11 @@ check_manager_window (XSettingsClient *client) XFlush (client->display); - if (client->manager_window && client->watch) + if (client->manager_window) { - if (!client->watch (client->manager_window, True, - PropertyChangeMask | StructureNotifyMask, - client->cb_data)) + if (!gdk_xsettings_watch (client->manager_window, True, + PropertyChangeMask | StructureNotifyMask, + client->screen)) { /* Inability to watch the window probably means that it was destroyed * after we ungrabbed @@ -406,15 +445,100 @@ check_manager_window (XSettingsClient *client) } } - read_settings (client); } +static GdkFilterReturn +gdk_xsettings_client_event_filter (GdkXEvent *xevent, + GdkEvent *event, + gpointer data) +{ + GdkScreen *screen = data; + XSettingsClient *client = GDK_X11_SCREEN (screen)->xsettings_client; + XEvent *xev = xevent; + + /* The checks here will not unlikely cause us to reread + * the properties from the manager window a number of + * times when the manager changes from A->B. But manager changes + * are going to be pretty rare. + */ + if (xev->xany.window == gdk_x11_window_get_xid (gdk_screen_get_root_window (screen))) + { + if (xev->xany.type == ClientMessage && + xev->xclient.message_type == client->manager_atom && + xev->xclient.data.l[1] == client->selection_atom) + { + check_manager_window (client); + return GDK_FILTER_REMOVE; + } + } + else if (xev->xany.window == client->manager_window) + { + if (xev->xany.type == DestroyNotify) + { + check_manager_window (client); + /* let GDK do its cleanup */ + return GDK_FILTER_CONTINUE; + } + else if (xev->xany.type == PropertyNotify) + { + read_settings (client); + return GDK_FILTER_REMOVE; + } + } + + return GDK_FILTER_CONTINUE;; +} + +static Bool +gdk_xsettings_watch (Window window, + Bool is_start, + long mask, + GdkScreen *screen) +{ + GdkWindow *gdkwin; + + gdkwin = gdk_x11_window_lookup_for_display (gdk_screen_get_display (screen), window); + + if (is_start) + { + if (gdkwin) + g_object_ref (gdkwin); + else + { + gdkwin = gdk_x11_window_foreign_new_for_display (gdk_screen_get_display (screen), window); + + /* gdk_window_foreign_new_for_display() can fail and return NULL if the + * window has already been destroyed. + */ + if (!gdkwin) + return False; + } + + gdk_window_add_filter (gdkwin, gdk_xsettings_client_event_filter, screen); + } + else + { + if (!gdkwin) + { + /* gdkwin should not be NULL here, since if starting the watch succeeded + * we have a reference on the window. It might mean that the caller didn't + * remove the watch when it got a DestroyNotify event. Or maybe the + * caller ignored the return value when starting the watch failed. + */ + g_warning ("gdk_xsettings_watch_cb(): Couldn't find window to unwatch"); + return False; + } + + gdk_window_remove_filter (gdkwin, gdk_xsettings_client_event_filter, screen); + g_object_unref (gdkwin); + } + + return True; +} + XSettingsClient * -xsettings_client_new (GdkScreen *screen, - XSettingsNotifyFunc notify, - XSettingsWatchFunc watch, - void *cb_data) +xsettings_client_new (GdkScreen *screen) { XSettingsClient *client; char buffer[256]; @@ -427,9 +551,7 @@ xsettings_client_new (GdkScreen *screen, client->screen = screen; client->display = gdk_x11_display_get_xdisplay (gdk_screen_get_display (screen)); - client->notify = notify; - client->watch = watch; - client->cb_data = cb_data; + client->screen = screen; client->manager_window = None; client->settings = NULL; @@ -448,9 +570,8 @@ xsettings_client_new (GdkScreen *screen, */ add_events (client->display, gdk_x11_window_get_xid (gdk_screen_get_root_window (screen)), StructureNotifyMask); - if (client->watch) - client->watch (gdk_x11_window_get_xid (gdk_screen_get_root_window (screen)), True, StructureNotifyMask, - client->cb_data); + gdk_xsettings_watch (gdk_x11_window_get_xid (gdk_screen_get_root_window (screen)), True, StructureNotifyMask, + client->screen); check_manager_window (client); @@ -460,11 +581,10 @@ xsettings_client_new (GdkScreen *screen, void xsettings_client_destroy (XSettingsClient *client) { - if (client->watch) - client->watch (gdk_x11_window_get_xid (gdk_screen_get_root_window (client->screen)), - False, 0, client->cb_data); - if (client->manager_window && client->watch) - client->watch (client->manager_window, False, 0, client->cb_data); + gdk_xsettings_watch (gdk_x11_window_get_xid (gdk_screen_get_root_window (client->screen)), + False, 0, client->screen); + if (client->manager_window) + gdk_xsettings_watch (client->manager_window, False, 0, client->screen); if (client->settings) g_hash_table_unref (client->settings); @@ -478,43 +598,6 @@ xsettings_client_get_setting (XSettingsClient *client, return g_hash_table_lookup (client->settings, name); } -Bool -xsettings_client_process_event (XSettingsClient *client, - XEvent *xev) -{ - /* The checks here will not unlikely cause us to reread - * the properties from the manager window a number of - * times when the manager changes from A->B. But manager changes - * are going to be pretty rare. - */ - if (xev->xany.window == gdk_x11_window_get_xid (gdk_screen_get_root_window (client->screen))) - { - if (xev->xany.type == ClientMessage && - xev->xclient.message_type == client->manager_atom && - xev->xclient.data.l[1] == client->selection_atom) - { - check_manager_window (client); - return True; - } - } - else if (xev->xany.window == client->manager_window) - { - if (xev->xany.type == DestroyNotify) - { - check_manager_window (client); - /* let GDK do its cleanup */ - return False; - } - else if (xev->xany.type == PropertyNotify) - { - read_settings (client); - return True; - } - } - - return False; -} - int xsettings_setting_equal (XSettingsSetting *setting_a, XSettingsSetting *setting_b) diff --git a/gdk/x11/xsettings-client.h b/gdk/x11/xsettings-client.h index 0b9aa805cc..5ba4673d91 100644 --- a/gdk/x11/xsettings-client.h +++ b/gdk/x11/xsettings-client.h @@ -72,26 +72,12 @@ struct _XSettingsSetting } data; }; -typedef void (*XSettingsNotifyFunc) (const char *name, - XSettingsAction action, - XSettingsSetting *setting, - void *cb_data); -typedef Bool (*XSettingsWatchFunc) (Window window, - Bool is_start, - long mask, - void *cb_data); - void xsettings_setting_free (XSettingsSetting *setting); int xsettings_setting_equal (XSettingsSetting *setting_a, XSettingsSetting *setting_b); -XSettingsClient *xsettings_client_new (GdkScreen *screen, - XSettingsNotifyFunc notify, - XSettingsWatchFunc watch, - void *cb_data); +XSettingsClient *xsettings_client_new (GdkScreen *screen); void xsettings_client_destroy (XSettingsClient *client); -Bool xsettings_client_process_event (XSettingsClient *client, - XEvent *xev); const XSettingsSetting * xsettings_client_get_setting (XSettingsClient *client, const char *name);