Rectangles is now actually playable, since I've used the new UI
[sgt/puzzles] / gtk.c
diff --git a/gtk.c b/gtk.c
index ff6c3f7..6a98726 100644 (file)
--- a/gtk.c
+++ b/gtk.c
@@ -9,6 +9,8 @@
 #include <stdarg.h>
 #include <string.h>
 
+#include <sys/time.h>
+
 #include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
 
@@ -63,6 +65,7 @@ struct frontend {
     GdkGC *gc;
     int bbox_l, bbox_r, bbox_u, bbox_d;
     int timer_active, timer_id;
+    struct timeval last_time;
     struct font *fonts;
     int nfonts, fontsize;
     config_item *cfg;
@@ -280,7 +283,7 @@ static gint button_event(GtkWidget *widget, GdkEventButton *event,
     if (!fe->pixmap)
         return TRUE;
 
-    if (event->type != GDK_BUTTON_PRESS)
+    if (event->type != GDK_BUTTON_PRESS && event->type != GDK_BUTTON_RELEASE)
         return TRUE;
 
     if (event->button == 2 || (event->state & GDK_SHIFT_MASK))
@@ -292,6 +295,33 @@ static gint button_event(GtkWidget *widget, GdkEventButton *event,
     else
        return FALSE;                  /* don't even know what button! */
 
+    if (event->type == GDK_BUTTON_RELEASE)
+        button += LEFT_RELEASE - LEFT_BUTTON;
+
+    if (!midend_process_key(fe->me, event->x, event->y, button))
+       gtk_widget_destroy(fe->window);
+
+    return TRUE;
+}
+
+static gint motion_event(GtkWidget *widget, GdkEventMotion *event,
+                         gpointer data)
+{
+    frontend *fe = (frontend *)data;
+    int button;
+
+    if (!fe->pixmap)
+        return TRUE;
+
+    if (event->state & (GDK_BUTTON2_MASK | GDK_SHIFT_MASK))
+       button = MIDDLE_DRAG;
+    else if (event->state & GDK_BUTTON1_MASK)
+       button = LEFT_DRAG;
+    else if (event->state & GDK_BUTTON3_MASK)
+       button = RIGHT_DRAG;
+    else
+       return FALSE;                  /* don't even know what button! */
+
     if (!midend_process_key(fe->me, event->x, event->y, button))
        gtk_widget_destroy(fe->window);
 
@@ -354,8 +384,15 @@ static gint timer_func(gpointer data)
 {
     frontend *fe = (frontend *)data;
 
-    if (fe->timer_active)
-        midend_timer(fe->me, 0.02);    /* may clear timer_active */
+    if (fe->timer_active) {
+       struct timeval now;
+       float elapsed;
+       gettimeofday(&now, NULL);
+       elapsed = ((now.tv_usec - fe->last_time.tv_usec) * 0.000001F +
+                  (now.tv_sec - fe->last_time.tv_sec));
+        midend_timer(fe->me, elapsed); /* may clear timer_active */
+       fe->last_time = now;
+    }
 
     return fe->timer_active;
 }
@@ -369,8 +406,10 @@ void deactivate_timer(frontend *fe)
 
 void activate_timer(frontend *fe)
 {
-    if (!fe->timer_active)
+    if (!fe->timer_active) {
         fe->timer_id = gtk_timeout_add(20, timer_func, fe);
+       gettimeofday(&fe->last_time, NULL);
+    }
     fe->timer_active = TRUE;
 }
 
@@ -857,7 +896,7 @@ static frontend *new_window(void)
 #if 0
        /* For GTK 2.0, should we be using gtk_widget_set_size_request? */
 #endif
-       gtk_widget_set_usize(viewport, x, req.height);
+       gtk_widget_set_usize(viewport, -1, req.height);
     } else
        fe->statusbar = NULL;
 
@@ -881,6 +920,10 @@ static frontend *new_window(void)
                       GTK_SIGNAL_FUNC(key_event), fe);
     gtk_signal_connect(GTK_OBJECT(fe->area), "button_press_event",
                       GTK_SIGNAL_FUNC(button_event), fe);
+    gtk_signal_connect(GTK_OBJECT(fe->area), "button_release_event",
+                      GTK_SIGNAL_FUNC(button_event), fe);
+    gtk_signal_connect(GTK_OBJECT(fe->area), "motion_notify_event",
+                      GTK_SIGNAL_FUNC(motion_event), fe);
     gtk_signal_connect(GTK_OBJECT(fe->area), "expose_event",
                       GTK_SIGNAL_FUNC(expose_area), fe);
     gtk_signal_connect(GTK_OBJECT(fe->window), "map_event",
@@ -888,7 +931,10 @@ static frontend *new_window(void)
     gtk_signal_connect(GTK_OBJECT(fe->area), "configure_event",
                       GTK_SIGNAL_FUNC(configure_area), fe);
 
-    gtk_widget_add_events(GTK_WIDGET(fe->area), GDK_BUTTON_PRESS_MASK);
+    gtk_widget_add_events(GTK_WIDGET(fe->area),
+                          GDK_BUTTON_PRESS_MASK |
+                          GDK_BUTTON_RELEASE_MASK |
+                         GDK_BUTTON_MOTION_MASK);
 
     gtk_widget_show(fe->area);
     gtk_widget_show(fe->window);