diff -r d3170ddf31ea src/video/windows/SDL_windowsevents.c --- a/src/video/windows/SDL_windowsevents.c Thu Feb 20 15:03:12 2014 -0500 +++ b/src/video/windows/SDL_windowsevents.c Thu Feb 20 15:48:41 2014 -0500 @@ -70,7 +70,13 @@ #endif #ifndef WM_MOUSEHWHEEL #define WM_MOUSEHWHEEL 0x020E -#endif +#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 ) @@ -310,6 +316,217 @@ } 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); + + /* FIXME: find a good way around this when maximum size is not set */ + if(!(maxw && maxh)) + { + HWND parent = GetParent(hwnd); + if(parent) + { + RECT rcRect; + GetClientRect(parent, &rcRect); + if(!maxw) + maxw = rcRect.right - rcRect.left; + if(!maxh) + maxh = rcRect.bottom - rcRect.top; + } + else + { + if(!maxw) + maxw = GetSystemMetrics(SM_CXSCREEN); + if(!maxh) + maxh = GetSystemMetrics(SM_CYSCREEN); + } + } + + if(data->grab == NCHIT_CAPTION) + { + OffsetRect(&data->rcSizing, dx, dy); + } + else + { + 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 WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) @@ -396,10 +613,24 @@ 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; + DWORD dwPos = GetMessagePos(); + ptPos.x = GET_X_LPARAM(dwPos); + ptPos.y = GET_Y_LPARAM(dwPos); + WIN_DoResize(hwnd, data, ptPos, SDL_TRUE); + } } /* don't break here, fall through to check the wParam like the button presses */ - case WM_LBUTTONUP: + case WM_LBUTTONUP: + { + if(msg == WM_LBUTTONUP && data->in_modeless_resize) + { + WIN_StopSizing(hwnd, data, SDL_FALSE); + } + } case WM_RBUTTONUP: case WM_MBUTTONUP: case WM_XBUTTONUP: @@ -525,7 +756,36 @@ 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; break; @@ -746,8 +1006,43 @@ case WM_ERASEBKGND: { } - return (1); - + return (1); + case WM_CAPTURECHANGED: + { + /* doing anything with capture here crashes the program + this means some other window had to become the foreground window anyway + so just stop resizing/moving + */ + if(data->in_modeless_resize && hwnd != (HWND)lParam) + data->in_modeless_resize = 0; + } + 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; + } + return 0; + } #if defined(SC_SCREENSAVE) || defined(SC_MONITORPOWER) case WM_SYSCOMMAND: { diff -r d3170ddf31ea src/video/windows/SDL_windowswindow.c --- a/src/video/windows/SDL_windowswindow.c Thu Feb 20 15:03:12 2014 -0500 +++ b/src/video/windows/SDL_windowswindow.c Thu Feb 20 15:48:41 2014 -0500 @@ -129,7 +129,8 @@ data->hdc = GetDC(hwnd); data->created = created; data->mouse_button_flags = 0; - data->videodata = videodata; + data->videodata = videodata; + data->in_modeless_resize = SDL_FALSE; window->driverdata = data; @@ -286,11 +287,11 @@ #if SDL_VIDEO_OPENGL_ES2 if ((window->flags & SDL_WINDOW_OPENGL) && _this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES -#if SDL_VIDEO_OPENGL_WGL +#if SDL_VIDEO_OPENGL_WGL && (!_this->gl_data || !_this->gl_data->HAS_WGL_EXT_create_context_es2_profile) -#endif +#endif ) { -#if SDL_VIDEO_OPENGL_EGL +#if SDL_VIDEO_OPENGL_EGL if (WIN_GLES_SetupWindow(_this, window) < 0) { WIN_DestroyWindow(_this, window); return -1; @@ -298,7 +299,7 @@ #else return SDL_SetError("Could not create GLES window surface (no EGL support available)"); #endif /* SDL_VIDEO_OPENGL_EGL */ - } else + } else #endif /* SDL_VIDEO_OPENGL_ES2 */ #if SDL_VIDEO_OPENGL_WGL diff -r d3170ddf31ea src/video/windows/SDL_windowswindow.h --- a/src/video/windows/SDL_windowswindow.h Thu Feb 20 15:03:12 2014 -0500 +++ b/src/video/windows/SDL_windowswindow.h Thu Feb 20 15:48:41 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);