summaryrefslogtreecommitdiff
path: root/services
diff options
authorMarco Trevisan (Treviño) <mail@3v1n0.net>2016-09-02 15:36:37 +0200
committerMarco Trevisan (Treviño) <mail@3v1n0.net>2016-09-02 15:36:37 +0200
commit1a8d47d4f27026ee9f7050fc6ab2bd6f1078ceec (patch)
treebc8c8b8026a2b1f3f3336c4fcd787e3e1baa2b00 /services
parent00d68bd94b4269ddfc55bdc862d41170e688a964 (diff)
parent858e4ed48b5a2a96ef6227b36017a419b9ad69dd (diff)
Merging with trunk
(bzr r4153.9.53)
Diffstat (limited to 'services')
-rw-r--r--services/panel-service.c88
1 files changed, 78 insertions, 10 deletions
diff --git a/services/panel-service.c b/services/panel-service.c
index b9b86cd7f..4451fffa5 100644
--- a/services/panel-service.c
+++ b/services/panel-service.c
@@ -80,6 +80,7 @@ struct _PanelServicePrivate
gint last_right;
gint last_bottom;
guint32 last_menu_button;
+ guint64 last_open_time;
GSettings *gsettings;
KeyBinding menu_toggle;
@@ -92,6 +93,7 @@ struct _PanelServicePrivate
/* Globals */
static gboolean suppress_signals = FALSE;
+static void (*default_menu_shell_deactivate) (GtkMenuShell *menu_shell);
enum
{
@@ -138,6 +140,7 @@ static void sort_indicators (PanelService *);
static void notify_object (IndicatorObject *object);
static void update_keybinding (GSettings *, const gchar *, gpointer);
static void emit_upstart_event (const gchar *);
+static void menu_shell_deactivate_override (GtkMenuShell *menu_shell);
static gchar * get_indicator_entry_id_by_entry (IndicatorObjectEntry *entry);
static IndicatorObjectEntry * get_indicator_entry_by_id (PanelService *self, const gchar *entry_id);
static GdkFilterReturn event_filter (GdkXEvent *, GdkEvent *, PanelService *);
@@ -161,7 +164,7 @@ panel_service_class_dispose (GObject *self)
if (GTK_IS_WIDGET (priv->last_menu) &&
gtk_widget_get_realized (GTK_WIDGET (priv->last_menu)))
{
- gtk_menu_popdown (GTK_MENU (priv->last_menu));
+ panel_service_close_active_entry (PANEL_SERVICE (self));
g_signal_handlers_disconnect_by_data (priv->last_menu, self);
priv->last_menu = NULL;
}
@@ -435,6 +438,25 @@ get_indicator_entry_by_id (PanelService *self, const gchar *entry_id)
return entry;
}
+static const gchar *
+get_indicator_entry_id_by_menu (PanelService *self, GtkMenu *menu)
+{
+ GHashTableIter iter;
+ IndicatorObjectEntry* entry;
+ gchar *id;
+
+ g_hash_table_iter_init (&iter, self->priv->id2entry_hash);
+ while (g_hash_table_iter_next (&iter, (gpointer*) &id, (gpointer*) &entry))
+ {
+ if (entry && entry->menu == menu)
+ {
+ return id;
+ }
+ }
+
+ return NULL;
+}
+
static void
ensure_entry_menu_is_closed (PanelService *self,
const gchar *panel_id,
@@ -446,7 +468,9 @@ ensure_entry_menu_is_closed (PanelService *self,
if (GTK_IS_MENU (priv->last_menu) && priv->last_menu == entry->menu)
{
if (!priv->last_panel || !panel_id || g_strcmp0 (priv->last_panel, panel_id) == 0)
- gtk_menu_popdown (entry->menu);
+ {
+ panel_service_close_active_entry (self);
+ }
}
}
@@ -590,17 +614,15 @@ event_filter (GdkXEvent *ev, GdkEvent *gev, PanelService *self)
event_matches_keybinding (event->mods.base, keysym, &priv->show_dash) ||
event_matches_keybinding (event->mods.base, keysym, &priv->show_hud))
{
- if (GTK_IS_MENU (priv->last_menu))
- gtk_menu_popdown (GTK_MENU (priv->last_menu));
-
+ panel_service_close_active_entry (self);
ret = GDK_FILTER_REMOVE;
}
else if (event->mods.base != GDK_CONTROL_MASK)
{
if (!IsModifierKey (keysym) && (event->mods.base != 0 || is_allowed_keysym (keysym)))
{
- if (GTK_IS_MENU (priv->last_menu) && !is_control_keysym (keysym))
- gtk_menu_popdown (GTK_MENU (priv->last_menu));
+ if (!is_control_keysym (keysym))
+ panel_service_close_active_entry (self);
reinject_key_event_to_root_window (event);
ret = GDK_FILTER_REMOVE;
@@ -1370,9 +1392,7 @@ on_indicator_menu_show (IndicatorObject *object,
if (!entry)
{
- if (GTK_IS_MENU (self->priv->last_menu))
- gtk_menu_popdown (GTK_MENU (self->priv->last_menu));
-
+ panel_service_close_active_entry (self);
return;
}
@@ -1840,8 +1860,16 @@ static void
on_active_menu_hidden (GtkMenu *menu, PanelService *self)
{
PanelServicePrivate *priv = self->priv;
+ GtkMenuShellClass *menu_shell_class = GTK_MENU_SHELL_GET_CLASS (priv->last_menu);
+
g_signal_handlers_disconnect_by_data (priv->last_menu, self);
+ if (menu_shell_class && default_menu_shell_deactivate &&
+ menu_shell_class->deactivate != default_menu_shell_deactivate)
+ {
+ menu_shell_class->deactivate = default_menu_shell_deactivate;
+ }
+
priv->last_x = 0;
priv->last_y = 0;
priv->last_menu_button = 0;
@@ -1853,6 +1881,7 @@ on_active_menu_hidden (GtkMenu *menu, PanelService *self)
priv->last_right = 0;
priv->last_top = 0;
priv->last_bottom = 0;
+ priv->last_open_time = 0;
priv->use_event = FALSE;
priv->pressed_entry = NULL;
@@ -2270,6 +2299,34 @@ menuitem_activated (GtkWidget *menuitem, IndicatorObjectEntry *entry)
}
static void
+menu_shell_deactivate_override (GtkMenuShell *menu_shell)
+{
+ PanelService *self = panel_service_get_default ();
+ const gchar *entry_id;
+
+ if (gtk_get_current_event () && GTK_MENU (menu_shell) == self->priv->last_menu)
+ {
+ guint64 ms_open = (g_get_monotonic_time () - self->priv->last_open_time) / 1000;
+
+ if (ms_open < 50)
+ {
+ /* If the menu shell deactivation was requested by an event, we ensure this
+ * didn't happen too early to activation, or there could be a race causing
+ * no menu to appear. Also since the item is now marked as inactive, we should
+ * manually highlight it. */
+ entry_id = get_indicator_entry_id_by_menu (self, self->priv->last_menu);
+
+ if (entry_id)
+ g_signal_emit (self, _service_signals[ENTRY_ACTIVATE_REQUEST], 0, entry_id);
+
+ return;
+ }
+ }
+
+ default_menu_shell_deactivate (menu_shell);
+}
+
+static void
panel_service_show_entry_common (PanelService *self,
IndicatorObject *object,
IndicatorObjectEntry *entry,
@@ -2281,6 +2338,7 @@ panel_service_show_entry_common (PanelService *self,
{
PanelServicePrivate *priv;
GtkWidget *last_menu;
+ GtkMenuShellClass *menu_shell_class;
g_return_if_fail (PANEL_IS_SERVICE (self));
g_return_if_fail (INDICATOR_IS_OBJECT (object));
@@ -2350,6 +2408,14 @@ panel_service_show_entry_common (PanelService *self,
g_signal_connect_after (priv->last_menu, "move-current",
G_CALLBACK (on_active_menu_move_current), self);
+ /* Override the menu deactivation in order to prevent it to close too early */
+ menu_shell_class = GTK_MENU_SHELL_GET_CLASS (priv->last_menu);
+ if (menu_shell_class && menu_shell_class->deactivate != menu_shell_deactivate_override)
+ {
+ default_menu_shell_deactivate = menu_shell_class->deactivate;
+ menu_shell_class->deactivate = menu_shell_deactivate_override;
+ }
+
gtk_menu_shell_set_take_focus (GTK_MENU_SHELL (priv->last_menu), TRUE);
gtk_menu_popup (priv->last_menu, NULL, NULL, positon_menu, self, button, CurrentTime);
gboolean visible = gtk_widget_is_visible (GTK_WIDGET (priv->last_menu));
@@ -2382,6 +2448,7 @@ panel_service_show_entry_common (PanelService *self,
priv->last_right = left + width -1;
priv->last_top = top;
priv->last_bottom = top + height -1;
+ priv->last_open_time = g_get_monotonic_time ();
}
else
{
@@ -2626,6 +2693,7 @@ panel_service_close_active_entry (PanelService *self)
if (GTK_IS_MENU (self->priv->last_menu))
{
+ self->priv->last_open_time = 0;
gtk_menu_popdown (GTK_MENU (self->priv->last_menu));
}
}