Commit 3361731e201e7ae62f2257ef0acdea52aed924cf

Thomas de Grivel 2020-03-23T15:24:54

drag n drop

diff --git a/rtbuf_gtk.c b/rtbuf_gtk.c
index 396e49f..a28f4bf 100644
--- a/rtbuf_gtk.c
+++ b/rtbuf_gtk.c
@@ -39,6 +39,42 @@ gint rtbuf_x = 100;
 gint rtbuf_y = 100;
 
 s_rtbuf_gtk_connection *modular_connections = NULL;
+s_rtbuf_gtk_connection *drag_connection = NULL;
+
+void rtbuf_gtk_drag_connection_end (RtbufInputWidget *input_widget)
+{
+  if (drag_connection) {
+    if (input_widget) {
+      printf("rtbuf-gtk drag connection connected to input\n");
+      drag_connection->input_widget = input_widget;
+    }
+    else {
+      printf("rtbuf-gtk drag connection abort\n");
+      rtbuf_gtk_connection_remove_one(&modular_connections,
+                                      drag_connection);
+      drag_connection = NULL;
+      gtk_widget_queue_draw(GTK_WIDGET(modular_layout));
+    }
+  }
+}
+
+gboolean rtbuf_gtk_input_motion (RtbufInputWidget *widget,
+                                       GdkEventMotion   *event)
+{
+  printf("rtbuf-gtk input motion\n");
+  if (drag_connection) {
+    if (!(event->state & GDK_BUTTON1_MASK)) {
+      rtbuf_gtk_drag_connection_end(widget);
+      return TRUE;
+    }
+    else {
+      drag_connection->input_widget = widget;
+      gtk_widget_queue_draw(GTK_WIDGET(modular_layout));
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
 
 RtbufWidget * rtbuf_gtk_modular_layout_new (s_rtbuf *rtbuf,
                                             const gint x, const gint y)
@@ -57,6 +93,9 @@ RtbufWidget * rtbuf_gtk_modular_layout_new (s_rtbuf *rtbuf,
   g_signal_connect_swapped(G_OBJECT(event_box), "button-press-event",
                            G_CALLBACK(rtbuf_gtk_rtbuf_button_press),
                            widget);
+  rtbuf_widget_connect_inputs
+    (widget, "motion-notify-event",
+     G_CALLBACK(rtbuf_gtk_input_motion));
   rtbuf_widget_connect_input_checks
     (widget, "button-press-event",
      G_CALLBACK(rtbuf_gtk_input_check_button_press));
@@ -154,8 +193,6 @@ void rtbuf_gtk_modular_draw_arrow (cairo_t *cr, int x1, int y1,
 {
   const int arrow_size = 4;
   int mx = (x2 - x1) / 3;
-  printf("rtbuf-gtk modular draw arrow (%i,%i) -> (%i,%i)\n",
-         x1, y1, x2, y2);
   if (mx < 0) {
     mx = -mx;
     mx += mx / 2;
@@ -248,7 +285,7 @@ gboolean rtbuf_gtk_modular_motion (GtkWidget       *widget,
 {
   if (drag_widget) {
     if (!(event->state & GDK_BUTTON1_MASK)) {
-      printf("rtbuf-gtk modular drop\n");
+      printf("rtbuf-gtk modular drop widget\n");
       drag_widget = NULL;
       return TRUE;
     }
@@ -265,15 +302,21 @@ gboolean rtbuf_gtk_modular_motion (GtkWidget       *widget,
       return TRUE;
     }
   }
-  /*
   else if (drag_connection) {
-    GdkWindow *window =
-      gtk_widget_get_window(GTK_WIDGET(modular_layout));
-    gdk_window_get_device_position(window, event->device,
-                                   &drag_x, &drag_y, NULL);
-    gtk_widget_queue_draw(GTK_WIDGET(modular_layout));
+    if (!(event->state & GDK_BUTTON1_MASK)) {
+      rtbuf_gtk_drag_connection_end(NULL);
+      return TRUE;
+    }
+    else {
+      GdkWindow *window =
+        gtk_widget_get_window(GTK_WIDGET(modular_layout));
+      gdk_window_get_device_position(window, event->device,
+                                     &drag_x, &drag_y, NULL);
+      drag_connection->input_widget = NULL;
+      gtk_widget_queue_draw(GTK_WIDGET(modular_layout));
+      return TRUE;
+    }
   }
-  */
   return FALSE;
 }
 
diff --git a/rtbuf_gtk.h b/rtbuf_gtk.h
index 2abbaa1..9fb0b87 100644
--- a/rtbuf_gtk.h
+++ b/rtbuf_gtk.h
@@ -38,9 +38,10 @@ s_rtbuf_gtk_connection *modular_connections;
 
 GtkTargetList *rtbuf_move_target_list;
 
-GtkWidget *drag_widget;
-gint       drag_x;
-gint       drag_y;
+GtkWidget              *drag_widget;
+s_rtbuf_gtk_connection *drag_connection;
+gint                    drag_x;
+gint                    drag_y;
 
 gboolean rtbuf_gtk_rtbuf_button_press (GtkWidget *widget,
                                        GdkEvent *event,
diff --git a/rtbuf_gtk_connection.c b/rtbuf_gtk_connection.c
index d8288e7..28dfea0 100644
--- a/rtbuf_gtk_connection.c
+++ b/rtbuf_gtk_connection.c
@@ -14,6 +14,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <assert.h>
 #include "data.h"
 #include "rtbuf_gtk.h"
 
@@ -40,3 +41,24 @@ void rtbuf_gtk_connection_delete (s_rtbuf_gtk_connection *connection)
 {
   data_delete(&g_rtbuf_gtk_connection_alloc, connection);
 }
+
+void rtbuf_gtk_connection_push (s_rtbuf_gtk_connection **head,
+                                s_rtbuf_gtk_connection *item)
+{
+  assert(!item->next);
+  item->next = *head;
+  *head = item;
+}
+
+int rtbuf_gtk_connection_remove_one (s_rtbuf_gtk_connection **head,
+                                     s_rtbuf_gtk_connection *item)
+{
+  s_rtbuf_gtk_connection **next = head;
+  while (*next && *next != item)
+    next = &(*next)->next;
+  if (*next == item) {
+    *next = item->next;
+    return 1;
+  }
+  return 0;
+}
diff --git a/rtbuf_gtk_connection.h b/rtbuf_gtk_connection.h
index ea348b5..b2856d1 100644
--- a/rtbuf_gtk_connection.h
+++ b/rtbuf_gtk_connection.h
@@ -16,4 +16,9 @@ void rtbuf_gtk_connection_init ();
 s_rtbuf_gtk_connection * rtbuf_gtk_connection_new ();
 void rtbuf_gtk_connection_delete (s_rtbuf_gtk_connection *connection);
 
+void rtbuf_gtk_connection_push (s_rtbuf_gtk_connection **head,
+                                s_rtbuf_gtk_connection *item);
+int rtbuf_gtk_connection_remove_one (s_rtbuf_gtk_connection **head,
+                                     s_rtbuf_gtk_connection *item);
+
 #endif
diff --git a/rtbuf_gtk_output.c b/rtbuf_gtk_output.c
index 6250c0a..9dac2fd 100644
--- a/rtbuf_gtk_output.c
+++ b/rtbuf_gtk_output.c
@@ -79,14 +79,8 @@ void rtbuf_gtk_output_drag (RtbufOutputWidget *widget,
     return;
   }
   connection->output_widget = widget;
-  connection->next = modular_connections;
-  modular_connections = connection;
-  gtk_drag_begin_with_coordinates(GTK_WIDGET(widget),
-                                  rtbuf_gtk_output_target_list,
-                                  GDK_ACTION_DEFAULT,
-                                  event->button,
-                                  (GdkEvent*) event,
-                                  -1, -1);
+  rtbuf_gtk_connection_push(&modular_connections, connection);
+  drag_connection = connection;
 }
 
 gboolean rtbuf_gtk_output_check_button_press (RtbufOutputWidget *widget,
diff --git a/rtbuf_input_widget.c b/rtbuf_input_widget.c
index 88cd869..990ea02 100644
--- a/rtbuf_input_widget.c
+++ b/rtbuf_input_widget.c
@@ -208,6 +208,14 @@ rtbuf_input_widget_update (RtbufInputWidget *widget)
   }
 }
 
+void rtbuf_input_widget_connect (GtkWidget *widget,
+                                 gpointer data)
+{
+  s_signal_binding *sb = (s_signal_binding*) data;
+  g_signal_connect(G_OBJECT(widget), sb->signal,
+                   sb->callback, NULL);
+}
+
 void rtbuf_input_widget_connect_check (GtkWidget *input,
                                        gpointer data)
 {
diff --git a/rtbuf_input_widget.h b/rtbuf_input_widget.h
index 83cbd76..887fba7 100644
--- a/rtbuf_input_widget.h
+++ b/rtbuf_input_widget.h
@@ -59,6 +59,8 @@ s_rtbuf *     rtbuf_input_widget_get_rtbuf (RtbufInputWidget *widget);
 unsigned int  rtbuf_input_widget_get_in    (RtbufInputWidget *widget);
 GtkWidget *   rtbuf_input_widget_get_check (RtbufInputWidget *widget);
 void          rtbuf_input_widget_update    (RtbufInputWidget *widget);
+void          rtbuf_input_widget_connect (GtkWidget *input,
+                                          gpointer data);
 void          rtbuf_input_widget_connect_check (GtkWidget *input,
                                                 gpointer data);
 
diff --git a/rtbuf_input_widget.ui b/rtbuf_input_widget.ui
index fbc2558..e667276 100644
--- a/rtbuf_input_widget.ui
+++ b/rtbuf_input_widget.ui
@@ -5,6 +5,7 @@
   <template class="RtbufInputWidget" parent="GtkBox">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
+    <property name="events">GDK_POINTER_MOTION_MASK | GDK_STRUCTURE_MASK</property>
     <child>
       <object class="GtkCheckButton" id="check">
         <property name="visible">True</property>
diff --git a/rtbuf_widget.c b/rtbuf_widget.c
index bf8b091..9b2629d 100644
--- a/rtbuf_widget.c
+++ b/rtbuf_widget.c
@@ -252,6 +252,18 @@ rtbuf_widget_get_rtbuf (RtbufWidget *widget)
   return NULL;
 }
 
+void rtbuf_widget_connect_inputs (RtbufWidget *widget,
+                                  const char *signal,
+                                  GCallback callback)
+{
+  RtbufWidgetPrivate *priv =
+    rtbuf_widget_get_instance_private(widget);
+  s_signal_binding sb = { signal, callback };
+  gtk_container_foreach(GTK_CONTAINER(priv->inputs),
+                        rtbuf_input_widget_connect,
+                        &sb);
+}
+
 void rtbuf_widget_connect_input_checks (RtbufWidget *widget,
                                         const char *signal,
                                         GCallback callback)
diff --git a/rtbuf_widget.h b/rtbuf_widget.h
index bd02d82..2e36a7d 100644
--- a/rtbuf_widget.h
+++ b/rtbuf_widget.h
@@ -61,6 +61,9 @@ void          rtbuf_widget_set_label (RtbufWidget *widget,
 const gchar * rtbuf_widget_get_label (RtbufWidget *widget);
 GtkWidget *   rtbuf_widget_get_event_box (RtbufWidget *widget);
 s_rtbuf *     rtbuf_widget_get_rtbuf (RtbufWidget *widget);
+void          rtbuf_widget_connect_inputs (RtbufWidget *widget,
+                                           const char *signal,
+                                           GCallback callback);
 void          rtbuf_widget_connect_input_checks (RtbufWidget *widget,
                                                  const char *signal,
                                                  GCallback callback);