[Xfce4-commits] <xfce4-panel:andrzejr/clock-timezone> Clock plugin: make the calendar popup modal again.

Andrzej noreply at xfce.org
Wed Feb 27 23:00:02 CET 2013


Updating branch refs/heads/andrzejr/clock-timezone
         to 6e309fe308ac56b036448d0a7aa8ba87059b5922 (commit)
       from 1360ea1f656e65508cf227354befe35adef2b068 (commit)

commit 6e309fe308ac56b036448d0a7aa8ba87059b5922
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Wed Feb 27 21:57:56 2013 +0000

    Clock plugin: make the calendar popup modal again.
    
    To force a non-modal popup behavior, use a middle mouse button
    or Ctrl+Btn1.

 plugins/clock/clock.c |  128 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 124 insertions(+), 4 deletions(-)

diff --git a/plugins/clock/clock.c b/plugins/clock/clock.c
index 65767f4..ed9f3c4 100644
--- a/plugins/clock/clock.c
+++ b/plugins/clock/clock.c
@@ -78,10 +78,22 @@ static void     clock_plugin_screen_position_changed   (XfcePanelPlugin       *p
 static void     clock_plugin_configure_plugin          (XfcePanelPlugin       *panel_plugin);
 static void     clock_plugin_set_mode                  (ClockPlugin           *plugin);
 static void     clock_plugin_reposition_calendar       (ClockPlugin           *plugin);
+static gboolean clock_plugin_pointer_grab              (ClockPlugin           *plugin,
+                                                        GtkWidget             *widget,
+                                                        gboolean               keep);
+static void     clock_plugin_pointer_ungrab            (ClockPlugin           *plugin,
+                                                        GtkWidget             *widget);
+static gboolean clock_plugin_calendar_pointed          (GtkWidget             *calendar_window,
+                                                        gdouble                x_root,
+                                                        gdouble                y_root);
+static gboolean clock_plugin_calendar_button_press_event (GtkWidget           *calendar_window,
+                                                          GdkEventButton      *event,
+                                                          ClockPlugin         *plugin);
 static gboolean clock_plugin_calendar_key_press_event  (GtkWidget             *calendar_window,
                                                         GdkEventKey           *event,
                                                         ClockPlugin           *plugin);
-static void     clock_plugin_popup_calendar            (ClockPlugin           *plugin);
+static void     clock_plugin_popup_calendar            (ClockPlugin           *plugin,
+                                                        gboolean               modal);
 static void     clock_plugin_hide_calendar             (ClockPlugin           *plugin);
 static gboolean clock_plugin_tooltip                   (gpointer               user_data);
 
@@ -134,6 +146,9 @@ struct _ClockPlugin
   gchar              *tooltip_format;
   ClockTimeTimeout   *tooltip_timeout;
 
+  GdkGrabStatus       grab_pointer;
+  GdkGrabStatus       grab_keyboard;
+
   gchar              *time_config_tool;
   ClockTime          *time;
 };
