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

Bug#401296: [g-i] wrong mapping of unicode keys



clone 401296 -1
reassign -1 kbd-chooser
retitle -1 kbd-chooser: do not properly load unicode keymaps in g-i
reassign 401296 libdirectfb-1.0-0
tags 401296 + d-i patch
thanks

On Mon, Dec 04, 2006 at 03:10:33PM +0100, Attilio Fiandrotti wrote:
> * Test results for bug #401296 (wrong encoding)
> 
> - There were no differences between gtk-demo and df_input test results: 
> both failed, as described by Eddy Petrisor for ro keymap and Miroslav 
> Kure for cz-[lat2 | us-qwerty], to display some accented letters.
> 
> -> I believe this bug is related to DFB or a lower lever component

This issue is actually the result of two problems related to the way
the Linux kernel handle unicode keymaps.

First issue is in kbd-chooser: when run from the graphical installer,
the keymap was not loaded using unicode symbols.  This is due to the
usage of the K_MEDIUMRAW keyboard mode by DirectFB, as pointed by
Davide [1].  To get an unicode keymap loaded by loadkeys the keyboard
must be in K_UNICODE mode ; so a temporary switch has to be done.

[1] http://bugs.debian.org/cgi-bin/bugreport.cgi?msg=35;bug=401296

The second issue is in DirectFB itself and is solved in this patch.  One
aspect is pretty similar: when the library asks the kernel for the key
symbols, the result are truncated for unicode symbols if the keyboard is
not in K_UNICODE mode.  So, a temporary switch is needed, as well as
applying the right bitmask in order to retrieve the full unicode symbol.

The attached patch fixes the issue in both the "keyboard" and
"linux_input" input drivers.  Both were displaying correct mapping on
"dfbinput -k".

It's really late now, and I might have made a mistake with my test
setup, but I needed to disable the "keyboard" driver was needed to get
the symbols properly showed in the GTK+ frontend of the
debian-installer.

Waow… this one really took some time to figure out… (and thanks free
software for being able to track a code path in 5 different projects,
from the debian-installer to the kernel itself!)

Cheers,
-- 
Jérémy Bobbio                        .''`. 
lunar@debian.org                    : :Ⓐ  :  # apt-get install anarchism
                                    `. `'` 
                                      `-   
diff --git a/inputdrivers/keyboard/keyboard.c b/inputdrivers/keyboard/keyboard.c
index 26dbad9..1f9b986 100644
--- a/inputdrivers/keyboard/keyboard.c
+++ b/inputdrivers/keyboard/keyboard.c
@@ -85,6 +85,10 @@ keyboard_get_symbol( int                             code,
      unsigned char index = KVAL(value);
      int           base  = (level == DIKSI_BASE);
 
+     /* Handle unicode characters directly */
+     if (type >= 0x0f) {
+          return DFB_KEY( UNICODE, value ^ 0xf000 );
+     }
      switch (type) {
           case KT_FN:
                if (index < 20)
@@ -413,10 +417,17 @@ driver_get_keymap_entry( CoreInputDevice               *device,
                          void                      *driver_data,
                          DFBInputDeviceKeymapEntry *entry )
 {
+     KeyboardData               *data = (KeyboardData*) driver_data;
      int                         code = entry->code;
      unsigned short              value;
      DFBInputDeviceKeyIdentifier identifier;
 
+     /* switch to unicode mode to get the full keymap */
+     if (ioctl( data->vt->fd, KDSKBMODE, K_UNICODE ) < 0) {
+          D_PERROR( "DirectFB/Keyboard: K_UNICODE failed!\n" );
+          return DFB_INIT;
+     }
+
      /* fetch the base level */
      value = keyboard_read_value( driver_data, K_NORMTAB, code );
 
@@ -460,6 +471,12 @@ driver_get_keymap_entry( CoreInputDevice               *device,
      entry->symbols[DIKSI_ALT_SHIFT] = keyboard_get_symbol( code, value,
                                                             DIKSI_ALT_SHIFT );
 
+     /* switch back to medium raw mode */
+     if (ioctl( data->vt->fd, KDSKBMODE, K_MEDIUMRAW ) < 0) {
+          D_PERROR( "DirectFB/Keyboard: K_MEDIUMRAW failed!\n" );
+          return DFB_INIT;
+     }
+
      return DFB_OK;
 }
 
diff --git a/inputdrivers/linux_input/linux_input.c b/inputdrivers/linux_input/linux_input.c
index a4fd232..655fffc 100644
--- a/inputdrivers/linux_input/linux_input.c
+++ b/inputdrivers/linux_input/linux_input.c
@@ -374,6 +374,10 @@ keyboard_get_symbol( int                             code,
      unsigned char index = KVAL(value);
      int           base  = (level == DIKSI_BASE);
 
+     /* Handle unicode characters directly */
+     if (type >= 0x0f) {
+          return DFB_KEY( UNICODE, value ^ 0xf000 );
+     }
      switch (type) {
           case KT_FN:
                if (index < 20)
@@ -1201,10 +1205,23 @@ driver_get_keymap_entry( CoreInputDevice           *device,
      int                         code = entry->code;
      unsigned short              value;
      DFBInputDeviceKeyIdentifier identifier;
+     int                         orig_mode;
 
      if (!data->vt)
           return DFB_UNSUPPORTED;
 
+     /* save keyboard mode in order to restore it later */
+     if (ioctl( data->vt->fd, KDGKBMODE, &orig_mode ) < 0) {
+          D_PERROR( "DirectFB/Keyboard: KDGKBMODE failed!\n" );
+          return DFB_INIT;
+     }
+
+     /* switch to unicode mode to get the full keymap */
+     if (ioctl( data->vt->fd, KDSKBMODE, K_UNICODE ) < 0) {
+          D_PERROR( "DirectFB/Keyboard: K_UNICODE failed!\n" );
+          return DFB_INIT;
+     }
+
      /* fetch the base level */
      value = keyboard_read_value( driver_data, K_NORMTAB, code );
 
@@ -1248,6 +1265,12 @@ driver_get_keymap_entry( CoreInputDevice           *device,
      entry->symbols[DIKSI_ALT_SHIFT] = keyboard_get_symbol( code, value,
                                                             DIKSI_ALT_SHIFT );
 
+     /* switch back to original mode */
+     if (ioctl( data->vt->fd, KDSKBMODE, orig_mode ) < 0) {
+          D_PERROR( "DirectFB/Keyboard: KDSKBMODE failed!\n" );
+          return DFB_INIT;
+     }
+
      return DFB_OK;
 #else
      return DFB_UNSUPPORTED;

Attachment: signature.asc
Description: Digital signature


Reply to: