Index: ui/base/win/events_win.cc |
diff --git a/ui/base/win/events_win.cc b/ui/base/win/events_win.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e841b28e997c7db89d0b175c8e29101635598232 |
--- /dev/null |
+++ b/ui/base/win/events_win.cc |
@@ -0,0 +1,210 @@ |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include <windowsx.h> |
+ |
+#include "ui/base/events.h" |
+ |
+#include "base/logging.h" |
+#include "ui/base/keycodes/keyboard_code_conversion_win.h" |
+#include "ui/gfx/point.h" |
+ |
+namespace { |
+ |
+// Get the native mouse key state from the native event message type. |
+int GetNativeMouseKey(const ui::NativeEvent& native_event) { |
+ switch (native_event.message) { |
+ case WM_LBUTTONDBLCLK: |
+ case WM_LBUTTONDOWN: |
+ case WM_LBUTTONUP: |
+ case WM_NCLBUTTONDBLCLK: |
+ case WM_NCLBUTTONDOWN: |
+ case WM_NCLBUTTONUP: |
+ return MK_LBUTTON; |
+ case WM_MBUTTONDBLCLK: |
+ case WM_MBUTTONDOWN: |
+ case WM_MBUTTONUP: |
+ case WM_NCMBUTTONDBLCLK: |
+ case WM_NCMBUTTONDOWN: |
+ case WM_NCMBUTTONUP: |
+ return MK_MBUTTON; |
+ case WM_RBUTTONDBLCLK: |
+ case WM_RBUTTONDOWN: |
+ case WM_RBUTTONUP: |
+ case WM_NCRBUTTONDBLCLK: |
+ case WM_NCRBUTTONDOWN: |
+ case WM_NCRBUTTONUP: |
+ return MK_RBUTTON; |
+ case WM_NCXBUTTONDBLCLK: |
+ case WM_NCXBUTTONDOWN: |
+ case WM_NCXBUTTONUP: |
+ case WM_XBUTTONDBLCLK: |
+ case WM_XBUTTONDOWN: |
+ case WM_XBUTTONUP: |
+ return MK_XBUTTON1; |
+ } |
+ return 0; |
+} |
+ |
+bool IsButtonDown(const ui::NativeEvent& native_event) { |
+ return ((MK_LBUTTON | MK_MBUTTON | MK_RBUTTON | MK_XBUTTON1 | MK_XBUTTON2) & |
+ native_event.wParam) != 0; |
+} |
+ |
+bool IsClientMouseEvent(const ui::NativeEvent& native_event) { |
+ return native_event.message == WM_MOUSELEAVE || |
+ native_event.message == WM_MOUSEHOVER || |
+ (native_event.message >= WM_MOUSEFIRST && |
+ native_event.message <= WM_MOUSELAST); |
+} |
+ |
+bool IsNonClientMouseEvent(const ui::NativeEvent& native_event) { |
+ return native_event.message == WM_NCMOUSELEAVE || |
+ native_event.message == WM_NCMOUSEHOVER || |
+ (native_event.message >= WM_NCMOUSEMOVE && |
+ native_event.message <= WM_NCXBUTTONDBLCLK); |
+} |
+ |
+bool IsDoubleClickMouseEvent(const ui::NativeEvent& native_event) { |
+ return native_event.message == WM_NCLBUTTONDBLCLK || |
+ native_event.message == WM_NCMBUTTONDBLCLK || |
+ native_event.message == WM_NCRBUTTONDBLCLK || |
+ native_event.message == WM_NCXBUTTONDBLCLK || |
+ native_event.message == WM_LBUTTONDBLCLK || |
+ native_event.message == WM_MBUTTONDBLCLK || |
+ native_event.message == WM_RBUTTONDBLCLK || |
+ native_event.message == WM_XBUTTONDBLCLK; |
+} |
+ |
+// Returns a mask corresponding to the set of pressed modifier keys. |
+// Checks the current global state and the state sent by client mouse messages. |
+int KeyStateFlagsFromNative(const ui::NativeEvent& native_event) { |
+ int flags = 0; |
+ flags |= (GetKeyState(VK_MENU) & 0x80) ? ui::EF_ALT_DOWN : 0; |
+ flags |= (GetKeyState(VK_SHIFT) & 0x80) ? ui::EF_SHIFT_DOWN : 0; |
+ flags |= (GetKeyState(VK_CONTROL) & 0x80) ? ui::EF_CONTROL_DOWN : 0; |
+ flags |= (HIWORD(native_event.lParam) & KF_EXTENDED) ? ui::EF_EXTENDED : 0; |
+ |
+ // Most client mouse messages include key state information. |
+ if (IsClientMouseEvent(native_event)) { |
+ int win_flags = GET_KEYSTATE_WPARAM(native_event.wParam); |
+ flags |= (win_flags & MK_SHIFT) ? ui::EF_SHIFT_DOWN : 0; |
+ flags |= (win_flags & MK_CONTROL) ? ui::EF_CONTROL_DOWN : 0; |
+ } |
+ |
+ return flags; |
+} |
+ |
+// Returns a mask corresponding to the set of pressed mouse buttons. |
+// This includes the button of the given message, even if it is being released. |
+int MouseStateFlagsFromNative(const ui::NativeEvent& native_event) { |
+ // TODO(msw): ORing the pressed/released button into the flags is _wrong_. |
+ // It makes it impossible to tell which button was modified when multiple |
+ // buttons are/were held down. Instead, we need to track the modified button |
+ // independently and audit event consumers to do the right thing. |
+ int win_flags = GetNativeMouseKey(native_event); |
+ |
+ // Client mouse messages provide key states in their WPARAMs. |
+ if (IsClientMouseEvent(native_event)) |
+ win_flags |= GET_KEYSTATE_WPARAM(native_event.wParam); |
+ |
+ int flags = 0; |
+ flags |= (win_flags & MK_LBUTTON) ? ui::EF_LEFT_BUTTON_DOWN : 0; |
+ flags |= (win_flags & MK_MBUTTON) ? ui::EF_MIDDLE_BUTTON_DOWN : 0; |
+ flags |= (win_flags & MK_RBUTTON) ? ui::EF_RIGHT_BUTTON_DOWN : 0; |
+ flags |= IsDoubleClickMouseEvent(native_event) ? ui::EF_IS_DOUBLE_CLICK: 0; |
+ flags |= IsNonClientMouseEvent(native_event) ? ui::EF_IS_NON_CLIENT : 0; |
+ return flags; |
+} |
+ |
+} // namespace |
+ |
+namespace ui { |
+ |
+EventType EventTypeFromNative(const NativeEvent& native_event) { |
+ switch (native_event.message) { |
+ case WM_KEYDOWN: |
+ case WM_SYSKEYDOWN: |
+ case WM_CHAR: |
+ return ET_KEY_PRESSED; |
+ case WM_KEYUP: |
+ case WM_SYSKEYUP: |
+ return ET_KEY_RELEASED; |
+ case WM_LBUTTONDBLCLK: |
+ case WM_LBUTTONDOWN: |
+ case WM_MBUTTONDBLCLK: |
+ case WM_MBUTTONDOWN: |
+ case WM_NCLBUTTONDBLCLK: |
+ case WM_NCLBUTTONDOWN: |
+ case WM_NCMBUTTONDBLCLK: |
+ case WM_NCMBUTTONDOWN: |
+ case WM_NCRBUTTONDBLCLK: |
+ case WM_NCRBUTTONDOWN: |
+ case WM_NCXBUTTONDBLCLK: |
+ case WM_NCXBUTTONDOWN: |
+ case WM_RBUTTONDBLCLK: |
+ case WM_RBUTTONDOWN: |
+ case WM_XBUTTONDBLCLK: |
+ case WM_XBUTTONDOWN: |
+ return ET_MOUSE_PRESSED; |
+ case WM_LBUTTONUP: |
+ case WM_MBUTTONUP: |
+ case WM_NCLBUTTONUP: |
+ case WM_NCMBUTTONUP: |
+ case WM_NCRBUTTONUP: |
+ case WM_NCXBUTTONUP: |
+ case WM_RBUTTONUP: |
+ case WM_XBUTTONUP: |
+ return ET_MOUSE_RELEASED; |
+ case WM_MOUSEMOVE: |
+ return IsButtonDown(native_event) ? ET_MOUSE_DRAGGED : ET_MOUSE_MOVED; |
+ case WM_NCMOUSEMOVE: |
+ return ET_MOUSE_MOVED; |
+ case WM_MOUSEWHEEL: |
+ return ET_MOUSEWHEEL; |
+ case WM_MOUSELEAVE: |
+ case WM_NCMOUSELEAVE: |
+ return ET_MOUSE_EXITED; |
+ default: |
+ NOTREACHED(); |
+ } |
+ return ET_UNKNOWN; |
+} |
+ |
+int EventFlagsFromNative(const NativeEvent& native_event) { |
+ int flags = KeyStateFlagsFromNative(native_event); |
+ if (IsMouseEvent(native_event)) |
+ flags |= MouseStateFlagsFromNative(native_event); |
+ |
+ return flags; |
+} |
+ |
+gfx::Point EventLocationFromNative(const NativeEvent& native_event) { |
+ // Client message. The position is contained in the LPARAM. |
+ if (IsClientMouseEvent(native_event)) |
+ return gfx::Point(native_event.lParam); |
+ DCHECK(IsNonClientMouseEvent(native_event)); |
+ // Non-client message. The position is contained in a POINTS structure in |
+ // LPARAM, and is in screen coordinates so we have to convert to client. |
+ POINT native_point = { GET_X_LPARAM(native_event.lParam), |
+ GET_Y_LPARAM(native_event.lParam) }; |
+ ScreenToClient(native_event.hwnd, &native_point); |
+ return gfx::Point(native_point); |
+} |
+ |
+KeyboardCode KeyboardCodeFromNative(const NativeEvent& native_event) { |
+ return KeyboardCodeForWindowsKeyCode(native_event.wParam); |
+} |
+ |
+bool IsMouseEvent(const NativeEvent& native_event) { |
+ return IsClientMouseEvent(native_event) || |
+ IsNonClientMouseEvent(native_event); |
+} |
+ |
+int GetMouseWheelOffset(const NativeEvent& native_event) { |
+ DCHECK(native_event.message == WM_MOUSEWHEEL); |
+ return GET_WHEEL_DELTA_WPARAM(native_event.wParam); |
+} |
+ |
+} // namespace ui |