[ghex/gtk4-port: 26/91] Context menu; kind-of-sort-of implement copy




commit f67f81153c8bfd53b283a0d39092e65359bcea21
Author: Logan Rathbone <poprocks gmail com>
Date:   Tue Jan 12 16:57:04 2021 -0500

    Context menu; kind-of-sort-of implement copy

 src/conversions-pane.h |   2 +-
 src/ghex.gresource.xml |   1 +
 src/gtkhex.c           | 127 ++++++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 122 insertions(+), 8 deletions(-)
---
diff --git a/src/conversions-pane.h b/src/conversions-pane.h
index d6c3ef15..491b2cc2 100644
--- a/src/conversions-pane.h
+++ b/src/conversions-pane.h
@@ -1,4 +1,4 @@
-/* vim: colorcolumn=80 tw=4 ts=4
+/* vim: colorcolumn=80 ts=4 sw=4
  */
 
 #ifndef CONVERSIONS_PANE_H
diff --git a/src/ghex.gresource.xml b/src/ghex.gresource.xml
index ec2534b9..2c7d8a29 100644
--- a/src/ghex.gresource.xml
+++ b/src/ghex.gresource.xml
@@ -7,5 +7,6 @@
        <gresource prefix="/org/gnome/ghex">
                <file preprocess="xml-stripblanks" compressed="true">ghex-application-window.ui</file>
                <file preprocess="xml-stripblanks" compressed="true">conversions-pane.ui</file>
+               <file preprocess="xml-stripblanks" compressed="true">context-menu.ui</file>
        </gresource>
 </gresources>
diff --git a/src/gtkhex.c b/src/gtkhex.c
index 000ddc1c..5d03efef 100644
--- a/src/gtkhex.c
+++ b/src/gtkhex.c
@@ -78,6 +78,7 @@
 #define SCROLL_TIMEOUT 100
 
 #define is_displayable(c) (((c) >= 0x20) && ((c) < 0x7f))
