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
path: root/intern
diff options
context:
space:
mode:
authorJulian Eisel <eiseljulian@gmail.com>2019-10-03 17:59:49 +0300
committerJulian Eisel <eiseljulian@gmail.com>2019-10-03 18:50:27 +0300
commitedffb0e9b19db62323b09ea93ce8f234f133656e (patch)
tree93299747b13308ff9b7aa1a9ed8ba56d3c41049c /intern
parent35ae1da16c6aab293adbe1e4eecba624006a085c (diff)
UI: Register File Browser as Child/Dialog-Window for the OS
For many users, this will make the File Browser window behave more like what they would expect. It addresses the issue of the File Browser becoming hidden behind the main window by clicking anywhere in the latter. It communicates the interruptive, but temporary nature of the operation a bit better. Further, on tiling window managers the File Browser now opens as floating by default, like in other applications. Note that this also makes sure the File Browser is always opened as separate window, so it doesn't re-use the Preferences, or any other temporary window anymore. This seems to have been a common annoyance. More concretely, this makes the File Browser window behave as follows: * Stays on top of its parent Blender window, but not on top of non-Blender windows. * Minimizes with its parent window * Can be moved independently * Doesn't add an own item in task bars * Doesn't block other Blender windows (we may want to have this though) * Opens as floating window for tiling window managers (e.g. i3wm/Sway) Further notes: * When opening a file browser from the Preference window (or any temporary window), the main window, as the file browsers parent is moved on top of the Preferences, which makes it seem like the Preferences were closed. This is the general issue of bad secondary window handling as window activation changes. I made it so that the window is moved back once the file browser is closed. This behavior is confusing and would be nice to avoid. It's a separate issue though. * On most window managers on Linux the temporary window can not be minimized and maximized, they disable that for dialog windows. * On Windows and macOS, only minimizing is disabled, as there is no decent way yet to restore a window if it's not shown in the taskbar. Reviewed By: Brecht van Lommel, Campbell Barton, William Reynish Edits and macOS implementation by Brecht. Differential Revision: https://developer.blender.org/D5810 Part of T69652.
Diffstat (limited to 'intern')
-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
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: