From 1cb199aa141e445a1b3628f6a8f8688f51adb74f Mon Sep 17 00:00:00 2001
From: Isaac Lenton <isaac@isuniversal.com>
Date: Sat, 31 Oct 2015 16:51:42 +1000
Subject: [PATCH 1/2] Change tile click behaviour to reveal square on click
 release.

    Changes behaviour of button-release event to only reveal tile
    that was originally clicked or cancel the operation.

    https://bugzilla.gnome.org/show_bug.cgi?id=741718
---
 src/minefield-view.vala | 18 ++++--------------
 src/tile.vala           |  9 ++++-----
 2 files changed, 8 insertions(+), 19 deletions(-)

diff --git a/src/minefield-view.vala b/src/minefield-view.vala
index 39ff817..9b393a8 100644
--- a/src/minefield-view.vala
+++ b/src/minefield-view.vala
@@ -194,7 +194,6 @@ public class MinefieldView : Gtk.Grid
                 {
                     mines[i,j] = new Tile (i, j);
                     mines[i,j].show ();
-                    mines[i,j].tile_mouse_over.connect ((x, y) => { tile_mouse_over_cb (x, y); });
                     mines[i,j].tile_pressed.connect ((x, y, event) => { tile_pressed_cb (x, y, event); });
                     mines[i,j].tile_released.connect ((x, y, event) => { tile_released_cb (x, y, event); });
                     add (mines[i,j], i, j);
@@ -218,19 +217,6 @@ public class MinefieldView : Gtk.Grid
         }
     }
 
-    public void tile_mouse_over_cb (int x, int y)
-    {
-        /* Check for end cases and paused game */
-        if (minefield.exploded || minefield.is_complete || minefield.paused)
-            return;
-
-        /* Check that the user isn't currently navigating with keyboard */
-        if (!selected.is_set || keyboard_cursor.is_set)
-            return;
-
-        selected.position = {x, y};
-    }
-
     public void tile_pressed_cb (int x, int y, Gdk.EventButton event)
     {
         /* Ignore double click events */
@@ -284,6 +270,10 @@ public class MinefieldView : Gtk.Grid
         if (!selected.is_set || keyboard_cursor.is_set)
             return;
 
+        /* Check if the square released is the sames as the square pressed. */
+        if (selected.x != x || selected.y != y)
+            return;
+
         /* Check if the user released button outside the minefield */
         if (!minefield.is_location (selected.x, selected.y))
             return;
diff --git a/src/tile.vala b/src/tile.vala
index 6ead583..c288406 100644
--- a/src/tile.vala
+++ b/src/tile.vala
@@ -38,17 +38,16 @@ public class Tile : Gtk.Button
         can_focus = false;
         add_class ("tile");
         set_image (scaling_image);
-        enter_notify_event.connect ((event) =>
-        {
-            tile_mouse_over (prow, pcol);
-            return false;
-        });
         size_allocate.connect ((allocation) =>
         {
             scaling_image.set_pixel_size (allocation.height/3*2);
         });
         button_press_event.connect ((event) =>
         {
+            /* By default windows with both button press and button release
+             * grab Gdk events, ungrab events here for other tiles. */
+            event.device.ungrab (event.time);
+
             tile_pressed (prow, pcol, event);
             return false;
         });
-- 
2.1.0


From b56d2918dc047179e3fc3421279a42a731e398a2 Mon Sep 17 00:00:00 2001
From: Isaac Lenton <isaac@isuniversal.com>
Date: Sat, 31 Oct 2015 18:42:07 +1000
Subject: [PATCH 2/2] Added swipe gesture support for adding flags

    Using a swipe gesture is faster than click-and-hold and
    less clumsy than double-tapping.

    https://bugzilla.gnome.org/show_bug.cgi?id=678272
---
 src/minefield-view.vala | 29 +++++++++++++++++++++++++++++
 src/tile.vala           | 27 ++++++++++++++++++++++++++-
 2 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/src/minefield-view.vala b/src/minefield-view.vala
index 9b393a8..fba124c 100644
--- a/src/minefield-view.vala
+++ b/src/minefield-view.vala
@@ -196,6 +196,7 @@ public class MinefieldView : Gtk.Grid
                     mines[i,j].show ();
                     mines[i,j].tile_pressed.connect ((x, y, event) => { tile_pressed_cb (x, y, event); });
                     mines[i,j].tile_released.connect ((x, y, event) => { tile_released_cb (x, y, event); });
+                    mines[i,j].tile_swiped.connect ((toggle, cancelled) => { tile_swiped_cb (toggle, cancelled); });
                     add (mines[i,j], i, j);
                 }
             }
@@ -217,6 +218,24 @@ public class MinefieldView : Gtk.Grid
         }
     }
 
+    public void tile_swiped_cb (bool toggle, bool cancelled)
+    {
+      if (cancelled)
+      {
+          selected.is_set = false;
+          return;
+      }
+
+      if (toggle)
+      {
+          toggle_mark (selected.x, selected.y);
+      }
+      else
+      {
+          clear_mark (selected.x, selected.y);
+      }
+    }
+
     public void tile_pressed_cb (int x, int y, Gdk.EventButton event)
     {
         /* Ignore double click events */
@@ -395,6 +414,16 @@ public class MinefieldView : Gtk.Grid
         }
     }
 
+    public void clear_mark (uint x, uint y)
+    {
+        if (minefield.is_cleared (x, y))
+            return;
+
+        mines[x,y].add_class ("flag");
+        mines[x,y].remove_class ("maybe");
+        minefield.set_flag (x, y, FlagType.NONE);
+    }
+
     public void toggle_mark (uint x, uint y)
     {
         if (minefield.is_cleared (x, y))
diff --git a/src/tile.vala b/src/tile.vala
index c288406..4a0881e 100644
--- a/src/tile.vala
+++ b/src/tile.vala
@@ -5,11 +5,14 @@ public class Tile : Gtk.Button
     public signal void tile_mouse_over (int x, int y);
     public signal void tile_pressed (int x, int y, Gdk.EventButton event);
     public signal void tile_released (int x, int y, Gdk.EventButton event);
+    public signal void tile_swiped (bool toggle, bool cancelled);
     private static string[] IMAGE_CLASSES = {"mine", "flag", "maybe", "overmine",
                                              "exploded", "1mines", "2mines",
                                              "3mines", "4mines", "5mines",
                                              "6mines", "7mines", "8mines"};
     private Gtk.Image scaling_image;
+    private Gtk.GestureSwipe swipe_gesture;
+    private const int SWIPE_TOL = 20;
 
     public int row
     {
@@ -38,6 +41,27 @@ public class Tile : Gtk.Button
         can_focus = false;
         add_class ("tile");
         set_image (scaling_image);
+        swipe_gesture = new Gtk.GestureSwipe (this);
+        swipe_gesture.touch_only = true;
+        swipe_gesture.swipe.connect ((dx, dy) =>
+        {
+            if (dx*dx + dy*dy > SWIPE_TOL)
+            {
+                if (Math.fabs (dy) < dx)                    // Swipe right
+                  tile_swiped (true, false);
+                else if (Math.fabs (dy) < Math.fabs (dx))   // Swipe left
+                  tile_swiped (false, false);
+                else                                        // Swipe cancelled
+                  tile_swiped (true, true);
+            }
+            else
+            {
+                /** Reveal the tile. */
+                var seq = swipe_gesture.get_last_updated_sequence ();
+                var evt = swipe_gesture.get_last_event (seq);
+                tile_released (prow, pcol, (Gdk.EventButton) evt);
+            }
+        });
         size_allocate.connect ((allocation) =>
         {
             scaling_image.set_pixel_size (allocation.height/3*2);
@@ -53,7 +77,8 @@ public class Tile : Gtk.Button
         });
         button_release_event.connect ((event) =>
         {
-            tile_released (prow, pcol, event);
+            if (!swipe_gesture.is_active ())
+                tile_released (prow, pcol, event);
             return false;
         });
     }
-- 
2.1.0