@@ -408,7 +423,7 @@ clock_plugin_button_press_event (GtkWidget      *widget,
 {
   GError      *error = NULL;
 
-  if (event->button == 1)
+  if (event->button == 1 || event->button == 2)
     {
       if (event->type == GDK_BUTTON_PRESS &&
           exo_str_is_empty (plugin->command))
@@ -416,7 +431,8 @@ clock_plugin_button_press_event (GtkWidget      *widget,
           /* toggle calendar window visibility */
           if (plugin->calendar_window == NULL
               || !gtk_widget_get_visible (GTK_WIDGET (plugin->calendar_window)))
-            clock_plugin_popup_calendar (plugin);
+            clock_plugin_popup_calendar
+              (plugin, event->button == 1 && !(event->state & GDK_CONTROL_MASK));
           else
             clock_plugin_hide_calendar (plugin);
 
@@ -1016,6 +1032,104 @@ clock_plugin_calendar_show_event (GtkWidget   *calendar_window,
 
 
 
+static void
+clock_plugin_pointer_ungrab (ClockPlugin *plugin,
+                             GtkWidget   *widget)
+{
+  if (plugin->grab_pointer == GDK_GRAB_SUCCESS)
+    gdk_pointer_ungrab (GDK_CURRENT_TIME);
+  if (plugin->grab_keyboard == GDK_GRAB_SUCCESS)
+    gdk_keyboard_ungrab (GDK_CURRENT_TIME);
+}
+
+
+
+static gboolean
+clock_plugin_pointer_grab (ClockPlugin *plugin,
+                           GtkWidget   *widget,
+                           gboolean     keep)
+{
+  GdkWindow     *window;
+  gboolean       grab_succeed = FALSE;
+  guint          i;
+  GdkEventMask   pointer_mask = GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
+                                | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK
+                                | GDK_POINTER_MOTION_MASK;
+
+  window = widget->window;
+
+  /* don't try to get the grab for longer then 1/4 second */
+  for (i = 0; i < (G_USEC_PER_SEC / 100 / 4); i++)
+    {
+      plugin->grab_keyboard = gdk_keyboard_grab (window, TRUE, GDK_CURRENT_TIME);
+      if (plugin->grab_keyboard == GDK_GRAB_SUCCESS)
+        {
+          plugin->grab_pointer = gdk_pointer_grab (window, TRUE, pointer_mask,
+                                                   NULL, NULL, GDK_CURRENT_TIME);
+          if (plugin->grab_pointer == GDK_GRAB_SUCCESS)
+            {
+              grab_succeed = TRUE;
+              break;
+            }
+        }
+
+      g_usleep (100);
+    }
+
+  /* release the grab */
+  if (!keep)
+    clock_plugin_pointer_ungrab (plugin, widget);
+
+  if (!grab_succeed)
+    {
+      clock_plugin_pointer_ungrab (plugin, widget);
+      g_printerr (PACKAGE_NAME ": Unable to get keyboard and mouse "
+                  "grab. Popup failed.\n");
+    }
+
+  return grab_succeed;
+}
+
+
+
+static gboolean
+clock_plugin_calendar_pointed (GtkWidget *calendar_window,
+                               gdouble    x_root,
+                               gdouble    y_root)
+{
+  gint          window_x, window_y;
+
+  if (gtk_widget_get_mapped (calendar_window))
+    {
+      gdk_window_get_position (calendar_window->window, &window_x, &window_y);
+
+      if (x_root >= window_x && x_root < window_x + calendar_window->allocation.width &&
+          y_root >= window_y && y_root < window_y + calendar_window->allocation.height)
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
+
+
+static gboolean
+clock_plugin_calendar_button_press_event (GtkWidget      *calendar_window,
+                                          GdkEventButton *event,
+                                          ClockPlugin    *plugin)
+{
+  if (event->type == GDK_BUTTON_PRESS &&
+      !clock_plugin_calendar_pointed (calendar_window, event->x_root, event->y_root))
+    {
+      clock_plugin_hide_calendar (plugin);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+
+
 static gboolean
 clock_plugin_calendar_key_press_event (GtkWidget      *calendar_window,
                                        GdkEventKey    *event,
@@ -1033,7 +1147,8 @@ clock_plugin_calendar_key_press_event (GtkWidget      *calendar_window,
 
 
 static void
-clock_plugin_popup_calendar (ClockPlugin *plugin)
+clock_plugin_popup_calendar (ClockPlugin *plugin,
+                             gboolean     modal)
 {
   if (plugin->calendar_window == NULL)
     {
@@ -1054,6 +1169,8 @@ clock_plugin_popup_calendar (ClockPlugin *plugin)
                                         | GTK_CALENDAR_SHOW_WEEK_NUMBERS);
       g_signal_connect (G_OBJECT (plugin->calendar_window), "show",
                         G_CALLBACK (clock_plugin_calendar_show_event), plugin);
+      g_signal_connect (G_OBJECT (plugin->calendar_window), "button-press-event",
+                        G_CALLBACK (clock_plugin_calendar_button_press_event), plugin);
       g_signal_connect (G_OBJECT (plugin->calendar_window), "key-press-event",
                         G_CALLBACK (clock_plugin_calendar_key_press_event), plugin);
       gtk_container_add (GTK_CONTAINER (plugin->calendar_window), plugin->calendar);
@@ -1063,6 +1180,8 @@ clock_plugin_popup_calendar (ClockPlugin *plugin)
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (plugin->button), TRUE);
   gtk_widget_show (GTK_WIDGET (plugin->calendar_window));
   xfce_panel_plugin_block_autohide (XFCE_PANEL_PLUGIN (plugin), TRUE);
+  if (modal)
+    clock_plugin_pointer_grab (plugin, GTK_WIDGET (plugin->calendar_window), TRUE);
 }
 
 
@@ -1072,6 +1191,7 @@ clock_plugin_hide_calendar (ClockPlugin *plugin)
 {
   panel_return_if_fail (plugin->calendar_window != NULL);
 
+  clock_plugin_pointer_ungrab (plugin, GTK_WIDGET (plugin->calendar_window));
   gtk_widget_hide (GTK_WIDGET (plugin->calendar_window));
   xfce_panel_plugin_block_autohide (XFCE_PANEL_PLUGIN (plugin), FALSE);
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (plugin->button), FALSE);


More information about the Xfce4-commits mailing list