Content-Type: multipart/mixed; boundary="===============1893281535==" MIME-Version: 1.0 Subject: [PATCH] * Workaround for modal window resize/move loop X-Mercurial-Node: a027905972e940f78714daea5cf23309c586c604 Message-Id: In-Reply-To: References: User-Agent: Mercurial-patchbomb/2.1.1 Date: Thu, 06 Feb 2014 00:12:25 -0500 From: Nate Fries To: nfries88@gmail.com --===============1893281535== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Patch subject is complete summary. --===============1893281535== Content-Type: text/x-patch; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=SDL.patch # HG changeset patch # User Nate@Nate-lenovo # Date 1391663349 18000 # Node ID a027905972e940f78714daea5cf23309c586c604 # Parent d7b7ec662687bdad27f3250eb391d3c57c3e6b75 * Workaround for modal window resize/move loop. diff -r d7b7ec662687 -r a027905972e9 src/video/windows/SDL_windowsevents.c --- a/src/video/windows/SDL_windowsevents.c Fri Jan 24 09:54:04 2014 -0300 +++ b/src/video/windows/SDL_windowsevents.c Thu Feb 06 00:09:09 2014 -0500 @@ -70,6 +70,12 @@ #ifndef WM_MOUSEHWHEEL #define WM_MOUSEHWHEEL 0x020E #endif + +#define NCHIT_LEFT 0x01 +#define NCHIT_TOP 0x02 +#define NCHIT_RIGHT 0x04 +#define NCHIT_BOTTOM 0x08 +#define NCHIT_CAPTION 0x00 static SDL_Scancode WindowsScanCodeToSDLScanCode( LPARAM lParam, WPARAM wParam ) @@ -284,6 +290,203 @@ return SDL_FALSE; } return SDL_TRUE; +} + +LRESULT WIN_SizeMove(HWND hwnd, SDL_WindowData *data, LONG action, DWORD dwPos) +{ + WINDOWINFO winfo; + RECT rcClipCursor; + int minw, minh, maxw, maxh; + + winfo.cbSize = sizeof(WINDOWINFO); + if(GetWindowInfo(hwnd, &winfo) == FALSE) + return 0; + /* can't move or resize a maximized or invisible window */ + if(winfo.dwStyle & WS_MAXIMIZE || !IsWindowVisible(hwnd)) + return 0; + + SDL_GetWindowMinimumSize(data->window, &minw, &minh); + SDL_GetWindowMaximumSize(data->window, &maxw, &maxh); + + data->grab = action; + data->ptCapture.x = GET_X_LPARAM(dwPos); + data->ptCapture.y = GET_Y_LPARAM(dwPos); + data->rcSizing = winfo.rcWindow; + if(winfo.dwStyle & WS_CHILD) + { + /* map points into the parent's coordinate space */ + HWND parent = GetParent(hwnd); + MapWindowPoints(0, parent, (LPPOINT)&data->rcSizing, 2); + GetWindowRect(parent, &rcClipCursor); + rcClipCursor = rcClipCursor; + MapWindowPoints(parent, HWND_DESKTOP, (LPPOINT)&rcClipCursor, 2); + } + else if(!(winfo.dwExStyle & WS_EX_TOPMOST)) + { + SystemParametersInfoW(SPI_GETWORKAREA, 0, &rcClipCursor, 0); + } + else + { + rcClipCursor.left = rcClipCursor.top = 0; + rcClipCursor.right = GetSystemMetrics(SM_CXSCREEN); + rcClipCursor.bottom = GetSystemMetrics(SM_CYSCREEN); + } + ClipCursor(&rcClipCursor); + data->rcOrig = data->rcSizing; + + if(GetCapture() != hwnd) + { + SetCapture(hwnd); + } + data->in_modeless_resize = SDL_TRUE; + return 0; +} + +void WIN_StopSizing(HWND hwnd, SDL_WindowData *data, SDL_bool cancel) +{ + ReleaseCapture(); + ClipCursor(NULL); + if(cancel) + SetWindowPos(hwnd, 0, data->rcOrig.left, data->rcOrig.top, + data->rcOrig.right - data->rcOrig.left, + data->rcOrig.bottom - data->rcOrig.top, + 0); + data->in_modeless_resize = SDL_FALSE; +} +void WIN_DoResize(HWND hwnd, SDL_WindowData *data, POINT pt, SDL_bool warpCursor) +{ + int dx, dy, minw, minh, maxw, maxh; + WPARAM wpHit = 0; + dx = pt.x - data->ptCapture.x; + dy = pt.y - data->ptCapture.y; + if(dx || dy) + { + SDL_GetWindowMinimumSize(data->window, &minw, &minh); + SDL_GetWindowMaximumSize(data->window, &maxw, &maxh); + + if(data->grab == NCHIT_CAPTION) + { + /* just moving */ + OffsetRect(&data->rcSizing, dx, dy); + } + else + { + /* note on minmax correction + if you do not correct the capture pos (set later from `pt`), + window will expand massively if user pulls back mouse + after failing to shrink when resizing from the + bottom or the right borders. + */ + /* when resizing using keys, Windows also moves the cursor */ + if(data->grab & NCHIT_LEFT) + { + int lmax = data->rcSizing.right - maxw; + int lmin = data->rcSizing.right - minw; + if(data->rcSizing.left + dx < lmax) + { + data->rcSizing.left = lmax; + } + else if(data->rcSizing.left + dx > lmin) + { + data->rcSizing.left = lmin; + } + else + { + data->rcSizing.left += dx; + } + pt.x = data->rcSizing.left; + wpHit = WMSZ_LEFT; + } + else if(data->grab & NCHIT_RIGHT) + { + int rmax = data->rcSizing.left + maxw; + int rmin = data->rcSizing.left + minw; + if(data->rcSizing.right + dx > rmax) + { + data->rcSizing.right = rmax; + } + else if(data->rcSizing.right + dx < rmin) + { + data->rcSizing.right = rmin; + } + else + { + data->rcSizing.right += dx; + } + pt.x = data->rcSizing.right; + wpHit = WMSZ_RIGHT; + } + if(data->grab & NCHIT_TOP) + { + int tmax = data->rcSizing.bottom - maxh; + int tmin = data->rcSizing.bottom - minh; + if(data->rcSizing.top + dy < tmax) + { + data->rcSizing.top = tmax; + } + else if(data->rcSizing.top + dy > tmin) + { + data->rcSizing.top = tmin; + } + else + { + data->rcSizing.top += dy; + } + pt.y = data->rcSizing.top; + if(wpHit == WMSZ_LEFT) + { + wpHit = WMSZ_TOPLEFT; + } + else if(wpHit == WMSZ_RIGHT) + { + wpHit = WMSZ_TOPRIGHT; + } + else + { + wpHit = WMSZ_TOP; + } + } + else if(data->grab & NCHIT_BOTTOM) + { + int bmax = data->rcSizing.top + maxh; + int bmin = data->rcSizing.top + minh; + if(data->rcSizing.bottom + dy > bmax) + { + data->rcSizing.bottom = bmax; + } + else if(data->rcSizing.bottom + dy < bmin) + { + data->rcSizing.bottom = bmin; + } + else + { + data->rcSizing.bottom += dy; + } + pt.y = data->rcSizing.bottom; + if(wpHit == WMSZ_LEFT) + { + wpHit = WMSZ_BOTTOMLEFT; + } + else if(wpHit == WMSZ_RIGHT) + { + wpHit = WMSZ_BOTTOMRIGHT; + } + else + { + wpHit = WMSZ_BOTTOM; + } + } + } + SetWindowPos(hwnd, 0, data->rcSizing.left, data->rcSizing.top, + data->rcSizing.right - data->rcSizing.left, + data->rcSizing.bottom - data->rcSizing.top, + 0); + + data->ptCapture = pt; + /* when resizing using keys, Windows also moves the cursor */ + if(warpCursor) + SetCursorPos(pt.x, pt.y); + } } LRESULT CALLBACK @@ -391,10 +594,23 @@ SDL_Mouse *mouse = SDL_GetMouse(); if (!mouse->relative_mode || mouse->relative_mode_warp) { SDL_SendMouseMotion(data->window, 0, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); + } + if(data->in_modeless_resize) + { + POINT ptPos; + ptPos.x = GET_X_LPARAM(lParam); + ptPos.y = GET_Y_LPARAM(lParam); + WIN_DoResize(hwnd, data, ptPos, SDL_FALSE); } } /* don't break here, fall through to check the wParam like the button presses */ - case WM_LBUTTONUP: + case WM_LBUTTONUP: + { + if(wParam == WM_LBUTTONUP) + { + WIN_StopSizing(hwnd, data, SDL_FALSE); + } + } case WM_RBUTTONUP: case WM_MBUTTONUP: case WM_XBUTTONUP: @@ -520,6 +736,35 @@ WIN_ConvertUTF32toUTF8(utf32, text); SDL_SendKeyboardText(text); } + } + else if(data->in_modeless_resize) + { + POINT ptPos; + DWORD dwPos = GetMessagePos(); + ptPos.x = GET_X_LPARAM(dwPos); + ptPos.y = GET_Y_LPARAM(dwPos); + switch(wParam) + { + case VK_RETURN: + WIN_StopSizing(hwnd, data, SDL_FALSE); + return 0; + case VK_ESCAPE: + WIN_StopSizing(hwnd, data, SDL_TRUE); + return 0; + case VK_UP: + ptPos.y-=8; + break; + case VK_DOWN: + ptPos.y+=8; + break; + case VK_LEFT: + ptPos.x-=8; + break; + case VK_RIGHT: + ptPos.x+=8; + break; + } + WIN_DoResize(hwnd, data, ptPos, SDL_TRUE); } } returnCode = 0; @@ -750,8 +995,38 @@ case WM_ERASEBKGND: { } - return (1); - + return (1); + case WM_KILLFOCUS: + { + if(data->in_modeless_resize) + data->in_modeless_resize = SDL_FALSE; + } + case WM_NCLBUTTONDOWN: + { + switch(wParam) + { + case HTLEFT: + return WIN_SizeMove(hwnd, data, NCHIT_LEFT, lParam); + case HTTOPLEFT: + return WIN_SizeMove(hwnd, data, NCHIT_LEFT | NCHIT_TOP, lParam); + case HTBOTTOMLEFT: + return WIN_SizeMove(hwnd, data, NCHIT_LEFT | NCHIT_BOTTOM, lParam); + case HTRIGHT: + return WIN_SizeMove(hwnd, data, NCHIT_RIGHT, lParam); + case HTTOPRIGHT: + return WIN_SizeMove(hwnd, data, NCHIT_RIGHT | NCHIT_TOP, lParam); + case HTBOTTOMRIGHT: + return WIN_SizeMove(hwnd, data, NCHIT_RIGHT | NCHIT_BOTTOM, lParam); + case HTTOP: + return WIN_SizeMove(hwnd, data, NCHIT_TOP, lParam); + case HTBOTTOM: + return WIN_SizeMove(hwnd, data, NCHIT_BOTTOM, lParam); + case HTCAPTION: + return WIN_SizeMove(hwnd, data, NCHIT_CAPTION, lParam); + default: + break; + } + } #if defined(SC_SCREENSAVE) || defined(SC_MONITORPOWER) case WM_SYSCOMMAND: { diff -r d7b7ec662687 -r a027905972e9 src/video/windows/SDL_windowswindow.h --- a/src/video/windows/SDL_windowswindow.h Fri Jan 24 09:54:04 2014 -0300 +++ b/src/video/windows/SDL_windowswindow.h Thu Feb 06 00:09:09 2014 -0500 @@ -23,7 +23,7 @@ #ifndef _SDL_windowswindow_h #define _SDL_windowswindow_h -#if SDL_VIDEO_OPENGL_EGL +#if SDL_VIDEO_OPENGL_EGL #include "../SDL_egl_c.h" #endif @@ -40,9 +40,14 @@ BOOL expected_resize; SDL_bool in_modal_loop; struct SDL_VideoData *videodata; -#if SDL_VIDEO_OPENGL_EGL +#if SDL_VIDEO_OPENGL_EGL EGLSurface egl_surface; -#endif +#endif + SDL_bool in_modeless_resize; + LONG grab; + POINT ptCapture; + RECT rcSizing; + RECT rcOrig; } SDL_WindowData; extern int WIN_CreateWindow(_THIS, SDL_Window * window); --===============1893281535==--