[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [30374] branches/soc-2010-merwin/intern/ ghost/intern: Hi-fi mouse input on Windows!
Mike Erwin
significant.bit at gmail.com
Thu Jul 15 14:24:14 CEST 2010
Revision: 30374
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=30374
Author: merwin
Date: 2010-07-15 14:24:14 +0200 (Thu, 15 Jul 2010)
Log Message:
-----------
Hi-fi mouse input on Windows!
The remains of a RawInput mouse attempt are included, but disabled. RawInput will still be used for multi-axis devices.
Eliminated the need for several #defines by requiring WinXP or newer.
Modified Paths:
--------------
branches/soc-2010-merwin/intern/ghost/intern/GHOST_SystemWin32.cpp
branches/soc-2010-merwin/intern/ghost/intern/GHOST_SystemWin32.h
Modified: branches/soc-2010-merwin/intern/ghost/intern/GHOST_SystemWin32.cpp
===================================================================
--- branches/soc-2010-merwin/intern/ghost/intern/GHOST_SystemWin32.cpp 2010-07-15 12:15:31 UTC (rev 30373)
+++ branches/soc-2010-merwin/intern/ghost/intern/GHOST_SystemWin32.cpp 2010-07-15 12:24:14 UTC (rev 30374)
@@ -37,6 +37,8 @@
#include "GHOST_SystemWin32.h"
#include "GHOST_EventDragnDrop.h"
+#include <stdio.h> // for debug [mce]
+
// win64 doesn't define GWL_USERDATA
#ifdef WIN32
#ifndef GWL_USERDATA
@@ -49,31 +51,16 @@
* According to the docs the mouse wheel message is supported from windows 98
* upwards. Leaving WINVER at default value, the WM_MOUSEWHEEL message and the
* wheel detent value are undefined.
- */
+
+ [mce] able to remove this too?
+
#ifndef WM_MOUSEWHEEL
#define WM_MOUSEWHEEL 0x020A
#endif // WM_MOUSEWHEEL
#ifndef WHEEL_DELTA
-#define WHEEL_DELTA 120 /* Value for rolling one detent, (old convention! MS changed it) */
+#define WHEEL_DELTA 120 // Value for rolling one detent, (old convention! MS changed it)
#endif // WHEEL_DELTA
-
-/*
- * Defines for mouse buttons 4 and 5 aka xbutton1 and xbutton2.
- * MSDN: Declared in Winuser.h, include Windows.h
- * This does not seem to work with MinGW so we define our own here.
*/
-#ifndef XBUTTON1
-#define XBUTTON1 0x0001
-#endif // XBUTTON1
-#ifndef XBUTTON2
-#define XBUTTON2 0x0002
-#endif // XBUTTON2
-#ifndef WM_XBUTTONUP
-#define WM_XBUTTONUP 524
-#endif // WM_XBUTTONUP
-#ifndef WM_XBUTTONDOWN
-#define WM_XBUTTONDOWN 523
-#endif // WM_XBUTTONDOWN
#include "GHOST_Debug.h"
#include "GHOST_DisplayManagerWin32.h"
@@ -135,9 +122,31 @@
m_displayManager = new GHOST_DisplayManagerWin32 ();
GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n");
m_displayManager->initialize();
-
+
// Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32.
OleInitialize(0);
+
+ m_input_fidelity_hint = HI_FI; // just for testing...
+
+/*
+ // register for RawInput devices
+ RAWINPUTDEVICE devices[2];
+
+ // standard HID mouse
+ devices[0].usUsagePage = 0x01;
+ devices[0].usUsage = 0x02;
+ devices[0].dwFlags = 0; // RIDEV_NOLEGACY; // ignore legacy mouse messages
+ devices[0].hwndTarget = NULL;
+
+ // multi-axis mouse (SpaceNavigator)
+ devices[1].usUsagePage = 0x01;
+ devices[1].usUsage = 0x08;
+ devices[1].dwFlags = 0;
+ devices[1].hwndTarget = NULL;
+
+ if (RegisterRawInputDevices(devices, 2, sizeof(RAWINPUTDEVICE)))
+ puts("registered for raw mouse and multi-axis input");
+*/
}
GHOST_SystemWin32::~GHOST_SystemWin32()
@@ -513,13 +522,15 @@
}
-GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow)
+GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow, int x, int y)
{
GHOST_TInt32 x_screen, y_screen;
GHOST_SystemWin32 * system = ((GHOST_SystemWin32 * ) getSystem());
GHOST_WindowWin32 * window = ( GHOST_WindowWin32 * ) Iwindow;
- system->getCursorPosition(x_screen, y_screen);
+// system->getCursorPosition(x_screen, y_screen);
+ x_screen = x;
+ y_screen = y;
if(window->getCursorGrabMode() != GHOST_kGrabDisable && window->getCursorGrabMode() != GHOST_kGrabNormal)
{
@@ -546,7 +557,7 @@
window->setCursorGrabAccum(x_accum + (x_screen - x_new), y_accum + (y_screen - y_new));
}else{
return new GHOST_EventCursor(system->getMilliSeconds(),
- GHOST_kEventCursorMove,
+ type,
window,
x_screen + x_accum,
y_screen + y_accum
@@ -556,7 +567,7 @@
}
else {
return new GHOST_EventCursor(system->getMilliSeconds(),
- GHOST_kEventCursorMove,
+ type,
window,
x_screen,
y_screen
@@ -628,23 +639,199 @@
minmax->ptMinTrackSize.y=240;
}
+bool GHOST_SystemWin32::processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* window, int& x, int& y)
+{
+ GHOST_IEvent* event = NULL;
+ bool eventSent = false;
+ puts("BEGIN");
+
+ if (raw.header.dwType == RIM_TYPEMOUSE)
+ {
+ USHORT const& buttonFlags = raw.data.mouse.usButtonFlags;
+ if (buttonFlags)
+ {
+ printf("button flags: %04X\n", buttonFlags);
+
+ if (buttonFlags & RI_MOUSE_LEFT_BUTTON_DOWN)
+ {
+ puts("left button down");
+ window->registerMouseClickEvent(true);
+ event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskLeft);
+ }
+ else if (buttonFlags & RI_MOUSE_LEFT_BUTTON_UP)
+ {
+ puts("left button up");
+ window->registerMouseClickEvent(false);
+ event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft);
+ }
+
+ if (buttonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN)
+ {
+ puts("right button down");
+ window->registerMouseClickEvent(true);
+ event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight);
+ }
+ else if (buttonFlags & RI_MOUSE_RIGHT_BUTTON_UP)
+ {
+ puts("right button up");
+ window->registerMouseClickEvent(false);
+ event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight);
+ }
+
+ if (buttonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN)
+ {
+ puts("middle button down");
+ window->registerMouseClickEvent(true);
+ event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskMiddle);
+ }
+ else if (buttonFlags & RI_MOUSE_MIDDLE_BUTTON_UP)
+ {
+ puts("middle button up");
+ window->registerMouseClickEvent(false);
+ event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskMiddle);
+ }
+
+ // similar for BUTTON_4 and BUTTON_5
+
+ if (buttonFlags & RI_MOUSE_WHEEL)
+ {
+ signed short wheelDelta = raw.data.mouse.usButtonData;
+ printf("wheel moved %+d\n", wheelDelta);
+ }
+ }
+
+ int dx = raw.data.mouse.lLastX; // These might be in Mickeys, not pixels.
+ int dy = raw.data.mouse.lLastY;
+ if (dx || dy)
+ {
+ printf("mouse moved (%+d,%+d)\n", dx, dy);
+ x += dx;
+ x += dy;
+ event = processCursorEvent(GHOST_kEventCursorMove, window, x, y);
+ }
+ }
+ else
+ puts("exotic device!");
+
+ // assume only one event will come from this RawInput report
+ // test and adjust assumptions as needed!
+
+ if (event)
+ {
+ pushEvent(event);
+ event = NULL;
+ eventSent = true;
+ }
+
+ puts("END");
+
+ return eventSent;
+}
+
+int GHOST_SystemWin32::getMoreMousePoints(int xLatest, int yLatest, int xPrev, int yPrev, GHOST_WindowWin32* window)
+ {
+ MOUSEMOVEPOINT point = {
+ xLatest & 0x0000FFFF, // confine to low word to make GetMouseMovePointsEx happy
+ yLatest & 0x0000FFFF,
+ 0, // time stamp unknown
+ NULL // no extra info
+ };
+
+ MOUSEMOVEPOINT morePoints[64];
+
+ int n = GetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &point, morePoints, 64, GMMP_USE_DISPLAY_POINTS);
+ if (n == -1)
+ {
+ printf("<!> can't get more mouse points (error %d)\n", (int) GetLastError());
+ return 0;
+ }
+
+ // search for 'prev' point (we want only newer points)
+ for (int i = 1; i < n; ++i)
+ if (morePoints[i].x == xPrev && morePoints[i].y == yPrev)
+ {
+ n = i; // don't include found point (or more ancient points)
+ break;
+ }
+
+ for (int i = n - 1; i > 0; --i)
+ {
+ signed short x = morePoints[i].x;
+ signed short y = morePoints[i].y;
+
+ printf("> (%d,%d)\n", x, y);
+
+ pushEvent(processCursorEvent(GHOST_kEventCursorMove, window, x, y));
+ }
+
+ return n;
+ } // END getMoreMousePoints
+
LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
- GHOST_Event* event = 0;
LRESULT lResult = 0;
GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem());
GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized")
+ // [mce] then why not register this function at the end of SystemWin32 constructor?
+ bool handled = false;
+
if (hwnd) {
GHOST_WindowWin32* window = (GHOST_WindowWin32*)::GetWindowLong(hwnd, GWL_USERDATA);
if (window) {
+ handled = system->handleEvent(window, msg, wParam, lParam);
+
+ // take care of misc. cases that need hwnd
+ if (msg == WM_ACTIVATE)
+ /* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL
+ will not be dispatched to OUR active window if we minimize one of OUR windows. */
+ lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
+ else if (msg == WM_PAINT)
+ /* An application sends the WM_PAINT message when the system or another application
+ * makes a request to paint a portion of an application's window. The message is sent
+ * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage
+ * function when the application obtains a WM_PAINT message by using the GetMessage or
+ * PeekMessage function. */
+ ::ValidateRect(hwnd, NULL);
+ }
+ else {
+ // Event found for a window before the pointer to the class has been set.
+ GHOST_PRINT("GHOST_SystemWin32::wndProc: GHOST window event before creation\n")
+
+ /* These are events we typically miss at this point:
+ WM_GETMINMAXINFO 0x24
+ WM_NCCREATE 0x81
+ WM_NCCALCSIZE 0x83
+ WM_CREATE 0x01
+ We let DefWindowProc do the work.
+ */
+ }
+ }
+ else {
+ // Events without valid hwnd
+ GHOST_PRINT("GHOST_SystemWin32::wndProc: event without window\n")
+ }
+
+ if (!handled)
+ lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
+
+ return lResult;
+}
+
+bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM wParam, LPARAM lParam)
+ {
+ GHOST_Event* event = NULL;
+ bool eventSent = false;
+
+ static int mousePosX = 0, mousePosY = 0; // track mouse position between calls
+
switch (msg) {
////////////////////////////////////////////////////////////////////////
// Keyboard events, processed
////////////////////////////////////////////////////////////////////////
case WM_KEYDOWN:
- /* The WM_KEYDOWN message is posted to the window with the keyboard focus when a
+ /* The WM_KEYDOWN message is posted to the window with the keyboard focus when a
* nonsystem key is pressed. A nonsystem key is a key that is pressed when the alt
* key is not pressed.
*/
@@ -660,33 +847,33 @@
case VK_SHIFT:
case VK_CONTROL:
case VK_MENU:
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list