[Bf-blender-cvs] [edffb0e9b19] master: UI: Register File Browser as Child/Dialog-Window for the OS

Julian Eisel noreply at git.blender.org
Thu Oct 3 17:51:45 CEST 2019


Commit: edffb0e9b19db62323b09ea93ce8f234f133656e
Author: Julian Eisel
Date:   Thu Oct 3 16:59:49 2019 +0200
Branches: master
https://developer.blender.org/rBedffb0e9b19db62323b09ea93ce8f234f133656e

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.

===================================================================

M	intern/ghost/GHOST_C-api.h
M	intern/ghost/GHOST_ISystem.h
M	intern/ghost/GHOST_IWindow.h
M	intern/ghost/intern/GHOST_C-api.cpp
M	intern/ghost/intern/GHOST_System.h
M	intern/ghost/intern/GHOST_SystemCocoa.h
M	intern/ghost/intern/GHOST_SystemCocoa.mm
M	intern/ghost/intern/GHOST_SystemSDL.cpp
M	intern/ghost/intern/GHOST_SystemSDL.h
M	intern/ghost/intern/GHOST_SystemWin32.cpp
M	intern/ghost/intern/GHOST_SystemWin32.h
M	intern/ghost/intern/GHOST_SystemX11.cpp
M	intern/ghost/intern/GHOST_SystemX11.h
M	intern/ghost/intern/GHOST_Window.h
M	intern/ghost/intern/GHOST_WindowCocoa.h
M	intern/ghost/intern/GHOST_WindowCocoa.mm
M	intern/ghost/intern/GHOST_WindowWin32.cpp
M	intern/ghost/intern/GHOST_WindowWin32.h
M	intern/ghost/intern/GHOST_WindowX11.cpp
M	intern/ghost/intern/GHOST_WindowX11.h
M	source/blender/editors/include/ED_screen.h
M	source/blender/editors/render/render_view.c
M	source/blender/editors/screen/screen_edit.c
M	source/blender/editors/screen/screen_ops.c
M	source/blender/windowmanager/WM_api.h
M	source/blender/windowmanager/intern/wm_event_system.c
M	source/blender/windowmanager/intern/wm_window.c

===================================================================

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
@@ -104,14 +104,6 @@ class GHOST_System : public GHOST_ISystem {
    * Display/window management functionality
    ***************************************************************************************/
 
-  /**
-   * 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.
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.
@@ -231,6 +232,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.
    */
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/g

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list