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

/* $Id$
*
* Copyright (c) 2005-2007 Jasper Huijsmans <jasper@xfce.org>
* Copyright (c) 2007 Nick Schermer <nick@xfce.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include <libwnck/libwnck.h>
#include <libxfce4util/libxfce4util.h>
#include <libxfce4panel/xfce-hvbox.h>
#include "tasklist.h"
#include "tasklist-dialogs.h"
#define TASKLIST_HANDLE_SIZE (8)
/* prototypes */
static gboolean tasklist_handle_exposed (GtkWidget *widget,
GdkEventExpose *event,
TasklistPlugin *tasklist);
static GdkPixbuf *tasklist_icon_loader (const gchar *name,
gint size,
guint flags,
TasklistPlugin *tasklist);
static TasklistPlugin *tasklist_plugin_new (XfcePanelPlugin *panel_plugin);
static void tasklist_plugin_screen_changed (TasklistPlugin *tasklist,
GdkScreen *previous_screen);
static void tasklist_plugin_orientation_changed (TasklistPlugin *tasklist,
GtkOrientation orientation);
static gboolean tasklist_plugin_size_changed (TasklistPlugin *tasklist,
guint size);
static void tasklist_plugin_size_request (TasklistPlugin *tasklist,
GtkRequisition *requisition);
static void tasklist_plugin_read (TasklistPlugin *tasklist);
static void tasklist_plugin_free (TasklistPlugin *tasklist);
static void tasklist_plugin_construct (XfcePanelPlugin *panel_plugin);
/* register with the panel */
XFCE_PANEL_PLUGIN_REGISTER_INTERNAL (tasklist_plugin_construct);
gboolean
tasklist_using_xinerama (XfcePanelPlugin *panel_plugin)
{
return (gdk_screen_get_n_monitors (gtk_widget_get_screen (GTK_WIDGET (panel_plugin))) > 1);
}
static gboolean
tasklist_handle_exposed (GtkWidget *widget,
GdkEventExpose *event,
TasklistPlugin *tasklist)
{
GtkOrientation orientation;
gint x, y, w, h;
if (GTK_WIDGET_DRAWABLE (widget))
{
/* get the panel orientation */
orientation = xfce_panel_plugin_get_orientation (tasklist->panel_plugin);
/* set sizes */
x = widget->allocation.x;
y = widget->allocation.y;
w = widget->allocation.width;
h = widget->allocation.height;
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
y += widget->style->ythickness;
h -= 2 * widget->style->ythickness;
}
else
{
x += widget->style->xthickness;
w -= 2 * widget->style->xthickness;
}
gtk_paint_handle (widget->style, widget->window,
GTK_WIDGET_STATE (widget), GTK_SHADOW_NONE,
&(event->area), widget, "handlebox",
x, y, w, h,
orientation == GTK_ORIENTATION_HORIZONTAL ?
GTK_ORIENTATION_VERTICAL :
GTK_ORIENTATION_HORIZONTAL);
return TRUE;
}
return FALSE;
}
static GdkPixbuf *
tasklist_icon_loader (const gchar *name,
gint size,
guint flags,
TasklistPlugin *tasklist)
{
GdkPixbuf *pixbuf = NULL;
gchar *base = NULL;
const gchar *p;
/* do nothing on invalid names */
if (G_UNLIKELY (name == NULL || *name == '\0'))
return NULL;
if (g_path_is_absolute (name))
{
if (g_file_test (name, G_FILE_TEST_EXISTS))
{
/* directly load the file */
pixbuf = gdk_pixbuf_new_from_file_at_size (name, size, size, NULL);
}
else
{
/* get the base name */
base = g_path_get_basename (name);
/* use this function to try again */
pixbuf = tasklist_icon_loader (base, size, flags, tasklist);
/* cleanup */
g_free (base);
}
}
else
{
/* strip prefix */
p = strrchr (name, '.');
if (G_UNLIKELY (p))
base = g_strndup (name, p - name);
/* load the icon */
pixbuf = gtk_icon_theme_load_icon (tasklist->icon_theme, base ? base : name, size, 0, NULL);
/* cleanup */
g_free (base);
}
return pixbuf;
}
static TasklistPlugin *
tasklist_plugin_new (XfcePanelPlugin *panel_plugin)
{
TasklistPlugin *tasklist;
GdkScreen *screen;
gint screen_n;
/* allocate structure */
tasklist = panel_slice_new0 (TasklistPlugin);
/* init data */
tasklist->panel_plugin = panel_plugin;
/* read settings */
tasklist_plugin_read (tasklist);
/* create hvbox */
tasklist->box = xfce_hvbox_new (xfce_panel_plugin_get_orientation (panel_plugin), FALSE, 0);
gtk_container_add (GTK_CONTAINER (panel_plugin), tasklist->box);
gtk_widget_show (tasklist->box);
/* create handle */
tasklist->handle = gtk_alignment_new (0.0, 0.0, 0.0, 0.0);
gtk_widget_set_size_request (tasklist->handle, TASKLIST_HANDLE_SIZE, TASKLIST_HANDLE_SIZE);
gtk_box_pack_start (GTK_BOX (tasklist->box), tasklist->handle, FALSE, FALSE, 0);
g_signal_connect (tasklist->handle, "expose-event", G_CALLBACK (tasklist_handle_exposed), tasklist);
if (tasklist->show_handles)
gtk_widget_show (tasklist->handle);
/* get the current screen number */
screen = gtk_widget_get_screen (GTK_WIDGET (panel_plugin));
screen_n = gdk_screen_get_number (screen);
/* set the icon theme */
tasklist->icon_theme = gtk_icon_theme_get_for_screen (screen);
/* create tasklist */
tasklist->list = wnck_tasklist_new (wnck_screen_get (screen_n));
gtk_box_pack_start (GTK_BOX (tasklist->box), tasklist->list, FALSE, FALSE, 0);
gtk_widget_show (tasklist->list);
/* set the tasklist settings */
wnck_tasklist_set_include_all_workspaces (WNCK_TASKLIST (tasklist->list), tasklist->all_workspaces);
wnck_tasklist_set_grouping (WNCK_TASKLIST (tasklist->list), tasklist->grouping);
wnck_tasklist_set_button_relief (WNCK_TASKLIST (tasklist->list), tasklist->flat_buttons ? GTK_RELIEF_NONE : GTK_RELIEF_NORMAL);
wnck_tasklist_set_icon_loader (WNCK_TASKLIST (tasklist->list), (WnckLoadIconFunction) tasklist_icon_loader, tasklist, NULL);
return tasklist;
}
static void
tasklist_plugin_screen_changed (TasklistPlugin *tasklist,
GdkScreen *previous_screen)
{
GdkScreen *screen;
WnckScreen *wnck_screen;
/* get the new screen */
screen = gtk_widget_get_screen (GTK_WIDGET (tasklist->panel_plugin));
if (G_UNLIKELY (screen == NULL))
screen = gdk_screen_get_default ();
/* get the wnck screen */
wnck_screen = wnck_screen_get (gdk_screen_get_number (screen));
/* set the new tasklist screen */
wnck_tasklist_set_screen (WNCK_TASKLIST (tasklist->list), wnck_screen);
/* set the icon theme */
tasklist->icon_theme = gtk_icon_theme_get_for_screen (screen);
}
static void
tasklist_plugin_orientation_changed (TasklistPlugin *tasklist,
GtkOrientation orientation)
{
/* set the new orientation of the hvbox */
xfce_hvbox_set_orientation (XFCE_HVBOX (tasklist->box), orientation);
/* redraw the handle */
gtk_widget_queue_draw (tasklist->handle);
}
gboolean
tasklist_plugin_size_changed (TasklistPlugin *tasklist,
guint size)
{
/* size is handled in the size_request function */
return TRUE;
}
static void
tasklist_plugin_size_request (TasklistPlugin *tasklist,
GtkRequisition *requisition)
{
const gint *size_hints;
gint length;
gint size;
GtkOrientation orientation;
/* get the size hints */
size_hints = wnck_tasklist_get_size_hint_list (WNCK_TASKLIST (tasklist->list), &length);
/* check for pairs of 2 */
if (G_LIKELY (length > 0))
{
/* get the first size */
size = size_hints[0];
/* add the handle size */
if (tasklist->show_handles)
size += TASKLIST_HANDLE_SIZE;
/* use the requested size when it is bigger then the prefered size */
if (tasklist->width > size)
size = tasklist->width;
/* get plugin orientation */
orientation = xfce_panel_plugin_get_orientation (tasklist->panel_plugin);
/* set the panel size */
requisition->width = requisition->height = xfce_panel_plugin_get_size (tasklist->panel_plugin);
/* set the requested plugin size */
if (orientation == GTK_ORIENTATION_HORIZONTAL)
requisition->width = size;
else
requisition->height = size;
/* save the requested size */
tasklist->req_size = size;
}
}
static void
tasklist_plugin_size_allocate (TasklistPlugin *tasklist,
GtkAllocation *allocation)
{
GtkOrientation orientation;
gint a_size, p_size;
/* get orientation */
orientation = xfce_panel_plugin_get_orientation (tasklist->panel_plugin);
/* get plugin size */
p_size = xfce_panel_plugin_get_size (tasklist->panel_plugin);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
a_size = MIN (tasklist->req_size, allocation->width);
else
a_size = MIN (tasklist->req_size, allocation->height);
if (tasklist->show_handles)
a_size -= TASKLIST_HANDLE_SIZE;
/* force the size request of the taskbar */
if (orientation == GTK_ORIENTATION_HORIZONTAL)
gtk_widget_set_size_request (GTK_WIDGET (tasklist->list), a_size, p_size);
else
gtk_widget_set_size_request (GTK_WIDGET (tasklist->list), p_size, a_size);
}
static void
tasklist_plugin_read (TasklistPlugin *tasklist)
{
gchar *file;
XfceRc *rc;
/* set defaults */
tasklist->grouping = WNCK_TASKLIST_AUTO_GROUP;
tasklist->all_workspaces = FALSE;
tasklist->expand = TRUE;
tasklist->flat_buttons = TRUE;
tasklist->show_handles = TRUE;
tasklist->width = 300;
/* get rc file name */
file = xfce_panel_plugin_lookup_rc_file (tasklist->panel_plugin);
if (G_LIKELY (file))
{
/* open the file, readonly */
rc = xfce_rc_simple_open (file, TRUE);
/* cleanup */
g_free (file);
if (G_LIKELY (rc))
{
/* read settings */
tasklist->grouping = xfce_rc_read_int_entry (rc, "grouping", tasklist->grouping);
tasklist->all_workspaces = xfce_rc_read_bool_entry (rc, "all_workspaces", tasklist->all_workspaces);
tasklist->flat_buttons = xfce_rc_read_bool_entry (rc, "flat_buttons", tasklist->flat_buttons);
tasklist->show_handles = xfce_rc_read_bool_entry (rc, "show_handles", tasklist->show_handles);
tasklist->width = xfce_rc_read_int_entry (rc, "width",tasklist->width);
/* only set expand flag if xinerama is used */
if (tasklist_using_xinerama (tasklist->panel_plugin))
tasklist->expand = xfce_rc_read_bool_entry (rc, "expand", tasklist->expand);
/* close the rc file */
xfce_rc_close (rc);
}
}
}
void
tasklist_plugin_write (TasklistPlugin *tasklist)
{
gchar *file;
XfceRc *rc;
/* get rc file name, create it if needed */
file = xfce_panel_plugin_save_location (tasklist->panel_plugin, TRUE);
if (G_LIKELY (file))
{
/* open the file, writable */
rc = xfce_rc_simple_open (file, FALSE);
/* cleanup */
g_free (file);
if (G_LIKELY (rc))
{
/* write settings */
xfce_rc_write_int_entry (rc, "grouping", tasklist->grouping);
xfce_rc_write_int_entry (rc, "width", tasklist->width);
xfce_rc_write_bool_entry (rc, "all_workspaces", tasklist->all_workspaces);
xfce_rc_write_bool_entry (rc, "expand", tasklist->expand);
xfce_rc_write_bool_entry (rc, "flat_buttons", tasklist->flat_buttons);
xfce_rc_write_bool_entry (rc, "show_handles", tasklist->show_handles);
/* close the rc file */
xfce_rc_close (rc);
}
}
}
static void
tasklist_plugin_free (TasklistPlugin *tasklist)
{
GtkWidget *dialog;
/* destroy the dialog */
dialog = g_object_get_data (G_OBJECT (tasklist->panel_plugin), I_("dialog"));
if (dialog)
gtk_widget_destroy (dialog);
/* disconnect screen changed signal */
g_signal_handler_disconnect (G_OBJECT (tasklist->panel_plugin), tasklist->screen_changed_id);
/* free slice */
panel_slice_free (TasklistPlugin, tasklist);
}
static void
tasklist_plugin_construct (XfcePanelPlugin *panel_plugin)
{
TasklistPlugin *tasklist;
/* create the tray panel plugin */
tasklist = tasklist_plugin_new (panel_plugin);
/* set the action widgets and show configure */
xfce_panel_plugin_add_action_widget (panel_plugin, tasklist->handle);
xfce_panel_plugin_menu_show_configure (panel_plugin);
/* whether to expand the plugin */
xfce_panel_plugin_set_expand (panel_plugin, tasklist->expand);
/* connect plugin signals */
g_signal_connect_swapped (G_OBJECT (panel_plugin), "orientation-changed",
G_CALLBACK (tasklist_plugin_orientation_changed), tasklist);
g_signal_connect_swapped (G_OBJECT (panel_plugin), "size-changed",
G_CALLBACK (tasklist_plugin_size_changed), tasklist);
g_signal_connect_swapped (G_OBJECT (panel_plugin), "size-request",
G_CALLBACK (tasklist_plugin_size_request), tasklist);
g_signal_connect_swapped (G_OBJECT (panel_plugin), "size-allocate",
G_CALLBACK (tasklist_plugin_size_allocate), tasklist);
g_signal_connect_swapped (G_OBJECT (panel_plugin), "save",
G_CALLBACK (tasklist_plugin_write), tasklist);
g_signal_connect_swapped (G_OBJECT (panel_plugin), "free-data",
G_CALLBACK (tasklist_plugin_free), tasklist);
g_signal_connect_swapped (G_OBJECT (panel_plugin), "configure-plugin",
G_CALLBACK (tasklist_dialogs_configure), tasklist);
/* screen changed signal */
tasklist->screen_changed_id =
g_signal_connect_swapped (G_OBJECT (panel_plugin), "screen-changed",
G_CALLBACK (tasklist_plugin_screen_changed), tasklist);
}