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.
 
 
 
 

1084 lines
27 KiB

/* $Id$
*
* Copyright (c) 2005 Jasper Huijsmans <jasper@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 Library 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
#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <libxfcegui4/libxfcegui4.h>
#include <libxfce4panel/xfce-panel-macros.h>
#include <libxfce4panel/xfce-panel-convenience.h>
#include "panel-app.h"
#include "panel-app-messages.h"
#include "panel-item-manager.h"
#include "panel-config.h"
#include "panel-properties.h"
#include "panel-dialogs.h"
#include "panel.h"
#ifndef _
#define _(x) x
#endif
#ifndef WAIT_ANY
#define WAIT_ANY (-1)
#endif
#define SELECTION_NAME "XFCE4_PANEL"
#define PANEL_LAUNCHER "launcher"
#define SAVE_TIMEOUT 30000
#define TEST_MULTIPLE_MONITORS FALSE
#if defined(TIMER) && defined(G_HAVE_ISO_VARARGS)
void
xfce_panel_program_log (const gchar *file,
const gint line,
const gchar *format,
...)
{
va_list args;
gchar *formatted;
gchar *message;
va_start (args, format);
formatted = g_strdup_vprintf (format, args);
va_end (args);
message = g_strdup_printf ("MARK: %s: %s:%d: %s",
g_get_prgname(), file, line, formatted);
access (message, F_OK);
g_free (formatted);
g_free (message);
}
#endif
/* types and global variables */
typedef enum
{
PANEL_RUN_STATE_NORMAL,
PANEL_RUN_STATE_RESTART,
PANEL_RUN_STATE_QUIT,
PANEL_RUN_STATE_QUIT_NOCONFIRM,
PANEL_RUN_STATE_QUIT_NOSAVE
}
PanelRunState;
typedef struct _PanelApp PanelApp;
struct _PanelApp
{
GtkWidget *gtk_ipc_window;
Window ipc_window;
SessionClient *session_client;
PanelRunState runstate;
GPtrArray *panel_list;
GPtrArray *monitor_list;
gint save_id;
gint current_panel;
GList *dialogs;
/* Initialization. Also unset before cleanup. */
guint initialized : 1;
/* Check whether monitors in Xinerama are aligned. */
guint xinerama_and_equal_width : 1;
guint xinerama_and_equal_height : 1;
};
static PanelApp panel_app = {0};
static gint signal_pipe[2];
/* cleanup */
static void
cleanup_panels (void)
{
guint i;
GList *l;
Panel *panel;
XfceMonitor *xmon;
if (!panel_app.initialized)
return;
panel_app.initialized = FALSE;
l = panel_app.dialogs;
panel_app.dialogs = NULL;
while (l)
{
gtk_dialog_response (GTK_DIALOG (l->data), GTK_RESPONSE_NONE);
l = g_list_delete_link (l, l);
}
for (i = 0; i < panel_app.panel_list->len; ++i)
{
panel = g_ptr_array_index (panel_app.panel_list, i);
gtk_widget_hide (GTK_WIDGET (panel));
panel_free_data (panel);
gtk_widget_destroy (GTK_WIDGET (panel));
DBG ("Destroyed panel %d", i + 1);
}
g_ptr_array_free (panel_app.panel_list, TRUE);
for (i = 0; i < panel_app.monitor_list->len; ++i)
{
xmon = g_ptr_array_index (panel_app.monitor_list, i);
panel_slice_free (XfceMonitor, xmon);
}
g_ptr_array_free (panel_app.monitor_list, TRUE);
}
/* signal handling */
/** copied from glibc manual, does this prevent zombies? */
static void
sigchld_handler (gint sig)
{
gint pid, status, serrno;
serrno = errno;
while (1)
{
pid = waitpid (WAIT_ANY, &status, WNOHANG);
if (pid < 0 || pid == 0)
break;
}
errno = serrno;
}
static void
sighandler (gint sig)
{
/* Don't do any real stuff here.
* Only write the signal to a pipe. The value will be picked up by a
* g_io_channel watch. This will prevent problems with gtk main loop
* threads and stuff.
*/
if (write (signal_pipe[1], &sig, sizeof (int)) != sizeof (int))
{
g_printerr ("unix signal %d lost\n", sig);
}
}
static gboolean
evaluate_run_state (void)
{
static gint recursive = 0;
gboolean quit = FALSE;
/* micro-optimization */
if (G_LIKELY (panel_app.runstate == PANEL_RUN_STATE_NORMAL))
return TRUE;
if (G_UNLIKELY (recursive))
return TRUE;
recursive++;
switch (panel_app.runstate)
{
case PANEL_RUN_STATE_RESTART:
case PANEL_RUN_STATE_QUIT_NOCONFIRM:
panel_app_save ();
quit = TRUE;
break;
case PANEL_RUN_STATE_QUIT_NOSAVE:
quit = TRUE;
break;
default:
if (panel_app.session_client)
{
logout_session (panel_app.session_client);
}
else if (xfce_confirm (_("Exit Xfce Panel?"),
GTK_STOCK_QUIT, NULL))
{
panel_app_save ();
quit = TRUE;
}
/* don't forget to set back the run state */
panel_app.runstate = PANEL_RUN_STATE_NORMAL;
break;
}
if (quit)
{
/* we quit on purpose, update session manager so
* it does not restart the program immediately */
client_session_set_restart_style(panel_app.session_client, SESSION_RESTART_IF_RUNNING);
if (panel_app.save_id)
{
g_source_remove (panel_app.save_id);
panel_app.save_id = 0;
}
close (signal_pipe[0]);
close (signal_pipe[1]);
gtk_main_quit ();
return FALSE;
}
recursive--;
return TRUE;
}
static gboolean
signal_pipe_io (GIOChannel *source,
GIOCondition cond,
gpointer data)
{
gint signal_;
gsize bytes_read;
if (G_IO_STATUS_NORMAL == g_io_channel_read_chars (source, (gchar *)&signal_,
sizeof (signal_),
&bytes_read, NULL)
&& sizeof(signal_) == bytes_read)
{
switch (signal_)
{
case SIGUSR1:
DBG ("USR1 signal caught");
panel_app.runstate = PANEL_RUN_STATE_RESTART;
break;
case SIGUSR2:
DBG ("USR2 signal caught");
panel_app.runstate = PANEL_RUN_STATE_QUIT;
break;
case SIGINT:
case SIGABRT:
DBG ("INT or ABRT signal caught");
panel_app.runstate = PANEL_RUN_STATE_QUIT_NOSAVE;
break;
default:
DBG ("Signal caught: %d", buf.signal);
panel_app.runstate = PANEL_RUN_STATE_QUIT_NOSAVE;
}
}
return evaluate_run_state ();
}
static gboolean
init_signal_pipe ( void )
{
GIOChannel *g_signal_in;
glong fd_flags;
/* create pipe and set writing end in non-blocking mode */
if (pipe (signal_pipe))
{
return FALSE;
}
fd_flags = fcntl (signal_pipe[1], F_GETFL);
if (fd_flags == -1)
{
return FALSE;
}
if (fcntl (signal_pipe[1], F_SETFL, fd_flags | O_NONBLOCK) == -1)
{
close (signal_pipe[0]);
close (signal_pipe[1]);
return FALSE;
}
/* convert the reading end of the pipe into a GIOChannel */
g_signal_in = g_io_channel_unix_new (signal_pipe[0]);
g_io_channel_set_encoding (g_signal_in, NULL, NULL);
g_io_channel_set_close_on_unref (g_signal_in, FALSE);
/* register the reading end with the event loop */
g_io_add_watch (g_signal_in, G_IO_IN | G_IO_PRI, signal_pipe_io, NULL);
g_io_channel_unref (g_signal_in);
return TRUE;
}
static void
init_signal_handlers ( void )
{
#ifdef HAVE_SIGACTION
struct sigaction act;
act.sa_handler = sighandler;
sigemptyset (&act.sa_mask);
# ifdef SA_RESTART
act.sa_flags = SA_RESTART;
# else
act.sa_flags = 0;
# endif
sigaction (SIGHUP, &act, NULL);
sigaction (SIGUSR1, &act, NULL);
sigaction (SIGUSR2, &act, NULL);
sigaction (SIGINT, &act, NULL);
sigaction (SIGABRT, &act, NULL);
sigaction (SIGTERM, &act, NULL);
act.sa_handler = sigchld_handler;
sigaction (SIGCHLD, &act, NULL);
#else
signal (SIGHUP, sighandler);
signal (SIGUSR1, sighandler);
signal (SIGUSR2, sighandler);
signal (SIGINT, sighandler);
signal (SIGABRT, sighandler);
signal (SIGTERM, sighandler);
signal (SIGCHLD, sigchld_handler);
#endif
}
/* session */
static void
session_save_yourself (gpointer data,
gint save_style,
gboolean shutdown,
gint interact_style,
gboolean fast)
{
panel_app_save ();
}
static void
session_die (gpointer client_data)
{
panel_app_quit_noconfirm ();
}
/* screen layout */
static void
monitor_size_changed (GdkScreen *screen)
{
guint i;
XfceMonitor *monitor;
GtkWidget *panel;
for (i = 0; i < panel_app.monitor_list->len; ++i)
{
monitor = g_ptr_array_index (panel_app.monitor_list, i);
/*
* With xrandr 1.2, monitors can be added/removed, so need
* to double check the number of monitors (bug #3620)...
*/
if ((monitor->screen == screen) && (monitor->num < gdk_screen_get_n_monitors (screen)))
{
gdk_screen_get_monitor_geometry (screen, monitor->num,
&(monitor->geometry));
}
}
for (i = 0; i < panel_app.panel_list->len; ++i)
{
panel = g_ptr_array_index (panel_app.panel_list, i);
if (screen == gtk_widget_get_screen (panel))
panel_screen_size_changed (screen, PANEL (panel));
}
}
static void
create_monitor_list (void)
{
GdkDisplay *display;
GdkScreen *screen;
XfceMonitor *monitor;
gint n_screens;
gint n_monitors = 0;
gint i, j;
guint k, m;
gint w = 0, h = 0;
gboolean equal_w, equal_h;
XfceMonitor *mon1, *mon2;
panel_app.monitor_list = g_ptr_array_new ();
display = gdk_display_get_default ();
n_screens = gdk_display_get_n_screens (display);
equal_w = equal_h = TRUE;
for (i = 0; i < n_screens; ++i)
{
screen = gdk_display_get_screen (display, i);
n_monitors = gdk_screen_get_n_monitors (screen);
for (j = 0; j < n_monitors; ++j)
{
monitor = panel_slice_new0 (XfceMonitor);
monitor->screen = screen;
monitor->num = j;
gdk_screen_get_monitor_geometry (screen, j, &(monitor->geometry));
g_ptr_array_add (panel_app.monitor_list, monitor);
if (j > 0)
{
if (w != monitor->geometry.width)
equal_w = FALSE;
if (h != monitor->geometry.height)
equal_h = FALSE;
}
w = monitor->geometry.width;
h = monitor->geometry.height;
#if TEST_MULTIPLE_MONITORS
monitor = panel_slice_new0 (XfceMonitor);
monitor->screen = screen;
monitor->num = j;
gdk_screen_get_monitor_geometry (screen, j, &(monitor->geometry));
g_ptr_array_add (panel_app.monitor_list, monitor);
#endif
}
g_signal_connect (G_OBJECT (screen), "size-changed",
G_CALLBACK (monitor_size_changed), NULL);
}
if (n_screens == 1 && n_monitors > 1)
{
panel_app.xinerama_and_equal_width = equal_w;
panel_app.xinerama_and_equal_height = equal_h;
}
/* check layout */
for (k = 0; k < panel_app.monitor_list->len; ++k)
{
mon1 = g_ptr_array_index (panel_app.monitor_list, k);
for (m = 0; m < panel_app.monitor_list->len; ++m)
{
if (m == k)
continue;
mon2 = g_ptr_array_index (panel_app.monitor_list, m);
if (mon2->geometry.x < mon1->geometry.x
&& mon2->geometry.y < mon1->geometry.y + mon1->geometry.height
&& mon2->geometry.y + mon2->geometry.height > mon1->geometry.y
)
{
mon1->has_neighbor_left = TRUE;
}
if (mon2->geometry.x > mon1->geometry.x
&& mon2->geometry.y < mon1->geometry.y + mon1->geometry.height
&& mon2->geometry.y + mon2->geometry.height > mon1->geometry.y
)
{
mon1->has_neighbor_right = TRUE;
}
if (mon2->geometry.y < mon1->geometry.y
&& mon2->geometry.x < mon1->geometry.x + mon1->geometry.width
&& mon2->geometry.x + mon2->geometry.width > mon1->geometry.x
)
{
mon1->has_neighbor_above = TRUE;
}
if (mon2->geometry.y > mon1->geometry.y
&& mon2->geometry.x < mon1->geometry.x + mon1->geometry.width
&& mon2->geometry.x + mon2->geometry.width > mon1->geometry.x
)
{
mon1->has_neighbor_below = TRUE;
}
}
}
}
/* open dialogs */
static void
unregister_dialog (GtkWidget *dialog)
{
GList *l;
for (l = panel_app.dialogs; l != NULL; l = l->next)
{
if (dialog == GTK_WIDGET (l->data))
{
panel_app.dialogs = g_list_delete_link (panel_app.dialogs, l);
break;
}
}
}
/* public API */
/**
* panel_app_init
*
* Initialize application. Creates ipc window if no other instance is
* running or sets the ipc window from the running instance.
*
* Returns: INIT_SUCCESS (0) on success, INIT_RUNNING (1) when an xfce4-panel
* instance already exists, and INIT_FAILURE (2) on failure.
**/
int
panel_app_init (void)
{
Atom selection_atom, manager_atom;
GtkWidget *invisible;
XClientMessageEvent xev;
if (panel_app.initialized)
return INIT_SUCCESS;
panel_app.initialized = TRUE;
selection_atom = XInternAtom (GDK_DISPLAY (), SELECTION_NAME, False);
panel_app.ipc_window = XGetSelectionOwner (GDK_DISPLAY (), selection_atom);
if (panel_app.ipc_window)
return INIT_RUNNING;
invisible = gtk_invisible_new ();
gtk_widget_realize (invisible);
panel_app.gtk_ipc_window = invisible;
panel_app.ipc_window = GDK_WINDOW_XWINDOW (invisible->window);
XSelectInput (GDK_DISPLAY (), panel_app.ipc_window, PropertyChangeMask);
XSetSelectionOwner (GDK_DISPLAY (), selection_atom, panel_app.ipc_window,
GDK_CURRENT_TIME);
if (XGetSelectionOwner (GDK_DISPLAY (), selection_atom) !=
panel_app.ipc_window)
{
g_critical ("Could not set ownership of selection \"%s\"",
SELECTION_NAME);
return INIT_FAILURE;
}
manager_atom = XInternAtom (GDK_DISPLAY (), "MANAGER", False);
xev.type = ClientMessage;
xev.window = GDK_ROOT_WINDOW ();
xev.message_type = manager_atom;
xev.format = 32;
xev.data.l[0] = GDK_CURRENT_TIME;
xev.data.l[1] = selection_atom;
xev.data.l[2] = panel_app.ipc_window;
xev.data.l[3] = 0; /* manager specific data */
xev.data.l[4] = 0; /* manager specific data */
XSendEvent (GDK_DISPLAY (), GDK_ROOT_WINDOW (), False,
StructureNotifyMask, (XEvent *) & xev);
/* listen for client messages */
panel_app_listen (invisible);
return INIT_SUCCESS;
}
/* fix position after showing panel for the first time */
static gboolean
expose_timeout (GtkWidget *panel)
{
gtk_widget_queue_resize (panel);
return FALSE;
}
static void
panel_app_init_panel (GtkWidget *panel)
{
MARK("start panel_app_init_panel: %p", panel);
panel_init_position (PANEL (panel));
panel_init_signals (PANEL (panel));
MARK(" + start show panel");
gtk_widget_show (panel);
MARK(" + end show panel");
g_idle_add ((GSourceFunc)expose_timeout, panel);
MARK("end panel_app_init_panel");
}
/**
* panel_app_run
*
* Run the panel application. Reads the configuration file(s) and sets up the
* panels, before turning over control to the main event loop.
*
* Returns: RUN_FAILURE (2) if something goes wrong, RUN_RESTART (1) to restart
* and RUN_SUCCESS (0) to quit.
**/
gint
panel_app_run (gchar *client_id)
{
gchar **restart_command;
/* initialize signal handling */
if (!init_signal_pipe ())
{
g_critical ("Unable to create signal-watch pipe: %s.",
strerror(errno));
return RUN_FAILURE;
}
init_signal_handlers ();
/* environment */
xfce_setenv ("DISPLAY",
gdk_display_get_name (gdk_display_get_default ()),
TRUE);
/* session management */
restart_command = g_new (gchar *, 3);
restart_command[0] = g_strdup ("xfce4-panel");
restart_command[1] = g_strdup ("-r");
restart_command[2] = NULL;
panel_app.session_client =
client_session_new_full (NULL,
SESSION_RESTART_IMMEDIATELY,
40,
client_id,
(gchar *) PACKAGE_NAME,
NULL,
restart_command,
g_strdupv (restart_command),
NULL,
NULL,
NULL);
panel_app.session_client->save_yourself = session_save_yourself;
panel_app.session_client->die = session_die;
MARK("connect to session manager");
if (!session_init (panel_app.session_client))
{
/* no indeed we're not connected... */
panel_app.session_client->current_state = SESSION_CLIENT_DISCONNECTED;
/* cleanup */
client_session_free (panel_app.session_client);
panel_app.session_client = NULL;
}
/* screen layout and geometry */
MARK("start monitor list creation");
create_monitor_list ();
/* configuration */
MARK("start init item manager");
xfce_panel_item_manager_init ();
MARK("start panel creation");
panel_app.panel_list = panel_config_create_panels ();
MARK("end panel creation");
g_ptr_array_foreach (panel_app.panel_list, (GFunc)panel_app_init_panel,
NULL);
/* Run Forrest, Run! */
panel_app.runstate = PANEL_RUN_STATE_NORMAL;
MARK("start main loop");
gtk_main ();
MARK("end main loop");
/* cleanup */
if (panel_app.session_client)
client_session_free (panel_app.session_client);
cleanup_panels ();
xfce_panel_item_manager_cleanup ();
if (panel_app.runstate == PANEL_RUN_STATE_RESTART)
return RUN_RESTART;
return RUN_SUCCESS;
}
static gboolean
save_timeout (void)
{
DBG (" ++ save timeout");
if (panel_app.save_id)
g_source_remove (panel_app.save_id);
panel_app.save_id = 0;
if (panel_app.runstate == PANEL_RUN_STATE_NORMAL)
{
DBG (" ++ really save");
panel_app_save ();
}
return FALSE;
}
void
panel_app_queue_save (void)
{
if (!panel_app.initialized)
return;
if (panel_app.runstate == PANEL_RUN_STATE_NORMAL)
{
if (!panel_app.save_id)
panel_app.save_id =
g_timeout_add (SAVE_TIMEOUT, (GSourceFunc)save_timeout, NULL);
}
}
void
panel_app_customize (void)
{
if (xfce_allow_panel_customization())
panel_manager_dialog (panel_app.panel_list);
}
void
panel_app_customize_items (GtkWidget *active_item)
{
if (xfce_allow_panel_customization())
add_items_dialog (panel_app.panel_list, active_item);
}
void
panel_app_save (void)
{
if (!panel_app.initialized)
return;
if (xfce_allow_panel_customization())
panel_config_save_panels (panel_app.panel_list);
}
void
panel_app_restart (void)
{
panel_app.runstate = PANEL_RUN_STATE_RESTART;
evaluate_run_state ();
}
void
panel_app_quit (void)
{
panel_app.runstate = PANEL_RUN_STATE_QUIT;
evaluate_run_state ();
}
void
panel_app_quit_noconfirm (void)
{
panel_app.runstate = PANEL_RUN_STATE_QUIT_NOCONFIRM;
evaluate_run_state ();
}
void
panel_app_quit_nosave (void)
{
panel_app.runstate = PANEL_RUN_STATE_QUIT_NOSAVE;
evaluate_run_state ();
}
void
panel_app_add_panel (void)
{
Panel *panel;
if (!xfce_allow_panel_customization())
return;
panel = panel_new ();
if (G_UNLIKELY (panel_app.panel_list == NULL))
panel_app.panel_list = g_ptr_array_sized_new (1);
g_ptr_array_add (panel_app.panel_list, panel);
panel_set_screen_position (panel, XFCE_SCREEN_POSITION_FLOATING_H);
panel_add_item (panel, PANEL_LAUNCHER);
panel_center (panel);
panel_init_position (panel);
panel_init_signals (panel);
gtk_widget_show (GTK_WIDGET (panel));
panel_app.current_panel = panel_app.panel_list->len - 1;
panel_app_customize ();
}
void
panel_app_remove_panel (GtkWidget *panel)
{
gint response = GTK_RESPONSE_NONE;
guint n;
gchar *first;
if (!xfce_allow_panel_customization())
return;
if (panel_app.panel_list->len == 1)
{
response =
xfce_message_dialog (NULL, _("Xfce Panel"),
GTK_STOCK_DIALOG_WARNING,
_("Exit Xfce Panel?"),
_("You can't remove the last panel. "
"Would you like to exit the program?"),
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_QUIT, GTK_RESPONSE_ACCEPT,
NULL);
if (response == GTK_RESPONSE_ACCEPT)
panel_app_quit_noconfirm ();
return;
}
for (n = 0; n < panel_app.panel_list->len; ++n)
{
if (panel == g_ptr_array_index (panel_app.panel_list, n))
break;
}
if (n == panel_app.panel_list->len)
return;
panel_block_autohide (PANEL (panel));
panel_set_items_sensitive (PANEL (panel), FALSE);
gtk_widget_set_sensitive (panel, FALSE);
gtk_drag_highlight (panel);
first = g_strdup_printf (_("Remove Panel \"%d\"?"), n + 1);
response = xfce_message_dialog (GTK_WINDOW (panel), _("Xfce Panel"),
GTK_STOCK_DIALOG_WARNING, first,
_("The selected panel and all its items "
"will be removed."),
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_REMOVE, GTK_RESPONSE_ACCEPT,
NULL);
g_free (first);
if (response != GTK_RESPONSE_ACCEPT)
{
gtk_drag_unhighlight (panel);
gtk_widget_set_sensitive (panel, TRUE);
panel_set_items_sensitive (PANEL (panel), TRUE);
panel_unblock_autohide (PANEL (panel));
return;
}
if (g_ptr_array_remove (panel_app.panel_list, (gpointer)panel))
{
gtk_widget_hide (panel);
panel_free_data (PANEL (panel));
gtk_widget_destroy (panel);
}
}
void
panel_app_about (GtkWidget *panel)
{
XfceAboutInfo *info;
GtkWidget *dlg;
GdkPixbuf *pb;
info = xfce_about_info_new (_("Xfce Panel"), "", _("Xfce Panel"),
XFCE_COPYRIGHT_TEXT ("2006", "Jasper Huijsmans"),
XFCE_LICENSE_GPL);
xfce_about_info_set_homepage (info, "http://www.xfce.org");
xfce_about_info_add_credit (info, "Jasper Huijsmans", "jasper@xfce.org", _("Developer"));
xfce_about_info_add_credit (info, "Nick Schermer", "nick@xfce.org", _("Developer"));
pb = xfce_themed_icon_load ("xfce4-panel", 48);
dlg = xfce_about_dialog_new_with_values (NULL, info, pb);
g_object_unref (G_OBJECT (pb));
gtk_window_set_screen (GTK_WINDOW (dlg), gtk_widget_get_screen (panel));
gtk_widget_set_size_request (dlg, 400, 300);
gtk_dialog_run (GTK_DIALOG (dlg));
gtk_widget_destroy (dlg);
xfce_about_info_free (info);
}
Window
panel_app_get_ipc_window (void)
{
panel_app_init ();
return panel_app.ipc_window;
}
XfceMonitor *
panel_app_get_monitor (guint n)
{
return g_ptr_array_index (panel_app.monitor_list,
MIN (n, panel_app.monitor_list->len - 1));
}
guint
panel_app_get_n_monitors (void)
{
return panel_app.monitor_list->len;
}
/* open dialogs */
void
panel_app_register_dialog (GtkWidget *dialog)
{
g_return_if_fail (GTK_IS_WIDGET (dialog));
g_signal_connect (G_OBJECT (dialog), "destroy",
G_CALLBACK (unregister_dialog), NULL);
panel_app.dialogs = g_list_prepend (panel_app.dialogs, dialog);
}
/* current panel */
void
panel_app_set_current_panel (gpointer *panel)
{
guint i;
panel_app.current_panel = 0;
for (i = 0; i < panel_app.panel_list->len; ++i)
{
if (g_ptr_array_index (panel_app.panel_list, i) == panel)
{
panel_app.current_panel = i;
break;
}
}
DBG ("Current panel: %d", panel_app.current_panel);
}
void
panel_app_unset_current_panel (gpointer *panel)
{
guint i;
for (i = 0; i < panel_app.panel_list->len; ++i)
{
if (g_ptr_array_index (panel_app.panel_list, i) == panel)
{
if (i == (guint) panel_app.current_panel)
panel_app.current_panel = 0;
break;
}
}
DBG ("Current panel: %d", panel_app.current_panel);
}
gint
panel_app_get_current_panel (void)
{
return panel_app.current_panel;
}
const GPtrArray *
panel_app_get_panel_list (void)
{
return panel_app.panel_list;
}
/* check whether monitors in Xinerama are aligned */
gboolean
panel_app_monitors_equal_height (void)
{
return panel_app.xinerama_and_equal_height;
}
gboolean
panel_app_monitors_equal_width (void)
{
return panel_app.xinerama_and_equal_width;
}