From cb9b34cd2126963c3650feeb48e036fb256e9660 Mon Sep 17 00:00:00 2001 From: Thierry Lorthiois Date: Sun, 7 Nov 2010 08:44:27 +0000 Subject: [PATCH] launcher : limit launcher_icon_theme to 1 theme. Add XSETTINGS client and read launcher_icon_theme if manager is running. --- CMakeLists.txt | 2 + src/config.c | 5 +- src/launcher/launcher.c | 57 ++-- src/launcher/launcher.h | 4 +- src/launcher/xsettings-client.c | 494 ++++++++++++++++++++++++++++++++ src/launcher/xsettings-client.h | 70 +++++ src/launcher/xsettings-common.c | 268 +++++++++++++++++ src/launcher/xsettings-common.h | 111 +++++++ src/server.c | 10 +- src/server.h | 4 +- src/tint.c | 6 +- src/tint2conf/main.c | 8 +- src/tint2conf/properties.c | 1 + 13 files changed, 998 insertions(+), 42 deletions(-) create mode 100644 src/launcher/xsettings-client.c create mode 100644 src/launcher/xsettings-client.h create mode 100644 src/launcher/xsettings-common.c create mode 100644 src/launcher/xsettings-common.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b6a2162..8773c48 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,6 +47,8 @@ set( SOURCES src/config.c src/clock/clock.c src/systray/systraybar.c src/launcher/launcher.c + src/launcher/xsettings-client.c + src/launcher/xsettings-common.c src/taskbar/task.c src/taskbar/taskbar.c src/taskbar/taskbarname.c diff --git a/src/config.c b/src/config.c index 7c87339..8ba2c08 100644 --- a/src/config.c +++ b/src/config.c @@ -589,8 +589,9 @@ void add_entry (char *key, char *value) panel_config.launcher.list_apps = g_slist_append(panel_config.launcher.list_apps, app); } else if (strcmp(key, "launcher_icon_theme") == 0) { - char *app = strdup(value); - panel_config.launcher.icon_theme_names = g_slist_append(panel_config.launcher.icon_theme_names, app); + // if XSETTINGS manager running, tint2 use it. + if (!icon_theme_name) + icon_theme_name = strdup(value); } /* Tooltip */ diff --git a/src/launcher/launcher.c b/src/launcher/launcher.c index e0266d1..6e49ba7 100644 --- a/src/launcher/launcher.c +++ b/src/launcher/launcher.c @@ -34,7 +34,9 @@ int launcher_enabled; int launcher_max_icon_size; -GSList *icon_themes = 0; +char *icon_theme_name; +XSettingsClient *xsettings_client; +GSList *icon_themes; #define ICON_FALLBACK "exec" @@ -46,15 +48,24 @@ Imlib_Image scale_icon(Imlib_Image original, int icon_size); void free_icon(Imlib_Image icon); void free_icon_theme(IconTheme *theme); + void default_launcher() { launcher_enabled = 0; launcher_max_icon_size = 0; + icon_themes = 0; + icon_theme_name = 0; + xsettings_client = NULL; + printf("default_launcher\n"); } void init_launcher() { + if (launcher_enabled) { + // if XSETTINGS manager running, tint2 read the icon_theme_name. + xsettings_client = xsettings_client_new(server.dsp, server.screen, xsettings_notify_cb, NULL, NULL); + } } @@ -78,9 +89,7 @@ void init_launcher_panel(void *p) launcher->area.on_screen = 1; panel_refresh = 1; - fprintf(stderr, "Loading themes...\n"); launcher_load_themes(launcher); - fprintf(stderr, "Done\n"); // Load apps (.desktop style launcher items) GSList* app = launcher->list_apps; @@ -105,6 +114,8 @@ void cleanup_launcher() { int i; + if (xsettings_client) + xsettings_client_destroy(xsettings_client); for (i = 0 ; i < nb_panel ; i++) { Panel *panel = &panel1[i]; Launcher *launcher = &panel->launcher; @@ -135,12 +146,9 @@ void cleanup_launcher() } g_slist_free(launcher->icon_themes); - for (l = launcher->icon_theme_names; l ; l = l->next) { - free(l->data); - } - g_slist_free(launcher->icon_theme_names); - launcher->list_apps = launcher->list_icons = launcher->icon_theme_names = launcher->icon_themes = NULL; + launcher->list_apps = launcher->list_icons = launcher->icon_themes = NULL; } + g_free(icon_theme_name); launcher_enabled = 0; } @@ -489,7 +497,6 @@ IconTheme *load_theme(char *name) } if (!file_name) { - fprintf(stderr, "Could not found theme '%s'\n", name); return NULL; } @@ -497,8 +504,6 @@ IconTheme *load_theme(char *name) fprintf(stderr, "Could not open theme '%s'\n", file_name); return NULL; } - else - fprintf(stderr, "Loading icon theme '%s'\n", file_name); g_free (file_name); @@ -657,26 +662,15 @@ void launcher_load_themes(Launcher *launcher) { // load the user theme, all the inherited themes recursively (DFS), and the hicolor theme // avoid inheritance loops - - GSList *queue = NULL; - GSList *queued = NULL; - - GSList* icon_theme_name_item; - for (icon_theme_name_item = launcher->icon_theme_names; icon_theme_name_item; icon_theme_name_item = g_slist_next(icon_theme_name_item)) { - int duplicate = 0; - GSList* queued_item = queued; - while (queued_item != NULL) { - if (strcmp(queued_item->data, icon_theme_name_item->data) == 0) { - duplicate = 1; - break; - } - queued_item = g_slist_next(queued_item); - } - if (!duplicate) { - queue = g_slist_append(queue, strdup(icon_theme_name_item->data)); - queued = g_slist_append(queued, strdup(icon_theme_name_item->data)); - } + if (!icon_theme_name) { + fprintf(stderr, "Missing launcher theme, default to 'hicolor'.\n"); + icon_theme_name = "hicolor"; } + else + fprintf(stderr, "Loading %s : ", icon_theme_name); + + GSList *queue = g_slist_append(NULL, strdup(icon_theme_name)); + GSList *queued = g_slist_append(NULL, strdup(icon_theme_name)); int hicolor_loaded = 0; while (queue || !hicolor_loaded) { @@ -698,6 +692,7 @@ void launcher_load_themes(Launcher *launcher) char *name = queue->data; queue = g_slist_remove(queue, name); + fprintf(stderr, "icon theme '%s', ", name); IconTheme *theme = load_theme(name); if (theme != NULL) { launcher->icon_themes = g_slist_append(launcher->icon_themes, theme); @@ -725,6 +720,7 @@ void launcher_load_themes(Launcher *launcher) } } } + fprintf(stderr, "\n"); // Free the queue GSList *l; @@ -915,3 +911,4 @@ char *icon_path(Launcher *launcher, const char *icon_name, int size) return NULL; } + diff --git a/src/launcher/launcher.h b/src/launcher/launcher.h index d44ade1..ddbc6e8 100644 --- a/src/launcher/launcher.h +++ b/src/launcher/launcher.h @@ -9,13 +9,13 @@ #include "common.h" #include "area.h" +#include "xsettings-client.h" typedef struct Launcher { // always start with area Area area; GSList *list_apps; // List of char*, each is a path to a app.desktop file GSList *list_icons; // List of LauncherIcon* - GSList *icon_theme_names; // List of char*, each is a theme name (oxygen, Tango...) GSList *icon_themes; // List of IconTheme* } Launcher; @@ -57,6 +57,8 @@ typedef struct IconTheme { extern int launcher_enabled; extern int launcher_max_icon_size; +extern char *icon_theme_name; // theme name +extern XSettingsClient *xsettings_client; // default global data void default_launcher(); diff --git a/src/launcher/xsettings-client.c b/src/launcher/xsettings-client.c new file mode 100644 index 0000000..fba7939 --- /dev/null +++ b/src/launcher/xsettings-client.c @@ -0,0 +1,494 @@ +/* + * Copyright © 2001 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Red Hat not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Red Hat makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Owen Taylor, Red Hat, Inc. + */ +#include +#include +#include +#include + +#include +#include /* For CARD16 */ + +#include "xsettings-client.h" +#include "server.h" +#include "panel.h" +#include "launcher.h" + +struct _XSettingsClient +{ + Display *display; + int screen; + XSettingsNotifyFunc notify; + XSettingsWatchFunc watch; + void *cb_data; + + Window manager_window; + XSettingsList *settings; +}; + + +void xsettings_notify_cb (const char *name, XSettingsAction action, XSettingsSetting *setting, void *data) +{ + //printf("xsettings_notify_cb\n"); + if ((action == XSETTINGS_ACTION_NEW || action == XSETTINGS_ACTION_CHANGED) && name != NULL && setting != NULL) { + if (!strcmp(name, "Net/IconThemeName") && setting->type == XSETTINGS_TYPE_STRING) { + printf("XSETTINGS_ACTION %s\n", setting->data.v_string); + if (icon_theme_name) { + if (strcmp(icon_theme_name, setting->data.v_string) == 0) + return; + g_free(icon_theme_name); + } + icon_theme_name = strdup(setting->data.v_string); + /* + cleanup_launcher(); + int i; + Panel *p; + for (i=0 ; i < nb_panel ; i++) { + p = &panel1[i]; + init_launcher_panel(p); + } + /* + MBTrayApp *mb = (MBTrayApp *)data; + mb->theme_name = strdup(setting->data.v_string); + if (mb->theme_cb) + mb->theme_cb(mb, mb->theme_name); + */ + } + } +} + + +static void notify_changes (XSettingsClient *client, XSettingsList *old_list) +{ + XSettingsList *old_iter = old_list; + XSettingsList *new_iter = client->settings; + + if (!client->notify) + return; + + while (old_iter || new_iter) { + int cmp; + + if (old_iter && new_iter) + cmp = strcmp (old_iter->setting->name, new_iter->setting->name); + else if (old_iter) + cmp = -1; + else + cmp = 1; + + if (cmp < 0) { + client->notify (old_iter->setting->name, XSETTINGS_ACTION_DELETED, NULL, client->cb_data); + } + else if (cmp == 0) { + if (!xsettings_setting_equal (old_iter->setting, new_iter->setting)) + client->notify (old_iter->setting->name, XSETTINGS_ACTION_CHANGED, new_iter->setting, client->cb_data); + } + else { + client->notify (new_iter->setting->name, XSETTINGS_ACTION_NEW, new_iter->setting, client->cb_data); + } + + if (old_iter) + old_iter = old_iter->next; + if (new_iter) + new_iter = new_iter->next; + } +} + + +static int ignore_errors (Display *display, XErrorEvent *event) +{ + return True; +} + +static char local_byte_order = '\0'; + +#define BYTES_LEFT(buffer) ((buffer)->data + (buffer)->len - (buffer)->pos) + +static XSettingsResult fetch_card16 (XSettingsBuffer *buffer, CARD16 *result) +{ + CARD16 x; + + if (BYTES_LEFT (buffer) < 2) + return XSETTINGS_ACCESS; + + x = *(CARD16 *)buffer->pos; + buffer->pos += 2; + + if (buffer->byte_order == local_byte_order) + *result = x; + else + *result = (x << 8) | (x >> 8); + + return XSETTINGS_SUCCESS; +} + + +static XSettingsResult fetch_ushort (XSettingsBuffer *buffer, unsigned short *result) +{ + CARD16 x; + XSettingsResult r; + + r = fetch_card16 (buffer, &x); + if (r == XSETTINGS_SUCCESS) + *result = x; + + return r; +} + + +static XSettingsResult fetch_card32 (XSettingsBuffer *buffer, CARD32 *result) +{ + CARD32 x; + + if (BYTES_LEFT (buffer) < 4) + return XSETTINGS_ACCESS; + + x = *(CARD32 *)buffer->pos; + buffer->pos += 4; + + if (buffer->byte_order == local_byte_order) + *result = x; + else + *result = (x << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | (x >> 24); + + return XSETTINGS_SUCCESS; +} + +static XSettingsResult fetch_card8 (XSettingsBuffer *buffer, CARD8 *result) +{ + if (BYTES_LEFT (buffer) < 1) + return XSETTINGS_ACCESS; + + *result = *(CARD8 *)buffer->pos; + buffer->pos += 1; + + return XSETTINGS_SUCCESS; +} + +#define XSETTINGS_PAD(n,m) ((n + m - 1) & (~(m-1))) + +static XSettingsList *parse_settings (unsigned char *data, size_t len) +{ + XSettingsBuffer buffer; + XSettingsResult result = XSETTINGS_SUCCESS; + XSettingsList *settings = NULL; + CARD32 serial; + CARD32 n_entries; + CARD32 i; + XSettingsSetting *setting = NULL; + + local_byte_order = xsettings_byte_order (); + + buffer.pos = buffer.data = data; + buffer.len = len; + + result = fetch_card8 (&buffer, (CARD8*)&buffer.byte_order); + if (buffer.byte_order != MSBFirst && buffer.byte_order != LSBFirst) { + fprintf (stderr, "Invalid byte order %x in XSETTINGS property\n", buffer.byte_order); + result = XSETTINGS_FAILED; + goto out; + } + + buffer.pos += 3; + + result = fetch_card32 (&buffer, &serial); + if (result != XSETTINGS_SUCCESS) + goto out; + + result = fetch_card32 (&buffer, &n_entries); + if (result != XSETTINGS_SUCCESS) + goto out; + + for (i = 0; i < n_entries; i++) { + CARD8 type; + CARD16 name_len; + CARD32 v_int; + size_t pad_len; + + result = fetch_card8 (&buffer, &type); + if (result != XSETTINGS_SUCCESS) + goto out; + + buffer.pos += 1; + + result = fetch_card16 (&buffer, &name_len); + if (result != XSETTINGS_SUCCESS) + goto out; + + pad_len = XSETTINGS_PAD(name_len, 4); + if (BYTES_LEFT (&buffer) < pad_len) { + result = XSETTINGS_ACCESS; + goto out; + } + + setting = malloc (sizeof *setting); + if (!setting) { + result = XSETTINGS_NO_MEM; + goto out; + } + setting->type = XSETTINGS_TYPE_INT; /* No allocated memory */ + + setting->name = malloc (name_len + 1); + if (!setting->name) { + result = XSETTINGS_NO_MEM; + goto out; + } + + memcpy (setting->name, buffer.pos, name_len); + setting->name[name_len] = '\0'; + buffer.pos += pad_len; + + result = fetch_card32 (&buffer, &v_int); + if (result != XSETTINGS_SUCCESS) + goto out; + setting->last_change_serial = v_int; + + switch (type) { + case XSETTINGS_TYPE_INT: + result = fetch_card32 (&buffer, &v_int); + if (result != XSETTINGS_SUCCESS) + goto out; + setting->data.v_int = (INT32)v_int; + break; + case XSETTINGS_TYPE_STRING: + result = fetch_card32 (&buffer, &v_int); + if (result != XSETTINGS_SUCCESS) + goto out; + + pad_len = XSETTINGS_PAD (v_int, 4); + if (v_int + 1 == 0 || /* Guard against wrap-around */ + BYTES_LEFT (&buffer) < pad_len) { + result = XSETTINGS_ACCESS; + goto out; + } + + setting->data.v_string = malloc (v_int + 1); + if (!setting->data.v_string) { + result = XSETTINGS_NO_MEM; + goto out; + } + + memcpy (setting->data.v_string, buffer.pos, v_int); + setting->data.v_string[v_int] = '\0'; + buffer.pos += pad_len; + break; + case XSETTINGS_TYPE_COLOR: + result = fetch_ushort (&buffer, &setting->data.v_color.red); + if (result != XSETTINGS_SUCCESS) + goto out; + result = fetch_ushort (&buffer, &setting->data.v_color.green); + if (result != XSETTINGS_SUCCESS) + goto out; + result = fetch_ushort (&buffer, &setting->data.v_color.blue); + if (result != XSETTINGS_SUCCESS) + goto out; + result = fetch_ushort (&buffer, &setting->data.v_color.alpha); + if (result != XSETTINGS_SUCCESS) + goto out; + break; + default: + /* Quietly ignore unknown types */ + break; + } + + setting->type = type; + + result = xsettings_list_insert (&settings, setting); + if (result != XSETTINGS_SUCCESS) + goto out; + + setting = NULL; + } + + out: + + if (result != XSETTINGS_SUCCESS) { + switch (result) { + case XSETTINGS_NO_MEM: + fprintf(stderr, "Out of memory reading XSETTINGS property\n"); + break; + case XSETTINGS_ACCESS: + fprintf(stderr, "Invalid XSETTINGS property (read off end)\n"); + break; + case XSETTINGS_DUPLICATE_ENTRY: + fprintf (stderr, "Duplicate XSETTINGS entry for '%s'\n", setting->name); + case XSETTINGS_FAILED: + case XSETTINGS_SUCCESS: + case XSETTINGS_NO_ENTRY: + break; + } + + if (setting) + xsettings_setting_free (setting); + + xsettings_list_free (settings); + settings = NULL; + } + + return settings; +} + + +static void read_settings (XSettingsClient *client) +{ + Atom type; + int format; + unsigned long n_items; + unsigned long bytes_after; + unsigned char *data; + int result; + + int (*old_handler) (Display *, XErrorEvent *); + + XSettingsList *old_list = client->settings; + client->settings = NULL; + printf("read_settings 1\n"); + + old_handler = XSetErrorHandler (ignore_errors); + result = XGetWindowProperty (client->display, client->manager_window, server.atom._XSETTINGS_SETTINGS, 0, LONG_MAX, False, server.atom._XSETTINGS_SETTINGS, &type, &format, &n_items, &bytes_after, &data); + XSetErrorHandler (old_handler); + + if (result == Success && type == server.atom._XSETTINGS_SETTINGS) { + if (format != 8) { + fprintf (stderr, "Invalid format for XSETTINGS property %d", format); + } + else + client->settings = parse_settings (data, n_items); + XFree (data); + } + + notify_changes (client, old_list); + xsettings_list_free (old_list); +} + + +static void check_manager_window (XSettingsClient *client) +{ + if (client->manager_window && client->watch) + client->watch (client->manager_window, False, 0, client->cb_data); + + XGrabServer (client->display); + + client->manager_window = XGetSelectionOwner (server.dsp, server.atom._XSETTINGS_SCREEN); + if (client->manager_window) + XSelectInput (server.dsp, client->manager_window, PropertyChangeMask | StructureNotifyMask); + + XUngrabServer (client->display); + XFlush (client->display); + + if (client->manager_window && client->watch) + client->watch (client->manager_window, True, PropertyChangeMask | StructureNotifyMask, client->cb_data); + + read_settings (client); +} + + +XSettingsClient *xsettings_client_new (Display *display, int screen, XSettingsNotifyFunc notify, XSettingsWatchFunc watch, void *cb_data) +{ + XSettingsClient *client; + + client = malloc (sizeof *client); + if (!client) + return NULL; + + client->display = display; + client->screen = screen; + client->notify = notify; + client->watch = watch; + client->cb_data = cb_data; + + client->manager_window = None; + client->settings = NULL; + + XGrabServer (server.dsp); + client->manager_window = XGetSelectionOwner (server.dsp, server.atom._XSETTINGS_SCREEN); + if (client->manager_window != None) + XSelectInput (server.dsp, client->manager_window, PropertyChangeMask | StructureNotifyMask); + XUngrabServer (client->display); + XFlush (client->display); + + if (client->manager_window == None) { + printf("NO XSETTINGS manager, tint2 use config 'launcher_icon_theme'.\n"); + free (client); + return NULL; + } + + if (client->watch) + client->watch (RootWindow (display, screen), True, StructureNotifyMask, client->cb_data); + + check_manager_window (client); + + return client; +} + + +void xsettings_client_destroy (XSettingsClient *client) +{ + if (client->watch) + client->watch (RootWindow (client->display, client->screen), False, 0, client->cb_data); + if (client->manager_window && client->watch) + client->watch (client->manager_window, False, 0, client->cb_data); + + xsettings_list_free (client->settings); + free (client); +} + + +XSettingsResult xsettings_client_get_setting (XSettingsClient *client, const char *name, XSettingsSetting **setting) +{ + XSettingsSetting *search = xsettings_list_lookup (client->settings, name); + if (search) { + *setting = xsettings_setting_copy (search); + return *setting ? XSETTINGS_SUCCESS : XSETTINGS_NO_MEM; + } + else + return XSETTINGS_NO_ENTRY; +} + + +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 == RootWindow (server.dsp, server.screen)) { + if (xev->xany.type == ClientMessage && xev->xclient.message_type == server.atom.MANAGER) { + check_manager_window (client); + return True; + } + } + else if (xev->xany.window == client->manager_window) { + if (xev->xany.type == DestroyNotify) { + check_manager_window (client); + return True; + } + else if (xev->xany.type == PropertyNotify) { + read_settings (client); + return True; + } + } + + return False; +} + diff --git a/src/launcher/xsettings-client.h b/src/launcher/xsettings-client.h new file mode 100644 index 0000000..2e95a54 --- /dev/null +++ b/src/launcher/xsettings-client.h @@ -0,0 +1,70 @@ +/* + * Copyright © 2001 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Red Hat not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Red Hat makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Owen Taylor, Red Hat, Inc. + */ +#ifndef XSETTINGS_CLIENT_H +#define XSETTINGS_CLIENT_H + +#include +#include "xsettings-common.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct _XSettingsClient XSettingsClient; + +typedef enum +{ + XSETTINGS_ACTION_NEW, + XSETTINGS_ACTION_CHANGED, + XSETTINGS_ACTION_DELETED +} XSettingsAction; + +typedef void (*XSettingsNotifyFunc) (const char *name, + XSettingsAction action, + XSettingsSetting *setting, + void *cb_data); +typedef void (*XSettingsWatchFunc) (Window window, + Bool is_start, + long mask, + void *cb_data); + +XSettingsClient *xsettings_client_new (Display *display, + int screen, + XSettingsNotifyFunc notify, + XSettingsWatchFunc watch, + void *cb_data); +void xsettings_client_destroy (XSettingsClient *client); +Bool xsettings_client_process_event (XSettingsClient *client, + XEvent *xev); + +void xsettings_notify_cb (const char *name, XSettingsAction action, XSettingsSetting *setting, void *data); + +XSettingsResult xsettings_client_get_setting (XSettingsClient *client, + const char *name, + XSettingsSetting **setting); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XSETTINGS_CLIENT_H */ diff --git a/src/launcher/xsettings-common.c b/src/launcher/xsettings-common.c new file mode 100644 index 0000000..1b2125f --- /dev/null +++ b/src/launcher/xsettings-common.c @@ -0,0 +1,268 @@ +/* + * Copyright © 2001 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Red Hat not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Red Hat makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Owen Taylor, Red Hat, Inc. + */ +#include "string.h" +#include "stdlib.h" + +#include +#include /* For CARD32 */ + +#include "xsettings-common.h" + +XSettingsSetting * +xsettings_setting_copy (XSettingsSetting *setting) +{ + XSettingsSetting *result; + size_t str_len; + + result = malloc (sizeof *result); + if (!result) + return NULL; + + str_len = strlen (setting->name); + result->name = malloc (str_len + 1); + if (!result->name) + goto err; + + memcpy (result->name, setting->name, str_len + 1); + + result->type = setting->type; + + switch (setting->type) + { + case XSETTINGS_TYPE_INT: + result->data.v_int = setting->data.v_int; + break; + case XSETTINGS_TYPE_COLOR: + result->data.v_color = setting->data.v_color; + break; + case XSETTINGS_TYPE_STRING: + str_len = strlen (setting->data.v_string); + result->data.v_string = malloc (str_len + 1); + if (!result->data.v_string) + goto err; + + memcpy (result->data.v_string, setting->data.v_string, str_len + 1); + break; + default: + break; + } + + result->last_change_serial = setting->last_change_serial; + + return result; + + err: + if (result->name) + free (result->name); + free (result); + + return NULL; +} + +XSettingsList * +xsettings_list_copy (XSettingsList *list) +{ + XSettingsList *new = NULL; + XSettingsList *old_iter = list; + XSettingsList *new_iter = NULL; + + while (old_iter) + { + XSettingsList *new_node; + + new_node = malloc (sizeof *new_node); + if (!new_node) + goto error; + + new_node->setting = xsettings_setting_copy (old_iter->setting); + if (!new_node->setting) + { + free (new_node); + goto error; + } + + if (new_iter) + new_iter->next = new_node; + else + new = new_node; + + new_iter = new_node; + + old_iter = old_iter->next; + } + + return new; + + error: + xsettings_list_free (new); + return NULL; +} + +int +xsettings_setting_equal (XSettingsSetting *setting_a, + XSettingsSetting *setting_b) +{ + if (setting_a->type != setting_b->type) + return 0; + + if (strcmp (setting_a->name, setting_b->name) != 0) + return 0; + + switch (setting_a->type) + { + case XSETTINGS_TYPE_INT: + return setting_a->data.v_int == setting_b->data.v_int; + case XSETTINGS_TYPE_COLOR: + return (setting_a->data.v_color.red == setting_b->data.v_color.red && + setting_a->data.v_color.green == setting_b->data.v_color.green && + setting_a->data.v_color.blue == setting_b->data.v_color.blue && + setting_a->data.v_color.alpha == setting_b->data.v_color.alpha); + case XSETTINGS_TYPE_STRING: + return strcmp (setting_a->data.v_string, setting_b->data.v_string) == 0; + default: + break; + } + + return 0; +} + +void +xsettings_setting_free (XSettingsSetting *setting) +{ + if (setting->type == XSETTINGS_TYPE_STRING) + free (setting->data.v_string); + + if (setting->name) + free (setting->name); + + free (setting); +} + +void +xsettings_list_free (XSettingsList *list) +{ + while (list) + { + XSettingsList *next = list->next; + + xsettings_setting_free (list->setting); + free (list); + + list = next; + } +} + +XSettingsResult +xsettings_list_insert (XSettingsList **list, + XSettingsSetting *setting) +{ + XSettingsList *node; + XSettingsList *iter; + XSettingsList *last = NULL; + + node = malloc (sizeof *node); + if (!node) + return XSETTINGS_NO_MEM; + node->setting = setting; + + iter = *list; + while (iter) + { + int cmp = strcmp (setting->name, iter->setting->name); + + if (cmp < 0) + break; + else if (cmp == 0) + { + free (node); + return XSETTINGS_DUPLICATE_ENTRY; + } + + last = iter; + iter = iter->next; + } + + if (last) + last->next = node; + else + *list = node; + + node->next = iter; + + return XSETTINGS_SUCCESS; +} + +XSettingsResult +xsettings_list_delete (XSettingsList **list, + const char *name) +{ + XSettingsList *iter; + XSettingsList *last = NULL; + + iter = *list; + while (iter) + { + if (strcmp (name, iter->setting->name) == 0) + { + if (last) + last->next = iter->next; + else + *list = iter->next; + + xsettings_setting_free (iter->setting); + free (iter); + + return XSETTINGS_SUCCESS; + } + + last = iter; + iter = iter->next; + } + + return XSETTINGS_FAILED; +} + +XSettingsSetting * +xsettings_list_lookup (XSettingsList *list, + const char *name) +{ + XSettingsList *iter; + + iter = list; + while (iter) + { + if (strcmp (name, iter->setting->name) == 0) + return iter->setting; + + iter = iter->next; + } + + return NULL; +} + +char +xsettings_byte_order (void) +{ + CARD32 myint = 0x01020304; + return (*(char *)&myint == 1) ? MSBFirst : LSBFirst; +} diff --git a/src/launcher/xsettings-common.h b/src/launcher/xsettings-common.h new file mode 100644 index 0000000..5f129ff --- /dev/null +++ b/src/launcher/xsettings-common.h @@ -0,0 +1,111 @@ +/* + * Copyright © 2001 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Red Hat not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Red Hat makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Owen Taylor, Red Hat, Inc. + */ +#ifndef XSETTINGS_COMMON_H +#define XSETTINGS_COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct _XSettingsBuffer XSettingsBuffer; +typedef struct _XSettingsColor XSettingsColor; +typedef struct _XSettingsList XSettingsList; +typedef struct _XSettingsSetting XSettingsSetting; + +/* Types of settings possible. Enum values correspond to + * protocol values. + */ +typedef enum +{ + XSETTINGS_TYPE_INT = 0, + XSETTINGS_TYPE_STRING = 1, + XSETTINGS_TYPE_COLOR = 2, + XSETTINGS_TYPE_NONE = 0xff +} XSettingsType; + +typedef enum +{ + XSETTINGS_SUCCESS, + XSETTINGS_NO_MEM, + XSETTINGS_ACCESS, + XSETTINGS_FAILED, + XSETTINGS_NO_ENTRY, + XSETTINGS_DUPLICATE_ENTRY +} XSettingsResult; + +struct _XSettingsBuffer +{ + char byte_order; + size_t len; + unsigned char *data; + unsigned char *pos; +}; + +struct _XSettingsColor +{ + unsigned short red, green, blue, alpha; +}; + +struct _XSettingsList +{ + XSettingsSetting *setting; + XSettingsList *next; +}; + +struct _XSettingsSetting +{ + char *name; + XSettingsType type; + + union { + int v_int; + char *v_string; + XSettingsColor v_color; + } data; + + unsigned long last_change_serial; +}; + +XSettingsSetting *xsettings_setting_copy (XSettingsSetting *setting); +void xsettings_setting_free (XSettingsSetting *setting); +int xsettings_setting_equal (XSettingsSetting *setting_a, + XSettingsSetting *setting_b); + +void xsettings_list_free (XSettingsList *list); +XSettingsList *xsettings_list_copy (XSettingsList *list); +XSettingsResult xsettings_list_insert (XSettingsList **list, + XSettingsSetting *setting); +XSettingsSetting *xsettings_list_lookup (XSettingsList *list, + const char *name); +XSettingsResult xsettings_list_delete (XSettingsList **list, + const char *name); + +char xsettings_byte_order (void); + +#define XSETTINGS_PAD(n,m) ((n + m - 1) & (~(m-1))) + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XSETTINGS_COMMON_H */ diff --git a/src/server.c b/src/server.c index f35bb96..6ec363b 100644 --- a/src/server.c +++ b/src/server.c @@ -80,17 +80,21 @@ void server_init_atoms () server.atom.__SWM_VROOT = XInternAtom(server.dsp, "__SWM_VROOT", False); server.atom._MOTIF_WM_HINTS = XInternAtom(server.dsp, "_MOTIF_WM_HINTS", False); server.atom.WM_HINTS = XInternAtom(server.dsp, "WM_HINTS", False); + char *name = g_strdup_printf("_XSETTINGS_S%d", DefaultScreen(server.dsp)); + server.atom._XSETTINGS_SCREEN = XInternAtom(server.dsp, name, False); + g_free(name); + server.atom._XSETTINGS_SETTINGS = XInternAtom(server.dsp, "_XSETTINGS_SETTINGS", False); // systray protocol - char *name_trayer = g_strdup_printf("_NET_SYSTEM_TRAY_S%d", DefaultScreen(server.dsp)); - server.atom._NET_SYSTEM_TRAY_SCREEN = XInternAtom(server.dsp, name_trayer, False); + name = g_strdup_printf("_NET_SYSTEM_TRAY_S%d", DefaultScreen(server.dsp)); + server.atom._NET_SYSTEM_TRAY_SCREEN = XInternAtom(server.dsp, name, False); + g_free(name); server.atom._NET_SYSTEM_TRAY_OPCODE = XInternAtom(server.dsp, "_NET_SYSTEM_TRAY_OPCODE", False); server.atom.MANAGER = XInternAtom(server.dsp, "MANAGER", False); server.atom._NET_SYSTEM_TRAY_MESSAGE_DATA = XInternAtom(server.dsp, "_NET_SYSTEM_TRAY_MESSAGE_DATA", False); server.atom._NET_SYSTEM_TRAY_ORIENTATION = XInternAtom(server.dsp, "_NET_SYSTEM_TRAY_ORIENTATION", False); server.atom._XEMBED = XInternAtom(server.dsp, "_XEMBED", False); server.atom._XEMBED_INFO = XInternAtom(server.dsp, "_XEMBED_INFO", False); - g_free(name_trayer); // drag 'n' drop server.atom.XdndAware = XInternAtom(server.dsp, "XdndAware", False); diff --git a/src/server.h b/src/server.h index 0ee6ea5..ec6bb1d 100644 --- a/src/server.h +++ b/src/server.h @@ -50,7 +50,7 @@ typedef struct Global_atom Atom _NET_WM_VISIBLE_NAME; Atom _NET_WM_STRUT; Atom _NET_WM_ICON; - Atom _NET_WM_ICON_GEOMETRY; + Atom _NET_WM_ICON_GEOMETRY; Atom _NET_CLOSE_WINDOW; Atom UTF8_STRING; Atom _NET_SUPPORTING_WM_CHECK; @@ -67,6 +67,8 @@ typedef struct Global_atom Atom _NET_SYSTEM_TRAY_ORIENTATION; Atom _XEMBED; Atom _XEMBED_INFO; + Atom _XSETTINGS_SCREEN; + Atom _XSETTINGS_SETTINGS; Atom XdndAware; Atom XdndPosition; Atom XdndStatus; diff --git a/src/tint.c b/src/tint.c index 1772681..794aefb 100644 --- a/src/tint.c +++ b/src/tint.c @@ -42,6 +42,7 @@ #include "panel.h" #include "tooltip.h" #include "timer.h" +#include "xsettings-client.h" void signal_handler(int sig) @@ -135,7 +136,7 @@ void init_X11() setlocale (LC_ALL, ""); // config file use '.' as decimal separator setlocale(LC_NUMERIC, "POSIX"); - + // load default icon gchar *path; const gchar * const *data_dirs; @@ -803,6 +804,9 @@ start: if (select(x11_fd+1, &fdset, 0, 0, timeout) > 0) { while (XPending (server.dsp)) { XNextEvent(server.dsp, &e); + if (xsettings_client != NULL) { + xsettings_client_process_event(xsettings_client, &e); + } panel = get_panel(e.xany.window); if (panel && panel_autohide) { diff --git a/src/tint2conf/main.c b/src/tint2conf/main.c index 2d65a19..39a8d08 100644 --- a/src/tint2conf/main.c +++ b/src/tint2conf/main.c @@ -327,19 +327,19 @@ static void menuProperties() GtkTreeSelection *sel; GtkTreeIter iter; GtkTreeModel *model; - char *file, *cmd; + char *file; sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(g_theme_view)); if (gtk_tree_selection_get_selected(GTK_TREE_SELECTION(sel), &model, &iter)) { gtk_tree_model_get(model, &iter, COL_THEME_FILE, &file, -1); -/* +//* GtkWidget *prop; prop = create_properties(); gtk_window_present(GTK_WINDOW(prop)); //printf("menuProperties : fin\n"); //*/ -//* - cmd = g_strdup_printf("%s \'%s\' &", g_cmd_property, file); +/* + char *cmd = g_strdup_printf("%s \'%s\' &", g_cmd_property, file); printf("cmd %s\n", cmd); system(cmd); g_free(cmd); diff --git a/src/tint2conf/properties.c b/src/tint2conf/properties.c index a70a730..82a3075 100644 --- a/src/tint2conf/properties.c +++ b/src/tint2conf/properties.c @@ -27,6 +27,7 @@ void change_paragraph(GtkWidget *widget); void create_general(GtkWidget *parent); void create_panel(GtkWidget *parent); +void create_launcher(GtkWidget *parent); void create_taskbar(GtkWidget *parent); void create_task(GtkWidget *parent); void create_clock(GtkWidget *parent); -- 2.43.0