[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