From 33a633cbd23c2be6a7962c2c9108a202571d4555 Mon Sep 17 00:00:00 2001 From: Volker Ruppert Date: Tue, 30 Dec 2014 16:31:17 +0000 Subject: [PATCH] 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). --- bochs/gui/win32.cc | 150 +++++++++++++++++++++++++-------------------- 1 file changed, 82 insertions(+), 68 deletions(-) diff --git a/bochs/gui/win32.cc b/bochs/gui/win32.cc index b1524eba5..e13e2a7e2 100644 --- a/bochs/gui/win32.cc +++ b/bochs/gui/win32.cc @@ -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);