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

@ -478,6 +478,18 @@ Bit32u win32_to_bx_key[2][0x100] =
VOID CALLBACK MyTimer(HWND,UINT,UINT,DWORD);
#endif
static void cursorWarped()
{
POINT pt = { 0, 0 };
ClientToScreen(stInfo.simWnd, &pt);
SetCursorPos(pt.x + stretched_x / 2, pt.y + stretched_y / 2);
EnterCriticalSection(&stInfo.mouseCS);
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;
@ -486,8 +498,7 @@ static void processMouseXY(int x, int y, int z, int windows_state, int implied_s
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)
{
if (old_bx_state != mouse_button_state) {
/* Make up for missing message */
BX_INFO(("&&&missing mouse state change"));
EnterCriticalSection(&stInfo.keyCS);
@ -501,40 +512,16 @@ static void processMouseXY(int x, int y, int z, int windows_state, int implied_s
ms_zdelta = z;
ms_lastx = x;
ms_lasty = y;
if (bx_state!=mouse_button_state)
{
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);
if (mouseCaptureMode && !win32MouseModeAbsXY) {
cursorWarped();
}
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);
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;
LeaveCriticalSection(&stInfo.mouseCS);
}
@ -955,7 +942,9 @@ DWORD WINAPI UIThread(LPVOID)
SetFocus(stInfo.simWnd);
ShowCursor(!mouseCaptureMode);
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,12 +1114,22 @@ void SetMouseCapture()
}
ShowCursor(!mouseCaptureMode);
ShowCursor(!mouseCaptureMode); // somehow one didn't do the trick (win98)
if (mouseCaptureMode && !win32MouseModeAbsXY) {
cursorWarped();
if (mouseCaptureMode)
}
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"));
@ -1444,7 +1458,7 @@ void enq_mouse_event(void)
}
current.mouse_z = ms_zdelta;
current.mouse_button_state = mouse_button_state;
resetDelta();
ms_ydelta = ms_xdelta = ms_zdelta = 0;
tail = (tail + 1) % SCANCODE_BUFSIZE;
}
LeaveCriticalSection(&stInfo.mouseCS);