2

I've been searching all over the place to find out how to get my program to close using the escape key. Not that many people use GTK+ I assume. Also, if it's not asking too much, can some please show me how to use the Gnome developer website so I could find this stuff out on my own? Thanks. So, closing the window with escape key, here's my code:

#include <stdio.h>
#include <string.h>
#include <gtk/gtk.h>
#include <stdlib.h>
#include <ctype.h>
#include <curses.h>

#define KEY_ESC '\033'

static GtkWidget *entry;

static gboolean kill_window(GtkWidget *widget, GdkEvent *event, gpointer data)
{
    gtk_main_quit();
    return FALSE;
}

static void button_press(GtkWidget *widget, gpointer data)
{
    const char *text = gtk_entry_get_text(GTK_ENTRY(entry));
    //system("cd" text);
    //printf("%s\n", text);
    const char *text2 = "&";
    char *concatenation;
    concatenation = malloc(strlen(text)+2);
    strcpy(concatenation, text);
    strcat(concatenation, text2);
    system(concatenation); 
    gtk_main_quit();
}

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

GtkWidget *window;
GtkWidget *button;
GtkWidget *button1;
GtkWidget *hbox;


gtk_init(&argc, &argv);

window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
button = gtk_button_new_with_label("Run");
button1 = gtk_button_new_with_label("Cancel");
entry = gtk_entry_new();
hbox = gtk_vbox_new(FALSE, 2);

gtk_window_set_title(GTK_WINDOW(window), "Run..");

gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS);
g_signal_connect(window, "delete_event", G_CALLBACK(kill_window), NULL);

g_signal_connect(button, "clicked", G_CALLBACK(button_press), NULL);

g_signal_connect(button1, "clicked", G_CALLBACK(kill_window), NULL);
g_signal_connect(entry, "activate", G_CALLBACK(button_press), NULL);
g_signal_connect(button1, "delete_event", G_CALLBACK(kill_window), NULL);
gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
gtk_window_set_default_size(GTK_WINDOW(window), 250, 100);
gtk_window_set_decorated(GTK_WINDOW(window), TRUE);

gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 2);

gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 2); 
gtk_box_pack_start(GTK_BOX(hbox), button1, FALSE, FALSE, 2);
gtk_container_add(GTK_CONTAINER(window), hbox);
gtk_widget_show_all(window);

gtk_main(); 

return 0;
}
IC2D
  • 471
  • 4
  • 11
  • 22

2 Answers2

4

Connect to the key_press_event signal on the top-level window:

g_signal_connect(window, "key_press_event", G_CALLBACK(check_escape), NULL);

The check_escape callback will look like this:

#include <gdk/gdkkeysyms.h>
...
static gboolean check_escape(GtkWidget *widget, GdkEventKey *event, gpointer data)
{
  if (event->keyval == GDK_KEY_Escape) {
    gtk_main_quit();
    return TRUE;
  }
  return FALSE;
}

Also, you don't need the <curses.h> include, nor the KEY_ESC definition.

If your top-level window is essentially a dialog, you might consider using a GtkDialog instead of a GtkWindow. A dialog provides stock responses such as "OK" and "Cancel", with enter and escape keys invoking the expected response.

user4815162342
  • 141,790
  • 18
  • 296
  • 355
  • HOw do I declare GDK_Escape as a variable? Is it a struct I must make? – IC2D Jul 19 '13 at 22:26
  • `GDK_Escape` is an integer value defined in ``; you shouldn't need any special declaration to get it. – user4815162342 Jul 19 '13 at 22:35
  • My apologies. I figured out why I was getting an error with the 'GDK_Escape variable'. It is not defined in . What is is however declared is GDK_KEY_Escape, which does the job. Thanks. – IC2D Jul 20 '13 at 07:31
  • @user1217522 I've now updated the answer to use `GDK_KEY_Escape`, which seems to be the preferred name now. (`GDK_Escape` works for me, possibly because I'm testing with a different GTK version.) – user4815162342 Jul 20 '13 at 07:34
  • If you need to test against multiple keys within `check_escape` you can `switch` on `event->keyval` (e.g. `switch (event->keyval) { case GDK_KEY_Escape: ...handle keypress...; break;` or instead of `break;` you can `return TRUE;` if no further processing of the keypress is required) – David C. Rankin Jan 17 '17 at 05:24
1

For your application I would consider using GtkDialog and stock buttons rather than GtkWindow, that way you just need to test a return variable from the dialog that GTK sets when the user presses a button rather than set up any signal handlers. It also automatically sets it up so to return GTK_RESPONSE_CANCEL if the dialog is cancelled and you can then destroy the window.

Phillip Wood
  • 831
  • 4
  • 5