wckbuttons-theme.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /* $Id$
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 3 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License along
  14. * with this program; if not, write to the Free Software Foundation, Inc.,
  15. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  16. *
  17. * Copyright (C) 2013 Cedric Leporcq <cedl38@gmail.com>
  18. *
  19. * Parts of this code is derived from xfwm4 sources (setting.c)
  20. *
  21. */
  22. #include <common/mypixmap.h>
  23. #include <common/theme.h>
  24. #include "wckbuttons-theme.h"
  25. #define XPM_COLOR_SYMBOL_SIZE 22
  26. static gboolean
  27. set_g_value (const gchar * lvalue, const GValue *rvalue, Settings *rc)
  28. {
  29. gint i;
  30. TRACE ("entering setValue");
  31. g_return_val_if_fail (lvalue != NULL, FALSE);
  32. g_return_val_if_fail (rvalue != NULL, FALSE);
  33. for (i = 0; rc[i].option; i++)
  34. {
  35. if (!g_ascii_strcasecmp (lvalue, rc[i].option))
  36. {
  37. if (rvalue)
  38. {
  39. if (rc[i].value)
  40. {
  41. g_value_unset (rc[i].value);
  42. g_value_init (rc[i].value, G_VALUE_TYPE(rvalue));
  43. }
  44. else
  45. {
  46. rc[i].value = g_new0(GValue, 1);
  47. g_value_init (rc[i].value, G_VALUE_TYPE(rvalue));
  48. }
  49. g_value_copy (rvalue, rc[i].value);
  50. return TRUE;
  51. }
  52. }
  53. }
  54. return FALSE;
  55. }
  56. static gboolean
  57. set_string_value (const gchar * lvalue, const gchar *value, Settings *rc)
  58. {
  59. GValue tmp_val = {0, };
  60. g_value_init(&tmp_val, G_TYPE_STRING);
  61. g_value_set_static_string(&tmp_val, value);
  62. return set_g_value (lvalue, &tmp_val, rc);
  63. }
  64. static void get_unity_pixbuf (const gchar *themedir, WBPlugin *wb) {
  65. gint i,j;
  66. gchar imagename[40];
  67. static const char *button_names[] = {
  68. "minimize",
  69. "unmaximize",
  70. "maximize",
  71. "close"
  72. };
  73. static const char *button_state_names[] = {
  74. "unfocused",
  75. "focused_normal",
  76. "focused_prelight",
  77. "focused_pressed"
  78. };
  79. for (i = 0; i < IMAGES_BUTTONS; i++)
  80. {
  81. for (j = 0; j < IMAGES_STATES; j++)
  82. {
  83. g_snprintf(imagename, sizeof (imagename), "%s_%s", button_names[i], button_state_names[j]);
  84. wb->pixbufs[i][j] = pixbuf_alpha_load (themedir, imagename);
  85. }
  86. }
  87. }
  88. gchar *button_layout_filter (const gchar *string, const gchar *default_layout)
  89. {
  90. guint i, j;
  91. gchar layout[BUTTONS] = {0};
  92. /* WARNING : beware of bluffer overflow !!! */
  93. j = 0;
  94. for (i = 0; i < strlen (string) && j < BUTTONS; i++)
  95. {
  96. switch (string[i])
  97. {
  98. case 'H':
  99. layout[j++] = 'H';
  100. break;
  101. case 'M':
  102. layout[j++] = 'M';
  103. break;
  104. case 'C':
  105. layout[j++] = 'C';
  106. }
  107. }
  108. layout[j] = '\0';
  109. if (layout[0] == '\0')
  110. return g_strdup (default_layout);
  111. return g_strdup (layout);
  112. }
  113. gchar *opposite_layout_filter (const gchar *string)
  114. {
  115. guint i, j;
  116. gchar layout[8] = {0};
  117. /* WARNING : beware of bluffer overflow !!! */
  118. j = 0;
  119. for (i = 0; i < strlen (string) && j < 8; i++)
  120. {
  121. switch (string[i])
  122. {
  123. case 'H':
  124. case 'M':
  125. case 'C':
  126. break;
  127. default:
  128. layout[j] = string[i];
  129. j++;
  130. }
  131. }
  132. layout[j] = '\0';
  133. return g_strdup (layout);
  134. }
  135. static int get_button_from_letter (char chr)
  136. {
  137. TRACE ("entering get_button_from_letter");
  138. switch (chr)
  139. {
  140. case 'H':
  141. return MINIMIZE_BUTTON;
  142. case 'M':
  143. return MAXIMIZE_BUTTON;
  144. case 'C':
  145. return CLOSE_BUTTON;
  146. default:
  147. return -1;
  148. }
  149. }
  150. /* Replace buttons accordingly to button_layout and visible state */
  151. void replace_buttons (const gchar *button_layout, WBPlugin *wb)
  152. {
  153. guint i, j;
  154. gint button;
  155. for (i = 0; i < BUTTONS; i++)
  156. gtk_widget_hide_all(GTK_WIDGET(wb->button[i]->eventbox));
  157. j = 0;
  158. for (i = 0; i < strlen (button_layout); i++)
  159. {
  160. button = get_button_from_letter (button_layout[i]);
  161. if (button >= 0 && wb->button[button]->image)
  162. {
  163. gtk_box_reorder_child (GTK_BOX (wb->hvbox), GTK_WIDGET(wb->button[button]->eventbox), j);
  164. gtk_widget_show_all(GTK_WIDGET(wb->button[button]->eventbox));
  165. j++;
  166. }
  167. }
  168. }
  169. gchar *get_rc_button_layout (const gchar *theme)
  170. {
  171. gchar *wm_themedir;
  172. wm_themedir = test_theme_dir(theme, "xfwm4", THEMERC);
  173. if (G_LIKELY(wm_themedir))
  174. {
  175. const gchar *rc_button_layout;
  176. gchar *filename;
  177. XfceRc *rc;
  178. /* check in the rc if the theme supports a custom button layout */
  179. filename = g_build_filename (wm_themedir, THEMERC, NULL);
  180. rc = xfce_rc_simple_open (filename, TRUE);
  181. g_free (filename);
  182. if (G_LIKELY (rc))
  183. {
  184. rc_button_layout = xfce_rc_read_entry (rc, "button_layout", NULL);
  185. if (rc_button_layout)
  186. return button_layout_filter (rc_button_layout, NULL);
  187. }
  188. }
  189. g_free (wm_themedir);
  190. return NULL;
  191. }
  192. /* load the theme according to xfwm4 theme format */
  193. void load_theme (const gchar *theme, WBPlugin *wb)
  194. {
  195. gint i;
  196. gchar *themedir;
  197. /* get theme dir */
  198. themedir = get_unity_theme_dir (wb->prefs->theme, DEFAULT_THEME);
  199. if (themedir)
  200. {
  201. get_unity_pixbuf (themedir, wb);
  202. g_free (themedir);
  203. /* try to replace missing images */
  204. for (i = 0; i < IMAGES_STATES; i++)
  205. {
  206. if (!wb->pixbufs[IMAGE_UNMAXIMIZE][i])
  207. wb->pixbufs[IMAGE_UNMAXIMIZE][i] = wb->pixbufs[IMAGE_MAXIMIZE][i];
  208. }
  209. for (i = 0; i < IMAGES_BUTTONS; i++)
  210. {
  211. if (!wb->pixbufs[i][IMAGE_UNFOCUSED] || !wb->pixbufs[i][IMAGE_PRESSED])
  212. wb->pixbufs[i][IMAGE_UNFOCUSED] = wb->pixbufs[i][IMAGE_FOCUSED];
  213. if (!wb->pixbufs[i][IMAGE_PRELIGHT])
  214. wb->pixbufs[i][IMAGE_PRELIGHT] = wb->pixbufs[i][IMAGE_PRESSED];
  215. }
  216. }
  217. }
  218. static void apply_wm_theme (WBPlugin *wb)
  219. {
  220. const gchar *wm_theme = xfconf_channel_get_string (wb->wm_channel, "/general/theme", NULL);
  221. if (G_LIKELY(wm_theme))
  222. {
  223. gchar *button_layout;
  224. wb->prefs->theme = g_strdup (wm_theme);
  225. load_theme (wb->prefs->theme, wb);
  226. button_layout = get_rc_button_layout (wm_theme);
  227. if (button_layout)
  228. {
  229. replace_buttons (button_layout, wb);
  230. }
  231. else
  232. {
  233. const gchar *wm_buttons_layout = xfconf_channel_get_string (wb->wm_channel, "/general/button_layout", wb->prefs->button_layout);
  234. wb->prefs->button_layout = button_layout_filter (wm_buttons_layout, wb->prefs->button_layout);
  235. replace_buttons (wb->prefs->button_layout, wb);
  236. }
  237. g_free (button_layout);
  238. }
  239. on_wck_state_changed (wb->win->controlwindow, wb);
  240. }
  241. static void
  242. on_x_chanel_property_changed (XfconfChannel *x_channel, const gchar *property_name, const GValue *value, WBPlugin *wb)
  243. {
  244. if (g_str_has_prefix(property_name, "/Net/") == TRUE)
  245. {
  246. const gchar *name = &property_name[5];
  247. switch (G_VALUE_TYPE(value))
  248. {
  249. case G_TYPE_STRING:
  250. if (!strcmp (name, "ThemeName"))
  251. {
  252. apply_wm_theme (wb);
  253. }
  254. break;
  255. default:
  256. g_warning("The property '%s' is not supported", property_name);
  257. break;
  258. }
  259. }
  260. }
  261. static void
  262. on_xfwm_channel_property_changed (XfconfChannel *wm_channel, const gchar *property_name, const GValue *value, WBPlugin *wb)
  263. {
  264. if (g_str_has_prefix(property_name, "/general/") == TRUE)
  265. {
  266. const gchar *name = &property_name[9];
  267. switch (G_VALUE_TYPE(value))
  268. {
  269. case G_TYPE_STRING:
  270. if (!strcmp (name, "theme")
  271. || !strcmp (name, "button_layout"))
  272. {
  273. apply_wm_theme (wb);
  274. }
  275. break;
  276. default:
  277. g_warning("The property '%s' is not supported", property_name);
  278. break;
  279. }
  280. }
  281. }
  282. void init_theme (WBPlugin *wb)
  283. {
  284. /* get the xfwm4 chanel */
  285. wb->wm_channel = wck_properties_get_channel (G_OBJECT (wb->plugin), "xfwm4");
  286. /* try to use the xfwm4 theme */
  287. if (wb->wm_channel && wb->prefs->sync_wm_theme)
  288. {
  289. apply_wm_theme (wb);
  290. g_signal_connect (wb->wm_channel, "property-changed", G_CALLBACK (on_xfwm_channel_property_changed), wb);
  291. }
  292. else
  293. {
  294. load_theme (wb->prefs->theme, wb);
  295. replace_buttons (wb->prefs->button_layout, wb);
  296. }
  297. /* get the xsettings chanel to update the gtk theme */
  298. wb->x_channel = wck_properties_get_channel (G_OBJECT (wb->plugin), "xsettings");
  299. if (wb->x_channel)
  300. g_signal_connect (wb->x_channel, "property-changed", G_CALLBACK (on_x_chanel_property_changed), wb);
  301. }