wckbuttons.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  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. */
  20. #ifdef HAVE_CONFIG_H
  21. #include <config.h>
  22. #endif
  23. #ifdef HAVE_STRING_H
  24. #include <string.h>
  25. #endif
  26. #include <gtk/gtk.h>
  27. #include <libxfce4util/libxfce4util.h>
  28. #include <libxfce4panel/xfce-panel-plugin.h>
  29. #include <libxfce4panel/xfce-hvbox.h>
  30. #include "wckbuttons.h"
  31. #include "wckbuttons-dialogs.h"
  32. #include "wckbuttons-theme.h"
  33. /* default settings */
  34. #define DEFAULT_ONLY_MAXIMIZED TRUE
  35. #define DEFAULT_SHOW_ON_DESKTOP FALSE
  36. #define DEFAULT_SYNC_WM_THEME TRUE
  37. #define DEFAULT_BUTTON_LAYOUT "HMC"
  38. #define DEFAULT_INACTIVE_TEXT_ALPHA 60
  39. #define DEFAULT_INACTIVE_TEXT_SHADE 110
  40. #define BUTTONS_SIGNALS_CONNECT(name, id) \
  41. g_signal_connect (G_OBJECT (wb->button[id]->eventbox), "button-press-event", G_CALLBACK (name##_button_pressed), wb); \
  42. g_signal_connect (G_OBJECT (wb->button[id]->eventbox), "button-release-event", G_CALLBACK (name##_button_release), wb); \
  43. g_signal_connect (G_OBJECT (wb->button[id]->eventbox), "enter-notify-event", ((GCallback) (name##_button_hover_enter)), wb); \
  44. g_signal_connect (G_OBJECT (wb->button[id]->eventbox), "leave-notify-event", G_CALLBACK (name##_button_hover_leave), wb);
  45. /* prototypes */
  46. static void
  47. wckbuttons_construct (XfcePanelPlugin *plugin);
  48. void
  49. wckbuttons_save (XfcePanelPlugin *plugin,
  50. WBPlugin *wb)
  51. {
  52. XfceRc *rc;
  53. gchar *file;
  54. /* get the config file location */
  55. file = xfce_panel_plugin_save_location (plugin, TRUE);
  56. if (G_UNLIKELY (file == NULL))
  57. {
  58. DBG ("Failed to open config file");
  59. return;
  60. }
  61. /* open the config file, read/write */
  62. rc = xfce_rc_simple_open (file, FALSE);
  63. g_free (file);
  64. if (G_LIKELY (rc != NULL))
  65. {
  66. /* save the settings */
  67. DBG(".");
  68. xfce_rc_write_bool_entry(rc, "only_maximized", wb->prefs->only_maximized);
  69. xfce_rc_write_bool_entry(rc, "show_on_desktop", wb->prefs->show_on_desktop);
  70. xfce_rc_write_bool_entry(rc, "sync_wm_theme", wb->prefs->sync_wm_theme);
  71. if (wb->prefs->button_layout)
  72. xfce_rc_write_entry (rc, "button_layout", wb->prefs->button_layout);
  73. if (wb->prefs->theme)
  74. xfce_rc_write_entry (rc, "theme", wb->prefs->theme);
  75. xfce_rc_write_int_entry (rc, "inactive_text_alpha", wb->prefs->inactive_text_alpha);
  76. xfce_rc_write_int_entry (rc, "inactive_text_shade", wb->prefs->inactive_text_shade);
  77. /* close the rc file */
  78. xfce_rc_close (rc);
  79. }
  80. }
  81. static void
  82. wckbuttons_read (WBPlugin *wb)
  83. {
  84. XfceRc *rc;
  85. gchar *file;
  86. const gchar *button_layout, *theme;
  87. /* allocate memory for the preferences structure */
  88. wb->prefs = g_slice_new0(WBPreferences);
  89. /* get the plugin config file location */
  90. file = xfce_panel_plugin_save_location (wb->plugin, TRUE);
  91. if (G_LIKELY (file != NULL))
  92. {
  93. /* open the config file, readonly */
  94. rc = xfce_rc_simple_open (file, TRUE);
  95. /* cleanup */
  96. g_free (file);
  97. if (G_LIKELY (rc != NULL))
  98. {
  99. /* read the settings */
  100. wb->prefs->only_maximized = xfce_rc_read_bool_entry(rc, "only_maximized", DEFAULT_ONLY_MAXIMIZED);
  101. wb->prefs->show_on_desktop = xfce_rc_read_bool_entry(rc, "show_on_desktop", DEFAULT_SHOW_ON_DESKTOP);
  102. wb->prefs->sync_wm_theme = xfce_rc_read_bool_entry(rc, "sync_wm_theme", DEFAULT_SYNC_WM_THEME);
  103. button_layout = xfce_rc_read_entry (rc, "button_layout", DEFAULT_BUTTON_LAYOUT);
  104. wb->prefs->button_layout = button_layout_filter (button_layout, DEFAULT_BUTTON_LAYOUT);
  105. theme = xfce_rc_read_entry (rc, "theme", DEFAULT_THEME);
  106. wb->prefs->theme = g_strdup (theme);
  107. wb->prefs->inactive_text_alpha = xfce_rc_read_int_entry (rc, "inactive_text_alpha", DEFAULT_INACTIVE_TEXT_ALPHA);
  108. wb->prefs->inactive_text_shade = xfce_rc_read_int_entry (rc, "inactive_text_shade", DEFAULT_INACTIVE_TEXT_SHADE);
  109. /* cleanup */
  110. xfce_rc_close (rc);
  111. /* leave the function, everything went well */
  112. return;
  113. }
  114. }
  115. /* something went wrong, apply default values */
  116. DBG ("Applying default settings");
  117. wb->prefs->only_maximized = DEFAULT_ONLY_MAXIMIZED;
  118. wb->prefs->show_on_desktop = DEFAULT_SHOW_ON_DESKTOP;
  119. wb->prefs->sync_wm_theme = DEFAULT_SYNC_WM_THEME;
  120. wb->prefs->button_layout = DEFAULT_BUTTON_LAYOUT;
  121. wb->prefs->theme = DEFAULT_THEME;
  122. wb->prefs->inactive_text_alpha = DEFAULT_INACTIVE_TEXT_ALPHA;
  123. wb->prefs->inactive_text_shade = DEFAULT_INACTIVE_TEXT_SHADE;
  124. }
  125. static WindowButton **create_buttons (WBPlugin *wb)
  126. {
  127. WindowButton **button = g_new(WindowButton*, BUTTONS);
  128. gint i;
  129. for (i=0; i<BUTTONS; i++)
  130. {
  131. button[i] = g_new0 (WindowButton, 1);
  132. button[i]->eventbox = GTK_EVENT_BOX (gtk_event_box_new());
  133. button[i]->image = GTK_IMAGE (gtk_image_new());
  134. gtk_widget_set_can_focus (GTK_WIDGET(button[i]->eventbox), TRUE);
  135. gtk_container_add (GTK_CONTAINER (button[i]->eventbox), GTK_WIDGET(button[i]->image));
  136. gtk_event_box_set_visible_window (button[i]->eventbox, FALSE);
  137. gtk_box_pack_start (GTK_BOX (wb->hvbox), GTK_WIDGET(button[i]->eventbox), TRUE, TRUE, 0);
  138. /* Add hover events to eventboxes */
  139. gtk_widget_add_events (GTK_WIDGET (button[i]->eventbox), GDK_ENTER_NOTIFY_MASK); //add the "enter" signal
  140. gtk_widget_add_events (GTK_WIDGET (button[i]->eventbox), GDK_LEAVE_NOTIFY_MASK); //add the "leave" signal
  141. }
  142. return button;
  143. }
  144. static WBPlugin *
  145. wckbuttons_new (XfcePanelPlugin *plugin)
  146. {
  147. WBPlugin *wb;
  148. GtkOrientation orientation;
  149. /* allocate memory for the plugin structure */
  150. wb = g_slice_new0 (WBPlugin);
  151. /* pointer to plugin */
  152. wb->plugin = plugin;
  153. /* read the user settings */
  154. wckbuttons_read (wb);
  155. /* get the current orientation */
  156. orientation = xfce_panel_plugin_get_orientation (plugin);
  157. /* create some panel widgets */
  158. wb->ebox = gtk_event_box_new ();
  159. gtk_event_box_set_visible_window(GTK_EVENT_BOX(wb->ebox), FALSE);
  160. gtk_widget_set_name(wb->ebox, "XfceWckButtonsPlugin");
  161. wb->hvbox = xfce_hvbox_new (orientation, FALSE, 2);
  162. /* create buttons */
  163. wb->button = create_buttons (wb);
  164. gtk_widget_show (wb->ebox);
  165. gtk_widget_show (wb->hvbox);
  166. gtk_container_add (GTK_CONTAINER (wb->ebox), wb->hvbox);
  167. return wb;
  168. }
  169. static void wckbuttons_free (XfcePanelPlugin *plugin, WBPlugin *wb)
  170. {
  171. GtkWidget *dialog;
  172. /* check if the dialog is still open. if so, destroy it */
  173. dialog = g_object_get_data (G_OBJECT (plugin), "dialog");
  174. if (G_UNLIKELY (dialog != NULL))
  175. gtk_widget_destroy (dialog);
  176. /* destroy the panel widgets */
  177. gtk_widget_destroy (wb->hvbox);
  178. /* cleanup the settings */
  179. if (G_LIKELY (wb->prefs->button_layout != NULL))
  180. g_free (wb->prefs->button_layout);
  181. /* free the plugin structure */
  182. g_slice_free(WckUtils, wb->win);
  183. g_slice_free(WBPreferences, wb->prefs);
  184. g_slice_free (WBPlugin, wb);
  185. }
  186. static void
  187. wckbuttons_orientation_changed (XfcePanelPlugin *plugin,
  188. GtkOrientation orientation,
  189. WBPlugin *wb)
  190. {
  191. /* change the orienation of the box */
  192. xfce_hvbox_set_orientation (XFCE_HVBOX (wb->hvbox), orientation);
  193. }
  194. static gboolean
  195. wckbuttons_size_changed (XfcePanelPlugin *plugin,
  196. gint size,
  197. WBPlugin *wb)
  198. {
  199. GtkOrientation orientation;
  200. /* get the orientation of the plugin */
  201. orientation = xfce_panel_plugin_get_orientation (plugin);
  202. /* set the widget size */
  203. if (orientation == GTK_ORIENTATION_HORIZONTAL)
  204. gtk_widget_set_size_request (GTK_WIDGET (plugin), -1, size);
  205. else
  206. gtk_widget_set_size_request (GTK_WIDGET (plugin), size, -1);
  207. /* we handled the orientation */
  208. return TRUE;
  209. }
  210. static void set_maximize_button_image (WBPlugin *wb, gushort image_state)
  211. {
  212. if (wb->win->controlwindow && wnck_window_is_maximized(wb->win->controlwindow)) {
  213. gtk_image_set_from_pixbuf (wb->button[MAXIMIZE_BUTTON]->image, wb->pixbufs[IMAGE_UNMAXIMIZE][image_state]);
  214. } else {
  215. gtk_image_set_from_pixbuf (wb->button[MAXIMIZE_BUTTON]->image, wb->pixbufs[IMAGE_MAXIMIZE][image_state]);
  216. }
  217. }
  218. void on_wck_state_changed (WnckWindow *controlwindow, gpointer data)
  219. {
  220. WBPlugin *wb = data;
  221. gushort image_state;
  222. if (controlwindow && (wnck_window_is_active(controlwindow)))
  223. image_state = 1;
  224. else
  225. image_state = 0;
  226. /* update buttons images */
  227. gtk_image_set_from_pixbuf (wb->button[MINIMIZE_BUTTON]->image, wb->pixbufs[IMAGE_MINIMIZE][image_state]);
  228. set_maximize_button_image (wb, image_state);
  229. gtk_image_set_from_pixbuf (wb->button[CLOSE_BUTTON]->image, wb->pixbufs[IMAGE_CLOSE][image_state]);
  230. }
  231. void on_control_window_changed (WnckWindow *controlwindow, WnckWindow *previous, gpointer data)
  232. {
  233. WBPlugin *wb = data;
  234. gint i;
  235. if (!controlwindow
  236. || ((wnck_window_get_window_type (controlwindow) == WNCK_WINDOW_DESKTOP)
  237. && !wb->prefs->show_on_desktop))
  238. {
  239. if (gtk_widget_get_visible(GTK_WIDGET(wb->hvbox)))
  240. gtk_widget_hide_all(GTK_WIDGET(wb->hvbox));
  241. }
  242. else
  243. {
  244. if (!gtk_widget_get_visible(GTK_WIDGET(wb->hvbox)))
  245. gtk_widget_show_all(GTK_WIDGET(wb->hvbox));
  246. }
  247. if (controlwindow)
  248. {
  249. if (wnck_window_get_window_type (controlwindow) != WNCK_WINDOW_DESKTOP)
  250. {
  251. for (i=0; i<BUTTONS; i++)
  252. gtk_widget_set_sensitive(GTK_WIDGET(wb->button[i]->eventbox), TRUE);
  253. on_wck_state_changed (controlwindow, wb);
  254. if (!gtk_widget_get_visible(GTK_WIDGET(wb->hvbox)))
  255. gtk_widget_show_all(GTK_WIDGET(wb->hvbox));
  256. }
  257. else if (wb->prefs->show_on_desktop)
  258. {
  259. gtk_widget_set_sensitive(GTK_WIDGET(wb->button[MINIMIZE_BUTTON]->eventbox), FALSE);
  260. gtk_widget_set_sensitive(GTK_WIDGET(wb->button[MAXIMIZE_BUTTON]->eventbox), FALSE);
  261. gtk_widget_set_sensitive(GTK_WIDGET(wb->button[CLOSE_BUTTON]->eventbox), TRUE);
  262. on_wck_state_changed (controlwindow, wb);
  263. }
  264. }
  265. }
  266. /* Called when we release the click on a button */
  267. static gboolean on_minimize_button_release (GtkWidget *event_box,
  268. GdkEventButton *event,
  269. WBPlugin *wb)
  270. {
  271. if (event->button != 1) return FALSE;
  272. wnck_window_minimize(wb->win->controlwindow);
  273. return TRUE;
  274. }
  275. /* Called when we click on a button */
  276. static gboolean on_minimize_button_pressed (GtkWidget *event_box,
  277. GdkEventButton *event,
  278. WBPlugin *wb)
  279. {
  280. if (event->button != 1) return FALSE;
  281. gtk_image_set_from_pixbuf (wb->button[MINIMIZE_BUTTON]->image, wb->pixbufs[IMAGE_MINIMIZE][IMAGE_PRESSED]);
  282. return TRUE;
  283. }
  284. /* Makes the button stop 'glowing' when the mouse leaves it */
  285. static gboolean on_minimize_button_hover_leave (GtkWidget *widget,
  286. GdkEventCrossing *event,
  287. WBPlugin *wb)
  288. {
  289. gboolean image_state;
  290. image_state = wnck_window_is_active(wb->win->controlwindow);
  291. gtk_image_set_from_pixbuf (wb->button[MINIMIZE_BUTTON]->image, wb->pixbufs[IMAGE_MINIMIZE][image_state]);
  292. return TRUE;
  293. }
  294. /* Makes the button 'glow' when the mouse enters it */
  295. static gboolean on_minimize_button_hover_enter (GtkWidget *widget,
  296. GdkEventCrossing *event,
  297. WBPlugin *wb)
  298. {
  299. gtk_image_set_from_pixbuf (wb->button[MINIMIZE_BUTTON]->image, wb->pixbufs[IMAGE_MINIMIZE][IMAGE_PRELIGHT]);
  300. return TRUE;
  301. }
  302. /* Called when we release the click on a button */
  303. static gboolean on_maximize_button_release (GtkWidget *event_box,
  304. GdkEventButton *event,
  305. WBPlugin *wb)
  306. {
  307. if (event->button != 1) return FALSE;
  308. toggle_maximize(wb->win->controlwindow);
  309. return TRUE;
  310. }
  311. /* Called when we click on a button */
  312. static gboolean on_maximize_button_pressed (GtkWidget *event_box,
  313. GdkEventButton *event,
  314. WBPlugin *wb)
  315. {
  316. if (event->button != 1) return FALSE;
  317. set_maximize_button_image (wb, IMAGE_PRESSED);
  318. return TRUE;
  319. }
  320. /* Makes the button stop 'glowing' when the mouse leaves it */
  321. static gboolean on_maximize_button_hover_leave (GtkWidget *widget,
  322. GdkEventCrossing *event,
  323. WBPlugin *wb)
  324. {
  325. if (wb->win->controlwindow) {
  326. set_maximize_button_image (wb, wnck_window_is_active(wb->win->controlwindow));
  327. }
  328. return TRUE;
  329. }
  330. /* Makes the button 'glow' when the mouse enters it */
  331. static gboolean on_maximize_button_hover_enter (GtkWidget *widget,
  332. GdkEventCrossing *event,
  333. WBPlugin *wb)
  334. {
  335. set_maximize_button_image (wb, IMAGE_PRELIGHT);
  336. return TRUE;
  337. }
  338. /* Called when we release the click on a button */
  339. static gboolean on_close_button_release (GtkWidget *event_box,
  340. GdkEventButton *event,
  341. WBPlugin *wb)
  342. {
  343. if (event->button != 1) return FALSE;
  344. wnck_window_close(wb->win->controlwindow, GDK_CURRENT_TIME);
  345. return TRUE;
  346. }
  347. /* Called when we click on a button */
  348. static gboolean on_close_button_pressed (GtkWidget *event_box,
  349. GdkEventButton *event,
  350. WBPlugin *wb)
  351. {
  352. if (event->button != 1) return FALSE;
  353. gtk_image_set_from_pixbuf (wb->button[CLOSE_BUTTON]->image, wb->pixbufs[IMAGE_CLOSE][IMAGE_PRESSED]);
  354. return TRUE;
  355. }
  356. /* Makes the button stop 'glowing' when the mouse leaves it */
  357. static gboolean on_close_button_hover_leave (GtkWidget *widget,
  358. GdkEventCrossing *event,
  359. WBPlugin *wb)
  360. {
  361. gboolean image_state;
  362. image_state = wnck_window_is_active(wb->win->controlwindow);
  363. gtk_image_set_from_pixbuf (wb->button[CLOSE_BUTTON]->image, wb->pixbufs[IMAGE_CLOSE][image_state]);
  364. return TRUE;
  365. }
  366. /* Makes the button 'glow' when the mouse enters it */
  367. static gboolean on_close_button_hover_enter (GtkWidget *widget,
  368. GdkEventCrossing *event,
  369. WBPlugin *wb)
  370. {
  371. gtk_image_set_from_pixbuf (wb->button[CLOSE_BUTTON]->image, wb->pixbufs[IMAGE_CLOSE][IMAGE_PRELIGHT]);
  372. return TRUE;
  373. }
  374. static void on_refresh_item_activated (GtkMenuItem *refresh, WBPlugin *wb)
  375. {
  376. wckbuttons_read (wb);
  377. init_theme(wb);
  378. reload_wnck (wb->win, wb->prefs->only_maximized, wb);
  379. }
  380. static void
  381. wckbuttons_construct (XfcePanelPlugin *plugin)
  382. {
  383. WBPlugin *wb;
  384. GtkWidget *refresh;
  385. /* setup transation domain */
  386. xfce_textdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8");
  387. /* create the plugin */
  388. wb = wckbuttons_new (plugin);
  389. /* add the ebox to the panel */
  390. gtk_container_add (GTK_CONTAINER (plugin), wb->ebox);
  391. /* show the panel's right-click menu on this ebox */
  392. xfce_panel_plugin_add_action_widget (plugin, wb->ebox);
  393. /* connect plugin signals */
  394. g_signal_connect (G_OBJECT (plugin), "free-data",
  395. G_CALLBACK (wckbuttons_free), wb);
  396. g_signal_connect (G_OBJECT (plugin), "save",
  397. G_CALLBACK (wckbuttons_save), wb);
  398. g_signal_connect (G_OBJECT (plugin), "size-changed",
  399. G_CALLBACK (wckbuttons_size_changed), wb);
  400. g_signal_connect (G_OBJECT (plugin), "orientation-changed",
  401. G_CALLBACK (wckbuttons_orientation_changed), wb);
  402. /* show the configure menu item and connect signal */
  403. xfce_panel_plugin_menu_show_configure (plugin);
  404. g_signal_connect (G_OBJECT (plugin), "configure-plugin",
  405. G_CALLBACK (wckbuttons_configure), wb);
  406. /* show the about menu item and connect signal */
  407. xfce_panel_plugin_menu_show_about (plugin);
  408. g_signal_connect (G_OBJECT (plugin), "about",
  409. G_CALLBACK (wck_about), "wckbuttons-plugin");
  410. /* add custom menu items */
  411. refresh = show_refresh_item (plugin);
  412. g_signal_connect (G_OBJECT (refresh), "activate", G_CALLBACK (on_refresh_item_activated), wb);
  413. /* start tracking windows */
  414. wb->win = g_slice_new0 (WckUtils);
  415. init_wnck(wb->win, wb->prefs->only_maximized, wb);
  416. /* get theme */
  417. init_theme(wb);
  418. /* start tracking buttons events*/
  419. BUTTONS_SIGNALS_CONNECT(on_minimize, MINIMIZE_BUTTON);
  420. BUTTONS_SIGNALS_CONNECT(on_maximize, MAXIMIZE_BUTTON);
  421. BUTTONS_SIGNALS_CONNECT(on_close, CLOSE_BUTTON);
  422. }
  423. /* register the plugin */
  424. XFCE_PANEL_PLUGIN_REGISTER (wckbuttons_construct);