+#define is_copyable(c) (is_displayable(c) || (c) == 0x0a || (c) == 0x0d)
 
 enum {
        CURSOR_MOVED_SIGNAL,
@@ -216,6 +217,49 @@ static void gtk_hex_update_auto_highlight(GtkHex *gh, GtkHex_AutoHighlight *ahl,
 
 static void recalc_displays(GtkHex *gh);
 
+
+
+static void
+popup_context_menu(GtkWidget *widget, double x, double y)
+{
+       GtkWidget *popover;
+       GtkBuilder *builder;
+       GMenuModel *menu;
+       GdkRectangle rect = { 0 };
+
+       rect.x = x;
+       rect.y = y;
+
+       builder = gtk_builder_new_from_resource ("/org/gnome/ghex/context-menu.ui");
+       menu = G_MENU_MODEL(gtk_builder_get_object (builder, "context-menu"));
+       popover = gtk_popover_menu_new_from_model (menu);
+
+       /* required by TFM. */
+       gtk_widget_set_parent (popover, widget);
+
+       gtk_popover_set_pointing_to (GTK_POPOVER(popover), &rect);
+       gtk_popover_popup (GTK_POPOVER(popover));
+
+       g_object_unref (menu);
+       g_object_unref (builder);
+}
+
+/* ACTIONS - just wrappers around callbacks for this widget. */
+
+static void
+copy_action (GtkWidget *widget,
+               const char *action_name,
+               GVariant *parameter)
+{
+       GtkHex *gh = GTK_HEX(widget);
+
+       g_return_if_fail (GTK_IS_HEX(gh));
+
+       (void)action_name, (void)parameter;
+
+       gtk_hex_copy_to_clipboard (gh);
+}
+
 /*
  * ?_to_pointer translates mouse coordinates in hex/ascii view
  * to cursor coordinates.
@@ -1403,8 +1447,8 @@ hex_pressed_cb (GtkGestureClick *gesture,
        button = gtk_gesture_single_get_current_button
                (GTK_GESTURE_SINGLE(gesture));
 
-       g_debug("%s: n_press: %d, x: %f - y: %f",
-                       __func__, n_press, x, y);
+       g_debug("%s: n_press: %d, x: %f - y: %f - button: %u",
+                       __func__, n_press, x, y, button);
 
        /* Single-press */
        if (button == GDK_BUTTON_PRIMARY)
@@ -1429,10 +1473,17 @@ hex_pressed_cb (GtkGestureClick *gesture,
                        hex_pressed_cb (gesture, n_press, x, y, user_data);
                }
        }
+       /* Right-click */
+       else if (button == GDK_BUTTON_SECONDARY)
+       {
+               g_debug("%s: RIGHT CLICK - TRYING TO POPUP CONTEXT MENU.", __func__);
+
+               popup_context_menu(widget, x, y);
+       }
        /* Middle-click press. */
        else if (button == GDK_BUTTON_MIDDLE)
        {
-               g_debug("%s: MIDDLE CLICK - NOT IMPLEMENTED.");
+               g_debug("%s: MIDDLE CLICK - NOT IMPLEMENTED.", __func__);
 #if 0
                GtkHexClass *klass = GTK_HEX_CLASS(GTK_WIDGET_GET_CLASS(gh));
                gchar *text;
@@ -1640,6 +1691,13 @@ ascii_pressed_cb (GtkGestureClick *gesture,
                        ascii_pressed_cb (gesture, n_press, x, y, user_data);
                }
        }
+       /* Right-click */
+       else if (button == GDK_BUTTON_SECONDARY)
+       {
+               g_debug("%s: RIGHT CLICK - TRYING TO POPUP CONTEXT MENU.", __func__);
+
+               popup_context_menu(widget, x, y);
+       }
        /* Middle-click press. */
        else if (button == GDK_BUTTON_MIDDLE)
        {
@@ -1786,7 +1844,14 @@ key_press_cb (GtkEventControllerKey *controller,
 
        hide_cursor(gh);
 
-       if (! state & GDK_SHIFT_MASK) {
+       /* don't trample over Ctrl */
+       if (state & GDK_CONTROL_MASK) {
+               g_debug("%s: CTRL PRESSED - RETURNING.", __func__);
+               return FALSE;
+       }
+
+       /* Figure out if we're holding shift or not. */
+       if (! (state & GDK_SHIFT_MASK)) {
                gh->selecting = FALSE;
        }
        else {
@@ -1794,7 +1859,7 @@ key_press_cb (GtkEventControllerKey *controller,
        }
 
        switch(keyval) {
-               // TEST
+               // TEST - COPY
        case GDK_KEY_F12:
                g_debug("F12 PRESSED - TESTING CLIPBOARD COPY");
                gtk_hex_copy_to_clipboard (gh);
@@ -1947,6 +2012,26 @@ key_press_cb (GtkEventControllerKey *controller,
        return ret;
 }
 
+static gboolean
+key_release_cb (GtkEventControllerKey *controller,
+               guint                  keyval,
+               guint                  keycode,
+               GdkModifierType        state,
+               gpointer               user_data)
+{
+       GtkHex *gh = GTK_HEX(user_data);
+       GtkWidget *widget = GTK_WIDGET(user_data);
+       gboolean ret = TRUE;
+
+       TEST_DEBUG_FUNCTION_START
+
+       /* avoid shift key getting 'stuck' */
+
+       if (state & GDK_SHIFT_MASK) {
+               gh->selecting = FALSE;
+       }
+}
+
 
 static void
 show_offsets_widget(GtkHex *gh)
@@ -2391,7 +2476,8 @@ gtk_hex_real_copy_to_clipboard (GtkHex *gh)
 
                for (cp = text; *cp != '\0'; ++cp)
                {
-                       if (! is_displayable(*cp))
+//                     if (! is_displayable(*cp))
+                       if (! is_copyable(*cp))
                                *cp = '?';
                }
 
@@ -2797,6 +2883,23 @@ gtk_hex_class_init(GtkHexClass *klass)
                                G_TYPE_NONE,
                                0);
        
+       /* ACTIONS */
+
+       gtk_widget_class_install_action (widget_class, "gtkhex.copy",
+                       NULL,   // GVariant string param_type
+                       copy_action);
+
+
+       /* SHORTCUTS (not to be confused with keybindings, which are set up
+        * in gtk_hex_init) */
+
+       /* Ctrl+c - copy */
+       gtk_widget_class_add_binding_action (widget_class,
+                       GDK_KEY_c,
+                       GDK_CONTROL_MASK,
+                       "gtkhex.copy",
+                       NULL);  // no args.
+
        // API CHANGES
 //     klass->primary = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
 //     klass->clipboard = gtk_clipboard_get(GDK_NONE);
@@ -3036,6 +3139,9 @@ gtk_hex_init(GtkHex *gh)
        /* click gestures */
        gesture = gtk_gesture_click_new ();
 
+       /* listen for any button */
+       gtk_gesture_single_set_button (GTK_GESTURE_SINGLE(gesture), 0);
+
        g_signal_connect (gesture, "pressed",
                        G_CALLBACK(hex_pressed_cb),
                        gh);
@@ -3065,6 +3171,9 @@ gtk_hex_init(GtkHex *gh)
        /* click gestures */
        gesture = gtk_gesture_click_new ();
 
+       /* listen for any button */
+       gtk_gesture_single_set_button (GTK_GESTURE_SINGLE(gesture), 0);
+
        g_signal_connect (gesture, "pressed",
                        G_CALLBACK(ascii_pressed_cb),
                        gh);
@@ -3106,13 +3215,17 @@ gtk_hex_init(GtkHex *gh)
        gtk_widget_add_controller (widget,
                        GTK_EVENT_CONTROLLER(controller));
 
-       /* Event controller - keyboard */
+       /* Event controller - keyboard - for the widget *as a whole* */
        
        controller = gtk_event_controller_key_new ();
 
        g_signal_connect(controller, "key-pressed",
                        G_CALLBACK(key_press_cb),
                        gh);
+       g_signal_connect(controller, "key-released",
+                       G_CALLBACK(key_release_cb),
+                       gh);
+
        gtk_widget_add_controller (widget,
                        GTK_EVENT_CONTROLLER(controller));
 


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