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.
497 lines
16 KiB
497 lines
16 KiB
/* $Id: xfce-tray-plugin.c 26462 2007-12-12 12:00:59Z nick $ */
|
|
/*
|
|
* 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 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 General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU 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
|
|
|
|
#define SMALL_PANEL_SIZE (26)
|
|
|
|
#include <gtk/gtk.h>
|
|
#include <libxfce4util/libxfce4util.h>
|
|
#include <libxfce4panel/libxfce4panel.h>
|
|
|
|
#include "xfce-tray-manager.h"
|
|
#include "xfce-tray-widget.h"
|
|
#include "xfce-tray-plugin.h"
|
|
#include "xfce-tray-dialogs.h"
|
|
|
|
|
|
|
|
/* prototypes */
|
|
static void xfce_tray_plugin_message (GtkMessageType type,
|
|
GdkScreen *screen,
|
|
const gchar *message);
|
|
static gboolean xfce_tray_plugin_check (GdkScreen *screen);
|
|
static void xfce_tray_plugin_update_position (XfceTrayPlugin *plugin);
|
|
static XfceTrayPlugin *xfce_tray_plugin_new (XfcePanelPlugin *panel_plugin);
|
|
static void xfce_tray_plugin_screen_position_changed (XfceTrayPlugin *plugin,
|
|
XfceScreenPosition position);
|
|
static void xfce_tray_plugin_orientation_changed (XfceTrayPlugin *plugin,
|
|
GtkOrientation orientation);
|
|
static gboolean xfce_tray_plugin_size_changed (XfceTrayPlugin *plugin,
|
|
guint size);
|
|
static void xfce_tray_plugin_read (XfceTrayPlugin *plugin);
|
|
static void xfce_tray_plugin_write (XfceTrayPlugin *plugin);
|
|
static void xfce_tray_plugin_free (XfceTrayPlugin *plugin);
|
|
static void xfce_tray_plugin_construct (XfcePanelPlugin *panel_plugin);
|
|
|
|
|
|
|
|
/* register the plugin */
|
|
XFCE_PANEL_PLUGIN_REGISTER_WITH_CHECK (xfce_tray_plugin_construct, xfce_tray_plugin_check);
|
|
|
|
|
|
|
|
static void
|
|
xfce_tray_plugin_message (GtkMessageType type,
|
|
GdkScreen *screen,
|
|
const gchar *message)
|
|
{
|
|
GtkWidget *dialog;
|
|
|
|
/* create a dialog */
|
|
dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, type, GTK_BUTTONS_CLOSE, _("System Tray"));
|
|
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s.", message);
|
|
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
|
|
gtk_window_set_screen (GTK_WINDOW (dialog), screen);
|
|
|
|
/* run the dialog */
|
|
gtk_dialog_run (GTK_DIALOG (dialog));
|
|
|
|
/* destroy */
|
|
gtk_widget_destroy (dialog);
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
xfce_tray_plugin_check (GdkScreen *screen)
|
|
{
|
|
gboolean running;
|
|
|
|
|
|
/* check if there is already a tray running */
|
|
running = xfce_tray_manager_check_running (screen);
|
|
|
|
/* message */
|
|
if (running)
|
|
{
|
|
xfce_tray_plugin_message (GTK_MESSAGE_INFO, screen,
|
|
_("There is already a system tray running on this screen"));
|
|
}
|
|
|
|
return (!running);
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
xfce_tray_plugin_update_position (XfceTrayPlugin *plugin)
|
|
{
|
|
XfceScreenPosition position;
|
|
GdkScreen *screen;
|
|
GdkRectangle geom;
|
|
gint mon, x, y;
|
|
GtkArrowType arrow_type;
|
|
|
|
panel_return_if_fail (GTK_WIDGET_REALIZED (plugin->panel_plugin));
|
|
|
|
/* get the plugin position */
|
|
position = xfce_panel_plugin_get_screen_position (plugin->panel_plugin);
|
|
|
|
/* get the button position */
|
|
switch (position)
|
|
{
|
|
/* horizontal west */
|
|
case XFCE_SCREEN_POSITION_NW_H:
|
|
case XFCE_SCREEN_POSITION_SW_H:
|
|
arrow_type = GTK_ARROW_RIGHT;
|
|
break;
|
|
|
|
/* horizontal east */
|
|
case XFCE_SCREEN_POSITION_N:
|
|
case XFCE_SCREEN_POSITION_NE_H:
|
|
case XFCE_SCREEN_POSITION_S:
|
|
case XFCE_SCREEN_POSITION_SE_H:
|
|
arrow_type = GTK_ARROW_LEFT;
|
|
break;
|
|
|
|
/* vertical north */
|
|
case XFCE_SCREEN_POSITION_NW_V:
|
|
case XFCE_SCREEN_POSITION_NE_V:
|
|
arrow_type = GTK_ARROW_DOWN;
|
|
break;
|
|
|
|
/* vertical south */
|
|
case XFCE_SCREEN_POSITION_W:
|
|
case XFCE_SCREEN_POSITION_SW_V:
|
|
case XFCE_SCREEN_POSITION_E:
|
|
case XFCE_SCREEN_POSITION_SE_V:
|
|
arrow_type = GTK_ARROW_UP;
|
|
break;
|
|
|
|
/* floating */
|
|
default:
|
|
/* get the screen information */
|
|
screen = gtk_widget_get_screen (GTK_WIDGET (plugin->panel_plugin));
|
|
mon = gdk_screen_get_monitor_at_window (screen, GTK_WIDGET (plugin->panel_plugin)->window);
|
|
gdk_screen_get_monitor_geometry (screen, mon, &geom);
|
|
gdk_window_get_root_origin (GTK_WIDGET (plugin->panel_plugin)->window, &x, &y);
|
|
|
|
/* get the position based on the screen position */
|
|
if (position == XFCE_SCREEN_POSITION_FLOATING_H)
|
|
arrow_type = ((x < (geom.x + geom.width / 2)) ? GTK_ARROW_RIGHT : GTK_ARROW_LEFT);
|
|
else
|
|
arrow_type = ((y < (geom.y + geom.height / 2)) ? GTK_ARROW_DOWN : GTK_ARROW_UP);
|
|
break;
|
|
}
|
|
|
|
/* set the arrow type of the tray widget */
|
|
xfce_tray_widget_set_arrow_type (XFCE_TRAY_WIDGET (plugin->tray), arrow_type);
|
|
|
|
/* update the manager orientation */
|
|
xfce_tray_manager_set_orientation (plugin->manager, xfce_screen_position_get_orientation (position));
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
xfce_tray_plugin_icon_added (XfceTrayManager *manager,
|
|
GtkWidget *icon,
|
|
XfceTrayPlugin *plugin)
|
|
{
|
|
gchar *name;
|
|
|
|
/* get the application name */
|
|
name = xfce_tray_manager_get_application_name (icon);
|
|
|
|
/* add the icon to the widget */
|
|
xfce_tray_widget_add_with_name (XFCE_TRAY_WIDGET (plugin->tray), icon, name);
|
|
|
|
/* cleanup */
|
|
g_free (name);
|
|
|
|
/* show icon */
|
|
gtk_widget_show (icon);
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
xfce_tray_plugin_icon_removed (XfceTrayManager *manager,
|
|
GtkWidget *icon,
|
|
XfceTrayPlugin *plugin)
|
|
{
|
|
/* remove from the tray */
|
|
gtk_container_remove (GTK_CONTAINER (plugin->tray), icon);
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
xfce_tray_plugin_lost_selection (XfceTrayManager *manager,
|
|
XfceTrayPlugin *plugin)
|
|
{
|
|
GdkScreen *screen;
|
|
|
|
/* get screen */
|
|
screen = gtk_widget_get_screen (GTK_WIDGET (plugin->panel_plugin));
|
|
|
|
/* message */
|
|
xfce_tray_plugin_message (GTK_MESSAGE_WARNING, screen, _("The tray manager lost selection"));
|
|
}
|
|
|
|
|
|
|
|
static XfceTrayPlugin *
|
|
xfce_tray_plugin_new (XfcePanelPlugin *panel_plugin)
|
|
{
|
|
XfceTrayPlugin *plugin;
|
|
gboolean result;
|
|
GError *error = NULL;
|
|
GdkScreen *screen;
|
|
|
|
/* create structure */
|
|
plugin = g_slice_new0 (XfceTrayPlugin);
|
|
|
|
/* set some data */
|
|
plugin->panel_plugin = panel_plugin;
|
|
plugin->manager = NULL;
|
|
plugin->show_frame = TRUE;
|
|
|
|
/* create the frame */
|
|
plugin->frame = gtk_frame_new (NULL);
|
|
gtk_container_add (GTK_CONTAINER (panel_plugin), plugin->frame);
|
|
gtk_widget_show (plugin->frame);
|
|
|
|
/* create tray widget */
|
|
plugin->tray = xfce_tray_widget_new ();
|
|
gtk_container_add (GTK_CONTAINER (plugin->frame), plugin->tray);
|
|
gtk_widget_show (plugin->tray);
|
|
|
|
/* create a tray manager */
|
|
plugin->manager = xfce_tray_manager_new ();
|
|
|
|
/* read the plugin settings */
|
|
xfce_tray_plugin_read (plugin);
|
|
|
|
/* set frame shadow */
|
|
gtk_frame_set_shadow_type (GTK_FRAME (plugin->frame), plugin->show_frame ? GTK_SHADOW_IN : GTK_SHADOW_NONE);
|
|
|
|
/* get screen */
|
|
screen = gtk_widget_get_screen (GTK_WIDGET (panel_plugin));
|
|
|
|
/* register the tray */
|
|
result = xfce_tray_manager_register (plugin->manager, screen, &error);
|
|
|
|
/* check for problems */
|
|
if (G_LIKELY (result == TRUE))
|
|
{
|
|
/* connect signals */
|
|
g_signal_connect (G_OBJECT (plugin->manager), "tray-icon-added", G_CALLBACK (xfce_tray_plugin_icon_added), plugin);
|
|
g_signal_connect (G_OBJECT (plugin->manager), "tray-icon-removed", G_CALLBACK (xfce_tray_plugin_icon_removed), plugin);
|
|
g_signal_connect (G_OBJECT (plugin->manager), "tray-lost-selection", G_CALLBACK (xfce_tray_plugin_lost_selection), plugin);
|
|
|
|
/* update the plugin position */
|
|
xfce_tray_plugin_update_position (plugin);
|
|
}
|
|
else
|
|
{
|
|
/* show error */
|
|
xfce_tray_plugin_message (GTK_MESSAGE_ERROR, screen, error->message);
|
|
|
|
/* free error */
|
|
g_error_free (error);
|
|
}
|
|
|
|
return plugin;
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
xfce_tray_plugin_screen_position_changed (XfceTrayPlugin *plugin,
|
|
XfceScreenPosition position)
|
|
{
|
|
/* update the plugin position */
|
|
xfce_tray_plugin_update_position (plugin);
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
xfce_tray_plugin_orientation_changed (XfceTrayPlugin *plugin,
|
|
GtkOrientation orientation)
|
|
{
|
|
/* update the plugin position */
|
|
xfce_tray_plugin_update_position (plugin);
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
xfce_tray_plugin_size_changed (XfceTrayPlugin *plugin,
|
|
guint size)
|
|
{
|
|
/* set the border sizes */
|
|
gtk_container_set_border_width (GTK_CONTAINER (plugin->frame), (size > SMALL_PANEL_SIZE && plugin->show_frame) ? 1 : 0);
|
|
gtk_container_set_border_width (GTK_CONTAINER (plugin->tray), plugin->show_frame ? 1 : 0);
|
|
|
|
/* we handled the size of the plugin */
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
xfce_tray_plugin_read (XfceTrayPlugin *plugin)
|
|
{
|
|
gchar *file;
|
|
gchar **names;
|
|
gboolean hidden;
|
|
XfceRc *rc;
|
|
guint i;
|
|
|
|
/* get rc file name */
|
|
file = xfce_panel_plugin_lookup_rc_file (plugin->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))
|
|
{
|
|
/* save global plugin settings */
|
|
xfce_rc_set_group (rc, "Global");
|
|
|
|
/* frame setting */
|
|
plugin->show_frame = xfce_rc_read_bool_entry (rc, "ShowFrame", TRUE);
|
|
|
|
/* set number of rows */
|
|
xfce_tray_widget_set_rows (XFCE_TRAY_WIDGET (plugin->tray), xfce_rc_read_int_entry (rc, "Rows", 1));
|
|
|
|
if (G_LIKELY (plugin->manager))
|
|
{
|
|
/* list of known applications */
|
|
names = xfce_rc_get_entries (rc, "Applications");
|
|
|
|
if (G_LIKELY (names))
|
|
{
|
|
/* set the group */
|
|
xfce_rc_set_group (rc, "Applications");
|
|
|
|
/* read their visibility */
|
|
for (i = 0; names[i] != NULL; i++)
|
|
{
|
|
/* whether the application is hidden */
|
|
hidden = xfce_rc_read_bool_entry (rc, names[i], FALSE);
|
|
|
|
/* add the application name */
|
|
xfce_tray_widget_name_add (XFCE_TRAY_WIDGET (plugin->tray), names[i], hidden);
|
|
}
|
|
|
|
/* cleanup */
|
|
g_strfreev (names);
|
|
}
|
|
}
|
|
|
|
/* close the rc file */
|
|
xfce_rc_close (rc);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
xfce_tray_plugin_write (XfceTrayPlugin *plugin)
|
|
{
|
|
gchar *file;
|
|
GList *names, *li;
|
|
XfceRc *rc;
|
|
const gchar *name;
|
|
gboolean hidden;
|
|
|
|
/* get rc file name, create it if needed */
|
|
file = xfce_panel_plugin_save_location (plugin->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))
|
|
{
|
|
/* save global plugin settings */
|
|
xfce_rc_set_group (rc, "Global");
|
|
|
|
/* write setting */
|
|
xfce_rc_write_bool_entry (rc, "ShowFrame", plugin->show_frame);
|
|
xfce_rc_write_int_entry (rc, "Rows", xfce_tray_widget_get_rows (XFCE_TRAY_WIDGET (plugin->tray)));
|
|
|
|
if (G_LIKELY (plugin->manager))
|
|
{
|
|
/* get the list of known applications */
|
|
names = xfce_tray_widget_name_list (XFCE_TRAY_WIDGET (plugin->tray));
|
|
|
|
if (names == NULL)
|
|
{
|
|
/* delete group */
|
|
if (xfce_rc_has_group (rc, "Applications"))
|
|
xfce_rc_delete_group (rc, "Applications", FALSE);
|
|
}
|
|
else
|
|
{
|
|
/* save the list of known applications and their visibility */
|
|
xfce_rc_set_group (rc, "Applications");
|
|
|
|
/* save their state */
|
|
for (li = names; li != NULL; li = li->next)
|
|
{
|
|
/* get name and status */
|
|
name = li->data;
|
|
hidden = xfce_tray_widget_name_hidden (XFCE_TRAY_WIDGET (plugin->tray), name);
|
|
|
|
/* write entry */
|
|
xfce_rc_write_bool_entry (rc, name, hidden);
|
|
}
|
|
|
|
/* cleanup */
|
|
g_list_free (names);
|
|
}
|
|
}
|
|
|
|
/* close the rc file */
|
|
xfce_rc_close (rc);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
xfce_tray_plugin_free (XfceTrayPlugin *plugin)
|
|
{
|
|
/* unregister manager */
|
|
xfce_tray_manager_unregister (plugin->manager);
|
|
|
|
/* release */
|
|
g_object_unref (G_OBJECT (plugin->manager));
|
|
|
|
/* free slice */
|
|
g_slice_free (XfceTrayPlugin, plugin);
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
xfce_tray_plugin_construct (XfcePanelPlugin *panel_plugin)
|
|
{
|
|
XfceTrayPlugin *plugin;
|
|
|
|
/* create the tray panel plugin */
|
|
plugin = xfce_tray_plugin_new (panel_plugin);
|
|
|
|
/* set the action widgets and show configure */
|
|
xfce_panel_plugin_add_action_widget (panel_plugin, plugin->frame);
|
|
xfce_panel_plugin_add_action_widget (panel_plugin, plugin->tray);
|
|
xfce_panel_plugin_menu_show_configure (panel_plugin);
|
|
|
|
/* connect signals */
|
|
g_signal_connect_swapped (G_OBJECT (panel_plugin), "screen-position-changed",
|
|
G_CALLBACK (xfce_tray_plugin_screen_position_changed), plugin);
|
|
g_signal_connect_swapped (G_OBJECT (panel_plugin), "orientation-changed",
|
|
G_CALLBACK (xfce_tray_plugin_orientation_changed), plugin);
|
|
g_signal_connect_swapped (G_OBJECT (panel_plugin), "size-changed",
|
|
G_CALLBACK (xfce_tray_plugin_size_changed), plugin);
|
|
g_signal_connect_swapped (G_OBJECT (panel_plugin), "save",
|
|
G_CALLBACK (xfce_tray_plugin_write), plugin);
|
|
g_signal_connect_swapped (G_OBJECT (panel_plugin), "free-data",
|
|
G_CALLBACK (xfce_tray_plugin_free), plugin);
|
|
g_signal_connect_swapped (G_OBJECT (panel_plugin), "configure-plugin",
|
|
G_CALLBACK (xfce_tray_dialogs_configure), plugin);
|
|
}
|
|
|