diff options
Diffstat (limited to 'intern/ghost')
-rw-r--r-- | intern/ghost/GHOST_C-api.h | 13 | ||||
-rw-r--r-- | intern/ghost/GHOST_ISystem.h | 4 | ||||
-rw-r--r-- | intern/ghost/GHOST_IWindow.h | 2 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_C-api.cpp | 35 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_System.h | 8 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemCocoa.h | 8 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemCocoa.mm | 25 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemSDL.cpp | 1 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemSDL.h | 1 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemWin32.cpp | 8 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemWin32.h | 5 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemX11.cpp | 8 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemX11.h | 3 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_Window.h | 5 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowCocoa.h | 7 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowCocoa.mm | 41 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowWin32.cpp | 72 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowWin32.h | 10 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowX11.cpp | 102 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowX11.h | 7 |
20 files changed, 299 insertions, 66 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: |