void KeyboardLayout::OnKeyDown (PRUint8 aVirtualKey) { #ifndef WINCE mLastVirtualKeyIndex = GetKeyIndex (aVirtualKey); if (mLastVirtualKeyIndex < 0) { // Does not produce any printable characters, but still preserves the dead-key state. mNumOfChars = 0; } else { BYTE kbdState [256]; if (::GetKeyboardState (kbdState)) { mLastShiftState = GetShiftState (kbdState); if (mVirtualKeys [mLastVirtualKeyIndex].IsDeadKey (mLastShiftState)) { if (mActiveDeadKey >= 0) { // Dead-key followed by another dead-key. Reset dead-key state and return both dead-key characters. PRInt32 activeDeadKeyIndex = GetKeyIndex (mActiveDeadKey); mVirtualKeys [activeDeadKeyIndex].GetUniChars (mDeadKeyShiftState, mChars, mShiftStates); mVirtualKeys [mLastVirtualKeyIndex].GetUniChars (mLastShiftState, &mChars [1], &mShiftStates [1]); mNumOfChars = 2; DeactivateDeadKeyState (); } else { // Dead-key state activated. No characters generated. mActiveDeadKey = aVirtualKey; mDeadKeyShiftState = mLastShiftState; mNumOfChars = 0; } } else { PRUint8 finalShiftState; PRUint16 uniChars [5]; PRUint32 numOfBaseChars = mVirtualKeys [mLastVirtualKeyIndex].GetUniChars (mLastShiftState, uniChars, &finalShiftState); if (mActiveDeadKey >= 0) { PRInt32 activeDeadKeyIndex = GetKeyIndex (mActiveDeadKey); // Dead-key was active. See if pressed base character does produce valid composite character. PRUint16 compositeChar = (numOfBaseChars == 1 && uniChars [0]) ? mVirtualKeys [activeDeadKeyIndex].GetCompositeChar (mDeadKeyShiftState, uniChars [0]) : 0; if (compositeChar) { // Active dead-key and base character does produce exactly one composite character. mChars [0] = compositeChar; mShiftStates [0] = finalShiftState; mNumOfChars = 1; } else { // There is no valid dead-key and base character combination. Return dead-key character followed by base character. mVirtualKeys [activeDeadKeyIndex].GetUniChars (mDeadKeyShiftState, mChars, mShiftStates); memcpy (&mChars [1], uniChars, numOfBaseChars * sizeof (PRUint16)); memset (&mShiftStates [1], finalShiftState, numOfBaseChars); mNumOfChars = numOfBaseChars + 1; } DeactivateDeadKeyState (); } else { // No dead-keys are active. Just return the produced characters. memcpy (mChars, uniChars, numOfBaseChars * sizeof (PRUint16)); memset (mShiftStates, finalShiftState, numOfBaseChars); mNumOfChars = numOfBaseChars; } } } } #endif }
//////////////////////////////////////////////////////////// /// Process a Win32 event //////////////////////////////////////////////////////////// void ProcessEvent(UINT Message, WPARAM WParam, LPARAM LParam) { // Don't process any message until window is created if (WindowhWnd == NULL) return; switch (Message) { // Destroy event case WM_DESTROY : { // Here we must cleanup resources ! Cleanup(); break; } // Set cursor event case WM_SETCURSOR : { // The mouse has moved, if the cursor is in our window we must refresh the cursor if (LOWORD(LParam) == HTCLIENT) SetCursor(WindowCursor); break; } // Close event case WM_CLOSE : { // Set window open state to false WindowIsOpened = false; MutexLock(&WindowEventMutex); WindowEvent.Type = Closed; EventUpdated = true; MutexUnlock(&WindowEventMutex); break; } // Resize event case WM_SIZE : { // Update window size RECT RectData; GetClientRect(WindowhWnd, &RectData); WindowWidth = RectData.right - RectData.left; WindowHeight = RectData.bottom - RectData.top; MutexLock(&WindowEventMutex); WindowEvent.Type = Resized; WindowEvent.Size.Width = WindowWidth; WindowEvent.Size.Height = WindowHeight; EventUpdated = true; MutexUnlock(&WindowEventMutex); break; } // Gain focus event case WM_SETFOCUS : { MutexLock(&WindowEventMutex); WindowEvent.Type = GainedFocus; EventUpdated = true; MutexUnlock(&WindowEventMutex); break; } // Lost focus event case WM_KILLFOCUS : { MutexLock(&WindowEventMutex); WindowEvent.Type = LostFocus; EventUpdated = true; MutexUnlock(&WindowEventMutex); break; } // Text event case WM_CHAR : { MutexLock(&WindowEventMutex); WindowEvent.Type = TextEntered; WindowEvent.Text.Unicode = (UInt32)(WParam); EventUpdated = true; MutexUnlock(&WindowEventMutex); break; } // Keydown event case WM_KEYDOWN : case WM_SYSKEYDOWN : { if (WindowKeyRepeatEnabled || ((LParam & (1 << 30)) == 0)) { MutexLock(&WindowEventMutex); WindowEvent.Type = KeyPressed; WindowEvent.Key.Alt = (HIWORD(GetAsyncKeyState(VK_MENU)) != 0); WindowEvent.Key.Control = (HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0); WindowEvent.Key.Shift = (HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0); if (WParam != VK_SHIFT) { WindowEvent.Key.Code = VirtualKeyCode(WParam, LParam); } else { // Special case for shift, its state can't be retrieved directly enum KeyCode Code = GetShiftState(true); if (Code != 0) WindowEvent.Key.Code = Code; } // Set the key status WindowSetKeyPressed(WindowEvent.Key.Code, true); EventUpdated = true; MutexUnlock(&WindowEventMutex); } break; } // Keyup event case WM_KEYUP : case WM_SYSKEYUP : { MutexLock(&WindowEventMutex); WindowEvent.Type = KeyReleased; WindowEvent.Key.Alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0; WindowEvent.Key.Control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0; WindowEvent.Key.Shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0; if (WParam != VK_SHIFT) { WindowEvent.Key.Code = VirtualKeyCode(WParam, LParam); } else { // Special case for shift, its state can't be retrieved directly enum KeyCode Code = GetShiftState(false); if (Code != 0) WindowEvent.Key.Code = Code; } // Release the key status WindowSetKeyPressed(WindowEvent.Key.Code, false); EventUpdated = true; MutexUnlock(&WindowEventMutex); break; } // Mouse wheel event case WM_MOUSEWHEEL : { MutexLock(&WindowEventMutex); WindowEvent.Type = MouseWheelMoved; WindowEvent.MouseWheel.Delta = (Int16)(HIWORD(WParam)) / 120; EventUpdated = true; MutexUnlock(&WindowEventMutex); break; } // Mouse left button down event case WM_LBUTTONDOWN : { MutexLock(&WindowEventMutex); WindowEvent.Type = MouseButtonPressed; WindowEvent.MouseButton.Button = LeftButton; WindowEvent.MouseButton.X = LOWORD(LParam); WindowEvent.MouseButton.Y = HIWORD(LParam); EventUpdated = true; MutexUnlock(&WindowEventMutex); break; } // Mouse left button up event case WM_LBUTTONUP : { MutexLock(&WindowEventMutex); WindowEvent.Type = MouseButtonReleased; WindowEvent.MouseButton.Button = LeftButton; WindowEvent.MouseButton.X = LOWORD(LParam); WindowEvent.MouseButton.Y = HIWORD(LParam); EventUpdated = true; MutexUnlock(&WindowEventMutex); break; } // Mouse right button down event case WM_RBUTTONDOWN : { MutexLock(&WindowEventMutex); WindowEvent.Type = MouseButtonPressed; WindowEvent.MouseButton.Button = RightButton; WindowEvent.MouseButton.X = LOWORD(LParam); WindowEvent.MouseButton.Y = HIWORD(LParam); EventUpdated = true; MutexUnlock(&WindowEventMutex); break; } // Mouse right button up event case WM_RBUTTONUP : { MutexLock(&WindowEventMutex); WindowEvent.Type = MouseButtonReleased; WindowEvent.MouseButton.Button = RightButton; WindowEvent.MouseButton.X = LOWORD(LParam); WindowEvent.MouseButton.Y = HIWORD(LParam); EventUpdated = true; MutexUnlock(&WindowEventMutex); break; } // Mouse wheel button down event case WM_MBUTTONDOWN : { MutexLock(&WindowEventMutex); WindowEvent.Type = MouseButtonPressed; WindowEvent.MouseButton.Button = Middle; WindowEvent.MouseButton.X = LOWORD(LParam); WindowEvent.MouseButton.Y = HIWORD(LParam); EventUpdated = true; MutexUnlock(&WindowEventMutex); break; } // Mouse wheel button up event case WM_MBUTTONUP : { MutexLock(&WindowEventMutex); WindowEvent.Type = MouseButtonReleased; WindowEvent.MouseButton.Button = Middle; WindowEvent.MouseButton.X = LOWORD(LParam); WindowEvent.MouseButton.Y = HIWORD(LParam); EventUpdated = true; MutexUnlock(&WindowEventMutex); break; } // Mouse X button down event case WM_XBUTTONDOWN : { MutexLock(&WindowEventMutex); WindowEvent.Type = MouseButtonPressed; WindowEvent.MouseButton.Button = HIWORD(WParam) == XBUTTON1 ? XButton1 : XButton2; WindowEvent.MouseButton.X = LOWORD(LParam); WindowEvent.MouseButton.Y = HIWORD(LParam); EventUpdated = true; MutexUnlock(&WindowEventMutex); break; } // Mouse X button up event case WM_XBUTTONUP : { MutexLock(&WindowEventMutex); WindowEvent.Type = MouseButtonReleased; WindowEvent.MouseButton.Button = HIWORD(WParam) == XBUTTON1 ? XButton1 : XButton2; WindowEvent.MouseButton.X = LOWORD(LParam); WindowEvent.MouseButton.Y = HIWORD(LParam); EventUpdated = true; MutexUnlock(&WindowEventMutex); break; } // Mouse move event case WM_MOUSEMOVE : { // Check if we need to generate a MouseEntered event if (!WindowIsCursorIn) { TRACKMOUSEEVENT MouseEvent; MouseEvent.cbSize = sizeof(TRACKMOUSEEVENT); MouseEvent.hwndTrack = WindowhWnd; MouseEvent.dwFlags = TME_LEAVE; TrackMouseEvent(&MouseEvent); WindowIsCursorIn = true; MutexLock(&WindowEventMutex); WindowEvent.Type = MouseEntered; EventUpdated = true; MutexUnlock(&WindowEventMutex); break; } MutexLock(&WindowEventMutex); WindowEvent.Type = MouseMoved; WindowEvent.MouseMove.X = LOWORD(LParam); WindowEvent.MouseMove.Y = HIWORD(LParam); EventUpdated = true; MutexUnlock(&WindowEventMutex); break; } // Mouse leave event case WM_MOUSELEAVE : { WindowIsCursorIn = false; MutexLock(&WindowEventMutex); WindowEvent.Type = MouseLeft; EventUpdated = true; MutexUnlock(&WindowEventMutex); break; } } }