Implementing overlapping shortcuts

一个人想着一个人 提交于 2020-05-17 07:44:32

问题


I'm trying to implement the Ctrl+C shortcut a widget without it disturbing other defined shortcuts.

Problem

My window looks like this:

  • GtkWindow
    • GtkEntry
    • GtkToggleButton

Part of the code

// --- add checkbox ---
GtkWidget * checkbutton = gtk_check_button_new_with_label("My Checkbox");
gtk_container_add(GTK_CONTAINER(vbox), GTK_WIDGET(checkbutton));

// --- setup checkbox shortcut ---

GtkAccelGroup * accel_group = gtk_accel_group_new();
gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);   

gtk_widget_add_accelerator(checkbutton, "clicked", accel_group, 
                          GDK_KEY_c, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); 
g_signal_connect(checkbutton, "clicked", G_CALLBACK(onCopyCheckbox), NULL);    
  // problem: this event fires, even if GtkEntry is focussed
  //          it then block the <kbd>Ctrl+C</kbd>-Event of GtkEntry

Expected behaviour

  • If GtkEntry is focussed and Ctrl+C is pressed, the function callback1() should be triggered.
  • If GtkToggleButton is focussed and Ctrl+C is pressed, it should print "onCopyCheckbox() called\n".

Actual behavior

  • If GtkEntry is focussed and Ctrl+C is pressed, "onCopyCheckbox() called\n" gets printed and nothing gets copied.
  • If GtkToggleButton is focussed and Ctrl+C is pressed, "onCopyCheckbox() called\n" gets printed.

Please do not...

  • tell me I should use a different shortcut / accelerator.

Full compilable and executable code:

#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

// ------------------------------------------------------------

void
onCopyCheckbox (GtkWidget      *widget,
                GdkDragContext *context,
                gpointer        user_data)
{
  printf("onCopyCheckbox() called\n");
}

// ------------------------------------------------------------

void fillWindow (GtkWindow * window)
{

  // ------- create layout ------------
  GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
  gtk_container_add(GTK_CONTAINER(window),GTK_WIDGET(vbox)); 

  // --- add line edit --- 
  GtkWidget * lineedit = gtk_entry_new();
  gtk_container_add(GTK_CONTAINER(vbox), GTK_WIDGET(lineedit));

  // --- add checkbox ---
  GtkWidget * checkbutton = gtk_check_button_new_with_label("My Checkbox");
  gtk_container_add(GTK_CONTAINER(vbox), GTK_WIDGET(checkbutton));

  // --- setup checkbox shortcut ---

  GtkAccelGroup * accel_group = gtk_accel_group_new();
  gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);   

  gtk_widget_add_accelerator(checkbutton, "clicked", accel_group, 
                            GDK_KEY_c, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); 
  g_signal_connect(checkbutton, "clicked", G_CALLBACK(onCopyCheckbox), NULL);    
    // problem: this event fires, even if GtkEntry is focussed
    //          it then block the <kbd>Ctrl+C</kbd>-Event of GtkEntry

}

// ------------------------------------------------------------

int main(int argc, char *argv[]) {

  gtk_init(&argc, &argv);

  GtkWindow * window;
  {
    window = (GtkWindow*)gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title (window, "Window title");
    gtk_window_set_default_size (window, 200, 200);
    g_signal_connect(window, "destroy", gtk_main_quit, NULL);
  }

  fillWindow(window);

  gtk_widget_show_all ((GtkWidget*)window);
  gtk_main();

  return 0;
}

// ------------------------------------------------------------

回答1:


Imagine you want to spawn the function below on Ctrl+C while the checkbox is focussed.

void 
shortcutAction(GSimpleAction* a, GVariant * b, gpointer c){
  printf("shortcutAction() called\n");
}

This is how you setup your checkbox

// --- add checkbox ---
GtkWidget * checkbox = gtk_check_button_new_with_label("My Checkbox");
gtk_container_add(GTK_CONTAINER(vbox), GTK_WIDGET(checkbox));

// ========= setup checkbox shortcut ==============

GtkApplication * app = GTK_APPLICATION(g_application_get_default());

// ------- Part 1: create the action itself -----------
  // All the action you want to add go in one ActionGroup
  GSimpleActionGroup * group = g_simple_action_group_new();

  // define all action you want to have
  //  these action can be basically seen as some kind of signal  
  static const GActionEntry actions[] {
    { .name="print", .activate=shortcutAction}
  };

  // ActionGroup.add(actions[])        
  g_action_map_add_action_entries(G_ACTION_MAP(group), actions, G_N_ELEMENTS(actions), NULL);

  // Widget.addActionGroup(ActionGroup) // connect widget and action group
  //  No you also create a name for the group. Here "checkbox" (but can be anything)
  gtk_widget_insert_action_group (GTK_WIDGET(checkbox), "checkbox", G_ACTION_GROUP(group));

// ------- Part 2: create the shortcut to create the action --------
const gchar * const shortcuts[] = { "<Ctrl>C", NULL };
gtk_application_set_accels_for_action (app, "checkbox.print", shortcuts);

Remarks

As you see in the code, there's a strict difference between

  • defining actions
  • defining shortcuts


来源:https://stackoverflow.com/questions/61368448/implementing-overlapping-shortcuts

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!