[california/wip/725767-week] Use unguaranteed click events to react quicker



commit 1371593c3b4c54f2cf7c9425ca353912cb440715
Author: Jim Nelson <jim yorba org>
Date:   Thu May 22 15:08:49 2014 -0700

    Use unguaranteed click events to react quicker

 src/toolkit/toolkit-button-connector.vala |   62 +++++++++++++++++++++++------
 src/view/week/week-grid.vala              |   14 +++++--
 2 files changed, 59 insertions(+), 17 deletions(-)
---
diff --git a/src/toolkit/toolkit-button-connector.vala b/src/toolkit/toolkit-button-connector.vala
index 49d303b..915134d 100644
--- a/src/toolkit/toolkit-button-connector.vala
+++ b/src/toolkit/toolkit-button-connector.vala
@@ -81,6 +81,7 @@ public class ButtonConnector : EventConnector {
      * The "raw" "button-pressed" signal received by { link ButtonConnector}.
      *
      * Signal subscribers should cancel the Cancellable to prevent propagation of the event.
+     * This will prevent the various "clicked" signals from firing.
      */
     public signal void pressed(Gtk.Widget widget, Gdk.EventButton event, Cancellable cancellable);
     
@@ -88,23 +89,40 @@ public class ButtonConnector : EventConnector {
      * The "raw" "button-released" signal received by { link ButtonConnector}.
      *
      * Signal subscribers should cancel the Cancellable to prevent propagation of the event.
+     * This will prevent the various "clicked" signals from firing.
      */
     public signal void released(Gtk.Widget widget, Gdk.EventButton event, Cancellable cancellable);
     
     /**
      * Fired when a button is pressed and released once.
+     *
+     * The "guaranteed" flag is important to distinguish here.  If set, that indicates a timeout
+     * has occurred and the user did not follow the click with a second or third.  If not set,
+     * this was fired immediately after the user released the button and it is unknown if the user
+     * intends to follow it with more clicks.
+     *
+     * Because no timeout has occurred, unguaranteed clicks can be processed immediately if they
+     * occur on a widget or location where double- and triple-clicks are meaningless.
+     *
+     * NOTE: This means "clicked" (and { link double_clicked} and { link triple_clicked} will be
+     * fired ''twice'', once unguaranteed, once guaranteed.  To prevent double-processing, handlers
+     * should always check the flag.
      */
-    public signal void clicked(ButtonEvent details);
+    public signal void clicked(ButtonEvent details, bool guaranteed);
     
     /**
      * Fired when a button is pressed and released twice in succession.
+     *
+     * See { link clicked} for an explanation of the { link guaranteed} flag.
      */
-    public signal void double_clicked(ButtonEvent details);
+    public signal void double_clicked(ButtonEvent details, bool guaranteed);
     
     /**
      * Fired when a button is pressed and released thrice in succession.
+     *
+     * See { link clicked} for an explanation of the { link guaranteed} flag.
      */
-    public signal void triple_clicked(ButtonEvent details);
+    public signal void triple_clicked(ButtonEvent details, bool guaranteed);
     
     /**
      * Create a new { link ButtonConnector} for monitoring (mouse) button events from Gtk.Widgets.
@@ -141,24 +159,24 @@ public class ButtonConnector : EventConnector {
      * Subclasses may override this method to hook into this event before or after the signal
      * has fired.
      */
-    protected virtual void notify_clicked(ButtonEvent details) {
-        clicked(details);
+    protected virtual void notify_clicked(ButtonEvent details, bool guaranteed) {
+        clicked(details, guaranteed);
     }
     
     /**
      * Subclasses may override this method to hook into this event before or after the signal
      * has fired.
      */
-    protected virtual void notify_double_clicked(ButtonEvent details) {
-        double_clicked(details);
+    protected virtual void notify_double_clicked(ButtonEvent details, bool guaranteed) {
+        double_clicked(details, guaranteed);
     }
     
     /**
      * Subclasses may override this method to hook into this event before or after the signal
      * has fired.
      */
-    protected virtual void notify_triple_clicked(ButtonEvent details) {
-        triple_clicked(details);
+    protected virtual void notify_triple_clicked(ButtonEvent details, bool guaranteed) {
+        triple_clicked(details, guaranteed);
     }
     
     protected override void connect_signals(Gtk.Widget widget) {
@@ -261,8 +279,26 @@ public class ButtonConnector : EventConnector {
                 // update saved state (if any) with release info and start timer
                 if (button_states != null) {
                     InternalButtonEvent? details = button_states.get(widget);
-                    if (details != null)
+                    if (details != null) {
+                        // fire "unguaranteed" clicked signals now (with button release) rather than
+                        // wait for timeout using the current value of press_type before the details
+                        // are updated
+                        switch (details.press_type) {
+                            case Gdk.EventType.BUTTON_PRESS:
+                                notify_clicked(details, false);
+                            break;
+                            
+                            case Gdk.EventType.2BUTTON_PRESS:
+                                notify_double_clicked(details, false);
+                            break;
+                            
+                            case Gdk.EventType.3BUTTON_PRESS:
+                                notify_triple_clicked(details, false);
+                            break;
+                        }
+                        
                         details.update_release(widget, event);
+                    }
                 }
             break;
         }
@@ -275,15 +311,15 @@ public class ButtonConnector : EventConnector {
         // notify subscribers
         switch (details.press_type) {
             case Gdk.EventType.BUTTON_PRESS:
-                notify_clicked(details);
+                notify_clicked(details, true);
             break;
             
             case Gdk.EventType.2BUTTON_PRESS:
-                notify_double_clicked(details);
+                notify_double_clicked(details, true);
             break;
             
             case Gdk.EventType.3BUTTON_PRESS:
-                notify_triple_clicked(details);
+                notify_triple_clicked(details, true);
             break;
         }
         
diff --git a/src/view/week/week-grid.vala b/src/view/week/week-grid.vala
index f0a87cf..d55da22 100644
--- a/src/view/week/week-grid.vala
+++ b/src/view/week/week-grid.vala
@@ -271,8 +271,9 @@ internal class Grid : Gtk.Box {
         return date_to_all_day.get(cell_date);
     }
     
-    private void on_day_pane_clicked(Toolkit.ButtonEvent details) {
-        if (details.button != Toolkit.Button.PRIMARY)
+    private void on_day_pane_clicked(Toolkit.ButtonEvent details, bool guaranteed) {
+        // only interested in unguaranteed clicks on the primary mouse button
+        if (details.button != Toolkit.Button.PRIMARY || guaranteed)
             return;
         
         DayPane day_pane = (DayPane) details.widget;
@@ -282,12 +283,17 @@ internal class Grid : Gtk.Box {
             owner.request_display_event(event, day_pane, details.press_point);
     }
     
-    private void on_day_pane_double_clicked(Toolkit.ButtonEvent details) {
-        if (details.button != Toolkit.Button.PRIMARY)
+    private void on_day_pane_double_clicked(Toolkit.ButtonEvent details, bool guaranteed) {
+        // only interested in unguaranteed double-clicks on the primary mouse button
+        if (details.button != Toolkit.Button.PRIMARY || guaranteed)
             return;
         
         DayPane day_pane = (DayPane) details.widget;
         
+        // if an event is at this location, don't process
+        if (day_pane.get_event_at(details.press_point) != null)
+            return;
+        
         // convert click into starting time on the day pane rounded down to the nearest half-hour
         Calendar.WallTime wall_time = day_pane.get_wall_time(details.press_point.y).round_down(
             30, Calendar.TimeUnit.MINUTE);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]