You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

481 lines
16 KiB

  1. /* $Id$
  2. *
  3. * Copyright (c) 2005-2007 Jasper Huijsmans <jasper@xfce.org>
  4. * Copyright (c) 2007 Nick Schermer <nick@xfce.org>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU Library General Public License as published
  8. * by the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Library General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Library General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  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 <libwnck/libwnck.h>
  27. #include <libxfce4util/libxfce4util.h>
  28. #include <libxfce4panel/xfce-hvbox.h>
  29. #include "tasklist.h"
  30. #include "tasklist-dialogs.h"
  31. #define TASKLIST_HANDLE_SIZE (8)
  32. /* prototypes */
  33. static gboolean tasklist_handle_exposed (GtkWidget *widget,
  34. GdkEventExpose *event,
  35. TasklistPlugin *tasklist);
  36. static GdkPixbuf *tasklist_icon_loader (const gchar *name,
  37. gint size,
  38. guint flags,
  39. TasklistPlugin *tasklist);
  40. static TasklistPlugin *tasklist_plugin_new (XfcePanelPlugin *panel_plugin);
  41. static void tasklist_plugin_screen_changed (TasklistPlugin *tasklist,
  42. GdkScreen *previous_screen);
  43. static void tasklist_plugin_orientation_changed (TasklistPlugin *tasklist,
  44. GtkOrientation orientation);
  45. static gboolean tasklist_plugin_size_changed (TasklistPlugin *tasklist,
  46. guint size);
  47. static void tasklist_plugin_size_request (TasklistPlugin *tasklist,
  48. GtkRequisition *requisition);
  49. static void tasklist_plugin_read (TasklistPlugin *tasklist);
  50. static void tasklist_plugin_free (TasklistPlugin *tasklist);
  51. static void tasklist_plugin_construct (XfcePanelPlugin *panel_plugin);
  52. /* register with the panel */
  53. XFCE_PANEL_PLUGIN_REGISTER_INTERNAL (tasklist_plugin_construct);
  54. gboolean
  55. tasklist_using_xinerama (XfcePanelPlugin *panel_plugin)
  56. {
  57. return (gdk_screen_get_n_monitors (gtk_widget_get_screen (GTK_WIDGET (panel_plugin))) > 1);
  58. }
  59. static gboolean
  60. tasklist_handle_exposed (GtkWidget *widget,
  61. GdkEventExpose *event,
  62. TasklistPlugin *tasklist)
  63. {
  64. GtkOrientation orientation;
  65. gint x, y, w, h;
  66. if (GTK_WIDGET_DRAWABLE (widget))
  67. {
  68. /* get the panel orientation */
  69. orientation = xfce_panel_plugin_get_orientation (tasklist->panel_plugin);
  70. /* set sizes */
  71. x = widget->allocation.x;
  72. y = widget->allocation.y;
  73. w = widget->allocation.width;
  74. h = widget->allocation.height;
  75. if (orientation == GTK_ORIENTATION_HORIZONTAL)
  76. {
  77. y += widget->style->ythickness;
  78. h -= 2 * widget->style->ythickness;
  79. }
  80. else
  81. {
  82. x += widget->style->xthickness;
  83. w -= 2 * widget->style->xthickness;
  84. }
  85. gtk_paint_handle (widget->style, widget->window,
  86. GTK_WIDGET_STATE (widget), GTK_SHADOW_NONE,
  87. &(event->area), widget, "handlebox",
  88. x, y, w, h,
  89. orientation == GTK_ORIENTATION_HORIZONTAL ?
  90. GTK_ORIENTATION_VERTICAL :
  91. GTK_ORIENTATION_HORIZONTAL);
  92. return TRUE;
  93. }
  94. return FALSE;
  95. }
  96. static GdkPixbuf *
  97. tasklist_icon_loader (const gchar *name,
  98. gint size,
  99. guint flags,
  100. TasklistPlugin *tasklist)
  101. {
  102. GdkPixbuf *pixbuf = NULL;
  103. gchar *base = NULL;
  104. const gchar *p;
  105. /* do nothing on invalid names */
  106. if (G_UNLIKELY (name == NULL || *name == '\0'))
  107. return NULL;
  108. if (g_path_is_absolute (name))
  109. {
  110. if (g_file_test (name, G_FILE_TEST_EXISTS))
  111. {
  112. /* directly load the file */
  113. pixbuf = gdk_pixbuf_new_from_file_at_size (name, size, size, NULL);
  114. }
  115. else
  116. {
  117. /* get the base name */
  118. base = g_path_get_basename (name);
  119. /* use this function to try again */
  120. pixbuf = tasklist_icon_loader (base, size, flags, tasklist);
  121. /* cleanup */
  122. g_free (base);
  123. }
  124. }
  125. else
  126. {
  127. /* strip prefix */
  128. p = strrchr (name, '.');
  129. if (G_UNLIKELY (p))
  130. base = g_strndup (name, p - name);
  131. /* load the icon */
  132. pixbuf = gtk_icon_theme_load_icon (tasklist->icon_theme, base ? base : name, size, 0, NULL);
  133. /* cleanup */
  134. g_free (base);
  135. }
  136. return pixbuf;
  137. }
  138. static TasklistPlugin *
  139. tasklist_plugin_new (XfcePanelPlugin *panel_plugin)
  140. {
  141. TasklistPlugin *tasklist;
  142. GdkScreen *screen;
  143. gint screen_n;
  144. /* allocate structure */
  145. tasklist = panel_slice_new0 (TasklistPlugin);
  146. /* init data */
  147. tasklist->panel_plugin = panel_plugin;
  148. /* read settings */
  149. tasklist_plugin_read (tasklist);
  150. /* create hvbox */
  151. tasklist->box = xfce_hvbox_new (xfce_panel_plugin_get_orientation (panel_plugin), FALSE, 0);
  152. gtk_container_add (GTK_CONTAINER (panel_plugin), tasklist->box);
  153. gtk_widget_show (tasklist->box);
  154. /* create handle */
  155. tasklist->handle = gtk_alignment_new (0.0, 0.0, 0.0, 0.0);
  156. gtk_widget_set_size_request (tasklist->handle, TASKLIST_HANDLE_SIZE, TASKLIST_HANDLE_SIZE);
  157. gtk_box_pack_start (GTK_BOX (tasklist->box), tasklist->handle, FALSE, FALSE, 0);
  158. g_signal_connect (tasklist->handle, "expose-event", G_CALLBACK (tasklist_handle_exposed), tasklist);
  159. if (tasklist->show_handles)
  160. gtk_widget_show (tasklist->handle);
  161. /* get the current screen number */
  162. screen = gtk_widget_get_screen (GTK_WIDGET (panel_plugin));
  163. screen_n = gdk_screen_get_number (screen);
  164. /* set the icon theme */
  165. tasklist->icon_theme = gtk_icon_theme_get_for_screen (screen);
  166. /* create tasklist */
  167. tasklist->list = wnck_tasklist_new (wnck_screen_get (screen_n));
  168. gtk_box_pack_start (GTK_BOX (tasklist->box), tasklist->list, FALSE, FALSE, 0);
  169. gtk_widget_show (tasklist->list);
  170. /* set the tasklist settings */
  171. wnck_tasklist_set_include_all_workspaces (WNCK_TASKLIST (tasklist->list), tasklist->all_workspaces);
  172. wnck_tasklist_set_grouping (WNCK_TASKLIST (tasklist->list), tasklist->grouping);
  173. wnck_tasklist_set_button_relief (WNCK_TASKLIST (tasklist->list), tasklist->flat_buttons ? GTK_RELIEF_NONE : GTK_RELIEF_NORMAL);
  174. wnck_tasklist_set_icon_loader (WNCK_TASKLIST (tasklist->list), (WnckLoadIconFunction) tasklist_icon_loader, tasklist, NULL);
  175. return tasklist;
  176. }
  177. static void
  178. tasklist_plugin_screen_changed (TasklistPlugin *tasklist,
  179. GdkScreen *previous_screen)
  180. {
  181. GdkScreen *screen;
  182. WnckScreen *wnck_screen;
  183. /* get the new screen */
  184. screen = gtk_widget_get_screen (GTK_WIDGET (tasklist->panel_plugin));
  185. if (G_UNLIKELY (screen == NULL))
  186. screen = gdk_screen_get_default ();
  187. /* get the wnck screen */
  188. wnck_screen = wnck_screen_get (gdk_screen_get_number (screen));
  189. /* set the new tasklist screen */
  190. wnck_tasklist_set_screen (WNCK_TASKLIST (tasklist->list), wnck_screen);
  191. /* set the icon theme */
  192. tasklist->icon_theme = gtk_icon_theme_get_for_screen (screen);
  193. }
  194. static void
  195. tasklist_plugin_orientation_changed (TasklistPlugin *tasklist,
  196. GtkOrientation orientation)
  197. {
  198. /* set the new orientation of the hvbox */
  199. xfce_hvbox_set_orientation (XFCE_HVBOX (tasklist->box), orientation);
  200. /* redraw the handle */
  201. gtk_widget_queue_draw (tasklist->handle);
  202. }
  203. gboolean
  204. tasklist_plugin_size_changed (TasklistPlugin *tasklist,
  205. guint size)
  206. {
  207. /* size is handled in the size_request function */
  208. return TRUE;
  209. }
  210. static void
  211. tasklist_plugin_size_request (TasklistPlugin *tasklist,
  212. GtkRequisition *requisition)
  213. {
  214. const gint *size_hints;
  215. gint length;
  216. gint size;
  217. GtkOrientation orientation;
  218. /* get the size hints */
  219. size_hints = wnck_tasklist_get_size_hint_list (WNCK_TASKLIST (tasklist->list), &length);
  220. /* check for pairs of 2 */
  221. if (G_LIKELY (length > 0))
  222. {
  223. /* get the first size */
  224. size = size_hints[0];
  225. /* add the handle size */
  226. if (tasklist->show_handles)
  227. size += TASKLIST_HANDLE_SIZE;
  228. /* use the requested size when it is bigger then the prefered size */
  229. if (tasklist->width > size)
  230. size = tasklist->width;
  231. /* get plugin orientation */
  232. orientation = xfce_panel_plugin_get_orientation (tasklist->panel_plugin);
  233. /* set the panel size */
  234. requisition->width = requisition->height = xfce_panel_plugin_get_size (tasklist->panel_plugin);
  235. /* set the requested plugin size */
  236. if (orientation == GTK_ORIENTATION_HORIZONTAL)
  237. requisition->width = size;
  238. else
  239. requisition->height = size;
  240. /* save the requested size */
  241. tasklist->req_size = size;
  242. }
  243. }
  244. static void
  245. tasklist_plugin_size_allocate (TasklistPlugin *tasklist,
  246. GtkAllocation *allocation)
  247. {
  248. GtkOrientation orientation;
  249. gint a_size, p_size;
  250. /* get orientation */
  251. orientation = xfce_panel_plugin_get_orientation (tasklist->panel_plugin);
  252. /* get plugin size */
  253. p_size = xfce_panel_plugin_get_size (tasklist->panel_plugin);
  254. if (orientation == GTK_ORIENTATION_HORIZONTAL)
  255. a_size = MIN (tasklist->req_size, allocation->width);
  256. else
  257. a_size = MIN (tasklist->req_size, allocation->height);
  258. if (tasklist->show_handles)
  259. a_size -= TASKLIST_HANDLE_SIZE;
  260. /* force the size request of the taskbar */
  261. if (orientation == GTK_ORIENTATION_HORIZONTAL)
  262. gtk_widget_set_size_request (GTK_WIDGET (tasklist->list), a_size, p_size);
  263. else
  264. gtk_widget_set_size_request (GTK_WIDGET (tasklist->list), p_size, a_size);
  265. }
  266. static void
  267. tasklist_plugin_read (TasklistPlugin *tasklist)
  268. {
  269. gchar *file;
  270. XfceRc *rc;
  271. /* set defaults */
  272. tasklist->grouping = WNCK_TASKLIST_AUTO_GROUP;
  273. tasklist->all_workspaces = FALSE;
  274. tasklist->expand = TRUE;
  275. tasklist->flat_buttons = TRUE;
  276. tasklist->show_handles = TRUE;
  277. tasklist->width = 300;
  278. /* get rc file name */
  279. file = xfce_panel_plugin_lookup_rc_file (tasklist->panel_plugin);
  280. if (G_LIKELY (file))
  281. {
  282. /* open the file, readonly */
  283. rc = xfce_rc_simple_open (file, TRUE);
  284. /* cleanup */
  285. g_free (file);
  286. if (G_LIKELY (rc))
  287. {
  288. /* read settings */
  289. tasklist->grouping = xfce_rc_read_int_entry (rc, "grouping", tasklist->grouping);
  290. tasklist->all_workspaces = xfce_rc_read_bool_entry (rc, "all_workspaces", tasklist->all_workspaces);
  291. tasklist->flat_buttons = xfce_rc_read_bool_entry (rc, "flat_buttons", tasklist->flat_buttons);
  292. tasklist->show_handles = xfce_rc_read_bool_entry (rc, "show_handles", tasklist->show_handles);
  293. tasklist->width = xfce_rc_read_int_entry (rc, "width",tasklist->width);
  294. /* only set expand flag if xinerama is used */
  295. if (tasklist_using_xinerama (tasklist->panel_plugin))
  296. tasklist->expand = xfce_rc_read_bool_entry (rc, "expand", tasklist->expand);
  297. /* close the rc file */
  298. xfce_rc_close (rc);
  299. }
  300. }
  301. }
  302. void
  303. tasklist_plugin_write (TasklistPlugin *tasklist)
  304. {
  305. gchar *file;
  306. XfceRc *rc;
  307. /* get rc file name, create it if needed */
  308. file = xfce_panel_plugin_save_location (tasklist->panel_plugin, TRUE);
  309. if (G_LIKELY (file))
  310. {
  311. /* open the file, writable */
  312. rc = xfce_rc_simple_open (file, FALSE);
  313. /* cleanup */
  314. g_free (file);
  315. if (G_LIKELY (rc))
  316. {
  317. /* write settings */
  318. xfce_rc_write_int_entry (rc, "grouping", tasklist->grouping);
  319. xfce_rc_write_int_entry (rc, "width", tasklist->width);
  320. xfce_rc_write_bool_entry (rc, "all_workspaces", tasklist->all_workspaces);
  321. xfce_rc_write_bool_entry (rc, "expand", tasklist->expand);
  322. xfce_rc_write_bool_entry (rc, "flat_buttons", tasklist->flat_buttons);
  323. xfce_rc_write_bool_entry (rc, "show_handles", tasklist->show_handles);
  324. /* close the rc file */
  325. xfce_rc_close (rc);
  326. }
  327. }
  328. }
  329. static void
  330. tasklist_plugin_free (TasklistPlugin *tasklist)
  331. {
  332. GtkWidget *dialog;
  333. /* destroy the dialog */
  334. dialog = g_object_get_data (G_OBJECT (tasklist->panel_plugin), I_("dialog"));
  335. if (dialog)
  336. gtk_widget_destroy (dialog);
  337. /* disconnect screen changed signal */
  338. g_signal_handler_disconnect (G_OBJECT (tasklist->panel_plugin), tasklist->screen_changed_id);
  339. /* free slice */
  340. panel_slice_free (TasklistPlugin, tasklist);
  341. }
  342. static void
  343. tasklist_plugin_construct (XfcePanelPlugin *panel_plugin)
  344. {
  345. TasklistPlugin *tasklist;
  346. /* create the tray panel plugin */
  347. tasklist = tasklist_plugin_new (panel_plugin);
  348. /* set the action widgets and show configure */
  349. xfce_panel_plugin_add_action_widget (panel_plugin, tasklist->handle);
  350. xfce_panel_plugin_menu_show_configure (panel_plugin);
  351. /* whether to expand the plugin */
  352. xfce_panel_plugin_set_expand (panel_plugin, tasklist->expand);
  353. /* connect plugin signals */
  354. g_signal_connect_swapped (G_OBJECT (panel_plugin), "orientation-changed",
  355. G_CALLBACK (tasklist_plugin_orientation_changed), tasklist);
  356. g_signal_connect_swapped (G_OBJECT (panel_plugin), "size-changed",
  357. G_CALLBACK (tasklist_plugin_size_changed), tasklist);
  358. g_signal_connect_swapped (G_OBJECT (panel_plugin), "size-request",
  359. G_CALLBACK (tasklist_plugin_size_request), tasklist);
  360. g_signal_connect_swapped (G_OBJECT (panel_plugin), "size-allocate",
  361. G_CALLBACK (tasklist_plugin_size_allocate), tasklist);
  362. g_signal_connect_swapped (G_OBJECT (panel_plugin), "save",
  363. G_CALLBACK (tasklist_plugin_write), tasklist);
  364. g_signal_connect_swapped (G_OBJECT (panel_plugin), "free-data",
  365. G_CALLBACK (tasklist_plugin_free), tasklist);
  366. g_signal_connect_swapped (G_OBJECT (panel_plugin), "configure-plugin",
  367. G_CALLBACK (tasklist_dialogs_configure), tasklist);
  368. /* screen changed signal */
  369. tasklist->screen_changed_id =
  370. g_signal_connect_swapped (G_OBJECT (panel_plugin), "screen-changed",
  371. G_CALLBACK (tasklist_plugin_screen_changed), tasklist);
  372. }