Re: gtk+ keynav screwed (at least on win32)



Hans Breuer writes:
 > Hi Owen et al., over the weekend I tried to implement the recently
 > missing bits in gdk/win32/gdkkeys-win32.c.

Ditto, I committed my changes last night... Argh, duplicated effort.

 > IMHO the previously code just worked fine (at least I haven't 
 > noticed any pressing problems in this area) but now I'm stumbling 
 > over the need of information possibly not even available via the 
 > win32 api.

I think all necessary information can be had through the Win32 API,
but not necessarily very straightforwardly. From my ChangeLog entry:

 	* gdk/win32/gdkkeys-win32.c: Implement the functions that until
	now just were non-functional stubs. For "hardware keycodes", we
	use Windows virtual keycodes. Not scancodes, although that at
	first might seem more low-level and a better match to X11
	keycodes. 

	The Windows API is really mixed up and confused with respect to
	scancodes and virtual keycodes. (Surprised?) Some scancodes are
	generated by two keys on the keyboard (!), and although the
	keyboard messages do have a flag to indicate which key the user
	pressed, other API that take a scan code as input don't let you
	specify which actual key you mean.

	(update_keymap): Function to build a X11-like representation of
	the keyboard. Each key has four keysyms: two levels (nonshifted
	and shifted) and two groups (normal and with AltGr).

	(gdk_keymap_get_direction): Use the codepage corresponding to the
	thread's input locale, not the system codepage.

 > Especially unclear to me is the "consumed modifiers" idea/implementation.

Ditto... One thing I don't understand is if
gdk_keymap_translate_keyboard_state() is supposed return a fixed value
for consumed_modifiers regardless of arguments?

 > My understanding was that all modifiers needed to create the keyval
 > are 'consumed' but apparently it doesn't work this way. 

That was also my first though, that the return value was supposed to
indicate what modifiers were used in a particular invokation of
gdk_keymap_translate_keyboard_state()?

Also I don't understand the logic in gdkkeys-x11.c, where (in the
non-XKB case) tmp_modifiers is first set

      tmp_modifiers = GDK_SHIFT_MASK | GDK_LOCK_MASK | group_switch_mask;

and then tested

if (tmp_keyval == GDK_Tab && (tmp_modifiers & GDK_SHIFT_MASK) == 0) 

That will always be false in the non-XKB case, as the GDK_SHIFT_MASK
bit always is set? Does this matter?

 > The attached patch does allow some basic keynav again (Tab, Cursors,
 > etc. do work again), but all the 'Hotkeys' - see testgtk::'key lookup'
 > still do not work and I currently have no clue how to fix it.

Hmm. I hadn't even noticed that test in testgtk ;-) But the 'item
factory' test works for me, I can invoke the menus through the
keyboard. *But* I have to use Alt-Shift-F to get the File menu open,
for instance. The same goes for the shortcuts (or are they called
accelerators?) to the Cancel and OK buttons on the various dialogs, I
have to use Alt-Shift-letter. Could this be because of a problem with
the returned consumed_modifiers value?

Another thing that doesn't work for me currently is tabbing backwards
with Shift-Tab. Shift-Tab behaves identically to unshifted Tab.

I today tried current GTK+ on Solaris, both with the Exceed and Sun
OpenWindows X servers, and I couldn't get said menus to open through
the keyboard at all, with or without shift... Could this be because of
some problem with X11 without XKB? Shift-Tab didn't work either, it
behaved like unshifted Tab.

 > Also in the attachement the file keys.txt, which lists the
 > keyinfo used internally by gdkkeys-win32.c. It is the output
 > of dump_keyinfo() and shows which key combination information
 > is available/used. IMHO the output is quite self-explanatory
 > [... denotes no info available].

The update_keymap() function now in gdkkeys-win32.c builds a similar
table, except that it is indexed on virtual keycodes, not scancodes.

BTW, here is a useful program to print out the keymap in all available
input locales:

#include <stdio.h>
#include <stdlib.h>
#define STRICT
#include <windows.h>

int
main (int argc, char **argv)
{
  BYTE key_state[256];
  BYTE buf[100];
  UINT vk;
  UINT i, j, k;
  HKL default_hkl = GetKeyboardLayout (0);
  HKL hkl = GetKeyboardLayout (0);
  BYTE c[2];

  for (i = 0; i < 256; i++)
    key_state[i] = 0;

  while (1)
    {
      printf ("hkl: %p ", hkl);
      GetLocaleInfo (MAKELCID (LOWORD (hkl), SORT_DEFAULT),
		     LOCALE_SENGLANGUAGE,
		     buf, sizeof (buf));
      printf ("%s\n", buf);
      for (vk = 0; vk < 256; vk++)
	{
	  printf ("vk: %#.02x ", vk);
	  if ((i = MapVirtualKey (vk, 0)) > 0)
	    {
	      int extflag = 0;

	      printf ("sc: %d ", i);

	      if (vk == VK_RCONTROL ||
		  vk == VK_RMENU ||
		  vk == VK_PRIOR ||
		  vk == VK_NEXT ||
		  vk == VK_END ||
		  vk == VK_HOME ||
		  vk == VK_LEFT ||
		  vk == VK_UP ||
		  vk == VK_RIGHT ||
		  vk == VK_DOWN ||
		  vk == VK_INSERT ||
		  vk == VK_DELETE)
		extflag = (1 << 24);

	      if (GetKeyNameText ((i<<16) | extflag, buf, sizeof (buf)) > 0)
		printf ("%20s ", buf);
	      else
		printf ("%20s ", "");

	      for (j = 0; j < 4; j++)
		{
		  switch (j)
		    {
		    case 0:
		      key_state[VK_SHIFT] = 0;
		      key_state[VK_CONTROL] = key_state[VK_MENU] = 0;
		      break;
		    case 1:
		      key_state[VK_SHIFT] = 0x80;
		      key_state[VK_CONTROL] = key_state[VK_MENU] = 0;
		      break;
		    case 2:
		      key_state[VK_SHIFT] = 0;
		      key_state[VK_CONTROL] = key_state[VK_MENU] = 0x80;
		      break;
		    case 3:
		      key_state[VK_SHIFT] = 0x80;
		      key_state[VK_CONTROL] = key_state[VK_MENU] = 0x80;
		      break;
		    }
		  key_state[vk] = 0x80;
		  if ((k = ToAsciiEx (vk, i, key_state, (LPWORD) c, 0, hkl)) == 1)
		    if (c[0] > ' ' && c[0] < 127)
		      printf ("%c ", c[0]);
		    else
		      printf ("\\%03o ", c[0]);
		  else if (k == 2)
		    {
		      if (c[0] >= ' ' && c[0] < 127)
			printf ("%c", c[0]);
		      else
			printf ("\\%03o", c[0]);
		      if (c[1] >= ' ' && c[1] < 127)
			printf ("%c ", c[1]);
		      else
			printf ("\\%03o ", c[1]);
		    }
		  key_state[vk] = 0;
		}
	    }
	  printf ("\n");
	}
      ActivateKeyboardLayout ((HKL) HKL_NEXT, 0);
      hkl = GetKeyboardLayout (0);
      if (hkl == default_hkl)
	break;
      // SetThreadLocale (MAKELCID (LOWORD (hkl), SORT_DEFAULT));
    }
  return 0;
}

--tml




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