diff options
author | Andrew P. <pan.pav.7c5@gmail.com> | 2014-06-09 18:49:08 +0300 |
---|---|---|
committer | Andrew P. <pan.pav.7c5@gmail.com> | 2014-06-09 18:49:08 +0300 |
commit | c8d2ac4112d362b59714e224300b78a7b6e14155 (patch) | |
tree | d27a7b43d83fc7ebb0c1748162ce9273367bb0c7 | |
parent | 35c44a0385bbac555d6f2dda16cdf20471040d8c (diff) | |
parent | 076d8fc3b76e3c2797ecdca85375e5d16b900a64 (diff) | |
download | lightdm-gtk-greeter-git-c8d2ac4112d362b59714e224300b78a7b6e14155.tar.gz |
Merged "new panel layout" branch
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/greeter_menu_bar.xml | 8 | ||||
-rw-r--r-- | src/greetermenubar.c | 342 | ||||
-rw-r--r-- | src/greetermenubar.h | 37 | ||||
-rw-r--r-- | src/lightdm-gtk-greeter.c | 255 |
5 files changed, 567 insertions, 78 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index a8d3393..f2752a9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,7 +7,8 @@ lightdm_gtk_greeter_built_sources = \ lightdm_gtk_greeter_SOURCES = \ $(lightdm_gtk_greeter_built_sources) \ - lightdm-gtk-greeter.c + lightdm-gtk-greeter.c \ + greetermenubar.c AM_CPPFLAGS = \ -I$(top_srcdir) \ diff --git a/src/greeter_menu_bar.xml b/src/greeter_menu_bar.xml new file mode 100644 index 0000000..a009c1a --- /dev/null +++ b/src/greeter_menu_bar.xml @@ -0,0 +1,8 @@ +<glade-catalog name="greeter_menu_bar" domain="glade-3" + depends="gtk+" version="1.0"> + <glade-widget-classes> + <glade-widget-class title="Greeter MenuBar" name="GreeterMenuBar" + generic-name="GreeterMenuBar" parent="GtkMenuBar" + icon-name="widget-gtk-window"/> + </glade-widget-classes> +</glade-catalog> diff --git a/src/greetermenubar.c b/src/greetermenubar.c new file mode 100644 index 0000000..dd383e5 --- /dev/null +++ b/src/greetermenubar.c @@ -0,0 +1,342 @@ +#include <gtk/gtk.h> +#include "greetermenubar.h" + + +static void greeter_menu_bar_size_allocate(GtkWidget* widget, GtkAllocation* allocation); + +G_DEFINE_TYPE(GreeterMenuBar, greeter_menu_bar, GTK_TYPE_MENU_BAR); + +static void +greeter_menu_bar_class_init(GreeterMenuBarClass* klass) +{ + GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass); + widget_class->size_allocate = greeter_menu_bar_size_allocate; +} + +static void +greeter_menu_bar_init(GreeterMenuBar* square) +{ + +} + +GtkWidget* +greeter_menu_bar_new() +{ + return GTK_WIDGET(g_object_new(greeter_menu_bar_get_type(), NULL)); +} + +#if GTK_CHECK_VERSION (3, 0, 0) +static gint +sort_minimal_size(gconstpointer a, gconstpointer b, GtkRequestedSize* sizes) +{ + gint a_size = sizes[GPOINTER_TO_INT(a)].natural_size; + gint b_size = sizes[GPOINTER_TO_INT(b)].natural_size; + return a_size == b_size ? 0 : a_size > b_size ? -1 : +1; +} + +static void +greeter_menu_bar_size_allocate(GtkWidget* widget, GtkAllocation* allocation) +{ + GList* item; + GList* shell_children; + GList* expand_nums = NULL; + guint visible_count = 0, expand_count = 0; + + g_return_if_fail(allocation != NULL); + g_return_if_fail(GREETER_IS_MENU_BAR(widget)); + + gtk_widget_set_allocation(widget, allocation); + + GtkPackDirection pack_direction = gtk_menu_bar_get_pack_direction(GTK_MENU_BAR(widget)); + g_return_if_fail(pack_direction == GTK_PACK_DIRECTION_LTR || pack_direction == GTK_PACK_DIRECTION_RTL); + + shell_children = gtk_container_get_children(GTK_CONTAINER(widget)); + + for(item = shell_children; item; item = g_list_next(item)) + if(gtk_widget_get_visible(item->data)) + { + if(gtk_widget_compute_expand(item->data, GTK_ORIENTATION_HORIZONTAL)) + { + expand_nums = g_list_prepend(expand_nums, GINT_TO_POINTER(visible_count)); + expand_count++; + } + visible_count++; + } + + if(gtk_widget_get_realized(widget)) + gdk_window_move_resize(gtk_widget_get_window(widget), + allocation->x, allocation->y, + allocation->width, allocation->height); + + if(visible_count > 0) + { + GtkAllocation remaining_space; + GtkStyleContext* context = gtk_widget_get_style_context(widget); + GtkStateFlags flags = gtk_widget_get_state_flags(widget); + GtkRequestedSize* requested_sizes = g_newa(GtkRequestedSize, visible_count); + guint border_width = gtk_container_get_border_width(GTK_CONTAINER(widget)); + GtkShadowType shadow_type = GTK_SHADOW_OUT; + GtkBorder border; + gint toggle_size; + + gtk_style_context_get_padding(context, flags, &border); + gtk_widget_style_get(widget, "shadow-type", &shadow_type, NULL); + + remaining_space.x = (border_width + border.left); + remaining_space.y = (border_width + border.top); + remaining_space.width = allocation->width - + 2 * border_width - border.left - border.right; + remaining_space.height = allocation->height - + 2 * border_width - border.top - border.bottom; + + if (shadow_type != GTK_SHADOW_NONE) + { + gtk_style_context_get_border(context, flags, &border); + + remaining_space.x += border.left; + remaining_space.y += border.top; + remaining_space.width -= border.left + border.right; + remaining_space.height -= border.top + border.bottom; + } + + GtkRequestedSize* request = requested_sizes; + int size = remaining_space.width; + gboolean ltr = (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_LTR) == (pack_direction == GTK_PACK_DIRECTION_LTR); + + for(item = shell_children; item; item = g_list_next(item)) + { + if (!gtk_widget_get_visible(item->data)) + continue; + + request->data = item->data; + gtk_widget_get_preferred_width_for_height(item->data, remaining_space.height, + &request->minimum_size, + &request->natural_size); + gtk_menu_item_toggle_size_request(GTK_MENU_ITEM(item->data), + &toggle_size); + request->minimum_size += toggle_size; + request->natural_size += toggle_size; + + gtk_menu_item_toggle_size_allocate(GTK_MENU_ITEM(item->data), toggle_size); + + size -= request->minimum_size; + request++; + } + + size = gtk_distribute_natural_allocation(size, visible_count, requested_sizes); + + /* Distribution extra space for widgets with expand=True */ + if(size > 0 && expand_nums) + { + expand_nums = g_list_sort_with_data(expand_nums, (GCompareDataFunc)sort_minimal_size, + requested_sizes); + GList* first_item = expand_nums; + gint needed_size = -1; + gint max_size = requested_sizes[GPOINTER_TO_INT(first_item->data)].natural_size; + gint total_needed_size = 0; + + + /* Free space that all widgets need to have the same (max_size) width + * [___max_width___][widget ][widget____ ] + * total_needed_size := [] + [ ] + [ ] + * total_needed_size = [ ] + */ + for(item = g_list_next(expand_nums); item; item = g_list_next(item)) + total_needed_size += max_size - requested_sizes[GPOINTER_TO_INT(item->data)].natural_size; + + while(first_item) + { + if(size >= total_needed_size) + { + /* total_needed_size is enough for all remaining widgets */ + needed_size = max_size + (size - total_needed_size)/expand_count; + break; + } + /* Removing current maximal widget from list */ + total_needed_size -= max_size - requested_sizes[GPOINTER_TO_INT(item->data)].natural_size; + first_item = g_list_next(first_item); + if(first_item) + max_size = requested_sizes[GPOINTER_TO_INT(first_item->data)].natural_size; + } + + for(item = first_item; item; item = g_list_next(item)) + { + request = &requested_sizes[GPOINTER_TO_INT(item->data)]; + gint dsize = needed_size - request->natural_size; + if(size < dsize) + dsize = size; + size -= dsize; + request->natural_size += dsize; + } + } + + gint i; + for(i = 0; i < visible_count; i++) + { + GtkAllocation child_allocation = remaining_space; + request = &requested_sizes[i]; + + child_allocation.width = request->natural_size; + remaining_space.width -= request->natural_size; + if (ltr) + remaining_space.x += request->natural_size; + else + child_allocation.x += remaining_space.width; + gtk_widget_size_allocate(request->data, &child_allocation); + } + g_list_free(expand_nums); + } + g_list_free(shell_children); +} +#else +static gboolean +widget_get_expand (GtkWidget* widget) +{ + return g_object_get_data(G_OBJECT(widget), + GREETER_MENU_BAR_EXPAND_PROP) != NULL; +} + +struct RequestedSize +{ + GtkWidget* child; + GtkRequisition size; +}; + +static gint +sort_minimal_size(gconstpointer a, gconstpointer b, struct RequestedSize* sizes) +{ + gint a_size = sizes[GPOINTER_TO_INT(a)].size.width; + gint b_size = sizes[GPOINTER_TO_INT(b)].size.width; + return a_size == b_size ? 0 : a_size > b_size ? -1 : +1; +} + +static void +greeter_menu_bar_size_allocate(GtkWidget* widget, GtkAllocation* allocation) +{ + GList* item; + GList* shell_children; + GList* expand_nums = NULL; + guint visible_count = 0, expand_count = 0; + + g_return_if_fail (GTK_IS_MENU_BAR (widget)); + g_return_if_fail (allocation != NULL); + + GtkPackDirection pack_direction = gtk_menu_bar_get_pack_direction(GTK_MENU_BAR(widget)); + g_return_if_fail(pack_direction == GTK_PACK_DIRECTION_LTR || pack_direction == GTK_PACK_DIRECTION_RTL); + + shell_children = GTK_MENU_SHELL (widget)->children; + + for(item = shell_children; item; item = g_list_next(item)) + if(gtk_widget_get_visible(item->data)) + { + if(widget_get_expand(item->data)) + { + expand_nums = g_list_prepend(expand_nums, GINT_TO_POINTER(visible_count)); + expand_count++; + } + visible_count++; + } + + widget->allocation = *allocation; + if (gtk_widget_get_realized (widget)) + gdk_window_move_resize (widget->window, + allocation->x, allocation->y, + allocation->width, allocation->height); + + if (visible_count) + { + gint toggle_size, ipadding; + GtkTextDirection direction = gtk_widget_get_direction (widget); + GtkShadowType shadow_type = GTK_SHADOW_OUT; + GtkAllocation remaining_space; + + gtk_widget_style_get (widget, "shadow-type", &shadow_type, NULL); + gtk_widget_style_get (widget, "internal-padding", &ipadding, NULL); + + remaining_space.x = (GTK_CONTAINER (widget)->border_width + ipadding); + remaining_space.y = (GTK_CONTAINER (widget)->border_width); + remaining_space.width = allocation->width - 2 * remaining_space.x; + remaining_space.height = allocation->height - 2 * remaining_space.y; + + if (shadow_type != GTK_SHADOW_NONE) + { + remaining_space.x += widget->style->xthickness; + remaining_space.y += widget->style->ythickness; + remaining_space.width -= 2 * widget->style->xthickness; + remaining_space.height -= 2 * widget->style->ythickness; + } + + struct RequestedSize* requested_sizes = g_newa(struct RequestedSize, visible_count); + struct RequestedSize* request = requested_sizes; + int size = remaining_space.width; + + for(item = shell_children; item; item = g_list_next(item)) + { + if (!gtk_widget_get_visible (item->data)) + continue; + request->child = item->data; + gtk_menu_item_toggle_size_request (GTK_MENU_ITEM (request->child), &toggle_size); + gtk_menu_item_toggle_size_allocate (GTK_MENU_ITEM (request->child), toggle_size); + gtk_widget_get_child_requisition (request->child, &request->size); + request->size.width += toggle_size; + request->size.height += toggle_size; + size -= request->size.width; + ++request; + } + + if(size > 0 && expand_nums) + { + expand_nums = g_list_sort_with_data(expand_nums, (GCompareDataFunc)sort_minimal_size, + requested_sizes); + GList* first_item = expand_nums; + gint needed_size = -1; + gint max_size = requested_sizes[GPOINTER_TO_INT(first_item->data)].size.width; + gint total_needed_size = 0; + + for(item = g_list_next(expand_nums); item; item = g_list_next(item)) + total_needed_size += max_size - requested_sizes[GPOINTER_TO_INT(item->data)].size.width; + + while(first_item) + { + if(size >= total_needed_size) + { + needed_size = max_size + (size - total_needed_size)/expand_count; + break; + } + total_needed_size -= max_size - requested_sizes[GPOINTER_TO_INT(item->data)].size.width; + first_item = g_list_next(first_item); + if(first_item) + max_size = requested_sizes[GPOINTER_TO_INT(first_item->data)].size.width; + } + + for(item = first_item; item; item = g_list_next(item)) + { + request = &requested_sizes[GPOINTER_TO_INT(item->data)]; + gint dsize = needed_size - request->size.width; + if(size < dsize) + dsize = size; + size -= dsize; + request->size.width += dsize; + } + } + + gboolean ltr = (direction == GTK_TEXT_DIR_LTR) == (pack_direction == GTK_PACK_DIRECTION_LTR); + GtkAllocation child_allocation; + gint i; + for(i = 0; i < visible_count; i++) + { + child_allocation = remaining_space; + request = &requested_sizes[i]; + + child_allocation.width = request->size.width; + remaining_space.width -= request->size.width; + if (ltr) + remaining_space.x += request->size.width; + else + child_allocation.x += remaining_space.width; + gtk_widget_size_allocate(request->child, &child_allocation); + } + g_list_free(expand_nums); + } +} +#endif diff --git a/src/greetermenubar.h b/src/greetermenubar.h new file mode 100644 index 0000000..7d356cd --- /dev/null +++ b/src/greetermenubar.h @@ -0,0 +1,37 @@ +#ifndef GREETER_MENU_BAR_H +#define GREETER_MENU_BAR_H + +#include <glib-object.h> +#include <gtk/gtk.h> + +#if !GTK_CHECK_VERSION (3, 0, 0) +#define GREETER_MENU_BAR_EXPAND_PROP "gtk2-fallback-expand" +#endif + +G_BEGIN_DECLS + +#define GREETER_MENU_BAR_TYPE (greeter_menu_bar_get_type()) +#define GREETER_MENU_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GREETER_MENU_BAR_TYPE, GreeterMenuBar)) +#define GREETER_MENU_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GREETER_MENU_BAR_TYPE, GreeterMenuBarClass)) +#define GREETER_IS_MENU_BAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GREETER_MENU_BAR_TYPE)) +#define GREETER_IS_MENU_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GREETER_MENU_BAR_TYPE)) + +typedef struct _GreeterMenuBar GreeterMenuBar; +typedef struct _GreeterMenuBarClass GreeterMenuBarClass; + +struct _GreeterMenuBar +{ + GtkMenuBar parent_instance; +}; + +struct _GreeterMenuBarClass +{ + GtkMenuBarClass parent_class; +}; + +GType greeter_menu_bar_get_type(void) G_GNUC_CONST; +GtkWidget *greeter_menu_bar_new(void); + +G_END_DECLS + +#endif /* GREETER_MENU_BAR_H */ diff --git a/src/lightdm-gtk-greeter.c b/src/lightdm-gtk-greeter.c index 26a2668..4a54f3b 100644 --- a/src/lightdm-gtk-greeter.c +++ b/src/lightdm-gtk-greeter.c @@ -55,7 +55,8 @@ #include <lightdm.h> -#include <src/lightdm-gtk-greeter-ui.h> +#include "src/greetermenubar.h" +#include "src/lightdm-gtk-greeter-ui.h" #if GTK_CHECK_VERSION (3, 0, 0) #include <src/lightdm-gtk-greeter-css-fallback.h> @@ -73,11 +74,11 @@ static GdkPixbuf *background_pixbuf = NULL; /* Panel Widgets */ static GtkWindow *panel_window; -static GtkWidget *clock_label; -static GtkWidget *menubar, *power_menuitem, *session_menuitem, *language_menuitem, *a11y_menuitem, +static GtkWidget *menubar; +static GtkWidget *power_menuitem, *session_menuitem, *language_menuitem, *a11y_menuitem, *layout_menuitem, *session_badge; static GtkWidget *suspend_menuitem, *hibernate_menuitem, *restart_menuitem, *shutdown_menuitem; -static GtkWidget *keyboard_menuitem; +static GtkWidget *keyboard_menuitem, *clock_menuitem, *clock_label, *host_menuitem; static GtkMenu *session_menu, *language_menu, *layout_menu; /* Login Window Widgets */ @@ -164,6 +165,35 @@ static const gchar *LAYOUT_DATA_NAME = "layout-name"; static XklEngine *xkl_engine; #endif +typedef enum +{ + PANEL_ITEM_INDICATOR, + PANEL_ITEM_SPACER, + PANEL_ITEM_SEPARATOR, + PANEL_ITEM_TEXT +} GreeterPanelItemType; + +#if GTK_CHECK_VERSION (3, 0, 0) +static const gchar *PANEL_ITEM_STYLE = "panel-item"; +static const gchar *PANEL_ITEM_STYLE_HOVERED = "panel-item-hovered"; + +static const gchar *PANEL_ITEM_STYLES[] = +{ + "panel-item-indicator", + "panel-item-spacer", + "panel-item-separator", + "panel-item-text" +}; +#endif + +static const gchar *PANEL_ITEM_DATA_INDEX = "panel-item-data-index"; + +#ifdef HAVE_LIBINDICATOR +static const gchar *INDICATOR_ITEM_DATA_OBJECT = "indicator-item-data-object"; +static const gchar *INDICATOR_ITEM_DATA_ENTRY = "indicator-item-data-entry"; +static const gchar *INDICATOR_ITEM_DATA_BOX = "indicator-item-data-box"; +static const gchar *INDICATOR_DATA_MENUITEMS = "indicator-data-menuitems"; +#endif static void pam_message_finalize (PAMConversationMessage *message) @@ -172,34 +202,60 @@ pam_message_finalize (PAMConversationMessage *message) g_free (message); } +#if GTK_CHECK_VERSION (3, 0, 0) +static gboolean +panel_item_enter_notify_cb (GtkWidget *widget, GdkEvent *event, gpointer enter) +{ + GtkStyleContext *context = gtk_widget_get_style_context (widget); + if (GPOINTER_TO_INT (enter)) + gtk_style_context_add_class (context, PANEL_ITEM_STYLE_HOVERED); + else + gtk_style_context_remove_class (context, PANEL_ITEM_STYLE_HOVERED); + return FALSE; +} +#endif + static void -add_indicator_to_panel (GtkWidget *indicator_item, gint index) +panel_add_item (GtkWidget *widget, gint index, GreeterPanelItemType item_type) { gint insert_pos = 0; GList* items = gtk_container_get_children (GTK_CONTAINER (menubar)); GList* item; for (item = items; item; item = item->next) { - if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item->data), "indicator-custom-index-data")) < index) + if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item->data), PANEL_ITEM_DATA_INDEX)) < index) break; insert_pos++; } g_list_free (items); - gtk_menu_shell_insert (GTK_MENU_SHELL (menubar), GTK_WIDGET (indicator_item), insert_pos); + #if GTK_CHECK_VERSION (3, 0, 0) + gtk_style_context_add_class (gtk_widget_get_style_context (widget), PANEL_ITEM_STYLE); + gtk_style_context_add_class (gtk_widget_get_style_context (widget), PANEL_ITEM_STYLES[item_type]); + if (item_type == PANEL_ITEM_INDICATOR) + { + g_signal_connect (G_OBJECT (widget), "enter-notify-event", + G_CALLBACK (panel_item_enter_notify_cb), GINT_TO_POINTER(TRUE)); + g_signal_connect (G_OBJECT (widget), "leave-notify-event", + G_CALLBACK (panel_item_enter_notify_cb), GINT_TO_POINTER(FALSE)); + } + #endif + + gtk_widget_show (widget); + gtk_menu_shell_insert (GTK_MENU_SHELL (menubar), widget, insert_pos); } #ifdef HAVE_LIBINDICATOR static gboolean -entry_scrolled (GtkWidget *menuitem, GdkEventScroll *event, gpointer data) +indicator_entry_scrolled_cb (GtkWidget *menuitem, GdkEventScroll *event, gpointer data) { IndicatorObject *io; IndicatorObjectEntry *entry; g_return_val_if_fail (GTK_IS_WIDGET (menuitem), FALSE); - io = g_object_get_data (G_OBJECT (menuitem), "indicator-custom-object-data"); - entry = g_object_get_data (G_OBJECT (menuitem), "indicator-custom-entry-data"); + io = g_object_get_data (G_OBJECT (menuitem), INDICATOR_ITEM_DATA_OBJECT); + entry = g_object_get_data (G_OBJECT (menuitem), INDICATOR_ITEM_DATA_ENTRY); g_return_val_if_fail (INDICATOR_IS_OBJECT (io), FALSE); @@ -210,15 +266,15 @@ entry_scrolled (GtkWidget *menuitem, GdkEventScroll *event, gpointer data) } static void -entry_activated (GtkWidget *widget, gpointer user_data) +indicator_entry_activated_cb (GtkWidget *widget, gpointer user_data) { IndicatorObject *io; IndicatorObjectEntry *entry; g_return_if_fail (GTK_IS_WIDGET (widget)); - io = g_object_get_data (G_OBJECT (widget), "indicator-custom-object-data"); - entry = g_object_get_data (G_OBJECT (widget), "indicator-custom-entry-data"); + io = g_object_get_data (G_OBJECT (widget), INDICATOR_ITEM_DATA_OBJECT); + entry = g_object_get_data (G_OBJECT (widget), INDICATOR_ITEM_DATA_ENTRY); g_return_if_fail (INDICATOR_IS_OBJECT (io)); @@ -226,10 +282,10 @@ entry_activated (GtkWidget *widget, gpointer user_data) } static GtkWidget* -create_menuitem (IndicatorObject *io, IndicatorObjectEntry *entry, GtkWidget *menubar) +indicator_entry_create_menuitem (IndicatorObject *io, IndicatorObjectEntry *entry, GtkWidget *menubar) { GtkWidget *box, *menuitem; - gint index = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (io), "indicator-custom-index-data")); + gint index = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (io), PANEL_ITEM_DATA_INDEX)); #if GTK_CHECK_VERSION (3, 0, 0) box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3); @@ -240,13 +296,13 @@ create_menuitem (IndicatorObject *io, IndicatorObjectEntry *entry, GtkWidget *me gtk_widget_add_events(GTK_WIDGET(menuitem), GDK_SCROLL_MASK); - g_object_set_data (G_OBJECT (menuitem), "indicator-custom-box-data", box); - g_object_set_data (G_OBJECT (menuitem), "indicator-custom-object-data", io); - g_object_set_data (G_OBJECT (menuitem), "indicator-custom-entry-data", entry); - g_object_set_data (G_OBJECT (menuitem), "indicator-custom-index-data", GINT_TO_POINTER (index)); + g_object_set_data (G_OBJECT (menuitem), INDICATOR_ITEM_DATA_BOX, box); + g_object_set_data (G_OBJECT (menuitem), INDICATOR_ITEM_DATA_OBJECT, io); + g_object_set_data (G_OBJECT (menuitem), INDICATOR_ITEM_DATA_ENTRY, entry); + g_object_set_data (G_OBJECT (menuitem), PANEL_ITEM_DATA_INDEX, GINT_TO_POINTER (index)); - g_signal_connect (G_OBJECT (menuitem), "activate", G_CALLBACK (entry_activated), NULL); - g_signal_connect (G_OBJECT (menuitem), "scroll-event", G_CALLBACK (entry_scrolled), NULL); + g_signal_connect (G_OBJECT (menuitem), "activate", G_CALLBACK (indicator_entry_activated_cb), NULL); + g_signal_connect (G_OBJECT (menuitem), "scroll-event", G_CALLBACK (indicator_entry_scrolled_cb), NULL); if (entry->image) gtk_box_pack_start (GTK_BOX(box), GTK_WIDGET(entry->image), FALSE, FALSE, 1); @@ -259,24 +315,24 @@ create_menuitem (IndicatorObject *io, IndicatorObjectEntry *entry, GtkWidget *me gtk_container_add (GTK_CONTAINER (menuitem), box); gtk_widget_show (box); - add_indicator_to_panel (menuitem, index); + panel_add_item(menuitem, index, PANEL_ITEM_INDICATOR); return menuitem; } static void -entry_added (IndicatorObject *io, IndicatorObjectEntry *entry, gpointer user_data) +indicator_entry_added_cb (IndicatorObject *io, IndicatorObjectEntry *entry, gpointer user_data) { GHashTable *menuitem_lookup; GtkWidget *menuitem; /* if the menuitem doesn't already exist, create it now */ - menuitem_lookup = g_object_get_data (G_OBJECT (io), "indicator-custom-menuitems-data"); + menuitem_lookup = g_object_get_data (G_OBJECT (io), INDICATOR_DATA_MENUITEMS); g_return_if_fail (menuitem_lookup); menuitem = g_hash_table_lookup (menuitem_lookup, entry); if (!GTK_IS_WIDGET (menuitem)) { - menuitem = create_menuitem (io, entry, GTK_WIDGET (user_data)); + menuitem = indicator_entry_create_menuitem (io, entry, GTK_WIDGET (user_data)); g_hash_table_insert (menuitem_lookup, entry, menuitem); } @@ -284,22 +340,22 @@ entry_added (IndicatorObject *io, IndicatorObjectEntry *entry, gpointer user_dat } static void -entry_removed_cb (GtkWidget *widget, gpointer userdata) +remove_indicator_entry_cb (GtkWidget *widget, gpointer userdata) { IndicatorObject *io; GHashTable *menuitem_lookup; GtkWidget *menuitem; gpointer entry; - io = g_object_get_data (G_OBJECT (widget), "indicator-custom-object-data"); + io = g_object_get_data (G_OBJECT (widget), INDICATOR_ITEM_DATA_OBJECT); if (!INDICATOR_IS_OBJECT (io)) return; - entry = g_object_get_data (G_OBJECT (widget), "indicator-custom-entry-data"); + entry = g_object_get_data (G_OBJECT (widget), INDICATOR_ITEM_DATA_ENTRY); if (entry != userdata) return; - menuitem_lookup = g_object_get_data (G_OBJECT (io), "indicator-custom-menuitems-data"); + menuitem_lookup = g_object_get_data (G_OBJECT (io), INDICATOR_DATA_MENUITEMS); g_return_if_fail (menuitem_lookup); menuitem = g_hash_table_lookup (menuitem_lookup, entry); if (GTK_IS_WIDGET (menuitem)) @@ -309,13 +365,13 @@ entry_removed_cb (GtkWidget *widget, gpointer userdata) } static void -entry_removed (IndicatorObject *io, IndicatorObjectEntry *entry, gpointer user_data) +indicator_entry_removed_cb (IndicatorObject *io, IndicatorObjectEntry *entry, gpointer user_data) { - gtk_container_foreach (GTK_CONTAINER (user_data), entry_removed_cb, entry); + gtk_container_foreach (GTK_CONTAINER (user_data), remove_indicator_entry_cb, entry); } static void -menu_show (IndicatorObject *io, IndicatorObjectEntry *entry, guint32 timestamp, gpointer user_data) +indicator_menu_show_cb (IndicatorObject *io, IndicatorObjectEntry *entry, guint32 timestamp, gpointer user_data) { IndicatorObjectEntry *entrydata; GtkWidget *menuitem; @@ -403,9 +459,14 @@ init_indicators (GKeyFile* config) GHashTable *builtin_items = NULL; GHashTableIter iter; gpointer iter_value; + #ifdef HAVE_LIBINDICATOR gboolean inited = FALSE; + #endif gboolean fallback = FALSE; + const gchar *DEFAULT_LAYOUT[] = {"~host", "~spacer", "~clock", "~spacer", + "~session", "~language", "~a11y", "~power", NULL}; + #ifdef START_INDICATOR_SERVICES GError *error = NULL; gchar *AT_SPI_CMD[] = {"/usr/lib/at-spi2-core/at-spi-bus-launcher", "--launch-immediately", NULL}; @@ -423,28 +484,67 @@ init_indicators (GKeyFile* config) fallback = TRUE; } - if (names && !fallback) + if (!names || fallback) { - builtin_items = g_hash_table_new (g_str_hash, g_str_equal); + names = (gchar**)DEFAULT_LAYOUT; + length = g_strv_length (names); + } - g_hash_table_insert (builtin_items, "~power", power_menuitem); - g_hash_table_insert (builtin_items, "~session", session_menuitem); - g_hash_table_insert (builtin_items, "~language", language_menuitem); - g_hash_table_insert (builtin_items, "~a11y", a11y_menuitem); - g_hash_table_insert (builtin_items, "~layout", layout_menuitem); + builtin_items = g_hash_table_new (g_str_hash, g_str_equal); - g_hash_table_iter_init (&iter, builtin_items); - while (g_hash_table_iter_next (&iter, NULL, &iter_value)) - gtk_container_remove (GTK_CONTAINER (menubar), iter_value); - } + g_hash_table_insert (builtin_items, "~power", power_menuitem); + g_hash_table_insert (builtin_items, "~session", session_menuitem); + g_hash_table_insert (builtin_items, "~language", language_menuitem); + g_hash_table_insert (builtin_items, "~a11y", a11y_menuitem); + g_hash_table_insert (builtin_items, "~layout", layout_menuitem); + g_hash_table_insert (builtin_items, "~host", host_menuitem); + g_hash_table_insert (builtin_items, "~clock", clock_menuitem); + + g_hash_table_iter_init (&iter, builtin_items); + while (g_hash_table_iter_next (&iter, NULL, &iter_value)) + gtk_container_remove (GTK_CONTAINER (menubar), iter_value); for (i = 0; i < length; ++i) { - if (names[i][0] == '~' && g_hash_table_lookup_extended (builtin_items, names[i], NULL, &iter_value)) + if (names[i][0] == '~') { /* Built-in indicators */ - g_object_set_data (G_OBJECT (iter_value), "indicator-custom-index-data", GINT_TO_POINTER (i)); - add_indicator_to_panel (iter_value, i); - g_hash_table_remove (builtin_items, (gconstpointer)names[i]); + GreeterPanelItemType item_type = PANEL_ITEM_INDICATOR; + if (g_hash_table_lookup_extended (builtin_items, names[i], NULL, &iter_value)) + g_hash_table_remove (builtin_items, (gconstpointer)names[i]); + else if (g_strcmp0 (names[i], "~separator") == 0) + { + #if GTK_CHECK_VERSION (3, 0, 0) + GtkWidget *separator = gtk_separator_new (GTK_ORIENTATION_VERTICAL); + #else + GtkWidget *separator = gtk_vseparator_new (); + #endif + item_type = PANEL_ITEM_SEPARATOR; + iter_value = gtk_separator_menu_item_new (); + gtk_widget_show (separator); + gtk_container_add (iter_value, separator); + } + else if (g_strcmp0 (names[i], "~spacer") == 0) + { + item_type = PANEL_ITEM_SPACER; + iter_value = gtk_separator_menu_item_new (); + gtk_menu_item_set_label (iter_value, ""); + #if GTK_CHECK_VERSION (3, 0, 0) + gtk_widget_set_hexpand (iter_value, TRUE); + #else + g_object_set_data(G_OBJECT(iter_value), GREETER_MENU_BAR_EXPAND_PROP, "1"); + #endif + } + else if (names[i][1] == '~') + { + item_type = PANEL_ITEM_TEXT; + iter_value = gtk_separator_menu_item_new (); + gtk_menu_item_set_label (iter_value, &names[i][2]); + } + else + continue; + + g_object_set_data (G_OBJECT (iter_value), PANEL_ITEM_DATA_INDEX, GINT_TO_POINTER (i)); + panel_add_item (iter_value, i, item_type); continue; } @@ -497,21 +597,21 @@ init_indicators (GKeyFile* config) GList *entries, *lp; /* used to store/fetch menu entries */ - g_object_set_data_full (G_OBJECT (io), "indicator-custom-menuitems-data", + g_object_set_data_full (G_OBJECT (io), INDICATOR_DATA_MENUITEMS, g_hash_table_new (g_direct_hash, g_direct_equal), (GDestroyNotify) g_hash_table_destroy); - g_object_set_data (G_OBJECT (io), "indicator-custom-index-data", GINT_TO_POINTER (i)); + g_object_set_data (G_OBJECT (io), PANEL_ITEM_DATA_INDEX, GINT_TO_POINTER (i)); g_signal_connect (G_OBJECT (io), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, - G_CALLBACK (entry_added), menubar); + G_CALLBACK (indicator_entry_added_cb), menubar); g_signal_connect (G_OBJECT (io), INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, - G_CALLBACK (entry_removed), menubar); + G_CALLBACK (indicator_entry_removed_cb), menubar); g_signal_connect (G_OBJECT (io), INDICATOR_OBJECT_SIGNAL_MENU_SHOW, - G_CALLBACK (menu_show), menubar); + G_CALLBACK (indicator_menu_show_cb), menubar); entries = indicator_object_get_entries (io); for (lp = entries; lp; lp = g_list_next (lp)) - entry_added (io, lp->data, menubar); + indicator_entry_added_cb (io, lp->data, menubar); g_list_free (entries); } else @@ -522,7 +622,7 @@ init_indicators (GKeyFile* config) g_free (path); #endif } - if (names) + if (names && names != (gchar**)DEFAULT_LAYOUT) g_strfreev (names); if (builtin_items) @@ -1691,9 +1791,6 @@ a11y_font_cb (GtkCheckMenuItem *item) gchar *font_name, **tokens; guint length; - /* Hide the clock since indicators are about to eat the screen. */ - gtk_widget_hide(GTK_WIDGET(clock_label)); - g_object_get (gtk_settings_get_default (), "gtk-font-name", &font_name, NULL); tokens = g_strsplit (font_name, " ", -1); length = g_strv_length (tokens); @@ -1715,8 +1812,6 @@ a11y_font_cb (GtkCheckMenuItem *item) else { g_object_set (gtk_settings_get_default (), "gtk-font-name", default_font_name, NULL); - /* Show the clock as needed */ - gtk_widget_show_all(GTK_WIDGET(clock_label)); } } @@ -2166,8 +2261,8 @@ clock_timeout_thread (void) strftime(time_str, 50, clock_format, timeinfo); markup = g_markup_printf_escaped("<b>%s</b>", time_str); - if (g_strcmp0(markup, gtk_label_get_label(GTK_LABEL(clock_label))) != 0) - gtk_label_set_markup( GTK_LABEL(clock_label), markup ); + if (g_strcmp0(markup, gtk_label_get_label (GTK_LABEL (clock_label))) != 0) + gtk_label_set_markup (GTK_LABEL (clock_label), markup); g_free(markup); return TRUE; @@ -2646,11 +2741,6 @@ main (int argc, char **argv) gtk_style_context_add_class(GTK_STYLE_CONTEXT(gtk_widget_get_style_context(GTK_WIDGET(panel_window))), GTK_STYLE_CLASS_MENUBAR); g_signal_connect (G_OBJECT (panel_window), "draw", G_CALLBACK (background_window_draw), NULL); #endif - gtk_label_set_text (GTK_LABEL (gtk_builder_get_object (builder, "hostname_label")), lightdm_get_hostname ()); - session_menu = GTK_MENU(gtk_builder_get_object (builder, "session_menu")); - language_menu = GTK_MENU(gtk_builder_get_object (builder, "language_menu")); - layout_menu = GTK_MENU(gtk_builder_get_object (builder, "layout_menu")); - clock_label = GTK_WIDGET(gtk_builder_get_object (builder, "clock_label")); menubar = GTK_WIDGET (gtk_builder_get_object (builder, "menubar")); /* Login window */ @@ -2704,11 +2794,16 @@ main (int argc, char **argv) /* Indicators */ session_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "session_menuitem")); + session_menu = GTK_MENU(gtk_builder_get_object (builder, "session_menu")); language_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "language_menuitem")); + language_menu = GTK_MENU(gtk_builder_get_object (builder, "language_menu")); a11y_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "a11y_menuitem")); power_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "power_menuitem")); layout_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "layout_menuitem")); + layout_menu = GTK_MENU(gtk_builder_get_object (builder, "layout_menu")); keyboard_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "keyboard_menuitem")); + clock_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "clock_menuitem")); + host_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "host_menuitem")); gtk_accel_map_add_entry ("<Login>/a11y/font", GDK_KEY_F1, 0); gtk_accel_map_add_entry ("<Login>/a11y/contrast", GDK_KEY_F2, 0); @@ -2738,15 +2833,6 @@ main (int argc, char **argv) g_free (value); } - /* Clock */ - gtk_widget_set_no_show_all(GTK_WIDGET(clock_label), - !g_key_file_get_boolean (config, "greeter", "show-clock", NULL)); - gtk_widget_show_all(GTK_WIDGET(clock_label)); - clock_format = g_key_file_get_value (config, "greeter", "clock-format", NULL); - if (!clock_format) - clock_format = "%a, %H:%M"; - clock_timeout_thread(); - /* Session menu */ if (gtk_widget_get_visible (session_menuitem)) { @@ -2814,7 +2900,7 @@ main (int argc, char **argv) } set_language (NULL); } - + /* a11y menu */ if (gtk_widget_get_visible (a11y_menuitem)) { @@ -2882,6 +2968,22 @@ main (int argc, char **argv) update_layouts_menu_state (); } + /* Host label */ + if (gtk_widget_get_visible (host_menuitem)) + gtk_menu_item_set_label (GTK_MENU_ITEM (host_menuitem), lightdm_get_hostname ()); + + /* Clock label */ + if (gtk_widget_get_visible (clock_menuitem)) + { + gtk_menu_item_set_label (GTK_MENU_ITEM (clock_menuitem), ""); + clock_label = gtk_bin_get_child (GTK_BIN (clock_menuitem)); + clock_format = g_key_file_get_value (config, "greeter", "clock-format", NULL); + if (!clock_format) + clock_format = "%a, %H:%M"; + clock_timeout_thread (); + gdk_threads_add_timeout (1000, (GSourceFunc) clock_timeout_thread, NULL); + } + #if GTK_CHECK_VERSION (3, 0, 0) /* A bit of CSS */ css_provider = gtk_css_provider_new (); @@ -3011,7 +3113,6 @@ main (int argc, char **argv) } gtk_widget_set_sensitive (keyboard_menuitem, a11y_keyboard_command != NULL); gtk_widget_set_visible (keyboard_menuitem, a11y_keyboard_command != NULL); - gdk_threads_add_timeout (1000, (GSourceFunc) clock_timeout_thread, NULL); /* focus fix (source: unity-greeter) */ GdkWindow* root_window = gdk_get_default_root_window (); |