From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.34) id 1BPrjk-0000LI-GH for qemu-devel@nongnu.org; Mon, 17 May 2004 19:41:36 -0400 Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.34) id 1BPrjC-0000B7-RH for qemu-devel@nongnu.org; Mon, 17 May 2004 19:41:34 -0400 Received: from [199.232.41.8] (helo=mx20.gnu.org) by monty-python.gnu.org with esmtp (TLSv1:DES-CBC3-SHA:168) (Exim 4.34) id 1BPrgj-0007oG-EX for qemu-devel@nongnu.org; Mon, 17 May 2004 19:38:29 -0400 Received: from [195.238.2.101] (helo=outmx004.isp.belgacom.be) by mx20.gnu.org with esmtp (Exim 4.34) id 1BPrUm-0007TN-Ui for qemu-devel@nongnu.org; Mon, 17 May 2004 19:26:09 -0400 Received: from easynet.be (244.54-201-80.adsl.skynet.be [80.201.54.244]) by outmx004.isp.belgacom.be (8.12.11/8.12.11/Skynet-OUT-2.22) with ESMTP id i4HNPpSj013152 for ; Tue, 18 May 2004 01:25:51 +0200 (envelope-from ) Message-ID: <40A95713.3050908@easynet.be> Date: Tue, 18 May 2004 02:21:39 +0200 From: Mark Jonckheere MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-15; format=flowed Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] keyboard shift-state problem Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org When the operator switches from qemu to another window while keeping one of the shift-keys (Shift, Ctrl, Alt) depressed (for example using Alt-TAB), qemu doesn't receive a Key-UP event for this shift-key. The result is that when the operator returns back to qemu, the guest OS accepts new keystrokes as if that shift-key is still depressed. A solution to this problem is storing the shift-state as every shift-key is depressed and released, and sending extra key-events when control is transferred to another window. I detected that in this case SDL sends a keyboard event with a zero scancode, so it is easy to detect when the shift-state should be adjusted. This has been tested on a RedHat 7.3 host (x86) with SDL version 1.2.3-7, it should be verified for other host environments. A second problem is the CapsLock and Numlock state. I detected that SDL handles these keys as shift-keys and not as toggles. Depressing and releasing one of those keys generates only a single event with alternating key down and key up codes. To turn CapsLock on and again off, you had to depress that key 4 times. I made a modification to translate this single event into a key-down, key-up sequence. This works well for CapsLock, but it can put NumLock into the opposite state between the host OS and the guest OS. This results in depressing the NumLock key by the operator at every switch between windows. There is no simple solution for this problem. One possible solution is to keep track of the commands from the guest OS to change the state of the keyboard LEDs and change the state of the host according to these. Or keeping track of the guest Numlock LED and sending back a Numlock down-up sequence before each key if the state is different from the host state. Another solution is to add a command to change the NumLock state from the monitor. Or simply leaving it as it was and documenting to the end-user that "To change the Numlock or CapsLock state, you should depress those keys twice". Greetings, Mark. ---8<----------------------------------------------------->8--- --- qemu/sdl.c Fri Apr 30 00:15:15 2004 +++ qemu.patched/sdl.c Tue May 18 00:34:19 2004 @@ -130,6 +130,7 @@ static void sdl_process_key(SDL_KeyboardEvent *ev) { int keycode, v; + static int modif; /* XXX: not portable, but avoids complicated mappings */ keycode = ev->keysym.scancode; @@ -151,6 +152,78 @@ keycode = 0; } + /* Adjust shift-key states when leaving window */ + + if (ev->keysym.scancode == 0) { + if ((modif ^ ev->keysym.mod) & KMOD_LSHIFT) + kbd_put_keycode(0x2a | (modif & KMOD_LSHIFT ? 0x80 : 0)); + if ((modif ^ ev->keysym.mod) & KMOD_RSHIFT) + kbd_put_keycode(0x36 | (modif & KMOD_RSHIFT ? 0x80 : 0)); + if ((modif ^ ev->keysym.mod) & KMOD_LCTRL) + kbd_put_keycode(0x1d | (modif & KMOD_LCTRL ? 0x80 : 0)); + if ((modif ^ ev->keysym.mod) & KMOD_RCTRL) { + kbd_put_keycode(0xe0 ); + kbd_put_keycode(0x1d | (modif & KMOD_RCTRL ? 0x80 : 0)); + } + if ((modif ^ ev->keysym.mod) & KMOD_LALT) + kbd_put_keycode(0x38 | (modif & KMOD_LALT ? 0x80 : 0)); + if ((modif ^ ev->keysym.mod) & KMOD_RALT) { + kbd_put_keycode(0xe0 ); + kbd_put_keycode(0x38 | (modif & KMOD_RALT ? 0x80 : 0)); + } + modif = ev->keysym.mod; + } + + /* remember shift-key state */ + + switch (keycode) { + case 0x2a: /* Left Shift */ + if (ev->type == SDL_KEYUP) + modif &= ~KMOD_LSHIFT; + else + modif |= KMOD_LSHIFT; + break; + case 0x36: /* Right Shift */ + if (ev->type == SDL_KEYUP) + modif &= ~KMOD_RSHIFT; + else + modif |= KMOD_RSHIFT; + break; + case 0x1d: /* Left CTRL */ + if (ev->type == SDL_KEYUP) + modif &= ~KMOD_LCTRL; + else + modif |= KMOD_LCTRL; + break; + case 0x1de0: /* Right CTRL */ + if (ev->type == SDL_KEYUP) + modif &= ~KMOD_RCTRL; + else + modif |= KMOD_RCTRL; + break; + case 0x38: /* Left ALT */ + if (ev->type == SDL_KEYUP) + modif &= ~KMOD_LALT; + else + modif |= KMOD_LALT; + break; + case 0x38e0: /* Right ALT */ + if (ev->type == SDL_KEYUP) + modif &= ~KMOD_RALT; + else + modif |= KMOD_RALT; + break; + case 0x45: /* Num Lock */ + kbd_put_keycode(0x45); + kbd_put_keycode(0xc5); + return; + case 0x3a: /* Caps Lock */ + kbd_put_keycode(0x3a); + kbd_put_keycode(0xba); + return; + + } + /* now send the key code */ while (keycode != 0) { v = keycode & 0xff; ---8<----------------------------------------------------->8---