Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--intern/ghost/GHOST_C-api.h13
-rw-r--r--intern/ghost/GHOST_ISystem.h4
-rw-r--r--intern/ghost/GHOST_IWindow.h2
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp35
-rw-r--r--intern/ghost/intern/GHOST_System.h8
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.h8
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm25
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.cpp1
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.h1
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp8
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h5
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp8
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.h3
-rw-r--r--intern/ghost/intern/GHOST_Window.h5
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.h7
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm41
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp72
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.h10
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.cpp102
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.h7
-rw-r--r--source/blender/editors/include/ED_screen.h3
-rw-r--r--source/blender/editors/render/render_view.c4
-rw-r--r--source/blender/editors/screen/screen_edit.c5
-rw-r--r--source/blender/editors/screen/screen_ops.c33
-rw-r--r--source/blender/windowmanager/WM_api.h10
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c3
-rw-r--r--source/blender/windowmanager/intern/wm_window.c211
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;