gnome-shell/src/tray/na-tray-manager.c
Florian Müllner 731d64e0e4 tray: Don't use gdk_display_supports_composite()
Composite is a hard requirement for mutter's compositor, so if we get
to the point of managing the tray, we already know that the extension
is supported. So let's get rid of yet another deprecation warning.
2015-10-15 23:05:11 +02:00

892 lines
25 KiB
C

/* na-tray-manager.c
* Copyright (C) 2002 Anders Carlsson <andersca@gnu.org>
* Copyright (C) 2003-2006 Vincent Untz
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*
* Used to be: eggtraymanager.c
*/
#include <config.h>
#include <string.h>
#include <libintl.h>
#include "na-tray-manager.h"
#if defined (GDK_WINDOWING_X11)
#include <gdk/gdkx.h>
#include <X11/Xatom.h>
#elif defined (GDK_WINDOWING_WIN32)
#include <gdk/gdkwin32.h>
#endif
#include <gtk/gtk.h>
/* Signals */
enum
{
TRAY_ICON_ADDED,
TRAY_ICON_REMOVED,
MESSAGE_SENT,
MESSAGE_CANCELLED,
LOST_SELECTION,
LAST_SIGNAL
};
enum {
PROP_0,
PROP_ORIENTATION
};
typedef struct
{
long id, len;
long remaining_len;
long timeout;
char *str;
#ifdef GDK_WINDOWING_X11
Window window;
#endif
} PendingMessage;
static guint manager_signals[LAST_SIGNAL];
#define SYSTEM_TRAY_REQUEST_DOCK 0
#define SYSTEM_TRAY_BEGIN_MESSAGE 1
#define SYSTEM_TRAY_CANCEL_MESSAGE 2
#define SYSTEM_TRAY_ORIENTATION_HORZ 0
#define SYSTEM_TRAY_ORIENTATION_VERT 1
#ifdef GDK_WINDOWING_X11
static gboolean na_tray_manager_check_running_screen_x11 (GdkScreen *screen);
#endif
static void na_tray_manager_finalize (GObject *object);
static void na_tray_manager_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void na_tray_manager_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void na_tray_manager_unmanage (NaTrayManager *manager);
G_DEFINE_TYPE (NaTrayManager, na_tray_manager, G_TYPE_OBJECT)
static void
na_tray_manager_init (NaTrayManager *manager)
{
manager->invisible = NULL;
manager->socket_table = g_hash_table_new (NULL, NULL);
manager->fg.red = 0;
manager->fg.green = 0;
manager->fg.blue = 0;
manager->error.red = 0xff;
manager->error.green = 0;
manager->error.blue = 0;
manager->warning.red = 0xff;
manager->warning.green = 0xff;
manager->warning.blue = 0;
manager->success.red = 0;
manager->success.green = 0xff;
manager->success.blue = 0;
}
static void
na_tray_manager_class_init (NaTrayManagerClass *klass)
{
GObjectClass *gobject_class;
gobject_class = (GObjectClass *)klass;
gobject_class->finalize = na_tray_manager_finalize;
gobject_class->set_property = na_tray_manager_set_property;
gobject_class->get_property = na_tray_manager_get_property;
g_object_class_install_property (gobject_class,
PROP_ORIENTATION,
g_param_spec_enum ("orientation",
"orientation",
"orientation",
GTK_TYPE_ORIENTATION,
GTK_ORIENTATION_HORIZONTAL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_NICK |
G_PARAM_STATIC_BLURB));
manager_signals[TRAY_ICON_ADDED] =
g_signal_new ("tray_icon_added",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NaTrayManagerClass, tray_icon_added),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
GTK_TYPE_SOCKET);
manager_signals[TRAY_ICON_REMOVED] =
g_signal_new ("tray_icon_removed",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NaTrayManagerClass, tray_icon_removed),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
GTK_TYPE_SOCKET);
manager_signals[MESSAGE_SENT] =
g_signal_new ("message_sent",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NaTrayManagerClass, message_sent),
NULL, NULL, NULL,
G_TYPE_NONE, 4,
GTK_TYPE_SOCKET,
G_TYPE_STRING,
G_TYPE_LONG,
G_TYPE_LONG);
manager_signals[MESSAGE_CANCELLED] =
g_signal_new ("message_cancelled",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NaTrayManagerClass, message_cancelled),
NULL, NULL, NULL,
G_TYPE_NONE, 2,
GTK_TYPE_SOCKET,
G_TYPE_LONG);
manager_signals[LOST_SELECTION] =
g_signal_new ("lost_selection",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NaTrayManagerClass, lost_selection),
NULL, NULL, NULL,
G_TYPE_NONE, 0);
#if defined (GDK_WINDOWING_X11)
/* Nothing */
#elif defined (GDK_WINDOWING_WIN32)
g_warning ("Port NaTrayManager to Win32");
#else
g_warning ("Port NaTrayManager to this GTK+ backend");
#endif
}
static void
na_tray_manager_finalize (GObject *object)
{
NaTrayManager *manager;
manager = NA_TRAY_MANAGER (object);
na_tray_manager_unmanage (manager);
g_list_free (manager->messages);
g_hash_table_destroy (manager->socket_table);
G_OBJECT_CLASS (na_tray_manager_parent_class)->finalize (object);
}
static void
na_tray_manager_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
NaTrayManager *manager = NA_TRAY_MANAGER (object);
switch (prop_id)
{
case PROP_ORIENTATION:
na_tray_manager_set_orientation (manager, g_value_get_enum (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
na_tray_manager_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
NaTrayManager *manager = NA_TRAY_MANAGER (object);
switch (prop_id)
{
case PROP_ORIENTATION:
g_value_set_enum (value, manager->orientation);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
NaTrayManager *
na_tray_manager_new (void)
{
NaTrayManager *manager;
manager = g_object_new (NA_TYPE_TRAY_MANAGER, NULL);
return manager;
}
#ifdef GDK_WINDOWING_X11
static gboolean
na_tray_manager_plug_removed (GtkSocket *socket,
NaTrayManager *manager)
{
NaTrayChild *child = NA_TRAY_CHILD (socket);
g_hash_table_remove (manager->socket_table,
GINT_TO_POINTER (child->icon_window));
g_signal_emit (manager, manager_signals[TRAY_ICON_REMOVED], 0, child);
/* This destroys the socket. */
return FALSE;
}
static void
na_tray_manager_handle_dock_request (NaTrayManager *manager,
XClientMessageEvent *xevent)
{
Window icon_window = xevent->data.l[2];
GtkWidget *child;
if (g_hash_table_lookup (manager->socket_table,
GINT_TO_POINTER (icon_window)))
{
/* We already got this notification earlier, ignore this one */
return;
}
child = na_tray_child_new (manager->screen, icon_window);
if (child == NULL) /* already gone or other error */
return;
g_signal_emit (manager, manager_signals[TRAY_ICON_ADDED], 0,
child);
/* If the child wasn't attached, then destroy it */
if (!GTK_IS_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (child))))
{
gtk_widget_destroy (child);
return;
}
g_signal_connect (child, "plug_removed",
G_CALLBACK (na_tray_manager_plug_removed), manager);
gtk_socket_add_id (GTK_SOCKET (child), icon_window);
if (!gtk_socket_get_plug_window (GTK_SOCKET (child)))
{
/* Embedding failed, we won't get a plug-removed signal */
/* This signal destroys the socket */
g_signal_emit (manager, manager_signals[TRAY_ICON_REMOVED], 0, child);
return;
}
g_hash_table_insert (manager->socket_table,
GINT_TO_POINTER (icon_window), child);
gtk_widget_show (child);
}
static void
pending_message_free (PendingMessage *message)
{
g_free (message->str);
g_free (message);
}
static void
na_tray_manager_handle_message_data (NaTrayManager *manager,
XClientMessageEvent *xevent)
{
GList *p;
int len;
/* Try to see if we can find the pending message in the list */
for (p = manager->messages; p; p = p->next)
{
PendingMessage *msg = p->data;
if (xevent->window == msg->window)
{
/* Append the message */
len = MIN (msg->remaining_len, 20);
memcpy ((msg->str + msg->len - msg->remaining_len),
&xevent->data, len);
msg->remaining_len -= len;
if (msg->remaining_len == 0)
{
GtkSocket *socket;
socket = g_hash_table_lookup (manager->socket_table,
GINT_TO_POINTER (msg->window));
if (socket)
g_signal_emit (manager, manager_signals[MESSAGE_SENT], 0,
socket, msg->str, msg->id, msg->timeout);
pending_message_free (msg);
manager->messages = g_list_remove_link (manager->messages, p);
g_list_free_1 (p);
}
break;
}
}
}
static void
na_tray_manager_handle_begin_message (NaTrayManager *manager,
XClientMessageEvent *xevent)
{
GtkSocket *socket;
GList *p;
PendingMessage *msg;
long timeout;
long len;
long id;
socket = g_hash_table_lookup (manager->socket_table,
GINT_TO_POINTER (xevent->window));
/* we don't know about this tray icon, so ignore the message */
if (!socket)
return;
timeout = xevent->data.l[2];
len = xevent->data.l[3];
id = xevent->data.l[4];
/* Check if the same message is already in the queue and remove it if so */
for (p = manager->messages; p; p = p->next)
{
PendingMessage *pmsg = p->data;
if (xevent->window == pmsg->window &&
id == pmsg->id)
{
/* Hmm, we found it, now remove it */
pending_message_free (pmsg);
manager->messages = g_list_remove_link (manager->messages, p);
g_list_free_1 (p);
break;
}
}
if (len == 0)
{
g_signal_emit (manager, manager_signals[MESSAGE_SENT], 0,
socket, "", id, timeout);
}
else
{
/* Now add the new message to the queue */
msg = g_new0 (PendingMessage, 1);
msg->window = xevent->window;
msg->timeout = timeout;
msg->len = len;
msg->id = id;
msg->remaining_len = msg->len;
msg->str = g_malloc (msg->len + 1);
msg->str[msg->len] = '\0';
manager->messages = g_list_prepend (manager->messages, msg);
}
}
static void
na_tray_manager_handle_cancel_message (NaTrayManager *manager,
XClientMessageEvent *xevent)
{
GList *p;
GtkSocket *socket;
long id;
id = xevent->data.l[2];
/* Check if the message is in the queue and remove it if so */
for (p = manager->messages; p; p = p->next)
{
PendingMessage *msg = p->data;
if (xevent->window == msg->window &&
id == msg->id)
{
pending_message_free (msg);
manager->messages = g_list_remove_link (manager->messages, p);
g_list_free_1 (p);
break;
}
}
socket = g_hash_table_lookup (manager->socket_table,
GINT_TO_POINTER (xevent->window));
if (socket)
{
g_signal_emit (manager, manager_signals[MESSAGE_CANCELLED], 0,
socket, xevent->data.l[2]);
}
}
static GdkFilterReturn
na_tray_manager_window_filter (GdkXEvent *xev,
GdkEvent *event,
gpointer data)
{
XEvent *xevent = (GdkXEvent *)xev;
NaTrayManager *manager = data;
if (xevent->type == ClientMessage)
{
/* _NET_SYSTEM_TRAY_OPCODE: SYSTEM_TRAY_REQUEST_DOCK */
if (xevent->xclient.message_type == manager->opcode_atom &&
xevent->xclient.data.l[1] == SYSTEM_TRAY_REQUEST_DOCK)
{
na_tray_manager_handle_dock_request (manager,
(XClientMessageEvent *) xevent);
return GDK_FILTER_REMOVE;
}
/* _NET_SYSTEM_TRAY_OPCODE: SYSTEM_TRAY_BEGIN_MESSAGE */
else if (xevent->xclient.message_type == manager->opcode_atom &&
xevent->xclient.data.l[1] == SYSTEM_TRAY_BEGIN_MESSAGE)
{
na_tray_manager_handle_begin_message (manager,
(XClientMessageEvent *) event);
return GDK_FILTER_REMOVE;
}
/* _NET_SYSTEM_TRAY_OPCODE: SYSTEM_TRAY_CANCEL_MESSAGE */
else if (xevent->xclient.message_type == manager->opcode_atom &&
xevent->xclient.data.l[1] == SYSTEM_TRAY_CANCEL_MESSAGE)
{
na_tray_manager_handle_cancel_message (manager,
(XClientMessageEvent *) event);
return GDK_FILTER_REMOVE;
}
/* _NET_SYSTEM_TRAY_MESSAGE_DATA */
else if (xevent->xclient.message_type == manager->message_data_atom)
{
na_tray_manager_handle_message_data (manager,
(XClientMessageEvent *) event);
return GDK_FILTER_REMOVE;
}
}
else if (xevent->type == SelectionClear)
{
g_signal_emit (manager, manager_signals[LOST_SELECTION], 0);
na_tray_manager_unmanage (manager);
}
return GDK_FILTER_CONTINUE;
}
#if 0
//FIXME investigate why this doesn't work
static gboolean
na_tray_manager_selection_clear_event (GtkWidget *widget,
GdkEventSelection *event,
NaTrayManager *manager)
{
g_signal_emit (manager, manager_signals[LOST_SELECTION], 0);
na_tray_manager_unmanage (manager);
return FALSE;
}
#endif
#endif
static void
na_tray_manager_unmanage (NaTrayManager *manager)
{
#ifdef GDK_WINDOWING_X11
GdkDisplay *display;
guint32 timestamp;
GtkWidget *invisible;
GdkWindow *window;
if (manager->invisible == NULL)
return;
invisible = manager->invisible;
window = gtk_widget_get_window (invisible);
g_assert (GTK_IS_INVISIBLE (invisible));
g_assert (gtk_widget_get_realized (invisible));
g_assert (GDK_IS_WINDOW (window));
display = gtk_widget_get_display (invisible);
if (gdk_selection_owner_get_for_display (display, manager->selection_atom) ==
window)
{
timestamp = gdk_x11_get_server_time (window);
gdk_selection_owner_set_for_display (display,
NULL,
manager->selection_atom,
timestamp,
TRUE);
}
gdk_window_remove_filter (window,
na_tray_manager_window_filter, manager);
manager->invisible = NULL; /* prior to destroy for reentrancy paranoia */
gtk_widget_destroy (invisible);
g_object_unref (G_OBJECT (invisible));
#endif
}
static void
na_tray_manager_set_orientation_property (NaTrayManager *manager)
{
#ifdef GDK_WINDOWING_X11
GdkWindow *window;
GdkDisplay *display;
Atom orientation_atom;
gulong data[1];
g_return_if_fail (manager->invisible != NULL);
window = gtk_widget_get_window (manager->invisible);
g_return_if_fail (window != NULL);
display = gtk_widget_get_display (manager->invisible);
orientation_atom = gdk_x11_get_xatom_by_name_for_display (display,
"_NET_SYSTEM_TRAY_ORIENTATION");
data[0] = manager->orientation == GTK_ORIENTATION_HORIZONTAL ?
SYSTEM_TRAY_ORIENTATION_HORZ :
SYSTEM_TRAY_ORIENTATION_VERT;
XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
GDK_WINDOW_XID (window),
orientation_atom,
XA_CARDINAL, 32,
PropModeReplace,
(guchar *) &data, 1);
#endif
}
static void
na_tray_manager_set_visual_property (NaTrayManager *manager)
{
#ifdef GDK_WINDOWING_X11
GdkWindow *window;
GdkDisplay *display;
Visual *xvisual;
Atom visual_atom;
gulong data[1];
g_return_if_fail (manager->invisible != NULL);
window = gtk_widget_get_window (manager->invisible);
g_return_if_fail (window != NULL);
/* The visual property is a hint to the tray icons as to what visual they
* should use for their windows. If the X server has RGBA colormaps, then
* we tell the tray icons to use a RGBA colormap and we'll composite the
* icon onto its parents with real transparency. Otherwise, we just tell
* the icon to use our colormap, and we'll do some hacks with parent
* relative backgrounds to simulate transparency.
*/
display = gtk_widget_get_display (manager->invisible);
visual_atom = gdk_x11_get_xatom_by_name_for_display (display,
"_NET_SYSTEM_TRAY_VISUAL");
if (gdk_screen_get_rgba_visual (manager->screen) != NULL)
xvisual = GDK_VISUAL_XVISUAL (gdk_screen_get_rgba_visual (manager->screen));
else
{
/* We actually want the visual of the tray where the icons will
* be embedded. In almost all cases, this will be the same as the visual
* of the screen.
*/
xvisual = GDK_VISUAL_XVISUAL (gdk_screen_get_system_visual (manager->screen));
}
data[0] = XVisualIDFromVisual (xvisual);
XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
GDK_WINDOW_XID (window),
visual_atom,
XA_VISUALID, 32,
PropModeReplace,
(guchar *) &data, 1);
#endif
}
static void
na_tray_manager_set_colors_property (NaTrayManager *manager)
{
#ifdef GDK_WINDOWING_X11
GdkWindow *window;
GdkDisplay *display;
Atom atom;
gulong data[12];
g_return_if_fail (manager->invisible != NULL);
window = gtk_widget_get_window (manager->invisible);
g_return_if_fail (window != NULL);
display = gtk_widget_get_display (manager->invisible);
atom = gdk_x11_get_xatom_by_name_for_display (display,
"_NET_SYSTEM_TRAY_COLORS");
data[0] = manager->fg.red * 0x101;
data[1] = manager->fg.green * 0x101;
data[2] = manager->fg.blue * 0x101;
data[3] = manager->error.red * 0x101;
data[4] = manager->error.green * 0x101;
data[5] = manager->error.blue * 0x101;
data[6] = manager->warning.red * 0x101;
data[7] = manager->warning.green * 0x101;
data[8] = manager->warning.blue * 0x101;
data[9] = manager->success.red * 0x101;
data[10] = manager->success.green * 0x101;
data[11] = manager->success.blue * 0x101;
XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
GDK_WINDOW_XID (window),
atom,
XA_CARDINAL, 32,
PropModeReplace,
(guchar *) &data, 12);
#endif
}
#ifdef GDK_WINDOWING_X11
static gboolean
na_tray_manager_manage_screen_x11 (NaTrayManager *manager,
GdkScreen *screen)
{
GdkDisplay *display;
Screen *xscreen;
GtkWidget *invisible;
GdkWindow *window;
char *selection_atom_name;
guint32 timestamp;
g_return_val_if_fail (NA_IS_TRAY_MANAGER (manager), FALSE);
g_return_val_if_fail (manager->screen == NULL, FALSE);
/* If there's already a manager running on the screen
* we can't create another one.
*/
#if 0
if (na_tray_manager_check_running_screen_x11 (screen))
return FALSE;
#endif
manager->screen = screen;
display = gdk_screen_get_display (screen);
xscreen = GDK_SCREEN_XSCREEN (screen);
invisible = gtk_invisible_new_for_screen (screen);
gtk_widget_realize (invisible);
gtk_widget_add_events (invisible,
GDK_PROPERTY_CHANGE_MASK | GDK_STRUCTURE_MASK);
selection_atom_name = g_strdup_printf ("_NET_SYSTEM_TRAY_S%d",
gdk_screen_get_number (screen));
manager->selection_atom = gdk_atom_intern (selection_atom_name, FALSE);
g_free (selection_atom_name);
manager->invisible = invisible;
g_object_ref (G_OBJECT (manager->invisible));
na_tray_manager_set_orientation_property (manager);
na_tray_manager_set_visual_property (manager);
na_tray_manager_set_colors_property (manager);
window = gtk_widget_get_window (invisible);
timestamp = gdk_x11_get_server_time (window);
/* Check if we could set the selection owner successfully */
if (gdk_selection_owner_set_for_display (display,
window,
manager->selection_atom,
timestamp,
TRUE))
{
XClientMessageEvent xev;
GdkAtom opcode_atom;
GdkAtom message_data_atom;
xev.type = ClientMessage;
xev.window = RootWindowOfScreen (xscreen);
xev.message_type = gdk_x11_get_xatom_by_name_for_display (display,
"MANAGER");
xev.format = 32;
xev.data.l[0] = timestamp;
xev.data.l[1] = gdk_x11_atom_to_xatom_for_display (display,
manager->selection_atom);
xev.data.l[2] = GDK_WINDOW_XID (window);
xev.data.l[3] = 0; /* manager specific data */
xev.data.l[4] = 0; /* manager specific data */
XSendEvent (GDK_DISPLAY_XDISPLAY (display),
RootWindowOfScreen (xscreen),
False, StructureNotifyMask, (XEvent *)&xev);
opcode_atom = gdk_atom_intern ("_NET_SYSTEM_TRAY_OPCODE", FALSE);
manager->opcode_atom = gdk_x11_atom_to_xatom_for_display (display,
opcode_atom);
message_data_atom = gdk_atom_intern ("_NET_SYSTEM_TRAY_MESSAGE_DATA",
FALSE);
manager->message_data_atom = gdk_x11_atom_to_xatom_for_display (display,
message_data_atom);
/* Add a window filter */
#if 0
/* This is for when we lose the selection of _NET_SYSTEM_TRAY_Sx */
g_signal_connect (invisible, "selection-clear-event",
G_CALLBACK (na_tray_manager_selection_clear_event),
manager);
#endif
gdk_window_add_filter (window,
na_tray_manager_window_filter, manager);
return TRUE;
}
else
{
gtk_widget_destroy (invisible);
g_object_unref (invisible);
manager->invisible = NULL;
manager->screen = NULL;
return FALSE;
}
}
#endif
gboolean
na_tray_manager_manage_screen (NaTrayManager *manager,
GdkScreen *screen)
{
g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
g_return_val_if_fail (manager->screen == NULL, FALSE);
#ifdef GDK_WINDOWING_X11
return na_tray_manager_manage_screen_x11 (manager, screen);
#else
return FALSE;
#endif
}
#ifdef GDK_WINDOWING_X11
static gboolean
na_tray_manager_check_running_screen_x11 (GdkScreen *screen)
{
GdkDisplay *display;
Atom selection_atom;
char *selection_atom_name;
display = gdk_screen_get_display (screen);
selection_atom_name = g_strdup_printf ("_NET_SYSTEM_TRAY_S%d",
gdk_screen_get_number (screen));
selection_atom = gdk_x11_get_xatom_by_name_for_display (display,
selection_atom_name);
g_free (selection_atom_name);
if (XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (display),
selection_atom) != None)
return TRUE;
else
return FALSE;
}
#endif
gboolean
na_tray_manager_check_running (GdkScreen *screen)
{
g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
#ifdef GDK_WINDOWING_X11
return na_tray_manager_check_running_screen_x11 (screen);
#else
return FALSE;
#endif
}
void
na_tray_manager_set_orientation (NaTrayManager *manager,
GtkOrientation orientation)
{
g_return_if_fail (NA_IS_TRAY_MANAGER (manager));
if (manager->orientation != orientation)
{
manager->orientation = orientation;
na_tray_manager_set_orientation_property (manager);
g_object_notify (G_OBJECT (manager), "orientation");
}
}
void
na_tray_manager_set_colors (NaTrayManager *manager,
ClutterColor *fg,
ClutterColor *error,
ClutterColor *warning,
ClutterColor *success)
{
g_return_if_fail (NA_IS_TRAY_MANAGER (manager));
if (!clutter_color_equal (&manager->fg, fg) ||
!clutter_color_equal (&manager->error, error) ||
!clutter_color_equal (&manager->warning, warning) ||
!clutter_color_equal (&manager->success, success))
{
manager->fg = *fg;
manager->error = *error;
manager->warning = *warning;
manager->success = *success;
na_tray_manager_set_colors_property (manager);
}
}
GtkOrientation
na_tray_manager_get_orientation (NaTrayManager *manager)
{
g_return_val_if_fail (NA_IS_TRAY_MANAGER (manager), GTK_ORIENTATION_HORIZONTAL);
return manager->orientation;
}