UI: Allow registering File Browser as child of other child windows

E.g. when opening the File Browser from the Preferences window, it would
be the child of the main window the Preferences belong to. Now it can be
a child of the Preferences window itself.
The File Browser always stays on top of its parent window. Which avoids
some issues with OS window management, see T76418 and T72693.
Also removes a now unnecessary workaround to move the child window back
to the front after closing the file browser (opening the file browser
would move the main window and the file browser to the front).

Fixes T76418, T72693.
This commit is contained in:
Julian Eisel 2020-05-20 17:02:36 +02:00
parent aa0e98d707
commit 796412dca0
Notes: blender-bot 2023-02-13 23:52:09 +01:00
Referenced by issue #88570, Regression: Crash when saving after pressing ctrl+S twice.
Referenced by issue #76926, Crash on saving or opening files with the Full Screen file browser window preference
Referenced by issue #76449, Crash on saving rendered image if you close the child window which shows the rendered image
Referenced by issue #76418, After render you want to save image, but saving window it is hidden below render windows when Blender.app in fullscreen mode
Referenced by issue #72693, File browser puts focus on wrong window after closing the dialog
4 changed files with 17 additions and 28 deletions

View File

@ -384,7 +384,7 @@ void wm_add_default(Main *bmain, bContext *C)
WorkSpaceLayout *layout = BKE_workspace_layout_find_global(bmain, screen, &workspace);
CTX_wm_manager_set(C, wm);
win = wm_window_new(bmain, wm, NULL);
win = wm_window_new(bmain, wm, NULL, false);
win->scene = CTX_data_scene(C);
STRNCPY(win->view_layer_name, CTX_data_view_layer(C)->name);
BKE_workspace_active_set(win->workspace_hook, workspace);

View File

@ -3442,19 +3442,13 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op)
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
const bool is_temp_screen = WM_window_is_temp_screen(win);
const bool opens_window = (U.filebrowser_display_type == USER_TEMP_SPACE_DISPLAY_WINDOW);
/* Don't add the file handler to the temporary window if one is opened, or else it owns the
* handlers for itself, causing dangling pointers once it's destructed through a handler. It has
* a parent which should hold the handlers itself. */
ListBase *modalhandlers = (is_temp_screen && opens_window) ? &win->parent->modalhandlers :
&win->modalhandlers;
/* Close any popups, like when opening a file browser from the splash. */
UI_popup_handlers_remove_all(C, modalhandlers);
UI_popup_handlers_remove_all(C, &win->modalhandlers);
if (!is_temp_screen) {
/* only allow 1 file selector open per window */
LISTBASE_FOREACH_MUTABLE (wmEventHandler *, handler_base, modalhandlers) {
LISTBASE_FOREACH_MUTABLE (wmEventHandler *, handler_base, &win->modalhandlers) {
if (handler_base->type == WM_HANDLER_TYPE_OP) {
wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base;
if (handler->is_fileselect == false) {
@ -3495,7 +3489,7 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op)
handler->context.area = CTX_wm_area(C);
handler->context.region = CTX_wm_region(C);
BLI_addhead(modalhandlers, handler);
BLI_addhead(&win->modalhandlers, handler);
/* check props once before invoking if check is available
* ensures initial properties are valid */

View File

@ -286,14 +286,15 @@ static int find_free_winid(wmWindowManager *wm)
}
/* don't change context itself */
wmWindow *wm_window_new(const Main *bmain, wmWindowManager *wm, wmWindow *parent)
wmWindow *wm_window_new(const Main *bmain, wmWindowManager *wm, wmWindow *parent, bool dialog)
{
wmWindow *win = MEM_callocN(sizeof(wmWindow), "window");
BLI_addtail(&wm->windows, win);
win->winid = find_free_winid(wm);
win->parent = (parent && parent->parent) ? parent->parent : parent;
/* Dialogs may have a child window as parent. Otherwise, a child must not be a parent too. */
win->parent = (!dialog && parent && parent->parent) ? parent->parent : parent;
win->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Stereo 3D Format (window)");
win->workspace_hook = BKE_workspace_instance_hook_create(bmain);
@ -307,8 +308,9 @@ wmWindow *wm_window_copy(Main *bmain,
const bool duplicate_layout,
const bool child)
{
const bool is_dialog = GHOST_IsDialogWindow(win_src->ghostwin);
wmWindow *win_parent = (child) ? win_src : win_src->parent;
wmWindow *win_dst = wm_window_new(bmain, wm, win_parent);
wmWindow *win_dst = wm_window_new(bmain, wm, win_parent, is_dialog);
WorkSpace *workspace = WM_window_get_active_workspace(win_src);
WorkSpaceLayout *layout_old = WM_window_get_active_layout(win_src);
WorkSpaceLayout *layout_new;
@ -417,7 +419,6 @@ void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win)
void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
{
wmWindow *win_other;
const bool is_dialog = (G.background == false) ? GHOST_IsDialogWindow(win->ghostwin) : false;
/* First check if there is another main window remaining. */
for (win_other = wm->windows.first; win_other; win_other = win_other->next) {
@ -431,20 +432,11 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
return;
}
/* Close child windows and bring windows back to front that dialogs have pushed behind the main
* window. */
LISTBASE_FOREACH (wmWindow *, iter_win, &wm->windows) {
/* Close child windows */
LISTBASE_FOREACH_MUTABLE (wmWindow *, iter_win, &wm->windows) {
if (iter_win->parent == win) {
wm_window_close(C, wm, iter_win);
}
else {
if (G.background == false) {
if (is_dialog && iter_win != win && iter_win->parent &&
(GHOST_GetWindowState(iter_win->ghostwin) != GHOST_kWindowStateMinimized)) {
wm_window_raise(iter_win);
}
}
}
}
bScreen *screen = WM_window_get_active_screen(win);
@ -834,7 +826,7 @@ wmWindow *WM_window_open(bContext *C, const rcti *rect)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win_prev = CTX_wm_window(C);
wmWindow *win = wm_window_new(CTX_data_main(C), wm, win_prev);
wmWindow *win = wm_window_new(CTX_data_main(C), wm, win_prev, false);
win->posx = rect->xmin;
win->posy = rect->ymin;
@ -905,7 +897,7 @@ wmWindow *WM_window_open_temp(bContext *C,
/* add new window? */
if (win == NULL) {
win = wm_window_new(bmain, wm, win_prev);
win = wm_window_new(bmain, wm, win_prev, dialog);
win->posx = rect.xmin;
win->posy = rect.ymin;

View File

@ -33,7 +33,10 @@ void wm_ghost_exit(void);
void wm_get_screensize(int *r_width, int *r_height);
void wm_get_desktopsize(int *r_width, int *r_height);
wmWindow *wm_window_new(const struct Main *bmain, wmWindowManager *wm, wmWindow *parent);
wmWindow *wm_window_new(const struct Main *bmain,
wmWindowManager *wm,
wmWindow *parent,
bool dialog);
wmWindow *wm_window_copy(struct Main *bmain,
wmWindowManager *wm,
wmWindow *win_src,