Index: testtray.c =================================================================== --- testtray.c (révision 787) +++ testtray.c (copie de travail) @@ -1,83 +1,262 @@ + #include #include #include #include "eggtraymanager.h" +#include "obox.h" + +static guint n_windows = 0; + +typedef struct +{ + GdkScreen *screen; + guint screen_num; + EggTrayManager *manager; + GtkWidget *window; + NaOBox *obox; + GtkLabel *count_label; +} TrayData; static void -lost_selection (EggTrayManager *manager) +do_add (GtkWidget *child, guint *n_children) { - g_print ("We lost our selection"); + *n_children += 1; } static void -tray_added (EggTrayManager *manager, GtkWidget *icon, GtkWidget *box) +update_child_count (TrayData *data) { - gtk_widget_show (icon); - gtk_box_pack_start (GTK_BOX (box), icon, FALSE, FALSE, 0); + guint n_children = 0; + char text[64]; + + gtk_container_foreach (GTK_CONTAINER (data->obox), (GtkCallback) do_add, &n_children); - g_print ("tray added: \"%s\"\n", egg_tray_manager_get_child_title (manager, icon)); + g_snprintf (text, sizeof (text), "%u icons", n_children); + gtk_label_set_text (data->count_label, text); +} + +static void +lost_selection (EggTrayManager *manager, TrayData *data) +{ + g_print ("[Screen %u] We lost our selection\n", data->screen_num); } static void -tray_removed (EggTrayManager *manager, GtkWidget *icon, GtkWidget *box) +tray_added (EggTrayManager *manager, GtkWidget *icon, TrayData *data) { - g_print ("tray removed: %p\n", icon); + GtkWidget *frame; + + frame = gtk_frame_new (NULL); + gtk_container_add (GTK_CONTAINER (frame), icon); + gtk_box_pack_start (GTK_BOX (data->obox), frame, FALSE, FALSE, 0); + gtk_widget_show_all (frame); + + g_print ("[Screen %u] Child %p added to tray: \"%s\"\n", + data->screen_num, icon, egg_tray_manager_get_child_title (manager, icon)); + + update_child_count (data); } static void -message_sent (EggTrayManager *manager, GtkWidget *icon, const char *text, glong id, glong timeout) +tray_removed (EggTrayManager *manager, GtkWidget *icon, TrayData *data) { - g_print ("got message: \"%s\" (%ld)\n", text, id); + GtkWidget *frame = icon->parent; + + g_return_if_fail (GTK_IS_FRAME (frame)); + + gtk_container_remove (GTK_CONTAINER (data->obox), frame); + + g_print ("[Screen %u] Child %p removed from tray\n", + data->screen_num, icon); + + update_child_count (data); } static void -message_cancelled (EggTrayManager *manager, GtkWidget *icon, glong id) +message_sent (EggTrayManager *manager, GtkWidget *icon, const char *text, glong id, glong timeout, TrayData *data) { - g_print ("message cancelled (%ld)\n", id); + g_print ("[Screen %u] Got message: \"%s\" (%ld)\n", + data->screen_num, text, id); +} + +static void +message_cancelled (EggTrayManager *manager, GtkWidget *icon, glong id, TrayData *data) +{ + g_print ("[Screen %u] Message cancelled (%ld)\n", data->screen_num, id); } -gint -main (gint argc, gchar **argv) +static void orientation_changed_cb (GtkComboBox *combo, TrayData *data) +{ + GtkOrientation orientation = (GtkOrientation) gtk_combo_box_get_active (combo); + + g_print ("[Screen %u] Setting orientation to \"%s\"\n", + data->screen_num, orientation == 0 ? "horizontal" : "vertical"); + + egg_tray_manager_set_orientation (data->manager, orientation); + na_obox_set_orientation (data->obox, orientation); +} + +#if 0 +static void +move_screen_cb (GtkWidget *button, TrayData *data) +{ + GdkScreen *screen; + GdkDisplay *display; + gint number_of_screens, screen_num; + + screen = gtk_widget_get_screen (data->window); + display = gdk_screen_get_display (screen); + screen_num = gdk_screen_get_number (screen); + number_of_screens = gdk_display_get_n_screens (display); + + if ((screen_num + 1) < number_of_screens) { + screen = gdk_display_get_screen (display, screen_num + 1); + } else { + screen = gdk_display_get_screen (display, 0); + } + + if (!egg_tray_manager_manage_screen (data->manager, screen)) { + g_warning ("Couldn't manage screen %d\n", gdk_screen_get_number (screen)); + return; + } + + gtk_window_set_screen (GTK_WINDOW (data->window), screen); +} +#endif + +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 TrayData * +create_tray_on_screen (GdkScreen *screen, + gboolean force) { EggTrayManager *manager; - GtkWidget *window, *hbox; - - gtk_init (&argc, &argv); + GtkWidget *window, *hbox, *vbox, *combo, *label, *obox; + TrayData *data; + + n_windows++; + + if (!force && egg_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); + #if 0 - /* FIXME multihead */ - if (egg_tray_manager_check_running_default_screen ()) - { - g_warning ("a tray manager is already running."); - return 0; - } + if (gdk_display_get_n_screens (gdk_screen_get_display (screen)) > 1) { + button = gtk_button_new_with_mnemonic ("_Move to next screen"); + g_signal_connect (button, "clicked", G_CALLBACK (move_screen_cb), data); + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); + } #endif - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - g_signal_connect (window, "destroy", - G_CALLBACK (gtk_main_quit), NULL); - hbox = gtk_hbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (window), hbox); - manager = egg_tray_manager_new (); + 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); + + obox = na_obox_new (); + data->obox = NA_OBOX (obox); + gtk_box_pack_start (GTK_BOX (vbox), obox, TRUE, TRUE, 0); + + data->manager = manager = egg_tray_manager_new (); g_signal_connect (manager, "lost_selection", - G_CALLBACK (lost_selection), NULL); + G_CALLBACK (lost_selection), data); g_signal_connect (manager, "tray_icon_added", - G_CALLBACK (tray_added), hbox); + G_CALLBACK (tray_added), data); g_signal_connect (manager, "tray_icon_removed", - G_CALLBACK (tray_removed), hbox); + G_CALLBACK (tray_removed), data); g_signal_connect (manager, "message_sent", - G_CALLBACK (message_sent), NULL); + G_CALLBACK (message_sent), data); g_signal_connect (manager, "message_cancelled", - G_CALLBACK (message_cancelled), NULL); + G_CALLBACK (message_cancelled), data); - if (!egg_tray_manager_manage_screen (manager, - gdk_screen_get_default ())) - { - g_warning ("could not set default screen."); - } + gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0); + if (!egg_tray_manager_manage_screen (data->manager, screen)) { + g_warning ("Couldn't manage screen %d\n", gdk_screen_get_number (screen)); + } + + gtk_window_set_screen (GTK_WINDOW (window), screen); + gtk_window_set_default_size (GTK_WINDOW (window), -1, 200); + + update_child_count (data); + gtk_widget_show_all (window); + + return data; +} + +int +main (int argc, char *argv[]) +{ + GdkDisplay *display; + GdkScreen *screen; + gint n_screens, i; + + gtk_init (&argc, &argv); + + 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; } Index: obox.c =================================================================== --- obox.c (révision 0) +++ obox.c (révision 0) @@ -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 +#include + +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)); +} Index: Makefile.am =================================================================== --- Makefile.am (révision 787) +++ Makefile.am (copie de travail) @@ -26,7 +26,7 @@ noinst_HEADERS = \ noinst_PROGRAMS = testtray testtrayicon teststatusicon -testtray_SOURCES = testtray.c +testtray_SOURCES = testtray.c obox.h obox.c testtray_LDFLAGS = libeggtray.la $(EGG_TRAY_LIBS) testtray_DEPENDENCIES = libeggtray.la Index: obox.h =================================================================== --- obox.h (révision 0) +++ obox.h (révision 0) @@ -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 + +#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__ */ Index: eggtraymanager.c =================================================================== --- eggtraymanager.c (révision 787) +++ eggtraymanager.c (copie de travail) @@ -629,7 +629,10 @@ egg_tray_manager_manage_xscreen (EggTray manager->invisible = invisible; g_object_ref (G_OBJECT (manager->invisible)); - + g_print ("Screen %d, manager window %u\n", + gdk_screen_get_number (screen), + GDK_WINDOW_XWINDOW (manager->invisible->window)); + manager->opcode_atom = XInternAtom (DisplayOfScreen (xscreen), "_NET_SYSTEM_TRAY_OPCODE", False); @@ -719,6 +722,8 @@ egg_tray_manager_get_child_title (EggTra child_window = g_object_get_data (G_OBJECT (child), "egg-tray-child-window"); + if (!child_window) + return NULL; utf8_string = XInternAtom (GDK_DISPLAY (), "UTF8_STRING", False); atom = XInternAtom (GDK_DISPLAY (), "_NET_WM_NAME", False);