shift-Tab question



I'm developing a UI where I'm trying to control which widget gets the
focus when Tab and shift-Tab are pressed.  I can capture the Tab key
press event with no problems, but I'm having problems with the shift-Tab
event.  It appears that the Tab key is unique in that a GDK_SHIFT_MASK
cannot be applied to a Tab key-event.  Unlike other keys (such as Return
or Escape), gtk/gdk appears to see a shift-tab as a unique key (as
opposed to a key with a modifier).  That is, gdk_keyval_name()
identifies a Tab as a Tab but a shift-Tab as an ISO_Left_Tab.  Thus the
following code would never see the shift mask because the case would
never be satisfied:

   switch(event->keyval) {
        case GDK_Tab:
                        /* this if block will never evaluate as true */
                if (event->state & GDK_SHIFT_MASK)
                        g_print("Tab: shift is pressed\n");
                else
                        g_print("Tab: shift is not pressed\n");
                break;
        }


Instead, to obtain the desired behavior I find myself using something
like this:

   switch(event->keyval) {
        case GDK_Tab:
                g_print("Tab\n");
                break;
        case GDK_ISO_Left_Tab:
                g_print("shift tab\n");
                break;
        }

My questions are this:
  - Is this the expected behavior?
  - How portable is GDK_ISO_Left_Tab when that code is run on l10n
systems
    (such as Japenese), or even other various brands of Unix?
  - Why does the Tab key operate differently from other keys such as
Return
    or Escape (which I can use GDK_SHIFT_MASK on)?

Being new to gtk, I'm not sure if I'm missing something big here.  Just
to clarify my ignorance :) I've attached a short program that exercises
this problem.

BTW, just in case it matters, I'm using a Stock Redhat 6.0 system (x86)
with gtk 1.2.1 release 10.

Sorry for being so long-winded but I'd really appreciate some help on
this.

	- Steve
	  steve@sarette.com

=======Begin program here===============================================

/**************************************************************************/
/**************************************************************************/
/*           A program designed to show off my confusion
with             */
/*           the Tab key and GDK_SHIFT_MASK. Compile
with:                */
/*                                                                       
*/
/* gcc -Wall -g key.c -o key `gtk-config --cflags` `gtk-config
--libs`    */
/*                                                                       
*/
/*           -Steve
Sarette                                               */
/*           
steve@sarette.com                                           */
/**************************************************************************/
/**************************************************************************/

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


gboolean
on_entry1_key_press_event              (GtkWidget       *widget,
                                        GdkEventKey     *event)
{


   g_print("key is %s\n", gdk_keyval_name(event->keyval));

        /* The way this switch is put together seems like
           the best approach, but I don't know why
           GDK_SHIFT_MASK doesn't work for tab keys
           I'm also not sure how portable ISO_Left_Tab is. */

   switch(event->keyval) {
        case GDK_Tab:
                g_print("Tab\n");
                break;
        case GDK_ISO_Left_Tab:
                g_print("shift tab\n");
                break;
        }
  return FALSE;
}

gboolean
on_entry2_key_press_event              (GtkWidget       *widget,
                                        GdkEventKey     *event)
{

   g_print("key is %s\n", gdk_keyval_name(event->keyval));

   /* All of the following noise is meant to show that
      GDK_SHIFT_MASK does not work with the tab key but
      it does work with other keys (such as the Return
      or Escape key) GDK_CONTROL_MASK works with the tab
      key as well */

   switch(event->keyval){
        case GDK_Tab:
        {
                        /* this if block will never evaluate as true
                           because GDK_Tab is not matched for a
                           shift-Tab */
                if (event->state & GDK_SHIFT_MASK)
                        g_print("Tab: shift is pressed\n");

                       /* this statement will be seen */
                else if (event->state & GDK_CONTROL_MASK)
                        g_print("Tab: Control is pressed\n");
                else
                        g_print("Tab: shift is not pressed\n");
                break;
        }

        case GDK_ISO_Left_Tab:
                        /* this if block will never evaluate as false */
                if (event->state & GDK_SHIFT_MASK)
                        g_print("ISO_Left_Tab: shift is pressed\n");
                else
                        g_print("ISO_Left_Tab: shift is not pressed\n");
                break;

        case GDK_Escape:
                        /* both states are possible */
                if (event->state & GDK_SHIFT_MASK)
                        g_print("Escape: shift is pressed\n");
                else
                        g_print("Escape: shift is not pressed\n");
                break;

        case GDK_Return:
                        /* both states are possible */
                if (event->state & GDK_SHIFT_MASK)
                        g_print("Return: shift is pressed\n");
                else
                        g_print("Return: shift is not pressed\n");
                break;
    }

  return FALSE;GtkWidget*
}


create_window1 ()
{

  GtkWidget *window1;
  GtkWidget *vbox1;
  GtkWidget *entry1;
  GtkWidget *entry2;
  GtkWidget *button1;

  window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_object_set_data (GTK_OBJECT (window1), "window1", window1);
  gtk_window_set_title (GTK_WINDOW (window1), "window1");
  gtk_window_position (GTK_WINDOW (window1), GTK_WIN_POS_CENTER);
  gtk_window_set_policy (GTK_WINDOW (window1), TRUE, TRUE, FALSE);

  vbox1 = gtk_vbox_new (FALSE, 0);
  gtk_object_set_data (GTK_OBJECT (window1), "vbox1", vbox1);
  gtk_widget_show (vbox1);
  gtk_container_add (GTK_CONTAINER (window1), vbox1);

  entry1 = gtk_entry_new ();
  gtk_object_set_data (GTK_OBJECT (window1), "entry1", entry1);
  gtk_widget_show (entry1);
  gtk_box_pack_start (GTK_BOX (vbox1), entry1, TRUE, TRUE, 0);
  gtk_signal_connect (GTK_OBJECT (entry1), "key_press_event",
                      GTK_SIGNAL_FUNC (on_entry1_key_press_event),
                      NULL);

  entry2 = gtk_entry_new ();
  gtk_object_set_data (GTK_OBJECT (window1), "entry2", entry2);
  gtk_widget_show (entry2);
  gtk_box_pack_start (GTK_BOX (vbox1), entry2, TRUE, TRUE, 0);
  gtk_signal_connect (GTK_OBJECT (entry2), "key_press_event",
                      GTK_SIGNAL_FUNC (on_entry2_key_press_event),
                      NULL);

  button1 = gtk_button_new_with_label ("Quit");
  gtk_object_set_data (GTK_OBJECT (window1), "button1", button1);
  gtk_widget_show (button1);
  gtk_box_pack_start (GTK_BOX (vbox1), button1, TRUE, TRUE, 0);
  gtk_signal_connect (GTK_OBJECT (button1), "clicked",
                      GTK_SIGNAL_FUNC (gtk_main_quit),
                      NULL);

  return window1;
}

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

  gtk_set_locale ();
  gtk_init (&argc, &argv);

  /*
   * The following code was added by Glade to create one of each
component
   * (except popup menus), just so that you see something after building
   * the project. Delete any components that you don't want shown
initially.
   */
  window1 = create_window1 ();
  gtk_widget_show (window1);

  gtk_main ();
  return 0;
}



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