Partial rewrite of the win32 mouse motion handling.

- If the mouse is captured, use ClipCursor() to keep the cursor in the window.
- After handling mouse motion event in relative mode, move the cursor back to
  the window center (similar to other guis).
This commit is contained in:
Volker Ruppert 2014-12-30 16:31:17 +00:00
parent 2f893a76ff
commit 33a633cbd2

View File

@ -92,11 +92,11 @@ struct QueueEvent {
QueueEvent* deq_key_event(void);
static QueueEvent keyevents[SCANCODE_BUFSIZE];
static unsigned head=0, tail=0;
static unsigned head = 0, tail = 0;
static int mouse_button_state = 0;
static int ms_xdelta=0, ms_ydelta=0, ms_zdelta=0;
static int ms_lastx=0, ms_lasty=0;
static int ms_savedx=0, ms_savedy=0;
static int ms_xdelta = 0, ms_ydelta = 0, ms_zdelta = 0;
static int ms_lastx = 0, ms_lasty = 0;
static int ms_savedx = 0, ms_savedy = 0;
static BOOL mouseCaptureMode, mouseCaptureNew, mouseToggleReq;
static BOOL win32MouseModeAbsXY = 0;
static HANDLE workerThread = 0;
@ -478,63 +478,50 @@ Bit32u win32_to_bx_key[2][0x100] =
VOID CALLBACK MyTimer(HWND,UINT,UINT,DWORD);
#endif
static void processMouseXY(int x, int y, int z, int windows_state, int implied_state_change)
{
int bx_state;
int old_bx_state;
EnterCriticalSection(&stInfo.mouseCS);
bx_state=((windows_state & MK_LBUTTON) ? 1 : 0) + ((windows_state & MK_RBUTTON) ? 2 : 0) +
((windows_state & MK_MBUTTON) ? 4 : 0);
old_bx_state=bx_state ^ implied_state_change;
if (old_bx_state!=mouse_button_state)
{
/* Make up for missing message */
BX_INFO(("&&&missing mouse state change"));
EnterCriticalSection(&stInfo.keyCS);
enq_mouse_event();
mouse_button_state=old_bx_state;
enq_key_event(mouse_button_state, MOUSE_PRESSED);
LeaveCriticalSection(&stInfo.keyCS);
}
ms_ydelta=ms_savedy-y;
ms_xdelta=x-ms_savedx;
ms_zdelta=z;
ms_lastx=x;
ms_lasty=y;
if (bx_state!=mouse_button_state)
{
EnterCriticalSection(&stInfo.keyCS);
enq_mouse_event();
mouse_button_state=bx_state;
enq_key_event(mouse_button_state, MOUSE_PRESSED);
LeaveCriticalSection(&stInfo.keyCS);
}
LeaveCriticalSection(&stInfo.mouseCS);
}
static void resetDelta()
{
EnterCriticalSection(&stInfo.mouseCS);
ms_savedx=ms_lastx;
ms_savedy=ms_lasty;
ms_ydelta=ms_xdelta=ms_zdelta=0;
LeaveCriticalSection(&stInfo.mouseCS);
}
static void cursorWarped()
{
POINT pt = { 0, 0 };
ClientToScreen(stInfo.simWnd, &pt);
SetCursorPos(pt.x + stretched_x/2, pt.y + stretched_y/2);
SetCursorPos(pt.x + stretched_x / 2, pt.y + stretched_y / 2);
EnterCriticalSection(&stInfo.mouseCS);
EnterCriticalSection(&stInfo.keyCS);
enq_mouse_event();
LeaveCriticalSection(&stInfo.keyCS);
ms_lastx=stretched_x/2;
ms_lasty=stretched_y/2;
ms_savedx=ms_lastx;
ms_savedy=ms_lasty;
ms_savedx = stretched_x / 2;
ms_savedy = stretched_y / 2;
LeaveCriticalSection(&stInfo.mouseCS);
}
static void processMouseXY(int x, int y, int z, int windows_state, int implied_state_change)
{
int bx_state;
int old_bx_state;
EnterCriticalSection(&stInfo.mouseCS);
bx_state = ((windows_state & MK_LBUTTON) ? 1 : 0) + ((windows_state & MK_RBUTTON) ? 2 : 0) +
((windows_state & MK_MBUTTON) ? 4 : 0);
old_bx_state = bx_state ^ implied_state_change;
if (old_bx_state != mouse_button_state) {
/* Make up for missing message */
BX_INFO(("&&&missing mouse state change"));
EnterCriticalSection(&stInfo.keyCS);
enq_mouse_event();
mouse_button_state = old_bx_state;
enq_key_event(mouse_button_state, MOUSE_PRESSED);
LeaveCriticalSection(&stInfo.keyCS);
}
ms_ydelta = ms_savedy - y;
ms_xdelta = x - ms_savedx;
ms_zdelta = z;
ms_lastx = x;
ms_lasty = y;
if (bx_state!=mouse_button_state) {
EnterCriticalSection(&stInfo.keyCS);
enq_mouse_event();
mouse_button_state = bx_state;
enq_key_event(mouse_button_state, MOUSE_PRESSED);
LeaveCriticalSection(&stInfo.keyCS);
}
if (mouseCaptureMode && !win32MouseModeAbsXY) {
cursorWarped();
}
LeaveCriticalSection(&stInfo.mouseCS);
}
@ -955,7 +942,9 @@ DWORD WINAPI UIThread(LPVOID)
SetFocus(stInfo.simWnd);
ShowCursor(!mouseCaptureMode);
cursorWarped();
if (mouseCaptureMode && !win32MouseModeAbsXY) {
cursorWarped();
}
hdc = GetDC(stInfo.simWnd);
MemoryBitmap = CreateCompatibleBitmap(hdc, win32_max_xres, win32_max_yres);
@ -1114,6 +1103,9 @@ LRESULT CALLBACK mainWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
void SetMouseCapture()
{
POINT pt = { 0, 0 };
RECT re;
if (mouseToggleReq) {
mouseCaptureMode = mouseCaptureNew;
mouseToggleReq = FALSE;
@ -1122,11 +1114,21 @@ void SetMouseCapture()
}
ShowCursor(!mouseCaptureMode);
ShowCursor(!mouseCaptureMode); // somehow one didn't do the trick (win98)
cursorWarped();
if (mouseCaptureMode)
if (mouseCaptureMode && !win32MouseModeAbsXY) {
cursorWarped();
}
if (mouseCaptureMode) {
ClientToScreen(stInfo.simWnd, &pt);
re.left = pt.x;
re.top = pt.y;
re.right = pt.x + stretched_x;
re.bottom = pt.y + stretched_y;
ClipCursor(&re);
SetStatusText(0, szMouseDisable, TRUE);
else
} else {
ClipCursor(NULL);
SetStatusText(0, szMouseEnable, TRUE);
}
}
LRESULT CALLBACK simWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
@ -1146,10 +1148,6 @@ LRESULT CALLBACK simWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
if (mouseToggleReq && (GetActiveWindow() == stInfo.mainWnd)) {
SetMouseCapture();
}
// If mouse escaped, bring it back
if (mouseCaptureMode && !win32MouseModeAbsXY) {
cursorWarped();
}
return 0;
case WM_PAINT:
@ -1177,7 +1175,24 @@ LRESULT CALLBACK simWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
LeaveCriticalSection(&stInfo.drawCS);
return 0;
case WM_SIZE:
if (mouseCaptureMode) {
POINT pt = { 0, 0 };
RECT re;
ClientToScreen(stInfo.simWnd, &pt);
re.left = pt.x;
re.top = pt.y;
re.right = pt.x + stretched_x;
re.bottom = pt.y + stretched_y;
ClipCursor(&re);
}
break;
case WM_MOUSEMOVE:
if ((LOWORD(lParam) == ms_savedx) && (HIWORD(lParam) == ms_savedy)) {
// Ignore mouse event generated by SetCursorPos().
return 0;
}
if (!mouseModeChange) {
processMouseXY(LOWORD(lParam), HIWORD(lParam), 0, (int) wParam, 0);
}
@ -1426,8 +1441,7 @@ void enq_key_event(Bit32u key, Bit32u press_release)
void enq_mouse_event(void)
{
EnterCriticalSection(&stInfo.mouseCS);
if (ms_xdelta || ms_ydelta || ms_zdelta)
{
if (ms_xdelta || ms_ydelta || ms_zdelta) {
if (((tail+1) % SCANCODE_BUFSIZE) == head) {
LeaveCriticalSection(&stInfo.mouseCS);
BX_ERROR(("enq_scancode: buffer full"));
@ -1442,9 +1456,9 @@ void enq_mouse_event(void)
current.mouse_x = ms_xdelta;
current.mouse_y = ms_ydelta;
}
current.mouse_z=ms_zdelta;
current.mouse_button_state=mouse_button_state;
resetDelta();
current.mouse_z = ms_zdelta;
current.mouse_button_state = mouse_button_state;
ms_ydelta = ms_xdelta = ms_zdelta = 0;
tail = (tail + 1) % SCANCODE_BUFSIZE;
}
LeaveCriticalSection(&stInfo.mouseCS);