backport fix for bug 118909 to the 3.0 maintenance stream
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java
index efe74d3..9f8fef5 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java
@@ -135,9 +135,11 @@
boolean ignoreMsgFilter;
/* Message Hook */
+ boolean ignoreNextKey;
Callback getMsgCallback, embeddedCallback;
int getMsgProc, msgHook, embeddedHwnd, embeddedProc;
static final String AWT_WINDOW_CLASS = "SunAwtWindow";
+ static final short [] ACCENTS = new short [] {'~', '`', '\'', '^', '"'};
/* Sync/Async Widget Communication */
Synchronizer synchronizer = new Synchronizer (this);
@@ -2108,14 +2110,57 @@
OS.MoveMemory (keyMsg, lParam, MSG.sizeof);
Control control = findControl (keyMsg.hwnd);
if (control != null) {
- keyMsg.hwnd = control.handle;
- int flags = OS.PM_REMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE;
- do {
- if (!(consumed |= filterMessage (keyMsg))) {
- OS.TranslateMessage (keyMsg);
- consumed |= OS.DispatchMessage (keyMsg) == 1;
- }
- } while (OS.PeekMessage (keyMsg, keyMsg.hwnd, OS.WM_KEYFIRST, OS.WM_KEYLAST, flags));
+ /*
+ * Feature in Windows. When the user types an accent key such
+ * as ^ in order to get an accented character on a German keyboard,
+ * calling TranslateMessage(), ToUnicode() or ToAscii() consumes
+ * the key. This means that a subsequent call to TranslateMessage()
+ * will see a regular key rather than the accented key. The fix
+ * is to use MapVirtualKey() and VkKeyScan () to detect an accent
+ * and avoid calls to TranslateMessage().
+ */
+ boolean accentKey = false;
+ switch (keyMsg.message) {
+ case OS.WM_KEYDOWN:
+ case OS.WM_SYSKEYDOWN:
+ if (!OS.IsWinCE) {
+ /*
+ * Bug in Windows. The high bit in the result of MapVirtualKey() on
+ * Windows NT is bit 32 while the high bit on Windows 95 is bit 16.
+ * They should both be bit 32. The fix is to test the right bit.
+ */
+ int mapKey = OS.MapVirtualKey (keyMsg.wParam, 2);
+ if (mapKey != 0) {
+ accentKey = (mapKey & (OS.IsWinNT ? 0x80000000 : 0x8000)) != 0;
+ if (!accentKey) {
+ for (int i=0; i<ACCENTS.length; i++) {
+ int value = OS.VkKeyScan (ACCENTS [i]);
+ if (value != -1 && (value & 0xFF) == keyMsg.wParam) {
+ int state = value >> 8;
+ if ((OS.GetKeyState (OS.VK_SHIFT) < 0) != ((state & 0x1) != 0)) break;
+ if ((OS.GetKeyState (OS.VK_CONTROL) < 0) != ((state & 0x2) != 0)) break;
+ if ((OS.GetKeyState (OS.VK_MENU) < 0) != ((state & 0x4) != 0)) break;
+ accentKey = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (!accentKey && !ignoreNextKey) {
+ keyMsg.hwnd = control.handle;
+ int flags = OS.PM_REMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE;
+ do {
+ if (!(consumed |= filterMessage (keyMsg))) {
+ OS.TranslateMessage (keyMsg);
+ consumed |= OS.DispatchMessage (keyMsg) == 1;
+ }
+ } while (OS.PeekMessage (keyMsg, keyMsg.hwnd, OS.WM_KEYFIRST, OS.WM_KEYLAST, flags));
+ }
+ switch (keyMsg.message) {
+ case OS.WM_KEYDOWN:
+ case OS.WM_SYSKEYDOWN: ignoreNextKey = accentKey;
+ }
}
if (consumed) {
int hHeap = OS.GetProcessHeap ();