diff options
27 files changed, 464 insertions, 170 deletions
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index 20bb144a924..220e7aab8cd 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -176,6 +176,17 @@ extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings); +extern GHOST_WindowHandle GHOST_CreateDialogWindow(GHOST_SystemHandle systemhandle, + GHOST_WindowHandle parent_windowhandle, + const char *title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type, + GHOST_GLSettings glSettings); + /** * Create a new offscreen context. * Never explicitly delete the context, use disposeContext() instead. @@ -207,6 +218,8 @@ extern GHOST_TUserDataPtr GHOST_GetWindowUserData(GHOST_WindowHandle windowhandl */ extern void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle, GHOST_TUserDataPtr userdata); +extern int GHOST_IsDialogWindow(GHOST_WindowHandle windowhandle); + /** * Dispose a window. * \param systemhandle The handle to the system diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 27be80a2f20..1eeb6cd852f 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -236,6 +236,7 @@ class GHOST_ISystem { * \param type: The type of drawing context installed in this window. * \param glSettings: Misc OpenGL settings. * \param exclusive: Use to show the window on top and ignore others (used fullscreen). + * \param is_dialog: Stay on top of parent window, no icon in taskbar, not minimizable. * \param parentWindow: Parent (embedder) window * \return The new window (or 0 if creation failed). */ @@ -248,7 +249,8 @@ class GHOST_ISystem { GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive = false, - const GHOST_TEmbedderWindowID parentWindow = 0) = 0; + const bool is_dialog = false, + const GHOST_IWindow *parentWindow = NULL) = 0; /** * Dispose a window. diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h index 03a0db9abbe..c19d4bdf6bd 100644 --- a/intern/ghost/GHOST_IWindow.h +++ b/intern/ghost/GHOST_IWindow.h @@ -241,6 +241,8 @@ class GHOST_IWindow { */ virtual void setUserData(const GHOST_TUserDataPtr userData) = 0; + virtual bool isDialog() const = 0; + /** * Returns the tablet data (pressure etc). * \return The tablet data (pressure etc). diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index a1a209af77a..d907c10570c 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -140,7 +140,33 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle, GHOST_ISystem *system = (GHOST_ISystem *)systemhandle; return (GHOST_WindowHandle)system->createWindow( - title, left, top, width, height, state, type, glSettings, false); + title, left, top, width, height, state, type, glSettings, false, false); +} + +GHOST_WindowHandle GHOST_CreateDialogWindow(GHOST_SystemHandle systemhandle, + GHOST_WindowHandle parent_windowhandle, + const char *title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type, + GHOST_GLSettings glSettings) +{ + GHOST_ISystem *system = (GHOST_ISystem *)systemhandle; + + return (GHOST_WindowHandle)system->createWindow(title, + left, + top, + width, + height, + state, + type, + glSettings, + false, + true, + (GHOST_IWindow *)parent_windowhandle); } GHOST_TUserDataPtr GHOST_GetWindowUserData(GHOST_WindowHandle windowhandle) @@ -156,6 +182,13 @@ void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle, GHOST_TUserDataPtr window->setUserData(userdata); } +int GHOST_IsDialogWindow(GHOST_WindowHandle windowhandle) +{ + GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; + + return (int)window->isDialog(); +} + GHOST_TSuccess GHOST_DisposeWindow(GHOST_SystemHandle systemhandle, GHOST_WindowHandle windowhandle) { diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index fbf8af01e59..2e45592e055 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -105,14 +105,6 @@ class GHOST_System : public GHOST_ISystem { ***************************************************************************************/ /** - * Inherited from GHOST_ISystem but left pure virtual - * - * virtual GHOST_TUns8 getNumDisplays() const = 0; - * virtual void getMainDisplayDimensions(...) const = 0; - * virtual GHOST_IWindow* createWindow(..) - */ - - /** * Dispose a window. * \param window Pointer to the window to be disposed. * \return Indication of success. diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index 109dd6c180d..1e44c3e31d4 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -109,7 +109,8 @@ class GHOST_SystemCocoa : public GHOST_System { GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive = false, - const GHOST_TEmbedderWindowID parentWindow = 0); + const bool is_dialog = false, + const GHOST_IWindow *parentWindow = NULL); /** * Create a new offscreen context. @@ -232,6 +233,11 @@ class GHOST_SystemCocoa : public GHOST_System { GHOST_TSuccess handleApplicationBecomeActiveEvent(); /** + * \return True if any dialog window is open. + */ + bool hasDialogWindow(); + + /** * External objects should call this when they send an event outside processEvents. */ void notifyExternalEventProcessed(); diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 2026c1b7b4f..68bac7d153b 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -707,7 +707,8 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const STR_String &title, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive, - const GHOST_TEmbedderWindowID parentWindow) + const bool is_dialog, + const GHOST_IWindow *parentWindow) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; GHOST_IWindow *window = NULL; @@ -735,7 +736,9 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const STR_String &title, state, type, glSettings.flags & GHOST_glStereoVisual, - glSettings.flags & GHOST_glDebugContext); + glSettings.flags & GHOST_glDebugContext, + is_dialog, + (GHOST_WindowCocoa *)parentWindow); if (window->getValid()) { // Store the pointer to the window @@ -972,6 +975,13 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) // Note: called from NSApplication delegate GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent() { + for (GHOST_IWindow *iwindow : m_windowManager->getWindows()) { + GHOST_WindowCocoa *window = (GHOST_WindowCocoa *)iwindow; + if (window->isDialog()) { + [window->getCocoaWindow() makeKeyAndOrderFront:nil]; + } + } + // Update the modifiers key mask, as its status may have changed when the application // was not active (that is when update events are sent to another application). unsigned int modifiers; @@ -1021,6 +1031,17 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent() return GHOST_kSuccess; } +bool GHOST_SystemCocoa::hasDialogWindow() +{ + for (GHOST_IWindow *iwindow : m_windowManager->getWindows()) { + GHOST_WindowCocoa *window = (GHOST_WindowCocoa *)iwindow; + if (window->isDialog()) { + return true; + } + } + return false; +} + void GHOST_SystemCocoa::notifyExternalEventProcessed() { m_outsideLoopEventProcessed = true; diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp index 520c62719f8..e3f6f4b6bb1 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.cpp +++ b/intern/ghost/intern/GHOST_SystemSDL.cpp @@ -58,6 +58,7 @@ GHOST_IWindow *GHOST_SystemSDL::createWindow(const STR_String &title, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive, + const bool /* is_dialog */, const GHOST_TEmbedderWindowID parentWindow) { GHOST_WindowSDL *window = NULL; diff --git a/intern/ghost/intern/GHOST_SystemSDL.h b/intern/ghost/intern/GHOST_SystemSDL.h index 7dbdc3ccec8..942b6297c22 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.h +++ b/intern/ghost/intern/GHOST_SystemSDL.h @@ -89,6 +89,7 @@ class GHOST_SystemSDL : public GHOST_System { GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive = false, + const bool is_dialog = false, const GHOST_TEmbedderWindowID parentWindow = 0); /* SDL specific */ diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 9073ed9944b..1b04e1fde79 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -266,7 +266,8 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const STR_String &title, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive, - const GHOST_TEmbedderWindowID parentWindow) + const bool is_dialog, + const GHOST_IWindow *parentWindow) { GHOST_WindowWin32 *window = new GHOST_WindowWin32( this, @@ -279,8 +280,9 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const STR_String &title, type, ((glSettings.flags & GHOST_glStereoVisual) != 0), ((glSettings.flags & GHOST_glAlphaBackground) != 0), - parentWindow, - ((glSettings.flags & GHOST_glDebugContext) != 0)); + (GHOST_WindowWin32 *)parentWindow, + ((glSettings.flags & GHOST_glDebugContext) != 0), + is_dialog); if (window->getValid()) { // Store the pointer to the window diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index 7ac6a3e3e20..a92dea84d70 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -112,7 +112,7 @@ class GHOST_SystemWin32 : public GHOST_System { * \param type The type of drawing context installed in this window. * \param glSettings: Misc OpenGL settings. * \param exclusive: Use to show the window ontop and ignore others (used fullscreen). - * \param parentWindow Parent (embedder) window + * \param parentWindow Parent window * \return The new window (or 0 if creation failed). */ GHOST_IWindow *createWindow(const STR_String &title, @@ -124,7 +124,8 @@ class GHOST_SystemWin32 : public GHOST_System { GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive = false, - const GHOST_TEmbedderWindowID parentWindow = 0); + const bool is_dialog = false, + const GHOST_IWindow *parentWindow = 0); /** * Create a new offscreen context. diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 639553f31bb..a9435f3faff 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -324,7 +324,7 @@ void GHOST_SystemX11::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 * \param type The type of drawing context installed in this window. * \param glSettings: Misc OpenGL settings. * \param exclusive: Use to show the window ontop and ignore others (used fullscreen). - * \param parentWindow Parent (embedder) window + * \param parentWindow Parent window * \return The new window (or 0 if creation failed). */ GHOST_IWindow *GHOST_SystemX11::createWindow(const STR_String &title, @@ -336,7 +336,8 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const STR_String &title, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive, - const GHOST_TEmbedderWindowID parentWindow) + const bool is_dialog, + const GHOST_IWindow *parentWindow) { GHOST_WindowX11 *window = NULL; @@ -351,8 +352,9 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const STR_String &title, width, height, state, - parentWindow, + (GHOST_WindowX11 *)parentWindow, type, + is_dialog, ((glSettings.flags & GHOST_glStereoVisual) != 0), exclusive, ((glSettings.flags & GHOST_glAlphaBackground) != 0), diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index 1fe94b40f17..6ad2d6decae 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -146,7 +146,8 @@ class GHOST_SystemX11 : public GHOST_System { GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive = false, - const GHOST_TEmbedderWindowID parentWindow = 0); + const bool is_dialog = false, + const GHOST_IWindow *parentWindow = 0); /** * Create a new offscreen context. diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h index 5f9e8ffdd5e..553a7d89df4 100644 --- a/intern/ghost/intern/GHOST_Window.h +++ b/intern/ghost/intern/GHOST_Window.h @@ -109,6 +109,11 @@ class GHOST_Window : public GHOST_IWindow { */ inline GHOST_TStandardCursor getCursorShape() const; + inline bool isDialog() const + { + return false; + } + /** * Set the shape of the cursor. * \param cursorShape: The new cursor shape type id. diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h index 66de8bcf7cc..d260d0eacbc 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.h +++ b/intern/ghost/intern/GHOST_WindowCocoa.h @@ -66,7 +66,9 @@ class GHOST_WindowCocoa : public GHOST_Window { GHOST_TWindowState state, GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, const bool stereoVisual = false, - bool is_debug = false); + bool is_debug = false, + bool dialog = false, + GHOST_WindowCocoa *parentWindow = 0); /** * Destructor. @@ -218,6 +220,8 @@ class GHOST_WindowCocoa : public GHOST_Window { NSCursor *getStandardCursor(GHOST_TStandardCursor cursor) const; void loadCursor(bool visible, GHOST_TStandardCursor cursor) const; + bool isDialog() const; + const GHOST_TabletData *GetTabletData() { return &m_tablet; @@ -328,6 +332,7 @@ class GHOST_WindowCocoa : public GHOST_Window { bool m_immediateDraw; bool m_debug_context; // for debug messages during context setup + bool m_is_dialog; }; #endif // __GHOST_WINDOWCOCOA_H__ diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 6087df978fa..1d89da90a32 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -166,7 +166,8 @@ - (BOOL)canBecomeKeyWindow { - return YES; + /* Don't make other windows active when a dialog window is open. */ + return (associatedWindow->isDialog() || !systemCocoa->hasDialogWindow()); } //The drag'n'drop dragging destination methods @@ -290,7 +291,9 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa, GHOST_TWindowState state, GHOST_TDrawingContextType type, const bool stereoVisual, - bool is_debug) + bool is_debug, + bool is_dialog, + GHOST_WindowCocoa *parentWindow) : GHOST_Window(width, height, state, stereoVisual, false), m_openGLView(nil), m_metalView(nil), @@ -298,7 +301,8 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa, m_systemCocoa(systemCocoa), m_customCursor(0), m_immediateDraw(false), - m_debug_context(is_debug) + m_debug_context(is_debug), + m_is_dialog(is_dialog) { m_fullScreen = false; @@ -313,12 +317,16 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa, rect.size.width = width; rect.size.height = height; - m_window = [[CocoaWindow alloc] - initWithContentRect:rect - styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | - NSWindowStyleMaskResizable | NSWindowStyleMaskMiniaturizable - backing:NSBackingStoreBuffered - defer:NO]; + NSWindowStyleMask styleMask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | + NSWindowStyleMaskResizable; + if (!is_dialog) { + styleMask |= NSWindowStyleMaskMiniaturizable; + } + + m_window = [[CocoaWindow alloc] initWithContentRect:rect + styleMask:styleMask + backing:NSBackingStoreBuffered + defer:NO]; if (m_window == nil) { [pool drain]; @@ -402,6 +410,10 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa, if (state == GHOST_kWindowStateFullScreen) setState(GHOST_kWindowStateFullScreen); + if (is_dialog && parentWindow) { + [parentWindow->getCocoaWindow() addChildWindow:m_window ordered:NSWindowAbove]; + } + setNativePixelSize(); [pool drain]; @@ -548,10 +560,8 @@ void GHOST_WindowCocoa::getClientBounds(GHOST_Rect &bounds) const NSRect screenSize = [[m_window screen] visibleFrame]; // Max window contents as screen size (excluding title bar...) - NSRect contentRect = [CocoaWindow - contentRectForFrameRect:screenSize - styleMask:(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | - NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable)]; + NSRect contentRect = [CocoaWindow contentRectForFrameRect:screenSize + styleMask:[m_window styleMask]]; rect = [m_window contentRectForFrameRect:[m_window frame]]; @@ -1045,6 +1055,11 @@ void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor shape) co [cursor set]; } +bool GHOST_WindowCocoa::isDialog() const +{ + return m_is_dialog; +} + GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorVisibility(bool visible) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index d283e9e3aff..e1c6aa1109c 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -23,6 +23,7 @@ #define _USE_MATH_DEFINES +#include "GHOST_WindowManager.h" #include "GHOST_WindowWin32.h" #include "GHOST_SystemWin32.h" #include "GHOST_DropTargetWin32.h" @@ -66,8 +67,9 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, GHOST_TDrawingContextType type, bool wantStereoVisual, bool alphaBackground, - GHOST_TEmbedderWindowID parentwindowhwnd, - bool is_debug) + GHOST_WindowWin32 *parentwindow, + bool is_debug, + bool dialog) : GHOST_Window(width, height, state, wantStereoVisual, false), m_inLiveResize(false), m_system(system), @@ -82,7 +84,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, m_fpGetPointerInfo(NULL), m_fpGetPointerPenInfo(NULL), m_fpGetPointerTouchInfo(NULL), - m_parentWindowHwnd(parentwindowhwnd), + m_parentWindowHwnd(parentwindow ? parentwindow->m_hWnd : NULL), m_debug_context(is_debug) { // Initialize tablet variables @@ -146,9 +148,9 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, top = monitor.rcWork.top; int wintype = WS_OVERLAPPEDWINDOW; - if (m_parentWindowHwnd != 0) { + if ((m_parentWindowHwnd != 0) && !dialog) { wintype = WS_CHILD; - GetWindowRect((HWND)m_parentWindowHwnd, &rect); + GetWindowRect(m_parentWindowHwnd, &rect); left = 0; top = 0; width = rect.right - rect.left; @@ -156,14 +158,14 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, } wchar_t *title_16 = alloc_utf16_from_8((char *)(const char *)title, 0); - m_hWnd = ::CreateWindowW(s_windowClassName, // pointer to registered class name - title_16, // pointer to window name - wintype, // window style - left, // horizontal position of window - top, // vertical position of window - width, // window width - height, // window height - (HWND)m_parentWindowHwnd, // handle to parent or owner window + m_hWnd = ::CreateWindowW(s_windowClassName, // pointer to registered class name + title_16, // pointer to window name + wintype, // window style + left, // horizontal position of window + top, // vertical position of window + width, // window width + height, // window height + dialog ? 0 : m_parentWindowHwnd, // handle to parent or owner window 0, // handle to menu or child-window identifier ::GetModuleHandle(0), // handle to application instance 0); // pointer to window-creation data @@ -267,7 +269,16 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, } } - if (parentwindowhwnd != 0) { + if (dialog && parentwindow) { + ::SetWindowLongPtr(m_hWnd, + GWL_STYLE, + WS_VISIBLE | WS_CHILD | WS_POPUPWINDOW | WS_CAPTION | WS_MAXIMIZEBOX | + WS_SIZEBOX); + ::SetWindowLongPtr(m_hWnd, GWLP_HWNDPARENT, (LONG_PTR)m_parentWindowHwnd); + ::SetWindowPos( + m_hWnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); + } + else if (parentwindow) { RAWINPUTDEVICE device = {0}; device.usUsagePage = 0x01; /* usUsagePage & usUsage for keyboard*/ device.usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */ @@ -386,6 +397,16 @@ GHOST_WindowWin32::~GHOST_WindowWin32() } if (m_hWnd) { + /* If this window is referenced by others as parent, clear that relation or windows will free + * the handle while we still reference it. */ + for (GHOST_IWindow *iter_win : m_system->getWindowManager()->getWindows()) { + GHOST_WindowWin32 *iter_winwin = (GHOST_WindowWin32 *)iter_win; + if (iter_winwin->m_parentWindowHwnd == m_hWnd) { + ::SetWindowLongPtr(iter_winwin->m_hWnd, GWLP_HWNDPARENT, NULL); + iter_winwin->m_parentWindowHwnd = 0; + } + } + if (m_dropTarget) { // Disable DragDrop RevokeDragDrop(m_hWnd); @@ -528,7 +549,7 @@ GHOST_TWindowState GHOST_WindowWin32::getState() const // we need to find a way to combine parented windows + resizing if we simply set the // state as GHOST_kWindowStateEmbedded we will need to check for them somewhere else. // It's also strange that in Windows is the only platform we need to make this separation. - if (m_parentWindowHwnd != 0) { + if ((m_parentWindowHwnd != 0) && !isDialog()) { state = GHOST_kWindowStateEmbedded; return state; } @@ -574,6 +595,7 @@ void GHOST_WindowWin32::clientToScreen(GHOST_TInt32 inX, GHOST_TSuccess GHOST_WindowWin32::setState(GHOST_TWindowState state) { GHOST_TWindowState curstate = getState(); + LONG_PTR newstyle = -1; WINDOWPLACEMENT wp; wp.length = sizeof(WINDOWPLACEMENT); ::GetWindowPlacement(m_hWnd, &wp); @@ -587,7 +609,7 @@ GHOST_TSuccess GHOST_WindowWin32::setState(GHOST_TWindowState state) break; case GHOST_kWindowStateMaximized: wp.showCmd = SW_SHOWMAXIMIZED; - ::SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW); + newstyle = WS_OVERLAPPEDWINDOW; break; case GHOST_kWindowStateFullScreen: if (curstate != state && curstate != GHOST_kWindowStateMinimized) @@ -595,17 +617,21 @@ GHOST_TSuccess GHOST_WindowWin32::setState(GHOST_TWindowState state) wp.showCmd = SW_SHOWMAXIMIZED; wp.ptMaxPosition.x = 0; wp.ptMaxPosition.y = 0; - ::SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_MAXIMIZE); + newstyle = WS_MAXIMIZE; break; case GHOST_kWindowStateEmbedded: - ::SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_CHILD); + newstyle = WS_CHILD; break; case GHOST_kWindowStateNormal: default: wp.showCmd = SW_SHOWNORMAL; - ::SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW); + newstyle = WS_OVERLAPPEDWINDOW; break; } + if ((newstyle >= 0) && !isDialog()) { + ::SetWindowLongPtr(m_hWnd, GWL_STYLE, newstyle); + } + /* Clears window cache for SetWindowLongPtr */ ::SetWindowPos(m_hWnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); @@ -737,6 +763,14 @@ void GHOST_WindowWin32::lostMouseCapture() } } +bool GHOST_WindowWin32::isDialog() const +{ + HWND parent = (HWND)::GetWindowLongPtr(m_hWnd, GWLP_HWNDPARENT); + long int style = (long int)::GetWindowLongPtr(m_hWnd, GWL_STYLE); + + return (parent != 0) && (style & WS_POPUPWINDOW); +} + void GHOST_WindowWin32::registerMouseClickEvent(int press) { diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index 8dac142d6f4..f72f03855fd 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -235,8 +235,9 @@ class GHOST_WindowWin32 : public GHOST_Window { GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, bool wantStereoVisual = false, bool alphaBackground = false, - GHOST_TEmbedderWindowID parentWindowHwnd = 0, - bool is_debug = false); + GHOST_WindowWin32 *parentWindow = 0, + bool is_debug = false, + bool dialog = false); /** * Destructor. @@ -381,6 +382,8 @@ class GHOST_WindowWin32 : public GHOST_Window { */ void lostMouseCapture(); + bool isDialog() const; + /** * Loads the windows equivalent of a standard GHOST cursor. * \param visible Flag for cursor visibility. @@ -528,8 +531,7 @@ class GHOST_WindowWin32 : public GHOST_Window { GHOST_WIN32_GetPointerPenInfo m_fpGetPointerPenInfo; GHOST_WIN32_GetPointerTouchInfo m_fpGetPointerTouchInfo; - /** Hwnd to parent window */ - GHOST_TEmbedderWindowID m_parentWindowHwnd; + HWND m_parentWindowHwnd; #ifdef WITH_INPUT_IME /** Handle input method editors event */ diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 8aa4a4e284a..ae8d705fe4a 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -72,7 +72,18 @@ typedef struct { long input_mode; } MotifWmHints; -#define MWM_HINTS_DECORATIONS (1L << 1) +enum { + MWM_HINTS_FUNCTIONS = (1L << 0), + MWM_HINTS_DECORATIONS = (1L << 1), +}; +enum { + MWM_FUNCTION_ALL = (1L << 0), + MWM_FUNCTION_RESIZE = (1L << 1), + MWM_FUNCTION_MOVE = (1L << 2), + MWM_FUNCTION_MINIMIZE = (1L << 3), + MWM_FUNCTION_MAXIMIZE = (1L << 4), + MWM_FUNCTION_CLOSE = (1L << 5), +}; #ifndef HOST_NAME_MAX # define HOST_NAME_MAX 64 @@ -191,8 +202,9 @@ GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, - const GHOST_TEmbedderWindowID parentWindow, + GHOST_WindowX11 *parentWindow, GHOST_TDrawingContextType type, + const bool is_dialog, const bool stereoVisual, const bool exclusive, const bool alphaBackground, @@ -259,7 +271,7 @@ GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system, m_display, RootWindow(m_display, m_visualInfo->screen), m_visualInfo->visual, AllocNone); /* create the window! */ - if (parentWindow == 0) { + if ((parentWindow == 0) || is_dialog) { m_window = XCreateWindow(m_display, RootWindow(m_display, m_visualInfo->screen), left, @@ -279,7 +291,7 @@ GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system, unsigned int w_return, h_return, border_w_return, depth_return; XGetGeometry(m_display, - parentWindow, + parentWindow->m_window, &root_return, &x_return, &y_return, @@ -294,7 +306,7 @@ GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system, height = h_return; m_window = XCreateWindow(m_display, - parentWindow, /* reparent against embedder */ + parentWindow->m_window, /* reparent against embedder */ left, top, width, @@ -306,7 +318,7 @@ GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system, xattributes_valuemask, &xattributes); - XSelectInput(m_display, parentWindow, SubstructureNotifyMask); + XSelectInput(m_display, parentWindow->m_window, SubstructureNotifyMask); } #ifdef WITH_XDND @@ -356,6 +368,10 @@ GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system, m_post_state = GHOST_kWindowStateNormal; } + if (is_dialog && parentWindow) { + setDialogHints(parentWindow); + } + /* Create some hints for the window manager on how * we want this window treated. */ { @@ -701,6 +717,42 @@ void GHOST_WindowX11::clientToScreen(GHOST_TInt32 inX, outY = ay; } +GHOST_TSuccess GHOST_WindowX11::setDialogHints(GHOST_WindowX11 *parentWindow) +{ + + Atom atom_window_type = XInternAtom(m_display, "_NET_WM_WINDOW_TYPE", False); + Atom atom_dialog = XInternAtom(m_display, "_NET_WM_WINDOW_TYPE_DIALOG", False); + MotifWmHints hints = {0}; + + XChangeProperty(m_display, + m_window, + atom_window_type, + XA_ATOM, + 32, + PropModeReplace, + (unsigned char *)&atom_dialog, + 1); + XSetTransientForHint(m_display, m_window, parentWindow->m_window); + + /* Disable minimizing of the window for now. + * Actually, most window managers disable minimizing and maximizing for dialogs, ignoring this. + * Leaving it here anyway in the hope it brings back maximizing on some window managers at least, + * we'd preferably have it even for dialog windows (e.g. file browser). */ + hints.flags = MWM_HINTS_FUNCTIONS; + hints.functions = MWM_FUNCTION_RESIZE | MWM_FUNCTION_MOVE | MWM_FUNCTION_MAXIMIZE | + MWM_FUNCTION_CLOSE; + XChangeProperty(m_display, + m_window, + m_system->m_atom._MOTIF_WM_HINTS, + m_system->m_atom._MOTIF_WM_HINTS, + 32, + PropModeReplace, + (unsigned char *)&hints, + 4); + + return GHOST_kSuccess; +} + void GHOST_WindowX11::icccmSetState(int state) { XEvent xev; @@ -1112,6 +1164,44 @@ GHOST_TSuccess GHOST_WindowX11::setOrder(GHOST_TWindowOrder order) return GHOST_kSuccess; } +bool GHOST_WindowX11::isDialog() const +{ + Atom atom_window_type = XInternAtom(m_display, "_NET_WM_WINDOW_TYPE", False); + Atom atom_dialog = XInternAtom(m_display, "_NET_WM_WINDOW_TYPE_DIALOG", False); + + Atom *prop_ret; + unsigned long bytes_after, num_ret; + Atom type_ret; + bool st; + int format_ret, ret; + + prop_ret = NULL; + st = False; + ret = XGetWindowProperty(m_display, + m_window, + atom_window_type, + 0, + INT_MAX, + False, + XA_ATOM, + &type_ret, + &format_ret, + &num_ret, + &bytes_after, + (unsigned char **)&prop_ret); + if ((ret == Success) && (prop_ret) && (format_ret == 32)) { + if (prop_ret[0] == atom_dialog) { + st = True; + } + } + + if (prop_ret) { + XFree(prop_ret); + } + + return st; +} + GHOST_TSuccess GHOST_WindowX11::invalidate() { /* So the idea of this function is to generate an expose event diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h index 0b8fe3a3a41..faf3acba234 100644 --- a/intern/ghost/intern/GHOST_WindowX11.h +++ b/intern/ghost/intern/GHOST_WindowX11.h @@ -75,8 +75,9 @@ class GHOST_WindowX11 : public GHOST_Window { GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, - const GHOST_TEmbedderWindowID parentWindow, + GHOST_WindowX11 *parentWindow, GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, + const bool is_dialog = false, const bool stereoVisual = false, const bool exclusive = false, const bool alphaBackground = false, @@ -92,6 +93,8 @@ class GHOST_WindowX11 : public GHOST_Window { void getClientBounds(GHOST_Rect &bounds) const; + bool isDialog() const; + GHOST_TSuccess setClientWidth(GHOST_TUns32 width); GHOST_TSuccess setClientHeight(GHOST_TUns32 height); @@ -185,6 +188,8 @@ class GHOST_WindowX11 : public GHOST_Window { GHOST_TSuccess endFullScreen() const; + GHOST_TSuccess setDialogHints(GHOST_WindowX11 *parentWindow); + GHOST_TUns16 getDPIHint(); protected: diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 7c3aac6c688..c3e61f5f2b2 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -246,7 +246,8 @@ ScrArea *ED_screen_temp_space_open(struct bContext *C, int sizex, int sizey, eSpace_Type space_type, - int display_type); + int display_type, + bool dialog); void ED_screens_header_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg); void ED_screens_footer_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg); void ED_screens_navigation_bar_tools_menu_create(struct bContext *C, diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c index 6873495e962..a54701f8725 100644 --- a/source/blender/editors/render/render_view.c +++ b/source/blender/editors/render/render_view.c @@ -156,8 +156,8 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports) } /* changes context! */ - if (WM_window_open_temp(C, IFACE_("Blender Render"), mx, my, sizex, sizey, SPACE_IMAGE) == - NULL) { + if (WM_window_open_temp( + C, IFACE_("Blender Render"), mx, my, sizex, sizey, SPACE_IMAGE, false) == NULL) { BKE_report(reports, RPT_ERROR, "Failed to open window!"); return NULL; } diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index c8008fe3cc7..bbdddfadc30 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -1375,13 +1375,14 @@ ScrArea *ED_screen_temp_space_open(bContext *C, int sizex, int sizey, eSpace_Type space_type, - int display_type) + int display_type, + bool dialog) { ScrArea *sa = NULL; switch (display_type) { case USER_TEMP_SPACE_DISPLAY_WINDOW: - if (WM_window_open_temp(C, title, x, y, sizex, sizey, (int)space_type)) { + if (WM_window_open_temp(C, title, x, y, sizex, sizey, (int)space_type, dialog)) { sa = CTX_wm_area(C); } break; diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 0b374617cce..866144c272d 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -4828,9 +4828,14 @@ static int userpref_show_invoke(bContext *C, wmOperator *op, const wmEvent *even int sizey = 520 * UI_DPI_FAC; /* changes context! */ - if (WM_window_open_temp( - C, IFACE_("Blender Preferences"), event->x, event->y, sizex, sizey, SPACE_USERPREF) != - NULL) { + if (WM_window_open_temp(C, + IFACE_("Blender Preferences"), + event->x, + event->y, + sizex, + sizey, + SPACE_USERPREF, + false) != NULL) { /* The header only contains the editor switcher and looks empty. * So hiding in the temp window makes sense. */ ScrArea *area = CTX_wm_area(C); @@ -4879,9 +4884,14 @@ static int drivers_editor_show_invoke(bContext *C, wmOperator *op, const wmEvent but = UI_context_active_but_prop_get(C, &ptr, &prop, &index); /* changes context! */ - if (WM_window_open_temp( - C, IFACE_("Blender Drivers Editor"), event->x, event->y, sizex, sizey, SPACE_GRAPH) != - NULL) { + if (WM_window_open_temp(C, + IFACE_("Blender Drivers Editor"), + event->x, + event->y, + sizex, + sizey, + SPACE_GRAPH, + false) != NULL) { ED_drivers_editor_init(C, CTX_wm_area(C)); /* activate driver F-Curve for the property under the cursor */ @@ -4939,9 +4949,14 @@ static int info_log_show_invoke(bContext *C, wmOperator *op, const wmEvent *even int shift_y = 480; /* changes context! */ - if (WM_window_open_temp( - C, IFACE_("Blender Info Log"), event->x, event->y + shift_y, sizex, sizey, SPACE_INFO) != - NULL) { + if (WM_window_open_temp(C, + IFACE_("Blender Info Log"), + event->x, + event->y + shift_y, + sizex, + sizey, + SPACE_INFO, + false) != NULL) { return OPERATOR_FINISHED; } else { diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 2d9fa9e5ab6..df253d619c9 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -156,8 +156,14 @@ void WM_opengl_context_activate(void *context); void WM_opengl_context_release(void *context); struct wmWindow *WM_window_open(struct bContext *C, const struct rcti *rect); -struct wmWindow *WM_window_open_temp( - struct bContext *C, const char *title, int x, int y, int sizex, int sizey, int space_type); +struct wmWindow *WM_window_open_temp(struct bContext *C, + const char *title, + int x, + int y, + int sizex, + int sizey, + int space_type, + bool dialog); void WM_window_set_dpi(wmWindow *win); bool WM_stereo3d_enabled(struct wmWindow *win, bool only_fullscreen_test); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 6991dd2f9a6..1eec08c2e7a 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2352,7 +2352,8 @@ static int wm_handler_fileselect_do(bContext *C, U.file_space_data.temp_win_sizex * UI_DPI_FAC, U.file_space_data.temp_win_sizey * UI_DPI_FAC, SPACE_FILE, - U.filebrowser_display_type))) { + U.filebrowser_display_type, + true))) { ARegion *region_header = BKE_area_find_region_type(area, RGN_TYPE_HEADER); BLI_assert(area->spacetype == SPACE_FILE); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 2c26a15dce0..1ae95917c99 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -409,8 +409,10 @@ void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win) /* this is event from ghost, or exit-blender op */ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) { - /* First check if there is another main window remaining. */ wmWindow *win_other; + const bool is_dialog = GHOST_IsDialogWindow(win->ghostwin); + + /* First check if there is another main window remaining. */ for (win_other = wm->windows.first; win_other; win_other = win_other->next) { if (win_other != win && win_other->parent == NULL && !WM_window_is_temp_screen(win_other)) { break; @@ -422,10 +424,15 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) return; } - /* close child windows */ - for (wmWindow *win_child = wm->windows.first; win_child; win_child = win_child->next) { - if (win_child->parent == win) { - wm_window_close(C, wm, win_child); + /* Close child windows and bring windows back to front that dialogs have pushed behind the main + * window. */ + for (wmWindow *iter_win = wm->windows.first; iter_win; iter_win = iter_win->next) { + if (iter_win->parent == win) { + wm_window_close(C, wm, iter_win); + } + else if (is_dialog && iter_win != win && iter_win->parent && + (GHOST_GetWindowState(iter_win->ghostwin) != GHOST_kWindowStateMinimized)) { + wm_window_raise(iter_win); } } @@ -547,7 +554,10 @@ static void wm_window_ensure_eventstate(wmWindow *win) } /* belongs to below */ -static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wmWindow *win) +static void wm_window_ghostwindow_add(wmWindowManager *wm, + const char *title, + wmWindow *win, + bool is_dialog) { GHOST_WindowHandle ghostwin; GHOST_GLSettings glSettings = {0}; @@ -569,15 +579,29 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm wmWindow *prev_windrawable = wm->windrawable; wm_window_clear_drawable(wm); - ghostwin = GHOST_CreateWindow(g_system, - title, - win->posx, - posy, - win->sizex, - win->sizey, - (GHOST_TWindowState)win->windowstate, - GHOST_kDrawingContextTypeOpenGL, - glSettings); + if (is_dialog && win->parent) { + ghostwin = GHOST_CreateDialogWindow(g_system, + win->parent->ghostwin, + title, + win->posx, + posy, + win->sizex, + win->sizey, + (GHOST_TWindowState)win->windowstate, + GHOST_kDrawingContextTypeOpenGL, + glSettings); + } + else { + ghostwin = GHOST_CreateWindow(g_system, + title, + win->posx, + posy, + win->sizex, + win->sizey, + (GHOST_TWindowState)win->windowstate, + GHOST_kDrawingContextTypeOpenGL, + glSettings); + } if (ghostwin) { GHOST_RectangleHandle bounds; @@ -635,6 +659,68 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm } } +static void wm_window_ghostwindow_ensure(wmWindowManager *wm, wmWindow *win, bool is_dialog) +{ + wmKeyMap *keymap; + + if (win->ghostwin == NULL) { + if ((win->sizex == 0) || (wm_init_state.override_flag & WIN_OVERRIDE_GEOM)) { + win->posx = wm_init_state.start_x; + win->posy = wm_init_state.start_y; + win->sizex = wm_init_state.size_x; + win->sizey = wm_init_state.size_y; + + if (wm_init_state.override_flag & WIN_OVERRIDE_GEOM) { + win->windowstate = GHOST_kWindowStateNormal; + wm_init_state.override_flag &= ~WIN_OVERRIDE_GEOM; + } + else { + win->windowstate = GHOST_WINDOW_STATE_DEFAULT; + } + } + + if (wm_init_state.override_flag & WIN_OVERRIDE_WINSTATE) { + win->windowstate = wm_init_state.windowstate; + wm_init_state.override_flag &= ~WIN_OVERRIDE_WINSTATE; + } + + /* without this, cursor restore may fail, T45456 */ + if (win->cursor == 0) { + win->cursor = WM_CURSOR_DEFAULT; + } + + wm_window_ghostwindow_add(wm, "Blender", win, is_dialog); + } + + if (win->ghostwin != NULL) { + /* If we have no ghostwin this is a buggy window that should be removed. + * However we still need to initialize it correctly so the screen doesn't hang. */ + + /* happens after fileread */ + wm_window_ensure_eventstate(win); + } + + /* add keymap handlers (1 handler for all keys in map!) */ + keymap = WM_keymap_ensure(wm->defaultconf, "Window", 0, 0); + WM_event_add_keymap_handler(&win->handlers, keymap); + + keymap = WM_keymap_ensure(wm->defaultconf, "Screen", 0, 0); + WM_event_add_keymap_handler(&win->handlers, keymap); + + keymap = WM_keymap_ensure(wm->defaultconf, "Screen Editing", 0, 0); + WM_event_add_keymap_handler(&win->modalhandlers, keymap); + + /* add drop boxes */ + { + ListBase *lb = WM_dropboxmap_find("Window", 0, 0); + WM_event_add_dropbox_handler(&win->handlers, lb); + } + wm_window_title(wm, win); + + /* add topbar */ + ED_screen_global_areas_refresh(win); +} + /** * Initialize #wmWindow without ghostwin, open these and clear. * @@ -650,9 +736,6 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm */ void wm_window_ghostwindows_ensure(wmWindowManager *wm) { - wmKeyMap *keymap; - wmWindow *win; - BLI_assert(G.background == false); /* No command-line prefsize? then we set this. @@ -682,63 +765,8 @@ void wm_window_ghostwindows_ensure(wmWindowManager *wm) #endif } - for (win = wm->windows.first; win; win = win->next) { - if (win->ghostwin == NULL) { - if ((win->sizex == 0) || (wm_init_state.override_flag & WIN_OVERRIDE_GEOM)) { - win->posx = wm_init_state.start_x; - win->posy = wm_init_state.start_y; - win->sizex = wm_init_state.size_x; - win->sizey = wm_init_state.size_y; - - if (wm_init_state.override_flag & WIN_OVERRIDE_GEOM) { - win->windowstate = GHOST_kWindowStateNormal; - wm_init_state.override_flag &= ~WIN_OVERRIDE_GEOM; - } - else { - win->windowstate = GHOST_WINDOW_STATE_DEFAULT; - } - } - - if (wm_init_state.override_flag & WIN_OVERRIDE_WINSTATE) { - win->windowstate = wm_init_state.windowstate; - wm_init_state.override_flag &= ~WIN_OVERRIDE_WINSTATE; - } - - /* without this, cursor restore may fail, T45456 */ - if (win->cursor == 0) { - win->cursor = WM_CURSOR_DEFAULT; - } - - wm_window_ghostwindow_add(wm, "Blender", win); - } - - if (win->ghostwin != NULL) { - /* If we have no ghostwin this is a buggy window that should be removed. - * However we still need to initialize it correctly so the screen doesn't hang. */ - - /* happens after fileread */ - wm_window_ensure_eventstate(win); - } - - /* add keymap handlers (1 handler for all keys in map!) */ - keymap = WM_keymap_ensure(wm->defaultconf, "Window", 0, 0); - WM_event_add_keymap_handler(&win->handlers, keymap); - - keymap = WM_keymap_ensure(wm->defaultconf, "Screen", 0, 0); - WM_event_add_keymap_handler(&win->handlers, keymap); - - keymap = WM_keymap_ensure(wm->defaultconf, "Screen Editing", 0, 0); - WM_event_add_keymap_handler(&win->modalhandlers, keymap); - - /* add drop boxes */ - { - ListBase *lb = WM_dropboxmap_find("Window", 0, 0); - WM_event_add_dropbox_handler(&win->handlers, lb); - } - wm_window_title(wm, win); - - /* add topbar */ - ED_screen_global_areas_refresh(win); + for (wmWindow *win = wm->windows.first; win; win = win->next) { + wm_window_ghostwindow_ensure(wm, win, false); } } @@ -795,10 +823,17 @@ wmWindow *WM_window_open(bContext *C, const rcti *rect) * \param space_type: SPACE_VIEW3D, SPACE_INFO, ... (eSpace_Type) * \return the window or NULL in case of failure. */ -wmWindow *WM_window_open_temp( - bContext *C, const char *title, int x, int y, int sizex, int sizey, int space_type) +wmWindow *WM_window_open_temp(bContext *C, + const char *title, + int x, + int y, + int sizex, + int sizey, + int space_type, + bool dialog) { Main *bmain = CTX_data_main(C); + wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win_prev = CTX_wm_window(C); wmWindow *win; bScreen *screen; @@ -823,9 +858,10 @@ wmWindow *WM_window_open_temp( /* changes rect to fit within desktop */ wm_window_check_position(&rect); - /* test if we have a temp screen already */ - for (win = CTX_wm_manager(C)->windows.first; win; win = win->next) { - if (WM_window_is_temp_screen(win)) { + /* Reuse temporary or dialog window if one is open (but don't use a dialog for a regular + * temporary window, or vice versa). */ + for (win = wm->windows.first; win; win = win->next) { + if (WM_window_is_temp_screen(win) && (dialog == GHOST_IsDialogWindow(win->ghostwin))) { break; } } @@ -843,11 +879,6 @@ wmWindow *WM_window_open_temp( win->sizex = BLI_rcti_size_x(&rect); win->sizey = BLI_rcti_size_y(&rect); - if (win->ghostwin) { - wm_window_set_size(win, win->sizex, win->sizey); - wm_window_raise(win); - } - if (WM_window_get_active_workspace(win) == NULL) { WorkSpace *workspace = WM_window_get_active_workspace(win_prev); BKE_workspace_active_set(win->workspace_hook, workspace); @@ -872,6 +903,9 @@ wmWindow *WM_window_open_temp( /* make window active, and validate/resize */ CTX_wm_window_set(C, win); + if (!win->ghostwin) { + wm_window_ghostwindow_ensure(wm, win, dialog); + } WM_check(C); /* It's possible `win->ghostwin == NULL`. @@ -887,15 +921,18 @@ wmWindow *WM_window_open_temp( ED_area_newspace(C, sa, space_type, false); ED_screen_change(C, screen); - ED_screen_refresh(CTX_wm_manager(C), win); /* test scale */ + ED_screen_refresh(wm, win); /* test scale */ if (win->ghostwin) { + wm_window_set_size(win, win->sizex, win->sizey); + wm_window_raise(win); + GHOST_SetTitle(win->ghostwin, title); return win; } else { /* very unlikely! but opening a new window can fail */ - wm_window_close(C, CTX_wm_manager(C), win); + wm_window_close(C, wm, win); CTX_wm_window_set(C, win_prev); return NULL; |