summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog77
-rw-r--r--common/Makefile.am2
-rw-r--r--configure.ac1
-rw-r--r--daemon/gdm-greeter-server.c2
-rw-r--r--gui/simple-greeter/Makefile.am23
-rw-r--r--gui/simple-greeter/cutnpaste/Makefile.am66
-rw-r--r--gui/simple-greeter/cutnpaste/fixedtip.c261
-rw-r--r--gui/simple-greeter/cutnpaste/fixedtip.h68
-rw-r--r--gui/simple-greeter/cutnpaste/na-marshal.list3
-rw-r--r--gui/simple-greeter/cutnpaste/na-tray-manager.c907
-rw-r--r--gui/simple-greeter/cutnpaste/na-tray-manager.h98
-rw-r--r--gui/simple-greeter/cutnpaste/na-tray.c679
-rw-r--r--gui/simple-greeter/cutnpaste/na-tray.h68
-rw-r--r--gui/simple-greeter/cutnpaste/obox.c130
-rw-r--r--gui/simple-greeter/cutnpaste/obox.h73
-rw-r--r--gui/simple-greeter/cutnpaste/testtray.c220
-rw-r--r--gui/simple-greeter/gdm-greeter-panel.c435
-rw-r--r--gui/simple-greeter/gdm-greeter-panel.h55
-rw-r--r--gui/simple-greeter/gdm-simple-greeter.c28
-rw-r--r--gui/simple-greeter/gdm-simple-greeter.glade25
-rw-r--r--gui/simple-greeter/greeter-main.c4
-rw-r--r--gui/simple-greeter/test-greeter-panel.c54
22 files changed, 3244 insertions, 35 deletions
diff --git a/ChangeLog b/ChangeLog
index 5e641436..2f31c136 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,82 @@
2007-09-05 William Jon McCann <mccann@jhu.edu>
+ * configure.ac:
+ * daemon/gdm-greeter-server.c: (handle_get_display_id):
+ * gui/simple-greeter/Makefile.am:
+ * gui/simple-greeter/cutnpaste/Makefile.am:
+ * gui/simple-greeter/cutnpaste/fixedtip.c: (button_press_handler),
+ (expose_handler), (na_fixed_tip_class_init), (na_fixed_tip_init),
+ (na_fixed_tip_position), (na_fixed_tip_parent_size_allocated),
+ (na_fixed_tip_parent_screen_changed), (na_fixed_tip_new),
+ (na_fixed_tip_set_markup), (na_fixed_tip_set_orientation):
+ * gui/simple-greeter/cutnpaste/fixedtip.h:
+ * gui/simple-greeter/cutnpaste/na-marshal.list:
+ * gui/simple-greeter/cutnpaste/na-tray-manager.c:
+ (na_tray_manager_init), (na_tray_manager_class_init),
+ (na_tray_manager_finalize), (na_tray_manager_set_property),
+ (na_tray_manager_get_property), (na_tray_manager_new),
+ (na_tray_manager_plug_removed),
+ (na_tray_manager_make_socket_transparent),
+ (na_tray_manager_socket_exposed),
+ (na_tray_manager_socket_style_set),
+ (na_tray_manager_handle_dock_request), (pending_message_free),
+ (na_tray_manager_handle_client_message_message_data),
+ (na_tray_manager_handle_begin_message),
+ (na_tray_manager_handle_cancel_message),
+ (na_tray_manager_handle_client_message_opcode),
+ (na_tray_manager_window_filter),
+ (na_tray_manager_selection_clear_event),
+ (na_tray_manager_unmanage),
+ (na_tray_manager_set_orientation_property),
+ (na_tray_manager_manage_screen_x11),
+ (na_tray_manager_manage_screen),
+ (na_tray_manager_check_running_screen_x11),
+ (na_tray_manager_check_running), (na_tray_manager_get_child_title),
+ (na_tray_manager_set_orientation),
+ (na_tray_manager_get_orientation):
+ * gui/simple-greeter/cutnpaste/na-tray-manager.h:
+ * gui/simple-greeter/cutnpaste/na-tray.c: (get_tray), (tray_added),
+ (tray_removed), (icon_tip_buffer_free), (icon_tip_free),
+ (icon_tip_buffer_compare), (icon_tip_show_next_clicked),
+ (icon_tip_show_next_timeout), (icon_tip_show_next), (message_sent),
+ (message_cancelled), (update_orientation_for_messages),
+ (update_size_and_orientation), (na_tray_init),
+ (na_tray_constructor), (na_tray_dispose), (na_tray_set_property),
+ (na_tray_size_request), (na_tray_size_allocate),
+ (na_tray_class_init), (na_tray_new_for_screen),
+ (na_tray_set_orientation), (na_tray_get_orientation),
+ (idle_redraw_cb), (na_tray_force_redraw):
+ * gui/simple-greeter/cutnpaste/na-tray.h:
+ * gui/simple-greeter/cutnpaste/obox.c: (na_obox_class_init),
+ (na_obox_init), (na_obox_new), (get_class), (na_obox_size_request),
+ (na_obox_size_allocate), (na_obox_set_orientation):
+ * gui/simple-greeter/cutnpaste/obox.h:
+ * gui/simple-greeter/cutnpaste/testtray.c: (do_add),
+ (update_child_count), (tray_added_cb), (tray_removed_cb),
+ (orientation_changed_cb), (maybe_quit),
+ (warning_dialog_response_cb), (add_tray_cb),
+ (create_tray_on_screen), (main):
+ * gui/simple-greeter/gdm-greeter-panel.c:
+ (gdm_greeter_panel_set_property), (gdm_greeter_panel_get_property),
+ (gdm_greeter_panel_constructor), (gdm_greeter_panel_dispose),
+ (gdm_greeter_panel_move_resize_window), (on_screen_size_changed),
+ (gdm_greeter_panel_real_realize),
+ (gdm_greeter_panel_real_unrealize), (get_outside_region),
+ (get_monitor_geometry), (set_struts), (update_struts),
+ (update_geometry), (gdm_greeter_panel_real_size_request),
+ (gdm_greeter_panel_class_init), (gdm_greeter_panel_init),
+ (gdm_greeter_panel_finalize), (gdm_greeter_panel_new):
+ * gui/simple-greeter/gdm-greeter-panel.h:
+ * gui/simple-greeter/gdm-simple-greeter.c: (set_sensitive),
+ (set_message), (create_greeter), (create_panel),
+ (gdm_simple_greeter_constructor):
+ * gui/simple-greeter/gdm-simple-greeter.glade:
+ * gui/simple-greeter/greeter-main.c: (get_display_id):
+ * gui/simple-greeter/test-greeter-panel.c: (main):
+ Add a greeter panel bar with an embedded notification area.
+
+2007-09-05 William Jon McCann <mccann@jhu.edu>
+
* daemon/gdm-factory-slave.c: (run_greeter):
* daemon/gdm-greeter-server.c: (handle_disconnect),
(handle_get_display_id), (greeter_handle_child_message),
diff --git a/common/Makefile.am b/common/Makefile.am
index d5021944..d1b31b93 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -100,7 +100,7 @@ test_log_SOURCES = \
$(NULL)
test_log_LDADD = \
- libgdmcommon.la \
+ libgdmcommon.la \
$(GLIB_LIBS) \
$(NULL)
diff --git a/configure.ac b/configure.ac
index 94f96d65..ced3ea57 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1306,6 +1306,7 @@ libgreeter/Makefile
gui/Makefile
gui/modules/Makefile
gui/simple-greeter/Makefile
+gui/simple-greeter/cutnpaste/Makefile
gui/simple-chooser/Makefile
utils/Makefile
data/Makefile
diff --git a/daemon/gdm-greeter-server.c b/daemon/gdm-greeter-server.c
index b3366c61..5e583ffd 100644
--- a/daemon/gdm-greeter-server.c
+++ b/daemon/gdm-greeter-server.c
@@ -404,7 +404,7 @@ handle_get_display_id (GdmGreeterServer *greeter_server,
reply = dbus_message_new_method_return (message);
dbus_message_iter_init_append (reply, &iter);
- dbus_message_iter_append_basic (&iter, DBUS_TYPE_G_OBJECT_PATH, &greeter_server->priv->display_id);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_OBJECT_PATH, &greeter_server->priv->display_id);
dbus_connection_send (connection, reply, NULL);
dbus_message_unref (reply);
diff --git a/gui/simple-greeter/Makefile.am b/gui/simple-greeter/Makefile.am
index 2f12e749..9051daa3 100644
--- a/gui/simple-greeter/Makefile.am
+++ b/gui/simple-greeter/Makefile.am
@@ -1,8 +1,13 @@
NULL =
+SUBDIRS = \
+ cutnpaste \
+ $(NULL)
+
INCLUDES = \
-I$(top_srcdir)/common \
-I$(top_srcdir)/libgreeter \
+ -I$(top_srcdir)/gui/simple-greeter/cutnpaste \
-DAUTHDIR=\""$(authdir)"\" \
-DDATADIR=\""$(datadir)"\" \
-DGDMCONFDIR=\"$(gdmconfdir)\" \
@@ -19,6 +24,21 @@ INCLUDES = \
$(GREETER_CFLAGS) \
$(NULL)
+noinst_PROGRAMS = \
+ test-greeter-panel \
+ $(NULL)
+
+test_greeter_panel_SOURCES = \
+ test-greeter-panel.c \
+ gdm-greeter-panel.h \
+ gdm-greeter-panel.c \
+ $(NULL)
+
+test_greeter_panel_LDADD = \
+ $(top_builddir)/gui/simple-greeter/cutnpaste/libnotificationarea.la \
+ $(GUI_LIBS) \
+ $(NULL)
+
libexec_PROGRAMS = \
gdm-simple-greeter
@@ -26,12 +46,15 @@ gdm_simple_greeter_SOURCES = \
greeter-main.c \
gdm-simple-greeter.c \
gdm-simple-greeter.h \
+ gdm-greeter-panel.h \
+ gdm-greeter-panel.c \
$(NULL)
gdm_simple_greeter_LDADD = \
$(EXTRA_GREETER_LIBS) \
-L$(top_builddir)/libgreeter \
-lgreeter \
+ $(top_builddir)/gui/simple-greeter/cutnpaste/libnotificationarea.la \
$(GLIB_LIBS) \
$(DBUS_LIBS) \
$(GOBJECT_LIBS) \
diff --git a/gui/simple-greeter/cutnpaste/Makefile.am b/gui/simple-greeter/cutnpaste/Makefile.am
new file mode 100644
index 00000000..7b5fde3c
--- /dev/null
+++ b/gui/simple-greeter/cutnpaste/Makefile.am
@@ -0,0 +1,66 @@
+NULL =
+
+INCLUDES = \
+ -I. \
+ -I.. \
+ -DBINDIR=\"$(bindir)\" \
+ -DDATADIR=\"$(datadir)\" \
+ -DLIBDIR=\"$(libdir)\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DLOGDIR=\"$(logdir)\" \
+ -DPIXMAPDIR=\"$(pixmapdir)\" \
+ -DSBINDIR=\"$(sbindir)\" \
+ $(GUI_CFLAGS) \
+ $(NULL)
+
+noinst_LTLIBRARIES = \
+ libnotificationarea.la \
+ $(NULL)
+
+BUILT_SOURCES = \
+ na-marshal.c \
+ na-marshal.h \
+ $(NULL)
+
+libnotificationarea_la_SOURCES = \
+ fixedtip.h \
+ fixedtip.c \
+ obox.c \
+ obox.h \
+ na-tray.c \
+ na-tray.h \
+ na-tray-manager.c \
+ na-tray-manager.h \
+ na-marshal.c \
+ na-marshal.h \
+ $(NULL)
+
+libnotificationarea_la_LIBADD = \
+ $(GUI_LIBS) \
+ $(NULL)
+
+libnotification_area_la_LDFLAGS = \
+ -export-dynamic \
+ $(NULL)
+
+EXTRA_DIST = \
+ na-marshal.list \
+ $(NULL)
+
+na-marshal.h: na-marshal.list $(GLIB_GENMARSHAL)
+ $(GLIB_GENMARSHAL) $< --header --prefix=_na_marshal > $@
+
+na-marshal.c: na-marshal.list $(GLIB_GENMARSHAL)
+ echo "#include \"na-marshal.h\"" > $@ && \
+ $(GLIB_GENMARSHAL) $< --body --prefix=_na_marshal >> $@
+
+noinst_PROGRAMS = testtray
+
+testtray_SOURCES = \
+ testtray.c \
+ $(NULL)
+
+testtray_LDADD = \
+ libnotificationarea.la \
+ $(GUI_LIBS) \
+ $(NULL)
diff --git a/gui/simple-greeter/cutnpaste/fixedtip.c b/gui/simple-greeter/cutnpaste/fixedtip.c
new file mode 100644
index 00000000..83bb77ed
--- /dev/null
+++ b/gui/simple-greeter/cutnpaste/fixedtip.c
@@ -0,0 +1,261 @@
+/* Metacity fixed tooltip routine */
+
+/*
+ * Copyright (C) 2001 Havoc Pennington
+ * Copyright (C) 2003-2006 Vincent Untz
+ *
+ * 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.
+ */
+
+#include "fixedtip.h"
+
+/* Signals */
+enum
+{
+ CLICKED,
+ LAST_SIGNAL
+};
+
+static guint fixedtip_signals[LAST_SIGNAL] = { 0 };
+
+struct _NaFixedTipPrivate
+{
+ GtkWidget *parent;
+ GtkWidget *label;
+ GtkOrientation orientation;
+};
+
+G_DEFINE_TYPE (NaFixedTip, na_fixed_tip, GTK_TYPE_WINDOW)
+
+static gboolean
+button_press_handler (GtkWidget *fixedtip,
+ GdkEventButton *event,
+ gpointer data)
+{
+ if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
+ g_signal_emit (fixedtip, fixedtip_signals[CLICKED], 0);
+
+ return FALSE;
+}
+
+static gboolean
+expose_handler (GtkWidget *fixedtip)
+{
+ GtkRequisition req;
+
+ gtk_widget_size_request (fixedtip, &req);
+
+ gtk_paint_flat_box (fixedtip->style, fixedtip->window,
+ GTK_STATE_NORMAL, GTK_SHADOW_OUT,
+ NULL, fixedtip, "tooltip",
+ 0, 0, req.width, req.height);
+
+ return FALSE;
+}
+
+static void
+na_fixed_tip_class_init (NaFixedTipClass *class)
+{
+ fixedtip_signals[CLICKED] =
+ g_signal_new ("clicked",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (NaFixedTipClass, clicked),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ g_type_class_add_private (class, sizeof (NaFixedTipPrivate));
+}
+
+/* Did you already see this code? Yes, it's gtk_tooltips_force_window() ;-) */
+static void
+na_fixed_tip_init (NaFixedTip *fixedtip)
+{
+ GtkWidget *label;
+
+ fixedtip->priv = G_TYPE_INSTANCE_GET_PRIVATE (fixedtip, NA_TYPE_FIXED_TIP,
+ NaFixedTipPrivate);
+
+ gtk_window_set_type_hint (GTK_WINDOW (fixedtip),
+ GDK_WINDOW_TYPE_HINT_TOOLTIP);
+
+ gtk_widget_set_app_paintable (GTK_WIDGET (fixedtip), TRUE);
+ gtk_window_set_resizable (GTK_WINDOW (fixedtip), FALSE);
+ gtk_widget_set_name (GTK_WIDGET (fixedtip), "gtk-tooltips");
+ gtk_container_set_border_width (GTK_CONTAINER (fixedtip), 4);
+
+ label = gtk_label_new (NULL);
+ gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5);
+ gtk_widget_show (label);
+ gtk_container_add (GTK_CONTAINER (fixedtip), label);
+ fixedtip->priv->label = label;
+
+ g_signal_connect (fixedtip, "expose_event",
+ G_CALLBACK (expose_handler), NULL);
+
+ gtk_widget_add_events (GTK_WIDGET (fixedtip), GDK_BUTTON_PRESS_MASK);
+
+ g_signal_connect (fixedtip, "button_press_event",
+ G_CALLBACK (button_press_handler), NULL);
+
+ fixedtip->priv->orientation = GTK_ORIENTATION_HORIZONTAL;
+}
+
+static void
+na_fixed_tip_position (NaFixedTip *fixedtip)
+{
+ GdkScreen *screen;
+ GtkRequisition req;
+ int root_x;
+ int root_y;
+ int parent_width;
+ int parent_height;
+ int screen_width;
+ int screen_height;
+
+ screen = gtk_widget_get_screen (fixedtip->priv->parent);
+ gtk_window_set_screen (GTK_WINDOW (fixedtip), screen);
+
+ gtk_widget_size_request (GTK_WIDGET (fixedtip), &req);
+
+ gdk_window_get_origin (fixedtip->priv->parent->window, &root_x, &root_y);
+ gdk_drawable_get_size (GDK_DRAWABLE (fixedtip->priv->parent->window),
+ &parent_width, &parent_height);
+
+ screen_width = gdk_screen_get_width (screen);
+ screen_height = gdk_screen_get_height (screen);
+
+ /* pad between panel and message window */
+#define PAD 5
+
+ if (fixedtip->priv->orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ if (root_x <= screen_width / 2)
+ root_x += parent_width + PAD;
+ else
+ root_x -= req.width + PAD;
+ }
+ else
+ {
+ if (root_y <= screen_height / 2)
+ root_y += parent_height + PAD;
+ else
+ root_y -= req.height + PAD;
+ }
+
+ /* Push onscreen */
+ if ((root_x + req.width) > screen_width)
+ root_x = screen_width - req.width;
+
+ if ((root_y + req.height) > screen_height)
+ root_y = screen_height - req.height;
+
+ gtk_window_move (GTK_WINDOW (fixedtip), root_x, root_y);
+}
+
+static void
+na_fixed_tip_parent_size_allocated (GtkWidget *parent,
+ GtkAllocation *allocation,
+ NaFixedTip *fixedtip)
+{
+ na_fixed_tip_position (fixedtip);
+}
+
+static void
+na_fixed_tip_parent_screen_changed (GtkWidget *parent,
+ GdkScreen *new_screen,
+ NaFixedTip *fixedtip)
+{
+ na_fixed_tip_position (fixedtip);
+}
+
+GtkWidget *
+na_fixed_tip_new (GtkWidget *parent,
+ GtkOrientation orientation)
+{
+ NaFixedTip *fixedtip;
+
+ g_return_val_if_fail (parent != NULL, NULL);
+
+ fixedtip = g_object_new (NA_TYPE_FIXED_TIP, NULL);
+
+ /* It doesn't work if we do this in na_fixed_tip_init(), so do it here */
+ GTK_WINDOW (fixedtip)->type = GTK_WINDOW_POPUP;
+
+ fixedtip->priv->parent = parent;
+
+#if 0
+ //FIXME: would be nice to be able to get the toplevel for the tip, but this
+ //doesn't work
+ GtkWidget *toplevel;
+
+ toplevel = gtk_widget_get_toplevel (parent);
+ /*
+ if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel) && GTK_IS_WINDOW (toplevel))
+ gtk_window_set_transient_for (GTK_WINDOW (fixedtip), GTK_WINDOW (toplevel));
+ */
+#endif
+
+ fixedtip->priv->orientation = orientation;
+
+ //FIXME: would be nice to move the tip when the notification area moves
+ g_signal_connect_object (parent, "size-allocate",
+ G_CALLBACK (na_fixed_tip_parent_size_allocated),
+ fixedtip, 0);
+ g_signal_connect_object (parent, "screen-changed",
+ G_CALLBACK (na_fixed_tip_parent_screen_changed),
+ fixedtip, 0);
+
+ na_fixed_tip_position (fixedtip);
+
+ return GTK_WIDGET (fixedtip);
+}
+
+void
+na_fixed_tip_set_markup (GtkWidget *widget,
+ const char *markup_text)
+{
+ NaFixedTip *fixedtip;
+
+ g_return_if_fail (NA_IS_FIXED_TIP (widget));
+
+ fixedtip = NA_FIXED_TIP (widget);
+
+ gtk_label_set_markup (GTK_LABEL (fixedtip->priv->label),
+ markup_text);
+
+ na_fixed_tip_position (fixedtip);
+}
+
+void
+na_fixed_tip_set_orientation (GtkWidget *widget,
+ GtkOrientation orientation)
+{
+ NaFixedTip *fixedtip;
+
+ g_return_if_fail (NA_IS_FIXED_TIP (widget));
+
+ fixedtip = NA_FIXED_TIP (widget);
+
+ if (orientation == fixedtip->priv->orientation)
+ return;
+
+ fixedtip->priv->orientation = orientation;
+
+ na_fixed_tip_position (fixedtip);
+}
diff --git a/gui/simple-greeter/cutnpaste/fixedtip.h b/gui/simple-greeter/cutnpaste/fixedtip.h
new file mode 100644
index 00000000..a29e85c9
--- /dev/null
+++ b/gui/simple-greeter/cutnpaste/fixedtip.h
@@ -0,0 +1,68 @@
+/* Fixed tooltip routine */
+
+/*
+ * Copyright (C) 2001 Havoc Pennington, 2002 Red Hat Inc.
+ * Copyright (C) 2003-2006 Vincent Untz
+ *
+ * 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.
+ */
+
+#ifndef FIXED_TIP_H
+#define FIXED_TIP_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define NA_TYPE_FIXED_TIP (na_fixed_tip_get_type ())
+#define NA_FIXED_TIP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NA_TYPE_FIXED_TIP, NaFixedTip))
+#define NA_FIXED_TIP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NA_TYPE_FIXED_TIP, NaFixedTipClass))
+#define NA_IS_FIXED_TIP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NA_TYPE_FIXED_TIP))
+#define NA_IS_FIXED_TIP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NA_TYPE_FIXED_TIP))
+#define NA_FIXED_TIP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NA_TYPE_FIXED_TIP, NaFixedTipClass))
+
+typedef struct _NaFixedTip NaFixedTip;
+typedef struct _NaFixedTipPrivate NaFixedTipPrivate;
+typedef struct _NaFixedTipClass NaFixedTipClass;
+
+struct _NaFixedTip
+{
+ GtkWindow parent_instance;
+
+ NaFixedTipPrivate *priv;
+};
+
+struct _NaFixedTipClass
+{
+ GtkWindowClass parent_class;
+
+ void (* clicked) (NaFixedTip *fixedtip);
+};
+
+GType na_fixed_tip_get_type (void);
+
+GtkWidget *na_fixed_tip_new (GtkWidget *parent,
+ GtkOrientation orientation);
+
+void na_fixed_tip_set_markup (GtkWidget *widget,
+ const char *markup_text);
+
+void na_fixed_tip_set_orientation (GtkWidget *widget,
+ GtkOrientation orientation);
+
+G_END_DECLS
+
+#endif /* FIXED_TIP_H */
diff --git a/gui/simple-greeter/cutnpaste/na-marshal.list b/gui/simple-greeter/cutnpaste/na-marshal.list
new file mode 100644
index 00000000..e3fc3993
--- /dev/null
+++ b/gui/simple-greeter/cutnpaste/na-marshal.list
@@ -0,0 +1,3 @@
+VOID:OBJECT,OBJECT
+VOID:OBJECT,STRING,LONG,LONG
+VOID:OBJECT,LONG
diff --git a/gui/simple-greeter/cutnpaste/na-tray-manager.c b/gui/simple-greeter/cutnpaste/na-tray-manager.c
new file mode 100644
index 00000000..59fdca36
--- /dev/null
+++ b/gui/simple-greeter/cutnpaste/na-tray-manager.c
@@ -0,0 +1,907 @@
+/* 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Used to be: eggtraymanager.c
+ */
+
+#include <config.h>
+#include <string.h>
+#include <libintl.h>
+
+#include "na-tray-manager.h"
+
+#include <gdkconfig.h>
+#include <glib/gi18n.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/gtkinvisible.h>
+#include <gtk/gtksocket.h>
+#include <gtk/gtkwindow.h>
+
+#include "na-marshal.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);
+}
+
+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,
+ g_cclosure_marshal_VOID__OBJECT,
+ 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,
+ g_cclosure_marshal_VOID__OBJECT,
+ 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,
+ _na_marshal_VOID__OBJECT_STRING_LONG_LONG,
+ 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,
+ _na_marshal_VOID__OBJECT_LONG,
+ 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,
+ g_cclosure_marshal_VOID__VOID,
+ 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)
+{
+ Window *window;
+
+ window = g_object_get_data (G_OBJECT (socket), "na-tray-child-window");
+
+ g_hash_table_remove (manager->socket_table, GINT_TO_POINTER (*window));
+ g_object_set_data (G_OBJECT (socket), "na-tray-child-window",
+ NULL);
+
+ g_signal_emit (manager, manager_signals[TRAY_ICON_REMOVED], 0, socket);
+
+ /* This destroys the socket. */
+ return FALSE;
+}
+
+static void
+na_tray_manager_make_socket_transparent (GtkWidget *widget,
+ gpointer user_data)
+{
+ if (GTK_WIDGET_NO_WINDOW (widget))
+ return;
+
+ gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
+}
+
+static gboolean
+na_tray_manager_socket_exposed (GtkWidget *widget,
+ GdkEventExpose *event,
+ gpointer user_data)
+{
+ gdk_window_clear_area (widget->window,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+ return FALSE;
+}
+
+static void
+na_tray_manager_socket_style_set (GtkWidget *widget,
+ GtkStyle *previous_style,
+ gpointer user_data)
+{
+ if (widget->window == NULL)
+ return;
+
+ na_tray_manager_make_socket_transparent (widget, user_data);
+}
+
+static void
+na_tray_manager_handle_dock_request (NaTrayManager *manager,
+ XClientMessageEvent *xevent)
+{
+ GtkWidget *socket;
+ Window *window;
+ GtkRequisition req;
+
+ if (g_hash_table_lookup (manager->socket_table, GINT_TO_POINTER (xevent->data.l[2])))
+ {
+ /* We already got this notification earlier, ignore this one */
+ return;
+ }
+
+ socket = gtk_socket_new ();
+
+ gtk_widget_set_app_paintable (socket, TRUE);
+ //FIXME: need to find a theme where this (and expose event) is needed
+ gtk_widget_set_double_buffered (socket, FALSE);
+ g_signal_connect (socket, "realize",
+ G_CALLBACK (na_tray_manager_make_socket_transparent), NULL);
+ g_signal_connect (socket, "expose_event",
+ G_CALLBACK (na_tray_manager_socket_exposed), NULL);
+ g_signal_connect_after (socket, "style_set",
+ G_CALLBACK (na_tray_manager_socket_style_set), NULL);
+
+ /* We need to set the child window here
+ * so that the client can call _get functions
+ * in the signal handler
+ */
+ window = g_new (Window, 1);
+ *window = xevent->data.l[2];
+
+ g_object_set_data_full (G_OBJECT (socket),
+ "na-tray-child-window",
+ window, g_free);
+ g_signal_emit (manager, manager_signals[TRAY_ICON_ADDED], 0,
+ socket);
+
+ /* Add the socket only if it's been attached */
+ if (GTK_IS_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (socket))))
+ {
+ g_signal_connect (socket, "plug_removed",
+ G_CALLBACK (na_tray_manager_plug_removed), manager);
+
+ gtk_socket_add_id (GTK_SOCKET (socket), *window);
+
+ g_hash_table_insert (manager->socket_table, GINT_TO_POINTER (*window), socket);
+
+ /*
+ * Make sure the icons have a meaningfull size ...
+ */
+ req.width = req.height = 1;
+ gtk_widget_size_request (socket, &req);
+ /*
+ if ((req.width < 16) || (req.height < 16))
+ {
+ gint nw = MAX (24, req.width);
+ gint nh = MAX (24, req.height);
+ g_warning (_("tray icon has requested a size of (%i x %i), resizing to (%i x %i)"),
+ req.width, req.height, nw, nh);
+ gtk_widget_set_size_request(icon, nw, nh);
+ }
+ */
+ gtk_widget_show(socket);
+ }
+ else
+ gtk_widget_destroy (socket);
+}
+
+static void
+pending_message_free (PendingMessage *message)
+{
+ g_free (message->str);
+ g_free (message);
+}
+
+static GdkFilterReturn
+na_tray_manager_handle_client_message_message_data (GdkXEvent *xev,
+ GdkEvent *event,
+ gpointer data)
+{
+ XClientMessageEvent *xevent;
+ NaTrayManager *manager;
+ GList *p;
+ int len;
+
+ xevent = (XClientMessageEvent *) xev;
+ manager = data;
+
+ /* 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;
+ }
+ }
+
+ return GDK_FILTER_REMOVE;
+}
+
+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;
+
+ /* Check if the same message is already 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 &&
+ xevent->data.l[4] == msg->id)
+ {
+ /* Hmm, we found it, now remove it */
+ pending_message_free (msg);
+ manager->messages = g_list_remove_link (manager->messages, p);
+ g_list_free_1 (p);
+ break;
+ }
+ }
+
+ timeout = xevent->data.l[2];
+ len = xevent->data.l[3];
+ id = xevent->data.l[4];
+
+ 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;
+
+ /* 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 &&
+ xevent->data.l[4] == 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_handle_client_message_opcode (GdkXEvent *xev,
+ GdkEvent *event,
+ gpointer data)
+{
+ XClientMessageEvent *xevent;
+ NaTrayManager *manager;
+
+ xevent = (XClientMessageEvent *) xev;
+ manager = data;
+
+ switch (xevent->data.l[1])
+ {
+ case SYSTEM_TRAY_REQUEST_DOCK:
+ /* Ignore this one since we don't know on which window this was received
+ * and so we can't know for which screen this is. It will be handled
+ * in na_tray_manager_window_filter() since we also receive it there */
+ break;
+
+ case SYSTEM_TRAY_BEGIN_MESSAGE:
+ na_tray_manager_handle_begin_message (manager, xevent);
+ return GDK_FILTER_REMOVE;
+
+ case SYSTEM_TRAY_CANCEL_MESSAGE:
+ na_tray_manager_handle_cancel_message (manager, xevent);
+ return GDK_FILTER_REMOVE;
+ default:
+ break;
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+static GdkFilterReturn
+na_tray_manager_window_filter (GdkXEvent *xev,
+ GdkEvent *event,
+ gpointer data)
+{
+ XEvent *xevent = (GdkXEvent *)xev;
+ NaTrayManager *manager = data;
+
+ if (xevent->type == ClientMessage)
+ {
+ /* We handle this client message here. See comment in
+ * na_tray_manager_handle_client_message_opcode() for details */
+ 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;
+ }
+ }
+ 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;
+
+ if (manager->invisible == NULL)
+ return;
+
+ invisible = manager->invisible;
+ g_assert (GTK_IS_INVISIBLE (invisible));
+ g_assert (GTK_WIDGET_REALIZED (invisible));
+ g_assert (GDK_IS_WINDOW (invisible->window));
+
+ display = gtk_widget_get_display (invisible);
+
+ if (gdk_selection_owner_get_for_display (display, manager->selection_atom) ==
+ invisible->window)
+ {
+ timestamp = gdk_x11_get_server_time (invisible->window);
+ gdk_selection_owner_set_for_display (display,
+ NULL,
+ manager->selection_atom,
+ timestamp,
+ TRUE);
+ }
+
+ //FIXME: we should also use gdk_remove_client_message_filter when it's
+ //available
+ // See bug #351254
+ gdk_window_remove_filter (invisible->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
+ GdkDisplay *display;
+ Atom orientation_atom;
+ gulong data[1];
+
+ if (!manager->invisible || !manager->invisible->window)
+ return;
+
+ 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_XWINDOW (manager->invisible->window),
+ orientation_atom,
+ XA_CARDINAL, 32,
+ PropModeReplace,
+ (guchar *) &data, 1);
+#endif
+}
+
+#ifdef GDK_WINDOWING_X11
+
+static gboolean
+na_tray_manager_manage_screen_x11 (NaTrayManager *manager,
+ GdkScreen *screen)
+{
+ GdkDisplay *display;
+ Screen *xscreen;
+ GtkWidget *invisible;
+ 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
+ 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);
+
+ na_tray_manager_set_orientation_property (manager);
+
+ timestamp = gdk_x11_get_server_time (invisible->window);
+
+ /* Check if we could set the selection owner successfully */
+ if (gdk_selection_owner_set_for_display (display,
+ invisible->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_XWINDOW (invisible->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);
+
+ manager->invisible = invisible;
+ g_object_ref (G_OBJECT (manager->invisible));
+
+ 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);
+
+ /* 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
+ /* This is for SYSTEM_TRAY_REQUEST_DOCK and SelectionClear */
+ gdk_window_add_filter (invisible->window,
+ na_tray_manager_window_filter, manager);
+ /* This is for SYSTEM_TRAY_BEGIN_MESSAGE and SYSTEM_TRAY_CANCEL_MESSAGE */
+ gdk_display_add_client_message_filter (display, opcode_atom,
+ na_tray_manager_handle_client_message_opcode,
+ manager);
+ /* This is for _NET_SYSTEM_TRAY_MESSAGE_DATA */
+ gdk_display_add_client_message_filter (display, message_data_atom,
+ na_tray_manager_handle_client_message_message_data,
+ manager);
+ return TRUE;
+ }
+ else
+ {
+ gtk_widget_destroy (invisible);
+
+ 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
+}
+
+char *
+na_tray_manager_get_child_title (NaTrayManager *manager,
+ NaTrayManagerChild *child)
+{
+ char *retval = NULL;
+#ifdef GDK_WINDOWING_X11
+ GdkDisplay *display;
+ Window *child_window;
+ Atom utf8_string, atom, type;
+ int result;
+ int format;
+ gulong nitems;
+ gulong bytes_after;
+ gchar *val;
+
+ g_return_val_if_fail (NA_IS_TRAY_MANAGER (manager), NULL);
+ g_return_val_if_fail (GTK_IS_SOCKET (child), NULL);
+
+ display = gdk_screen_get_display (manager->screen);
+
+ child_window = g_object_get_data (G_OBJECT (child),
+ "na-tray-child-window");
+
+ utf8_string = gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING");
+ atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME");
+
+ gdk_error_trap_push ();
+
+ result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
+ *child_window,
+ atom,
+ 0, G_MAXLONG,
+ False, utf8_string,
+ &type, &format, &nitems,
+ &bytes_after, (guchar **)&val);
+
+ if (gdk_error_trap_pop () || result != Success)
+ return NULL;
+
+ if (type != utf8_string ||
+ format != 8 ||
+ nitems == 0)
+ {
+ if (val)
+ XFree (val);
+ return NULL;
+ }
+
+ if (!g_utf8_validate (val, nitems, NULL))
+ {
+ XFree (val);
+ return NULL;
+ }
+
+ retval = g_strndup (val, nitems);
+
+ XFree (val);
+#endif
+ return retval;
+}
+
+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");
+ }
+}
+
+GtkOrientation
+na_tray_manager_get_orientation (NaTrayManager *manager)
+{
+ g_return_val_if_fail (NA_IS_TRAY_MANAGER (manager), GTK_ORIENTATION_HORIZONTAL);
+
+ return manager->orientation;
+}
diff --git a/gui/simple-greeter/cutnpaste/na-tray-manager.h b/gui/simple-greeter/cutnpaste/na-tray-manager.h
new file mode 100644
index 00000000..4d4e7880
--- /dev/null
+++ b/gui/simple-greeter/cutnpaste/na-tray-manager.h
@@ -0,0 +1,98 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* na-tray-manager.h
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Used to be: eggtraymanager.h
+ */
+
+#ifndef __NA_TRAY_MANAGER_H__
+#define __NA_TRAY_MANAGER_H__
+
+#include <gtk/gtkwidget.h>
+#ifdef GDK_WINDOWING_X11
+#include <gdk/gdkx.h>
+#endif
+
+G_BEGIN_DECLS
+
+#define NA_TYPE_TRAY_MANAGER (na_tray_manager_get_type ())
+#define NA_TRAY_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NA_TYPE_TRAY_MANAGER, NaTrayManager))
+#define NA_TRAY_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NA_TYPE_TRAY_MANAGER, NaTrayManagerClass))
+#define NA_IS_TRAY_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NA_TYPE_TRAY_MANAGER))
+#define NA_IS_TRAY_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NA_TYPE_TRAY_MANAGER))
+#define NA_TRAY_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NA_TYPE_TRAY_MANAGER, NaTrayManagerClass))
+
+typedef struct _NaTrayManager NaTrayManager;
+typedef struct _NaTrayManagerClass NaTrayManagerClass;
+typedef struct _NaTrayManagerChild NaTrayManagerChild;
+
+struct _NaTrayManager
+{
+ GObject parent_instance;
+
+#ifdef GDK_WINDOWING_X11
+ GdkAtom selection_atom;
+ Atom opcode_atom;
+#endif
+
+ GtkWidget *invisible;
+ GdkScreen *screen;
+ GtkOrientation orientation;
+
+ GList *messages;
+ GHashTable *socket_table;
+};
+
+struct _NaTrayManagerClass
+{
+ GObjectClass parent_class;
+
+ void (* tray_icon_added) (NaTrayManager *manager,
+ NaTrayManagerChild *child);
+ void (* tray_icon_removed) (NaTrayManager *manager,
+ NaTrayManagerChild *child);
+
+ void (* message_sent) (NaTrayManager *manager,
+ NaTrayManagerChild *child,
+ const gchar *message,
+ glong id,
+ glong timeout);
+
+ void (* message_cancelled) (NaTrayManager *manager,
+ NaTrayManagerChild *child,
+ glong id);
+
+ void (* lost_selection) (NaTrayManager *manager);
+};
+
+GType na_tray_manager_get_type (void);
+
+gboolean na_tray_manager_check_running (GdkScreen *screen);
+NaTrayManager *na_tray_manager_new (void);
+gboolean na_tray_manager_manage_screen (NaTrayManager *manager,
+ GdkScreen *screen);
+char *na_tray_manager_get_child_title (NaTrayManager *manager,
+ NaTrayManagerChild *child);
+void na_tray_manager_set_orientation (NaTrayManager *manager,
+ GtkOrientation orientation);
+GtkOrientation na_tray_manager_get_orientation (NaTrayManager *manager);
+
+G_END_DECLS
+
+#endif /* __NA_TRAY_MANAGER_H__ */
diff --git a/gui/simple-greeter/cutnpaste/na-tray.c b/gui/simple-greeter/cutnpaste/na-tray.c
new file mode 100644
index 00000000..9bfc19f2
--- /dev/null
+++ b/gui/simple-greeter/cutnpaste/na-tray.c
@@ -0,0 +1,679 @@
+/*
+ * Copyright (C) 2002 Red Hat, Inc.
+ * Copyright (C) 2003-2006 Vincent Untz
+ * Copyright (C) 2007 Christian Persch
+ *
+ * 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.
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+
+#include "na-tray-manager.h"
+#include "fixedtip.h"
+#include "obox.h"
+
+#include "na-tray.h"
+
+#define ICON_SPACING 1
+#define MIN_BOX_SIZE 3
+
+typedef struct
+{
+ NaTrayManager *tray_manager;
+ GSList *all_trays;
+ GHashTable *icon_table;
+ GHashTable *tip_table;
+} TraysScreen;
+
+struct _NaTrayPrivate
+{
+ GdkScreen *screen;
+ TraysScreen *trays_screen;
+
+ GtkWidget *box;
+ GtkWidget *frame;
+
+ guint idle_redraw_id;
+
+ GtkOrientation orientation;
+};
+
+typedef struct
+{
+ char *text;
+ glong id;
+ glong timeout;
+} IconTipBuffer;
+
+typedef struct
+{
+ NaTray *tray; /* tray containing the tray icon */
+ GtkWidget *icon; /* tray icon sending the message */
+ GtkWidget *fixedtip;
+ guint source_id;
+ glong id; /* id of the current message */
+ GSList *buffer; /* buffered messages */
+} IconTip;
+
+enum
+{
+ PROP_0,
+ PROP_ORIENTATION,
+ PROP_SCREEN
+};
+
+static gboolean initialized = FALSE;
+static TraysScreen *trays_screens = NULL;
+
+static void icon_tip_show_next (IconTip *icontip);
+
+G_DEFINE_TYPE (NaTray, na_tray, GTK_TYPE_BIN);
+
+static NaTray *
+get_tray (TraysScreen *trays_screen)
+{
+ if (trays_screen->all_trays == NULL)
+ return NULL;
+
+ return trays_screen->all_trays->data;
+}
+
+static void
+tray_added (NaTrayManager *manager,
+ GtkWidget *icon,
+ TraysScreen *trays_screen)
+{
+ NaTray *tray;
+ NaTrayPrivate *priv;
+
+ tray = get_tray (trays_screen);
+ if (tray == NULL)
+ return;
+
+ priv = tray->priv;
+
+ g_assert (priv->trays_screen == trays_screen);
+
+ g_hash_table_insert (trays_screen->icon_table, icon, tray);
+
+ gtk_box_pack_end (GTK_BOX (priv->box), icon, FALSE, FALSE, 0);
+
+ gtk_widget_show (icon);
+ na_tray_force_redraw (tray);
+}
+
+static void
+tray_removed (NaTrayManager *manager,
+ GtkWidget *icon,
+ TraysScreen *trays_screen)
+{
+ NaTray *tray;
+
+ tray = g_hash_table_lookup (trays_screen->icon_table, icon);
+ if (tray == NULL)
+ return;
+
+ g_assert (tray->priv->trays_screen == trays_screen);
+
+ na_tray_force_redraw (tray);
+
+ g_hash_table_remove (trays_screen->icon_table, icon);
+ /* this will also destroy the tip associated to this icon */
+ g_hash_table_remove (trays_screen->tip_table, icon);
+}
+
+static void
+icon_tip_buffer_free (gpointer data,
+ gpointer userdata)
+{
+ IconTipBuffer *buffer;
+
+ buffer = data;
+
+ g_free (buffer->text);
+ buffer->text = NULL;
+
+ g_free (buffer);
+}
+
+static void
+icon_tip_free (gpointer data)
+{
+ IconTip *icontip;
+
+ if (data == NULL)
+ return;
+
+ icontip = data;
+
+ if (icontip->fixedtip != NULL)
+ gtk_widget_destroy (GTK_WIDGET (icontip->fixedtip));
+ icontip->fixedtip = NULL;
+
+ if (icontip->source_id != 0)
+ g_source_remove (icontip->source_id);
+ icontip->source_id = 0;
+
+ if (icontip->buffer != NULL)
+ {
+ g_slist_foreach (icontip->buffer, icon_tip_buffer_free, NULL);
+ g_slist_free (icontip->buffer);
+ }
+ icontip->buffer = NULL;
+
+ g_free (icontip);
+}
+
+static int
+icon_tip_buffer_compare (gconstpointer a,
+ gconstpointer b)
+{
+ const IconTipBuffer *buffer_a = a;
+ const IconTipBuffer *buffer_b = b;
+
+ if (buffer_a == NULL || buffer_b == NULL)
+ return !(buffer_a == buffer_b);
+
+ return buffer_a->id - buffer_b->id;
+}
+
+static void
+icon_tip_show_next_clicked (GtkWidget *widget,
+ gpointer data)
+{
+ icon_tip_show_next ((IconTip *) data);
+}
+
+static gboolean
+icon_tip_show_next_timeout (gpointer data)
+{
+ IconTip *icontip = (IconTip *) data;
+
+ icon_tip_show_next (icontip);
+
+ return FALSE;
+}
+
+static void
+icon_tip_show_next (IconTip *icontip)
+{
+ IconTipBuffer *buffer;
+
+ if (icontip->buffer == NULL)
+ {
+ /* this will also destroy the tip window */
+ g_hash_table_remove (icontip->tray->priv->trays_screen->tip_table,
+ icontip->icon);
+ return;
+ }
+
+ if (icontip->source_id != 0)
+ g_source_remove (icontip->source_id);
+ icontip->source_id = 0;
+
+ buffer = icontip->buffer->data;
+ icontip->buffer = g_slist_remove (icontip->buffer, buffer);
+
+ if (icontip->fixedtip == NULL)
+ {
+ icontip->fixedtip = na_fixed_tip_new (icontip->icon,
+ na_tray_get_orientation (icontip->tray));
+
+ g_signal_connect (icontip->fixedtip, "clicked",
+ G_CALLBACK (icon_tip_show_next_clicked), icontip);
+ }
+
+ na_fixed_tip_set_markup (icontip->fixedtip, buffer->text);
+
+ if (!GTK_WIDGET_MAPPED (icontip->fixedtip))
+ gtk_widget_show (icontip->fixedtip);
+
+ icontip->id = buffer->id;
+
+ if (buffer->timeout > 0)
+ icontip->source_id = g_timeout_add (buffer->timeout * 1000,
+ icon_tip_show_next_timeout, icontip);
+
+ icon_tip_buffer_free (buffer, NULL);
+}
+
+static void
+message_sent (NaTrayManager *manager,
+ GtkWidget *icon,
+ const char *text,
+ glong id,
+ glong timeout,
+ TraysScreen *trays_screen)
+{
+ IconTip *icontip;
+ IconTipBuffer find_buffer;
+ IconTipBuffer *buffer;
+ gboolean show_now;
+
+ icontip = g_hash_table_lookup (trays_screen->tip_table, icon);
+
+ find_buffer.id = id;
+ if (icontip &&
+ (icontip->id == id ||
+ g_slist_find_custom (icontip->buffer, &find_buffer,
+ icon_tip_buffer_compare) != NULL))
+ /* we already have this message, so ignore it */
+ /* FIXME: in an ideal world, we'd remember all the past ids and ignore them
+ * too */
+ return;
+
+ show_now = FALSE;
+
+ if (icontip == NULL)
+ {
+ NaTray *tray;
+
+ tray = g_hash_table_lookup (trays_screen->icon_table, icon);
+ if (tray == NULL)
+ {
+ /* We don't know about the icon sending the message, so ignore it.
+ * But this should never happen since NaTrayManager shouldn't send
+ * us the message if there's no socket for it. */
+ g_critical ("Ignoring a message sent by a tray icon "
+ "we don't know: \"%s\".\n", text);
+ return;
+ }
+
+ icontip = g_new0 (IconTip, 1);
+ icontip->tray = tray;
+ icontip->icon = icon;
+
+ g_hash_table_insert (trays_screen->tip_table, icon, icontip);
+
+ show_now = TRUE;
+ }
+
+ buffer = g_new0 (IconTipBuffer, 1);
+
+ buffer->text = g_strdup (text);
+ buffer->id = id;
+ buffer->timeout = timeout;
+
+ icontip->buffer = g_slist_append (icontip->buffer, buffer);
+
+ if (show_now)
+ icon_tip_show_next (icontip);
+}
+
+static void
+message_cancelled (NaTrayManager *manager,
+ GtkWidget *icon,
+ glong id,
+ TraysScreen *trays_screen)
+{
+ IconTip *icontip;
+ IconTipBuffer find_buffer;
+ GSList *cancel_buffer_l;
+ IconTipBuffer *cancel_buffer;
+
+ icontip = g_hash_table_lookup (trays_screen->tip_table, icon);
+ if (icontip == NULL)
+ return;
+
+ if (icontip->id == id)
+ {
+ icon_tip_show_next (icontip);
+ return;
+ }
+
+ find_buffer.id = id;
+ cancel_buffer_l = g_slist_find_custom (icontip->buffer, &find_buffer,
+ icon_tip_buffer_compare);
+ if (cancel_buffer_l == NULL)
+ return;
+
+ cancel_buffer = cancel_buffer_l->data;
+ icon_tip_buffer_free (cancel_buffer, NULL);
+
+ icontip->buffer = g_slist_remove_link (icontip->buffer, cancel_buffer_l);
+ g_slist_free_1 (cancel_buffer_l);
+}
+
+static void
+update_orientation_for_messages (gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ NaTray *tray;
+ IconTip *icontip;
+
+ if (value == NULL)
+ return;
+
+ icontip = value;
+ tray = data;
+ if (icontip->tray != tray)
+ return;
+
+ if (icontip->fixedtip)
+ na_fixed_tip_set_orientation (icontip->fixedtip, tray->priv->orientation);
+}
+
+static void
+update_size_and_orientation (NaTray *tray)
+{
+ NaTrayPrivate *priv = tray->priv;
+
+ na_obox_set_orientation (NA_OBOX (priv->box), priv->orientation);
+
+ /* This only happens when setting the property during object construction */
+ if (!priv->trays_screen)
+ return;
+
+ g_hash_table_foreach (priv->trays_screen->tip_table,
+ update_orientation_for_messages, tray);
+
+ if (get_tray (priv->trays_screen) == tray)
+ na_tray_manager_set_orientation (priv->trays_screen->tray_manager,
+ priv->orientation);
+
+ /* note, you want this larger if the frame has non-NONE relief by default. */
+ switch (priv->orientation)
+ {
+ case GTK_ORIENTATION_VERTICAL:
+ /* Give box a min size so the frame doesn't look dumb */
+ gtk_widget_set_size_request (priv->box, MIN_BOX_SIZE, -1);
+ break;
+ case GTK_ORIENTATION_HORIZONTAL:
+ gtk_widget_set_size_request (priv->box, -1, MIN_BOX_SIZE);
+ break;
+ }
+
+ na_tray_force_redraw (tray);
+}
+
+static void
+na_tray_init (NaTray *tray)
+{
+ NaTrayPrivate *priv;
+
+ priv = tray->priv = G_TYPE_INSTANCE_GET_PRIVATE (tray, NA_TYPE_TRAY, NaTrayPrivate);
+
+ priv->screen = NULL;
+ priv->orientation = GTK_ORIENTATION_HORIZONTAL;
+
+ priv->frame = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
+ gtk_container_add (GTK_CONTAINER (tray), priv->frame);
+ gtk_widget_show (priv->frame);
+
+ priv->box = na_obox_new ();
+ gtk_box_set_spacing (GTK_BOX (priv->box), ICON_SPACING);
+ gtk_container_add (GTK_CONTAINER (priv->frame), priv->box);
+ gtk_widget_show (priv->box);
+}
+
+static GObject *
+na_tray_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object;
+ NaTray *tray;
+ NaTrayPrivate *priv;
+ int screen_number;
+
+ object = G_OBJECT_CLASS (na_tray_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_params);
+ tray = NA_TRAY (object);
+ priv = tray->priv;
+
+ g_assert (priv->screen != NULL);
+
+ if (!initialized)
+ {
+ GdkDisplay *display;
+ int n_screens;
+
+ display = gdk_display_get_default ();
+ n_screens = gdk_display_get_n_screens (display);
+ trays_screens = g_new0 (TraysScreen, n_screens);
+ initialized = TRUE;
+ }
+
+ screen_number = gdk_screen_get_number (priv->screen);
+
+ if (trays_screens [screen_number].tray_manager == NULL)
+ {
+ NaTrayManager *tray_manager;
+
+ tray_manager = na_tray_manager_new ();
+
+ if (na_tray_manager_manage_screen (tray_manager, priv->screen))
+ {
+ trays_screens [screen_number].tray_manager = tray_manager;
+
+ g_signal_connect (tray_manager, "tray_icon_added",
+ G_CALLBACK (tray_added),
+ &trays_screens [screen_number]);
+ g_signal_connect (tray_manager, "tray_icon_removed",
+ G_CALLBACK (tray_removed),
+ &trays_screens [screen_number]);
+ g_signal_connect (tray_manager, "message_sent",
+ G_CALLBACK (message_sent),
+ &trays_screens [screen_number]);
+ g_signal_connect (tray_manager, "message_cancelled",
+ G_CALLBACK (message_cancelled),
+ &trays_screens [screen_number]);
+
+ trays_screens [screen_number].icon_table = g_hash_table_new (NULL,
+ NULL);
+ trays_screens [screen_number].tip_table = g_hash_table_new_full (
+ NULL,
+ NULL,
+ NULL,
+ icon_tip_free);
+ }
+ else
+ {
+ g_printerr ("System tray didn't get the system tray manager selection for screen %d\n",
+ screen_number);
+ g_object_unref (tray_manager);
+ }
+ }
+
+ priv->trays_screen = &trays_screens [screen_number];
+ trays_screens [screen_number].all_trays = g_slist_append (trays_screens [screen_number].all_trays,
+ tray);
+
+ update_size_and_orientation (tray);
+
+ return object;
+}
+
+static void
+na_tray_dispose (GObject *object)
+{
+ NaTray *tray = NA_TRAY (object);
+ NaTrayPrivate *priv = tray->priv;
+ TraysScreen *trays_screen = priv->trays_screen;
+
+ if (trays_screen != NULL)
+ {
+ trays_screen->all_trays = g_slist_remove (trays_screen->all_trays, tray);
+
+ if (trays_screen->all_trays == NULL)
+ {
+ /* Make sure we drop the manager selection */
+ g_object_unref (trays_screen->tray_manager);
+ trays_screen->tray_manager = NULL;
+
+ g_hash_table_destroy (trays_screen->icon_table);
+ trays_screen->icon_table = NULL;
+
+ g_hash_table_destroy (trays_screen->tip_table);
+ trays_screen->tip_table = NULL;
+ }
+ else
+ {
+ NaTray *new_tray;
+
+ new_tray = get_tray (trays_screen);
+ if (new_tray != NULL)
+ na_tray_manager_set_orientation (trays_screen->tray_manager,
+ na_tray_get_orientation (new_tray));
+ }
+ }
+
+ priv->trays_screen = NULL;
+
+ if (priv->idle_redraw_id != 0)
+ {
+ g_source_remove (priv->idle_redraw_id);
+ priv->idle_redraw_id = 0;
+ }
+
+ G_OBJECT_CLASS (na_tray_parent_class)->dispose (object);
+}
+
+static void
+na_tray_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ NaTray *tray = NA_TRAY (object);
+ NaTrayPrivate *priv = tray->priv;
+
+ switch (prop_id)
+ {
+ case PROP_ORIENTATION:
+ na_tray_set_orientation (tray, g_value_get_enum (value));
+ break;
+ case PROP_SCREEN:
+ priv->screen = g_value_get_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+na_tray_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ gtk_widget_size_request (gtk_bin_get_child (GTK_BIN (widget)), requisition);
+}
+
+static void
+na_tray_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ gtk_widget_size_allocate (gtk_bin_get_child (GTK_BIN (widget)), allocation);
+}
+
+static void
+na_tray_class_init (NaTrayClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gobject_class->constructor = na_tray_constructor;
+ gobject_class->set_property = na_tray_set_property;
+ gobject_class->dispose = na_tray_dispose;
+
+ widget_class->size_request = na_tray_size_request;
+ widget_class->size_allocate = na_tray_size_allocate;
+
+ g_object_class_install_property
+ (gobject_class,
+ PROP_ORIENTATION,
+ g_param_spec_enum ("orientation", "orientation", "orientation",
+ GTK_TYPE_ORIENTATION,
+ GTK_ORIENTATION_HORIZONTAL,
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ g_object_class_install_property
+ (gobject_class,
+ PROP_SCREEN,
+ g_param_spec_object ("screen", "screen", "screen",
+ GDK_TYPE_SCREEN,
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ g_type_class_add_private (gobject_class, sizeof (NaTrayPrivate));
+}
+
+NaTray *
+na_tray_new_for_screen (GdkScreen *screen,
+ GtkOrientation orientation)
+{
+ return g_object_new (NA_TYPE_TRAY,
+ "screen", screen,
+ "orientation", orientation,
+ NULL);
+}
+
+void
+na_tray_set_orientation (NaTray *tray,
+ GtkOrientation orientation)
+{
+ NaTrayPrivate *priv = tray->priv;
+
+ if (orientation == priv->orientation)
+ return;
+
+ priv->orientation = orientation;
+
+ update_size_and_orientation (tray);
+}
+
+GtkOrientation
+na_tray_get_orientation (NaTray *tray)
+{
+ return tray->priv->orientation;
+}
+
+static gboolean
+idle_redraw_cb (NaTray *tray)
+{
+ NaTrayPrivate *priv = tray->priv;
+
+ priv->idle_redraw_id = 0;
+ gtk_widget_hide (priv->box);
+ gtk_widget_show (priv->box);
+
+ return FALSE;
+}
+
+void
+na_tray_force_redraw (NaTray *tray)
+{
+ NaTrayPrivate *priv = tray->priv;
+
+ /* Force the icons to redraw their backgrounds.
+ * gtk_widget_queue_draw() doesn't work across process boundaries,
+ * so we do this instead.
+ */
+ if (priv->idle_redraw_id == 0)
+ priv->idle_redraw_id = g_idle_add ((GSourceFunc) idle_redraw_cb, tray);
+}
diff --git a/gui/simple-greeter/cutnpaste/na-tray.h b/gui/simple-greeter/cutnpaste/na-tray.h
new file mode 100644
index 00000000..db6f058a
--- /dev/null
+++ b/gui/simple-greeter/cutnpaste/na-tray.h
@@ -0,0 +1,68 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* na-tray-tray.h
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Used to be: eggtraytray.h
+ */
+
+#ifndef __NA_TRAY_H__
+#define __NA_TRAY_H__
+
+#include <gtk/gtkwidget.h>
+#ifdef GDK_WINDOWING_X11
+#include <gdk/gdkx.h>
+#endif
+
+G_BEGIN_DECLS
+
+#define NA_TYPE_TRAY (na_tray_get_type ())
+#define NA_TRAY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NA_TYPE_TRAY, NaTray))
+#define NA_TRAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NA_TYPE_TRAY, NaTrayClass))
+#define NA_IS_TRAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NA_TYPE_TRAY))
+#define NA_IS_TRAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NA_TYPE_TRAY))
+#define NA_TRAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NA_TYPE_TRAY, NaTrayClass))
+
+typedef struct _NaTray NaTray;
+typedef struct _NaTrayPrivate NaTrayPrivate;
+typedef struct _NaTrayClass NaTrayClass;
+typedef struct _NaTrayChild NaTrayChild;
+
+struct _NaTray
+{
+ GtkBin parent_instance;
+
+ NaTrayPrivate *priv;
+};
+
+struct _NaTrayClass
+{
+ GtkBinClass parent_class;
+};
+
+GType na_tray_get_type (void);
+NaTray *na_tray_new_for_screen (GdkScreen *screen,
+ GtkOrientation orientation);
+void na_tray_set_orientation (NaTray *tray,
+ GtkOrientation orientation);
+GtkOrientation na_tray_get_orientation (NaTray *tray);
+void na_tray_force_redraw (NaTray *tray);
+
+G_END_DECLS
+
+#endif /* __NA_TRAY_H__ */
diff --git a/gui/simple-greeter/cutnpaste/obox.c b/gui/simple-greeter/cutnpaste/obox.c
new file mode 100644
index 00000000..96e4265c
--- /dev/null
+++ b/gui/simple-greeter/cutnpaste/obox.c
@@ -0,0 +1,130 @@
+/* OBox Copyright (C) 2002 Red Hat Inc. based on GtkHBox */
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GTK+ Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#include "obox.h"
+
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkvbox.h>
+
+static void na_obox_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void na_obox_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+
+
+G_DEFINE_TYPE (NaOBox, na_obox, GTK_TYPE_BOX)
+
+static void
+na_obox_class_init (NaOBoxClass *class)
+{
+ GtkWidgetClass *widget_class;
+
+ widget_class = (GtkWidgetClass*) class;
+
+ widget_class->size_request = na_obox_size_request;
+ widget_class->size_allocate = na_obox_size_allocate;
+}
+
+static void
+na_obox_init (NaOBox *obox)
+{
+ obox->orientation = GTK_ORIENTATION_HORIZONTAL;
+}
+
+GtkWidget*
+na_obox_new (void)
+{
+ NaOBox *obox;
+
+ obox = g_object_new (NA_TYPE_OBOX, NULL);
+
+ return GTK_WIDGET (obox);
+}
+
+static GtkWidgetClass*
+get_class (NaOBox *obox)
+{
+ GtkWidgetClass *klass;
+
+ switch (obox->orientation)
+ {
+ case GTK_ORIENTATION_HORIZONTAL:
+ klass = GTK_WIDGET_CLASS (gtk_type_class (GTK_TYPE_HBOX));
+ break;
+ case GTK_ORIENTATION_VERTICAL:
+ klass = GTK_WIDGET_CLASS (gtk_type_class (GTK_TYPE_VBOX));
+ break;
+ default:
+ g_assert_not_reached ();
+ klass = NULL;
+ break;
+ }
+
+ return klass;
+}
+
+static void
+na_obox_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkWidgetClass *klass;
+ NaOBox *obox;
+
+ obox = NA_OBOX (widget);
+
+ klass = get_class (obox);
+
+ klass->size_request (widget, requisition);
+}
+
+static void
+na_obox_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkWidgetClass *klass;
+ NaOBox *obox;
+
+ obox = NA_OBOX (widget);
+
+ klass = get_class (obox);
+
+ klass->size_allocate (widget, allocation);
+}
+
+void
+na_obox_set_orientation (NaOBox *obox,
+ GtkOrientation orientation)
+{
+ g_return_if_fail (NA_IS_OBOX (obox));
+
+ if (obox->orientation == orientation)
+ return;
+
+ obox->orientation = orientation;
+
+ gtk_widget_queue_resize (GTK_WIDGET (obox));
+}
diff --git a/gui/simple-greeter/cutnpaste/obox.h b/gui/simple-greeter/cutnpaste/obox.h
new file mode 100644
index 00000000..5995da46
--- /dev/null
+++ b/gui/simple-greeter/cutnpaste/obox.h
@@ -0,0 +1,73 @@
+/* OBox Copyright (C) 2002 Red Hat Inc. based on GtkHBox */
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GTK+ Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#ifndef __NA_OBOX_H__
+#define __NA_OBOX_H__
+
+#include <gtk/gtkbox.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define NA_TYPE_OBOX (na_obox_get_type ())
+#define NA_OBOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NA_TYPE_OBOX, NaOBox))
+#define NA_OBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NA_TYPE_OBOX, NaOBoxClass))
+#define NA_IS_OBOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NA_TYPE_OBOX))
+#define NA_IS_OBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NA_TYPE_OBOX))
+#define NA_OBOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NA_TYPE_OBOX, NaOBoxClass))
+
+
+typedef struct _NaOBox NaOBox;
+typedef struct _NaOBoxClass NaOBoxClass;
+
+struct _NaOBox
+{
+ GtkBox box;
+
+ GtkOrientation orientation;
+};
+
+struct _NaOBoxClass
+{
+ GtkBoxClass parent_class;
+};
+
+
+GType na_obox_get_type (void) G_GNUC_CONST;
+GtkWidget* na_obox_new (void);
+
+void na_obox_set_orientation (NaOBox *obox,
+ GtkOrientation orientation);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __NA_OBOX_H__ */
diff --git a/gui/simple-greeter/cutnpaste/testtray.c b/gui/simple-greeter/cutnpaste/testtray.c
new file mode 100644
index 00000000..42d37329
--- /dev/null
+++ b/gui/simple-greeter/cutnpaste/testtray.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2002 Anders Carlsson <andersca@gnu.org>
+ * Copyright (C) 2003-2006 Vincent Untz
+ * Copyright (C) 2006, 2007 Christian Persch
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <gtk/gtk.h>
+#include "na-tray-manager.h"
+#include "na-tray.h"
+
+#define NOTIFICATION_AREA_ICON "gnome-panel-notification-area"
+
+static guint n_windows = 0;
+
+typedef struct
+{
+ GdkScreen *screen;
+ guint screen_num;
+ GtkWidget *window;
+ NaTray *tray;
+ GtkWidget *box;
+ GtkLabel *count_label;
+} TrayData;
+
+static void
+do_add (GtkWidget *child, guint *n_children)
+{
+ *n_children += 1;
+}
+
+static void
+update_child_count (TrayData *data)
+{
+ guint n_children = 0;
+ char text[64];
+
+ if (!GTK_WIDGET_REALIZED (data->window))
+ return;
+
+ gtk_container_foreach (GTK_CONTAINER (data->box), (GtkCallback) do_add, &n_children);
+
+ g_snprintf (text, sizeof (text), "%u icons", n_children);
+ gtk_label_set_text (data->count_label, text);
+}
+
+static void
+tray_added_cb (GtkContainer *box, GtkWidget *icon, TrayData *data)
+{
+ g_print ("[Screen %u tray %p] Child %p added to tray: \"%s\"\n",
+ data->screen_num, data->tray, icon, "XXX");//na_tray_manager_get_child_title (manager, icon));
+
+ update_child_count (data);
+}
+
+static void
+tray_removed_cb (GtkContainer *box, GtkWidget *icon, TrayData *data)
+{
+ g_print ("[Screen %u tray %p] Child %p removed from tray\n",
+ data->screen_num, data->tray, icon);
+
+ update_child_count (data);
+}
+
+static void orientation_changed_cb (GtkComboBox *combo, TrayData *data)
+{
+ GtkOrientation orientation = (GtkOrientation) gtk_combo_box_get_active (combo);
+
+ g_print ("[Screen %u tray %p] Setting orientation to \"%s\"\n",
+ data->screen_num, data->tray, orientation == 0 ? "horizontal" : "vertical");
+
+ na_tray_set_orientation (data->tray, orientation);
+}
+
+static void
+maybe_quit (gpointer data,
+ GObject *zombie)
+{
+ if (--n_windows == 0) {
+ gtk_main_quit ();
+ }
+}
+
+static TrayData *create_tray_on_screen (GdkScreen *screen, gboolean force);
+
+static void
+warning_dialog_response_cb (GtkWidget *dialog,
+ gint response,
+ GdkScreen *screen)
+{
+ if (response == GTK_RESPONSE_YES) {
+ create_tray_on_screen (screen, TRUE);
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+add_tray_cb (GtkWidget *button, TrayData *data)
+{
+ create_tray_on_screen (data->screen, TRUE);
+}
+
+static TrayData *
+create_tray_on_screen (GdkScreen *screen,
+ gboolean force)
+{
+ GtkWidget *window, *hbox, *vbox, *button, *combo, *label;
+ TrayData *data;
+
+ n_windows++;
+
+ if (!force && na_tray_manager_check_running (screen)) {
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO,
+ "Override tray manager?");
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "There is already a tray manager running on screen %d.",
+ gdk_screen_get_number (screen));
+ gtk_window_set_screen (GTK_WINDOW (dialog), screen);
+ g_signal_connect (dialog, "response", G_CALLBACK (warning_dialog_response_cb), screen);
+ gtk_window_present (GTK_WINDOW (dialog));
+ g_object_weak_ref (G_OBJECT (dialog), (GWeakNotify) maybe_quit, NULL);
+ return NULL;
+ }
+
+ data = g_new0 (TrayData, 1);
+ data->screen = screen;
+ data->screen_num = gdk_screen_get_number (screen);
+
+ data->window = window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ g_object_weak_ref (G_OBJECT (window), (GWeakNotify) maybe_quit, NULL);
+
+ vbox = gtk_vbox_new (FALSE, 6);
+ gtk_container_add (GTK_CONTAINER (window), vbox);
+
+ button = gtk_button_new_with_mnemonic ("_Add another tray");
+ g_signal_connect (button, "clicked", G_CALLBACK (add_tray_cb), data);
+ gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+ label = gtk_label_new_with_mnemonic ("_Orientation:");
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+ combo = gtk_combo_box_new_text ();
+ gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "Horizontal");
+ gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "Vertical");
+ g_signal_connect (combo, "changed",
+ G_CALLBACK (orientation_changed_cb), data);
+ gtk_box_pack_start (GTK_BOX (hbox), combo, FALSE, FALSE, 0);
+
+ label = gtk_label_new (NULL);
+ data->count_label = GTK_LABEL (label);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+
+ data->tray = na_tray_new_for_screen (screen, GTK_ORIENTATION_HORIZONTAL);
+ gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (data->tray), TRUE, TRUE, 0);
+
+ data->box = GTK_BIN (GTK_BIN (data->tray)->child)->child;
+ g_signal_connect_after (data->box, "add", G_CALLBACK (tray_added_cb), data);
+ g_signal_connect_after (data->box, "remove", G_CALLBACK (tray_removed_cb), data);
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
+
+ gtk_window_set_screen (GTK_WINDOW (window), screen);
+ gtk_window_set_default_size (GTK_WINDOW (window), -1, 200);
+
+ /* gtk_window_set_resizable (GTK_WINDOW (window), FALSE); */
+
+ gtk_widget_show_all (window);
+
+ update_child_count (data);
+
+ return data;
+}
+
+int
+main (int argc, char *argv[])
+{
+ GdkDisplay *display;
+ GdkScreen *screen;
+ int n_screens, i;
+
+ gtk_init (&argc, &argv);
+
+ gtk_window_set_default_icon_name (NOTIFICATION_AREA_ICON);
+
+ display = gdk_display_get_default ();
+ n_screens = gdk_display_get_n_screens (display);
+ for (i = 0; i < n_screens; ++i) {
+ screen = gdk_display_get_screen (display, i);
+
+ create_tray_on_screen (screen, FALSE);
+ }
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/gui/simple-greeter/gdm-greeter-panel.c b/gui/simple-greeter/gdm-greeter-panel.c
new file mode 100644
index 00000000..a96b4095
--- /dev/null
+++ b/gui/simple-greeter/gdm-greeter-panel.c
@@ -0,0 +1,435 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include "gdm-greeter-panel.h"
+
+#include "na-tray.h"
+
+#define GDM_GREETER_PANEL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_GREETER_PANEL, GdmGreeterPanelPrivate))
+
+struct GdmGreeterPanelPrivate
+{
+ int monitor;
+ GdkRectangle geometry;
+ GtkWidget *hbox;
+};
+
+enum {
+ PROP_0,
+};
+
+static void gdm_greeter_panel_class_init (GdmGreeterPanelClass *klass);
+static void gdm_greeter_panel_init (GdmGreeterPanel *greeter_panel);
+static void gdm_greeter_panel_finalize (GObject *object);
+
+G_DEFINE_TYPE (GdmGreeterPanel, gdm_greeter_panel, GTK_TYPE_WINDOW)
+
+static void
+gdm_greeter_panel_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GdmGreeterPanel *self;
+
+ self = GDM_GREETER_PANEL (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gdm_greeter_panel_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GdmGreeterPanel *self;
+
+ self = GDM_GREETER_PANEL (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gdm_greeter_panel_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GdmGreeterPanel *greeter_panel;
+ GdmGreeterPanelClass *klass;
+
+ klass = GDM_GREETER_PANEL_CLASS (g_type_class_peek (GDM_TYPE_GREETER_PANEL));
+
+ greeter_panel = GDM_GREETER_PANEL (G_OBJECT_CLASS (gdm_greeter_panel_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (greeter_panel);
+}
+
+static void
+gdm_greeter_panel_dispose (GObject *object)
+{
+ GdmGreeterPanel *greeter_panel;
+
+ greeter_panel = GDM_GREETER_PANEL (object);
+
+ g_debug ("Disposing greeter_panel");
+
+ G_OBJECT_CLASS (gdm_greeter_panel_parent_class)->dispose (object);
+}
+
+/* copied from panel-toplevel.c */
+static void
+gdm_greeter_panel_move_resize_window (GdmGreeterPanel *panel,
+ gboolean move,
+ gboolean resize)
+{
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (panel);
+
+ g_assert (GTK_WIDGET_REALIZED (widget));
+
+ if (move && resize) {
+ gdk_window_move_resize (widget->window,
+ panel->priv->geometry.x,
+ panel->priv->geometry.y,
+ panel->priv->geometry.width,
+ panel->priv->geometry.height);
+ } else if (move) {
+ gdk_window_move (widget->window,
+ panel->priv->geometry.x,
+ panel->priv->geometry.y);
+ } else if (resize) {
+ gdk_window_resize (widget->window,
+ panel->priv->geometry.width,
+ panel->priv->geometry.height);
+ }
+}
+
+static void
+on_screen_size_changed (GdkScreen *screen,
+ GdmGreeterPanel *panel)
+{
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+}
+
+static void
+gdm_greeter_panel_real_realize (GtkWidget *widget)
+{
+ if (GTK_WIDGET_CLASS (gdm_greeter_panel_parent_class)->realize) {
+ GTK_WIDGET_CLASS (gdm_greeter_panel_parent_class)->realize (widget);
+ }
+
+ gdm_greeter_panel_move_resize_window (GDM_GREETER_PANEL (widget), TRUE, TRUE);
+
+ g_signal_connect (gtk_window_get_screen (GTK_WINDOW (widget)),
+ "size_changed",
+ G_CALLBACK (on_screen_size_changed),
+ widget);
+}
+
+static void
+gdm_greeter_panel_real_unrealize (GtkWidget *widget)
+{
+ g_signal_handlers_disconnect_by_func (gtk_window_get_screen (GTK_WINDOW (widget)),
+ on_screen_size_changed,
+ widget);
+
+ if (GTK_WIDGET_CLASS (gdm_greeter_panel_parent_class)->unrealize) {
+ GTK_WIDGET_CLASS (gdm_greeter_panel_parent_class)->unrealize (widget);
+ }
+}
+
+static GdkRegion *
+get_outside_region (GdmGreeterPanel *panel)
+{
+ int i;
+ GdkRegion *region;
+
+ region = gdk_region_new ();
+ for (i = 0; i < panel->priv->monitor; i++) {
+ GdkRectangle geometry;
+
+ gdk_screen_get_monitor_geometry (GTK_WINDOW (panel)->screen,
+ i,
+ &geometry);
+ gdk_region_union_with_rect (region, &geometry);
+ }
+
+ return region;
+}
+
+static void
+get_monitor_geometry (GdmGreeterPanel *panel,
+ GdkRectangle *geometry)
+{
+ GdkRegion *outside_region;
+ GdkRegion *monitor_region;
+ GdkRectangle geom;
+
+ outside_region = get_outside_region (panel);
+
+ gdk_screen_get_monitor_geometry (GTK_WINDOW (panel)->screen,
+ panel->priv->monitor,
+ &geom);
+ monitor_region = gdk_region_rectangle (&geom);
+ gdk_region_subtract (monitor_region, outside_region);
+ gdk_region_destroy (outside_region);
+
+ gdk_region_get_clipbox (monitor_region, geometry);
+ gdk_region_destroy (monitor_region);
+}
+
+static void
+set_struts (GdmGreeterPanel *panel,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ gulong data[12] = { 0, };
+ int screen_height;
+
+ /* _NET_WM_STRUT_PARTIAL: CARDINAL[12]/32
+ *
+ * 0: left 1: right 2: top 3: bottom
+ * 4: left_start_y 5: left_end_y 6: right_start_y 7: right_end_y
+ * 8: top_start_x 9: top_end_x 10: bottom_start_x 11: bottom_end_x
+ *
+ * Note: In xinerama use struts relative to combined screen dimensions,
+ * not just the current monitor.
+ */
+
+ /* for bottom panel */
+ screen_height = gdk_screen_get_height (gtk_window_get_screen (GTK_WINDOW (panel)));
+
+ /* bottom */
+ data[3] = screen_height - panel->priv->geometry.y - panel->priv->geometry.height + height;
+ /* bottom_start_x */
+ data[10] = x;
+ /* bottom_end_x */
+ data[11] = x + width;
+
+ g_debug ("Setting strut: bottom=%lu bottom_start_x=%lu bottom_end_x=%lu", data[3], data[10], data[11]);
+
+ gdk_error_trap_push ();
+
+ gdk_property_change (GTK_WIDGET (panel)->window,
+ gdk_atom_intern ("_NET_WM_STRUT_PARTIAL", FALSE),
+ gdk_atom_intern ("CARDINAL", FALSE),
+ 32,
+ GDK_PROP_MODE_REPLACE,
+ (guchar *) &data,
+ 12);
+
+ gdk_property_change (GTK_WIDGET (panel)->window,
+ gdk_atom_intern ("_NET_WM_STRUT", FALSE),
+ gdk_atom_intern ("CARDINAL", FALSE),
+ 32,
+ GDK_PROP_MODE_REPLACE,
+ (guchar *) &data,
+ 4);
+
+ gdk_error_trap_pop ();
+}
+
+static void
+update_struts (GdmGreeterPanel *panel)
+{
+ GdkRectangle geometry;
+
+ get_monitor_geometry (panel, &geometry);
+
+ /* FIXME: assumes only one panel */
+ set_struts (panel,
+ panel->priv->geometry.x,
+ panel->priv->geometry.y,
+ panel->priv->geometry.width,
+ panel->priv->geometry.height);
+}
+
+static void
+update_geometry (GdmGreeterPanel *panel,
+ GtkRequisition *requisition)
+{
+ GdkRectangle geometry;
+ int height;
+
+ get_monitor_geometry (panel, &geometry);
+
+ height = requisition->height;
+ panel->priv->geometry.width = geometry.width;
+ panel->priv->geometry.height = height * 2;
+
+ panel->priv->geometry.x = geometry.x;
+ panel->priv->geometry.y = geometry.y + geometry.height - panel->priv->geometry.height;
+
+ g_debug ("Setting geometry x:%d y:%d w:%d h:%d",
+ panel->priv->geometry.x,
+ panel->priv->geometry.y,
+ panel->priv->geometry.width,
+ panel->priv->geometry.height);
+
+ update_struts (panel);
+}
+
+static void
+gdm_greeter_panel_real_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GdmGreeterPanel *panel;
+ GtkBin *bin;
+ GdkRectangle old_geometry;
+ int position_changed = FALSE;
+ int size_changed = FALSE;
+
+ panel = GDM_GREETER_PANEL (widget);
+ bin = GTK_BIN (widget);
+
+ if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) {
+ gtk_widget_size_request (bin->child, requisition);
+ }
+
+ old_geometry = panel->priv->geometry;
+
+ update_geometry (panel, requisition);
+
+ requisition->width = panel->priv->geometry.width;
+ requisition->height = panel->priv->geometry.height;
+
+ if (! GTK_WIDGET_REALIZED (widget)) {
+ return;
+ }
+
+ if (old_geometry.width != panel->priv->geometry.width ||
+ old_geometry.height != panel->priv->geometry.height) {
+ size_changed = TRUE;
+ }
+
+ if (old_geometry.x != panel->priv->geometry.x ||
+ old_geometry.y != panel->priv->geometry.y) {
+ position_changed = TRUE;
+ }
+
+ gdm_greeter_panel_move_resize_window (panel, position_changed, size_changed);
+}
+
+static void
+gdm_greeter_panel_class_init (GdmGreeterPanelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = gdm_greeter_panel_get_property;
+ object_class->set_property = gdm_greeter_panel_set_property;
+ object_class->constructor = gdm_greeter_panel_constructor;
+ object_class->dispose = gdm_greeter_panel_dispose;
+ object_class->finalize = gdm_greeter_panel_finalize;
+
+ widget_class->realize = gdm_greeter_panel_real_realize;
+ widget_class->unrealize = gdm_greeter_panel_real_unrealize;
+ widget_class->size_request = gdm_greeter_panel_real_size_request;
+
+ g_type_class_add_private (klass, sizeof (GdmGreeterPanelPrivate));
+}
+
+static void
+gdm_greeter_panel_init (GdmGreeterPanel *panel)
+{
+ GtkWidget *label;
+ GtkWidget *tray;
+
+ panel->priv = GDM_GREETER_PANEL_GET_PRIVATE (panel);
+
+ panel->priv->geometry.x = -1;
+ panel->priv->geometry.y = -1;
+ panel->priv->geometry.width = -1;
+ panel->priv->geometry.height = -1;
+
+ gtk_window_set_decorated (GTK_WINDOW (panel), FALSE);
+
+ gtk_window_set_skip_taskbar_hint (GTK_WINDOW (panel), TRUE);
+ gtk_window_set_skip_pager_hint (GTK_WINDOW (panel), TRUE);
+
+ gtk_window_set_keep_above (GTK_WINDOW (panel), TRUE);
+ gtk_window_set_type_hint (GTK_WINDOW (panel), GDK_WINDOW_TYPE_HINT_DOCK);
+
+ panel->priv->hbox = gtk_hbox_new (FALSE, 12);
+ gtk_widget_show (panel->priv->hbox);
+ gtk_container_add (GTK_CONTAINER (panel), panel->priv->hbox);
+
+ label = gtk_label_new (g_get_host_name ());
+ gtk_box_pack_start (GTK_BOX (panel->priv->hbox), label, FALSE, FALSE, 6);
+ gtk_widget_show (label);
+
+ tray = na_tray_new_for_screen (gtk_window_get_screen (GTK_WINDOW (panel)),
+ GTK_ORIENTATION_HORIZONTAL);
+ gtk_box_pack_end (GTK_BOX (panel->priv->hbox), tray, FALSE, FALSE, 6);
+ gtk_widget_show (tray);
+
+}
+
+static void
+gdm_greeter_panel_finalize (GObject *object)
+{
+ GdmGreeterPanel *greeter_panel;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GDM_IS_GREETER_PANEL (object));
+
+ greeter_panel = GDM_GREETER_PANEL (object);
+
+ g_return_if_fail (greeter_panel->priv != NULL);
+
+ G_OBJECT_CLASS (gdm_greeter_panel_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gdm_greeter_panel_new (void)
+{
+ GObject *object;
+
+ object = g_object_new (GDM_TYPE_GREETER_PANEL,
+ NULL);
+
+ return GTK_WIDGET (object);
+}
diff --git a/gui/simple-greeter/gdm-greeter-panel.h b/gui/simple-greeter/gdm-greeter-panel.h
new file mode 100644
index 00000000..21e2848e
--- /dev/null
+++ b/gui/simple-greeter/gdm-greeter-panel.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __GDM_GREETER_PANEL_H
+#define __GDM_GREETER_PANEL_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GDM_TYPE_GREETER_PANEL (gdm_greeter_panel_get_type ())
+#define GDM_GREETER_PANEL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_GREETER_PANEL, GdmGreeterPanel))
+#define GDM_GREETER_PANEL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_GREETER_PANEL, GdmGreeterPanelClass))
+#define GDM_IS_GREETER_PANEL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_GREETER_PANEL))
+#define GDM_IS_GREETER_PANEL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_GREETER_PANEL))
+#define GDM_GREETER_PANEL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_GREETER_PANEL, GdmGreeterPanelClass))
+
+typedef struct GdmGreeterPanelPrivate GdmGreeterPanelPrivate;
+
+typedef struct
+{
+ GtkWindow parent;
+ GdmGreeterPanelPrivate *priv;
+} GdmGreeterPanel;
+
+typedef struct
+{
+ GtkWindowClass parent_class;
+} GdmGreeterPanelClass;
+
+GType gdm_greeter_panel_get_type (void);
+
+GtkWidget * gdm_greeter_panel_new (void);
+
+G_END_DECLS
+
+#endif /* __GDM_GREETER_PANEL_H */
diff --git a/gui/simple-greeter/gdm-simple-greeter.c b/gui/simple-greeter/gdm-simple-greeter.c
index 92e02558..66eedfb1 100644
--- a/gui/simple-greeter/gdm-simple-greeter.c
+++ b/gui/simple-greeter/gdm-simple-greeter.c
@@ -48,6 +48,8 @@
#include "gdm-settings-client.h"
#include "gdm-settings-keys.h"
+#include "gdm-greeter-panel.h"
+
#if HAVE_PAM
#include <security/pam_appl.h>
#define PW_ENTRY_SIZE PAM_MAX_RESP_SIZE
@@ -71,7 +73,8 @@ enum {
struct GdmSimpleGreeterPrivate
{
- GladeXML *xml;
+ GladeXML *xml;
+ GtkWidget *panel;
};
enum {
@@ -136,10 +139,10 @@ set_sensitive (GdmSimpleGreeter *greeter,
{
GtkWidget *box;
- box = glade_xml_get_widget (greeter->priv->xml, "input-box");
+ box = glade_xml_get_widget (greeter->priv->xml, "auth-input-box");
gtk_widget_set_sensitive (box, sensitive);
- box = glade_xml_get_widget (greeter->priv->xml, "button-box");
+ box = glade_xml_get_widget (greeter->priv->xml, "auth-button-box");
gtk_widget_set_sensitive (box, sensitive);
}
@@ -149,7 +152,7 @@ set_message (GdmSimpleGreeter *greeter,
{
GtkWidget *label;
- label = glade_xml_get_widget (greeter->priv->xml, "message-label");
+ label = glade_xml_get_widget (greeter->priv->xml, "auth-message-label");
gtk_label_set_text (GTK_LABEL (label), text);
}
@@ -423,22 +426,17 @@ create_greeter (GdmSimpleGreeter *greeter)
/* FIXME: */
}
- button = glade_xml_get_widget (greeter->priv->xml, "ok-button");
+ button = glade_xml_get_widget (greeter->priv->xml, "auth-ok-button");
if (dialog != NULL) {
gtk_widget_grab_default (button);
g_signal_connect (button, "clicked", G_CALLBACK (ok_button_clicked), greeter);
}
- button = glade_xml_get_widget (greeter->priv->xml, "cancel-button");
+ button = glade_xml_get_widget (greeter->priv->xml, "auth-cancel-button");
if (dialog != NULL) {
g_signal_connect (button, "clicked", G_CALLBACK (cancel_button_clicked), greeter);
}
- button = glade_xml_get_widget (greeter->priv->xml, "suspend-button");
- if (dialog != NULL) {
- g_signal_connect (button, "clicked", G_CALLBACK (suspend_button_clicked), greeter);
- }
-
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ALWAYS);
gtk_window_set_deletable (GTK_WINDOW (dialog), FALSE);
gtk_window_set_decorated (GTK_WINDOW (dialog), FALSE);
@@ -447,6 +445,13 @@ create_greeter (GdmSimpleGreeter *greeter)
set_busy (greeter);
}
+static void
+create_panel (GdmSimpleGreeter *greeter)
+{
+ greeter->priv->panel = gdm_greeter_panel_new ();
+ gtk_widget_show (greeter->priv->panel);
+}
+
static GObject *
gdm_simple_greeter_constructor (GType type,
guint n_construct_properties,
@@ -461,6 +466,7 @@ gdm_simple_greeter_constructor (GType type,
n_construct_properties,
construct_properties));
create_greeter (greeter);
+ create_panel (greeter);
return G_OBJECT (greeter);
}
diff --git a/gui/simple-greeter/gdm-simple-greeter.glade b/gui/simple-greeter/gdm-simple-greeter.glade
index c3aeb6aa..5e22069d 100644
--- a/gui/simple-greeter/gdm-simple-greeter.glade
+++ b/gui/simple-greeter/gdm-simple-greeter.glade
@@ -21,13 +21,13 @@
<property name="urgency_hint">False</property>
<child>
- <widget class="GtkVBox" id="vbox1">
+ <widget class="GtkVBox" id="auth-vbox">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">12</property>
<child>
- <widget class="GtkHBox" id="input-box">
+ <widget class="GtkHBox" id="auth-input-box">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">6</property>
@@ -85,7 +85,7 @@
</child>
<child>
- <widget class="GtkLabel" id="message-label">
+ <widget class="GtkLabel" id="auth-message-label">
<property name="visible">True</property>
<property name="label" translatable="yes"></property>
<property name="use_underline">False</property>
@@ -110,25 +110,13 @@
</child>
<child>
- <widget class="GtkHButtonBox" id="button-box">
+ <widget class="GtkHButtonBox" id="auth-button-box">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<property name="spacing">6</property>
<child>
- <widget class="GtkButton" id="suspend-button">
- <property name="visible">True</property>
- <property name="can_default">True</property>
- <property name="can_focus">True</property>
- <property name="label">Suspend</property>
- <property name="use_underline">True</property>
- <property name="relief">GTK_RELIEF_NORMAL</property>
- <property name="focus_on_click">True</property>
- </widget>
- </child>
-
- <child>
- <widget class="GtkButton" id="cancel-button">
+ <widget class="GtkButton" id="auth-cancel-button">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
@@ -140,7 +128,7 @@
</child>
<child>
- <widget class="GtkButton" id="ok-button">
+ <widget class="GtkButton" id="auth-ok-button">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
@@ -160,5 +148,4 @@
</widget>
</child>
</widget>
-
</glade-interface>
diff --git a/gui/simple-greeter/greeter-main.c b/gui/simple-greeter/greeter-main.c
index 4fa3c569..d1100c8a 100644
--- a/gui/simple-greeter/greeter-main.c
+++ b/gui/simple-greeter/greeter-main.c
@@ -266,15 +266,13 @@ get_display_id (void)
GError *error;
char *id;
- g_debug ("GREETER disconnected");
-
id = NULL;
error = NULL;
res = dbus_g_proxy_call (server_proxy,
"GetDisplayId",
&error,
G_TYPE_INVALID,
- G_TYPE_STRING, &id,
+ DBUS_TYPE_G_OBJECT_PATH, &id,
G_TYPE_INVALID);
if (! res) {
g_warning ("Unable to GetDisplayId: %s", error->message);
diff --git a/gui/simple-greeter/test-greeter-panel.c b/gui/simple-greeter/test-greeter-panel.c
new file mode 100644
index 00000000..ba9a0595
--- /dev/null
+++ b/gui/simple-greeter/test-greeter-panel.c
@@ -0,0 +1,54 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <libintl.h>
+#include <locale.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "gdm-greeter-panel.h"
+
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *panel;
+
+ bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ setlocale (LC_ALL, "");
+
+ gtk_init (&argc, &argv);
+
+ panel = gdm_greeter_panel_new ();
+ gtk_widget_show (panel);
+
+ gtk_main ();
+
+ return 0;
+}