Hi, I've come back to this after a while, sorry for abandoning the thread! I've only tested this in Scratchbox (strace etc. on personalisation_app worked wonders ), but hopefully, it should work for refreshing the theme. If it doesn't work, you may have to switch to another theme because the underlying components realise that you're reapplying the same theme; if that's the case, I don't know what to do PHP Code: #include <stdlib.h> #include <string.h> #include <libgen.h> #include <X11/Xatom.h> #include <gdk/gdkx.h> #include <gtk/gtk.h> struct _theme_info { gchar *base_path; gchar *theme_name; }; static gboolean current_theme_info (struct _theme_info *theme_info) { #define THEME_DIR "/etc/hildon/theme" #define INDEX_THEME_FILE G_DIR_SEPARATOR_S "index.theme" #define STD_INDEX_LOC THEME_DIR INDEX_THEME_FILE gboolean retval = FALSE; gchar *linkdest1 = NULL, *linkdest2 = NULL; GKeyFile *theme_key = g_key_file_new(); if ((!g_file_test (STD_INDEX_LOC, G_FILE_TEST_EXISTS)) || (!g_key_file_load_from_file (theme_key, STD_INDEX_LOC, G_KEY_FILE_NONE, NULL)) || !(theme_info->theme_name = g_key_file_get_string (theme_key, "Desktop Entry", "Name", NULL))) goto getout; linkdest1 = g_file_read_link (THEME_DIR, NULL); if (!linkdest1) goto getout; linkdest2 = g_file_read_link (linkdest1, NULL); /* Is it a folder that's symlinked to another, like: default->alpha? */ theme_info->base_path = g_path_get_basename (linkdest2 ? linkdest2 : linkdest1); retval = theme_info->base_path != NULL; getout: g_free (linkdest2); g_free (linkdest1); g_key_file_free (theme_key); return retval; #undef STD_INDEX_LOC #undef INDEX_THEME_FILE #undef THEME_DIR } static gboolean update_symbolic_link (const gchar *newtheme) { gboolean retval = FALSE; if (newtheme) { gint exit_status; gchar *cmdline; cmdline = g_strdup_printf ("%s %s/%s", "/usr/bin/personalisation", "/usr/share/themes", newtheme); retval = g_spawn_command_line_sync (cmdline, NULL, NULL, &exit_status, NULL) || exit_status != 0; g_free (cmdline); } return retval; } static void send_refresh_signal (void) { GdkEventClient event; event.type = GDK_CLIENT_EVENT; event.send_event = TRUE; event.window = NULL; event.message_type = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE); event.data_format = 8; gdk_event_send_clientmessage_toall ((GdkEvent *) &event); } static void refresh_matchbox (const gchar *base_path) { Display *disp = XOpenDisplay (getenv ("DISPLAY")); Atom _MB_THEME = XInternAtom (disp, "_MB_THEME", False); if (_MB_THEME != None) { Window root = DefaultRootWindow(disp); XChangeProperty (disp, root, _MB_THEME, XA_STRING, 8, PropModeReplace, (unsigned char*) base_path, strlen (base_path)); Atom _MB_COMMAND = XInternAtom (disp, "_MB_COMMAND", False); if (_MB_COMMAND != None) { XEvent ev = { '\0', }; ev.xclient.type = ClientMessage; ev.xclient.window = root; ev.xclient.message_type = _MB_COMMAND; ev.xclient.format = 8; ev.xclient.data.l[0] = 1; XSendEvent(disp, root, False, SubstructureRedirectMask|SubstructureNotifyMask, &ev); } XSync (disp, True); } XCloseDisplay (disp); } int main (int argc, char *argv[]) { struct _theme_info theme_info; gtk_init (&argc, &argv); g_assert (current_theme_info(&theme_info)); if (!update_symbolic_link (theme_info.base_path)) return 1; /* Fails in my SB - "invalid cross-device link */ GtkSettings *settings = gtk_settings_get_default(); gtk_settings_set_string_property (settings, "gtk-theme-name", theme_info.theme_name, basename(argv[0])); //g_object_notify (G_OBJECT (settings), "gtk-theme-name"); gtk_rc_reset_styles (settings); send_refresh_signal(); gchar *maemo_launcher_pid_s; if (g_file_get_contents ("/tmp/maemo-launcher.pid", &maemo_launcher_pid_s, NULL, NULL)) { pid_t maemo_launcher_pid = (pid_t) atoi (maemo_launcher_pid_s); if (maemo_launcher_pid > 0) kill (maemo_launcher_pid, SIGHUP); g_free (maemo_launcher_pid_s); } refresh_matchbox (theme_info.base_path); g_free (theme_info.base_path); g_free (theme_info.theme_name); return 0; } Just using gtk+-2.0 for pkg-config works to compile it
#include <stdlib.h> #include <string.h> #include <libgen.h> #include <X11/Xatom.h> #include <gdk/gdkx.h> #include <gtk/gtk.h> struct _theme_info { gchar *base_path; gchar *theme_name; }; static gboolean current_theme_info (struct _theme_info *theme_info) { #define THEME_DIR "/etc/hildon/theme" #define INDEX_THEME_FILE G_DIR_SEPARATOR_S "index.theme" #define STD_INDEX_LOC THEME_DIR INDEX_THEME_FILE gboolean retval = FALSE; gchar *linkdest1 = NULL, *linkdest2 = NULL; GKeyFile *theme_key = g_key_file_new(); if ((!g_file_test (STD_INDEX_LOC, G_FILE_TEST_EXISTS)) || (!g_key_file_load_from_file (theme_key, STD_INDEX_LOC, G_KEY_FILE_NONE, NULL)) || !(theme_info->theme_name = g_key_file_get_string (theme_key, "Desktop Entry", "Name", NULL))) goto getout; linkdest1 = g_file_read_link (THEME_DIR, NULL); if (!linkdest1) goto getout; linkdest2 = g_file_read_link (linkdest1, NULL); /* Is it a folder that's symlinked to another, like: default->alpha? */ theme_info->base_path = g_path_get_basename (linkdest2 ? linkdest2 : linkdest1); retval = theme_info->base_path != NULL; getout: g_free (linkdest2); g_free (linkdest1); g_key_file_free (theme_key); return retval; #undef STD_INDEX_LOC #undef INDEX_THEME_FILE #undef THEME_DIR } static gboolean update_symbolic_link (const gchar *newtheme) { gboolean retval = FALSE; if (newtheme) { gint exit_status; gchar *cmdline; cmdline = g_strdup_printf ("%s %s/%s", "/usr/bin/personalisation", "/usr/share/themes", newtheme); retval = g_spawn_command_line_sync (cmdline, NULL, NULL, &exit_status, NULL) || exit_status != 0; g_free (cmdline); } return retval; } static void send_refresh_signal (void) { GdkEventClient event; event.type = GDK_CLIENT_EVENT; event.send_event = TRUE; event.window = NULL; event.message_type = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE); event.data_format = 8; gdk_event_send_clientmessage_toall ((GdkEvent *) &event); } static void refresh_matchbox (const gchar *base_path) { Display *disp = XOpenDisplay (getenv ("DISPLAY")); Atom _MB_THEME = XInternAtom (disp, "_MB_THEME", False); if (_MB_THEME != None) { Window root = DefaultRootWindow(disp); XChangeProperty (disp, root, _MB_THEME, XA_STRING, 8, PropModeReplace, (unsigned char*) base_path, strlen (base_path)); Atom _MB_COMMAND = XInternAtom (disp, "_MB_COMMAND", False); if (_MB_COMMAND != None) { XEvent ev = { '\0', }; ev.xclient.type = ClientMessage; ev.xclient.window = root; ev.xclient.message_type = _MB_COMMAND; ev.xclient.format = 8; ev.xclient.data.l[0] = 1; XSendEvent(disp, root, False, SubstructureRedirectMask|SubstructureNotifyMask, &ev); } XSync (disp, True); } XCloseDisplay (disp); } int main (int argc, char *argv[]) { struct _theme_info theme_info; gtk_init (&argc, &argv); g_assert (current_theme_info(&theme_info)); if (!update_symbolic_link (theme_info.base_path)) return 1; /* Fails in my SB - "invalid cross-device link */ GtkSettings *settings = gtk_settings_get_default(); gtk_settings_set_string_property (settings, "gtk-theme-name", theme_info.theme_name, basename(argv[0])); //g_object_notify (G_OBJECT (settings), "gtk-theme-name"); gtk_rc_reset_styles (settings); send_refresh_signal(); gchar *maemo_launcher_pid_s; if (g_file_get_contents ("/tmp/maemo-launcher.pid", &maemo_launcher_pid_s, NULL, NULL)) { pid_t maemo_launcher_pid = (pid_t) atoi (maemo_launcher_pid_s); if (maemo_launcher_pid > 0) kill (maemo_launcher_pid, SIGHUP); g_free (maemo_launcher_pid_s); } refresh_matchbox (theme_info.base_path); g_free (theme_info.base_path); g_free (theme_info.theme_name); return 0; }