diff options
author | Alexander Kuznetsov <kuzsasha@gmail.com> | 2013-04-09 21:21:05 +0400 |
---|---|---|
committer | Alexander Kuznetsov <kuzsasha@gmail.com> | 2013-04-09 21:21:05 +0400 |
commit | f652b11ed13b4d9e6705ede9cc990042a2fad4b4 (patch) | |
tree | bba6d8fe597c75d3f92fb5bf7db40f9d3703935f /intern | |
parent | 13780935dc600d35ee9887bbe759c45beaf99170 (diff) |
Live window resizing on Windows
Custom implementation for resizing (GHOST_SizerWin32)
Some things still don't work:
* esc cancel
* max windows size
* aero (sizing) snap on win7
hbrBackground = 0 to disable clear screen.
Thanks to dfelinto for help in finding of root cause.
Diffstat (limited to 'intern')
-rw-r--r-- | intern/ghost/CMakeLists.txt | 2 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SizerWin32.cpp | 202 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SizerWin32.h | 61 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemWin32.cpp | 32 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowWin32.cpp | 3 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowWin32.h | 3 |
6 files changed, 298 insertions, 5 deletions
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index 12dd4c0d3eb..5bad9922d15 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -296,6 +296,7 @@ elseif(WIN32) intern/GHOST_SystemPathsWin32.cpp intern/GHOST_WindowWin32.cpp intern/GHOST_DropTargetWin32.cpp + intern/GHOST_SizerWin32.cpp intern/GHOST_DisplayManagerWin32.h intern/GHOST_DropTargetWin32.h @@ -303,6 +304,7 @@ elseif(WIN32) intern/GHOST_SystemPathsWin32.h intern/GHOST_WindowWin32.h intern/GHOST_TaskbarWin32.h + intern/GHOST_SizerWin32.h ) if(WITH_INPUT_NDOF) diff --git a/intern/ghost/intern/GHOST_SizerWin32.cpp b/intern/ghost/intern/GHOST_SizerWin32.cpp new file mode 100644 index 00000000000..9aa9ba313e6 --- /dev/null +++ b/intern/ghost/intern/GHOST_SizerWin32.cpp @@ -0,0 +1,202 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Alexandr Kuznetsov + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file ghost/intern/GHOST_SizerWin32.cpp + * \ingroup GHOST + */ + +#ifndef __GHOST_SIZERWIN32_CPP__ +#define __GHOST_SIZERWIN32_CPP__ + + +#include "GHOST_SizerWin32.h" +#include <Windowsx.h> + +#define T_NONE (0) +#define T_SIZE (1) +#define T_MOVE (2) +#define T_MOVESIZE (3) + + +static void RectCopyH(RECT * t, RECT * f) +{ + t->left = f->left; + t->right = f->right; +} + +static void RectCopyV(RECT * t, RECT * f) +{ + t->top = f->top; + t->bottom = f->bottom; +} + +static void RectCopy(RECT * t, RECT * f) +{ + RectCopyH(t,f); + RectCopyV(t,f); +} + + +GHOST_SizerWin32::GHOST_SizerWin32(void) +{ + hortransf = vertransf = 0; + minsize[0] = minsize[1] = 0; + hwnd = 0; +} + +GHOST_SizerWin32::~GHOST_SizerWin32(void) +{ + if(isWinChanges()) + cancel(); +} + +void GHOST_SizerWin32::setMinSize(int minx, int miny) +{ + minsize[0] = minx; + minsize[1] = miny; + + +} + +bool GHOST_SizerWin32::isWinChanges(void) +{ + return hortransf||vertransf; +} + + +void GHOST_SizerWin32::startSizing(unsigned short type) +{ + //SetCapture(hwnd); + POINT coord; + + switch(type & 0xf) + { + + case WMSZ_LEFT: hortransf = T_MOVESIZE; + vertransf = T_NONE; break; + case WMSZ_RIGHT: hortransf = T_SIZE; + vertransf = T_NONE; break; + case WMSZ_TOP: hortransf = T_NONE; + vertransf = T_MOVESIZE; break; + case WMSZ_TOPLEFT: hortransf = T_MOVESIZE; + vertransf = T_MOVESIZE; break; + case WMSZ_TOPRIGHT: hortransf = T_SIZE; + vertransf = T_MOVESIZE; break; + case WMSZ_BOTTOM: hortransf = T_NONE; + vertransf = T_SIZE; break; + case WMSZ_BOTTOMLEFT: hortransf = T_MOVESIZE; + vertransf = T_SIZE; break; + case WMSZ_BOTTOMRIGHT: hortransf = T_SIZE; + vertransf = T_SIZE; break; + + } + + + + POINT mp; + GetCursorPos(&mp); + startpos[0]=mp.x; + startpos[1]=mp.y; + + GetWindowRect(hwnd, &initrect); + initrect.bottom-=initrect.top; + initrect.right-=initrect.left; + RectCopy(&goodrect,&initrect); + +} + +void GHOST_SizerWin32::setHWND(HWND hWnd) +{ + this->hwnd = hWnd; +} + + +void GHOST_SizerWin32::updateWindowSize(void) +{ + if(!isWinChanges()) + return; + if(hortransf||vertransf){ + POINT mp; + GetCursorPos(&mp); + int hordelta = mp.x-startpos[0]; + int verdelta = mp.y-startpos[1]; + + RECT newrect; + RectCopy(&newrect, &initrect); + + switch(hortransf) + { + case T_SIZE: + newrect.right+=hordelta; + break; + case T_MOVESIZE: + newrect.right-=hordelta; + case T_MOVE: + newrect.left+=hordelta; + break; + } + + switch(vertransf) + { + case T_SIZE: + newrect.bottom+=verdelta; + break; + case T_MOVESIZE: + newrect.bottom-=verdelta; + case T_MOVE: + newrect.top+=verdelta; + break; + } + + + if(newrect.right<minsize[0]) + RectCopyH(&newrect,&goodrect); + if(newrect.bottom<minsize[1]) + RectCopyV(&newrect,&goodrect); + + SetWindowPos(hwnd,0,newrect.left, newrect.top, + newrect.right, newrect.bottom, + 0); + + RectCopy(&goodrect, &newrect); + + +} +} + +void GHOST_SizerWin32::cancel(void) +{ + accept(); + SetWindowPos(hwnd,0,initrect.left, initrect.top, + initrect.right, initrect.bottom, 0); +} + +void GHOST_SizerWin32::accept(void) +{ + hortransf=vertransf=0; +} + + +#endif /* __GHOST_SIZERWIN32_CPP__*/
\ No newline at end of file diff --git a/intern/ghost/intern/GHOST_SizerWin32.h b/intern/ghost/intern/GHOST_SizerWin32.h new file mode 100644 index 00000000000..f7d11e78ad7 --- /dev/null +++ b/intern/ghost/intern/GHOST_SizerWin32.h @@ -0,0 +1,61 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Alexandr Kuznetsov + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file ghost/intern/GHOST_SizerWin32.h + * \ingroup GHOST + */ +#ifndef __GHOST_SIZERWIN32_H__ +#define __GHOST_SIZERWIN32_H__ + +#include <windows.h> +class GHOST_SizerWin32 +{ + private: + HWND hwnd; + int startpos[2]; + int minsize[2]; + RECT initrect; + RECT goodrect; + unsigned char hortransf, vertransf; + + + public: + GHOST_SizerWin32(void); + ~GHOST_SizerWin32(void); + + bool isWinChanges(void); + void startSizing(unsigned short type); + void updateWindowSize(void); + + void setHWND(HWND hWnd); + void setMinSize(int minx, int miny); + + void cancel(void); + void accept(void); + + +}; + +#endif /*#ifndef __GHOST_SIZERWIN32_H__*/
\ No newline at end of file diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index a6e14ac362e..f19f4a67732 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -400,7 +400,7 @@ GHOST_TSuccess GHOST_SystemWin32::init() } if (success) { - WNDCLASSW wc; + WNDCLASSW wc = {0}; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = s_wndProc; wc.cbClsExtra = 0; @@ -412,7 +412,7 @@ GHOST_TSuccess GHOST_SystemWin32::init() ::LoadIcon(NULL, IDI_APPLICATION); } wc.hCursor = ::LoadCursor(0, IDC_ARROW); - wc.hbrBackground = (HBRUSH) ::GetStockObject(BLACK_BRUSH); + wc.hbrBackground = 0; wc.lpszMenuName = 0; wc.lpszClassName = L"GHOST_WindowClass"; @@ -979,7 +979,16 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, * maximize, minimize or close the window are triggered. Also it is sent when ALT * button is press for menu. To prevent this we must return preventing DefWindowProc. */ - if (wParam == SC_KEYMENU) return 0; + if (wParam == SC_KEYMENU) + { + eventHandled = true; + } else + if((wParam&0xfff0)==SC_SIZE) + { + window->registerMouseClickEvent(0); + window->m_wsh.startSizing(wParam); + eventHandled = true; + } break; //////////////////////////////////////////////////////////////////////// // Tablet events, processed @@ -1017,7 +1026,10 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, break; case WM_LBUTTONUP: window->registerMouseClickEvent(1); - event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft); + if(window->m_wsh.isWinChanges()) + window->m_wsh.accept(); + else + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft); break; case WM_MBUTTONUP: window->registerMouseClickEvent(1); @@ -1037,7 +1049,10 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, } break; case WM_MOUSEMOVE: - event = processCursorEvent(GHOST_kEventCursorMove, window); + if(window->m_wsh.isWinChanges()) + window->m_wsh.updateWindowSize(); + else + event = processCursorEvent(GHOST_kEventCursorMove, window); break; case WM_MOUSEWHEEL: /* The WM_MOUSEWHEEL message is sent to the focus window @@ -1105,6 +1120,9 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window); /* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL * will not be dispatched to OUR active window if we minimize one of OUR windows. */ + if(LOWORD(wParam)==WA_INACTIVE) + window->lostMouseCapture(); + lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); break; } @@ -1235,6 +1253,10 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, * In GHOST, we let DefWindowProc call the timer callback. */ break; + case WM_CANCELMODE: + if(window->m_wsh.isWinChanges()) + window->m_wsh.cancel(); + } } else { diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index 2b1bdfa78f0..e5e734e4e57 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -272,6 +272,9 @@ GHOST_WindowWin32::GHOST_WindowWin32( // Store a pointer to this class in the window structure ::SetWindowLongPtr(m_hWnd, GWL_USERDATA, (LONG_PTR) this); + m_wsh.setHWND(m_hWnd); + m_wsh.setMinSize(320, 240); + // Store the device context m_hDC = ::GetDC(m_hWnd); diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index 2af4b703930..d46f1b61493 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -38,6 +38,7 @@ #endif // WIN32 #include "GHOST_Window.h" +#include "GHOST_SizerWin32.h" #include "GHOST_TaskbarWin32.h" #define _WIN32_WINNT 0x501 // require Windows XP or newer @@ -280,6 +281,8 @@ public: GHOST_TSuccess endFullScreen() const {return GHOST_kFailure;} + GHOST_SizerWin32 m_wsh; + protected: GHOST_TSuccess initMultisample(PIXELFORMATDESCRIPTOR pfd); |