diff options
Diffstat (limited to 'source/blender/windowmanager/intern/wm_window.c')
-rw-r--r-- | source/blender/windowmanager/intern/wm_window.c | 249 |
1 files changed, 154 insertions, 95 deletions
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 0f96500b8b3..05a84f6acaa 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -65,6 +65,9 @@ #include "wm_platform_support.h" #include "wm_window.h" #include "wm_window_private.h" +#ifdef WITH_XR_OPENXR +# include "wm_xr.h" +#endif #include "ED_anim_api.h" #include "ED_fileselect.h" @@ -81,11 +84,11 @@ #include "GPU_batch.h" #include "GPU_batch_presets.h" #include "GPU_context.h" -#include "GPU_draw.h" #include "GPU_framebuffer.h" #include "GPU_immediate.h" #include "GPU_init_exit.h" #include "GPU_platform.h" +#include "GPU_state.h" #include "UI_resources.h" @@ -283,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); @@ -304,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; @@ -321,7 +326,7 @@ wmWindow *wm_window_copy(Main *bmain, layout_new = duplicate_layout ? ED_workspace_layout_duplicate(bmain, workspace, layout_old, win_dst) : layout_old; - BKE_workspace_hook_layout_for_workspace_set(win_dst->workspace_hook, workspace, layout_new); + BKE_workspace_active_layout_set(win_dst->workspace_hook, workspace, layout_new); *win_dst->stereo3d_format = *win_src->stereo3d_format; @@ -414,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) { @@ -428,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. */ - for (wmWindow *iter_win = wm->windows.first; iter_win; iter_win = iter_win->next) { + /* 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); @@ -761,22 +756,9 @@ void wm_window_ghostwindows_ensure(wmWindowManager *wm) * in practice the window manager will likely move to the correct monitor */ wm_init_state.start_x = 0; wm_init_state.start_y = 0; - -#ifdef WITH_X11 /* X11 */ - /* X11, don't start maximized because we can't figure out the dimensions - * of a single display yet if there are multiple, due to lack of Xinerama - * handling in GHOST. */ - wm_init_state.size_x = min_ii(wm_init_state.size_x, WM_WIN_INIT_SIZE_X); - wm_init_state.size_y = min_ii(wm_init_state.size_y, WM_WIN_INIT_SIZE_Y); - /* pad */ - wm_init_state.start_x = WM_WIN_INIT_PAD; - wm_init_state.start_y = WM_WIN_INIT_PAD; - wm_init_state.size_x -= WM_WIN_INIT_PAD * 2; - wm_init_state.size_y -= WM_WIN_INIT_PAD * 2; -#endif } - for (wmWindow *win = wm->windows.first; win; win = win->next) { + LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { wm_window_ghostwindow_ensure(wm, win, false); } } @@ -799,6 +781,36 @@ void wm_window_ghostwindows_remove_invalid(bContext *C, wmWindowManager *wm) } } +/* Update window size and position based on data from GHOST window. */ +static bool wm_window_update_size_position(wmWindow *win) +{ + GHOST_RectangleHandle client_rect; + int l, t, r, b, scr_w, scr_h; + int sizex, sizey, posx, posy; + + client_rect = GHOST_GetClientBounds(win->ghostwin); + GHOST_GetRectangle(client_rect, &l, &t, &r, &b); + + GHOST_DisposeRectangle(client_rect); + + wm_get_desktopsize(&scr_w, &scr_h); + sizex = r - l; + sizey = b - t; + posx = l; + posy = scr_h - t - win->sizey; + + if (win->sizex != sizex || win->sizey != sizey || win->posx != posx || win->posy != posy) { + win->sizex = sizex; + win->sizey = sizey; + win->posx = posx; + win->posy = posy; + return true; + } + else { + return false; + } +} + /** * new window, no screen yet, but we open ghostwindow for it, * also gets the window level handlers @@ -809,7 +821,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; @@ -849,7 +861,7 @@ wmWindow *WM_window_open_temp(bContext *C, wmWindow *win_prev = CTX_wm_window(C); wmWindow *win; bScreen *screen; - ScrArea *sa; + ScrArea *area; Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); @@ -880,7 +892,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; @@ -915,7 +927,8 @@ wmWindow *WM_window_open_temp(bContext *C, /* make window active, and validate/resize */ CTX_wm_window_set(C, win); - if (!win->ghostwin) { + const bool new_window = (win->ghostwin == NULL); + if (new_window) { wm_window_ghostwindow_ensure(wm, win, dialog); } WM_check(C); @@ -927,18 +940,25 @@ wmWindow *WM_window_open_temp(bContext *C, */ /* ensure it shows the right spacetype editor */ - sa = screen->areabase.first; - CTX_wm_area_set(C, sa); + area = screen->areabase.first; + CTX_wm_area_set(C, area); - ED_area_newspace(C, sa, space_type, false); + ED_area_newspace(C, area, space_type, false); ED_screen_change(C, screen); - ED_screen_refresh(wm, win); /* test scale */ - if (win->ghostwin) { + if (!new_window) { + /* Set size in GHOST window and then update size and position from GHOST, + * in case they where changed by GHOST to fit the monitor/screen. */ wm_window_set_size(win, win->sizex, win->sizey); - wm_window_raise(win); + wm_window_update_size_position(win); + } + /* Refresh screen dimensions, after the effective window size is known. */ + ED_screen_refresh(wm, win); + + if (win->ghostwin) { + wm_window_raise(win); GHOST_SetTitle(win->ghostwin, title); return win; } @@ -1346,21 +1366,6 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr /* win32: gives undefined window size when minimized */ if (state != GHOST_kWindowStateMinimized) { - GHOST_RectangleHandle client_rect; - int l, t, r, b, scr_w, scr_h; - int sizex, sizey, posx, posy; - - client_rect = GHOST_GetClientBounds(win->ghostwin); - GHOST_GetRectangle(client_rect, &l, &t, &r, &b); - - GHOST_DisposeRectangle(client_rect); - - wm_get_desktopsize(&scr_w, &scr_h); - sizex = r - l; - sizey = b - t; - posx = l; - posy = scr_h - t - win->sizey; - /* * Ghost sometimes send size or move events when the window hasn't changed. * One case of this is using compiz on linux. To alleviate the problem @@ -1369,15 +1374,9 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr * It might be good to eventually do that at Ghost level, but that is for * another time. */ - if (win->sizex != sizex || win->sizey != sizey || win->posx != posx || - win->posy != posy) { + if (wm_window_update_size_position(win)) { const bScreen *screen = WM_window_get_active_screen(win); - win->sizex = sizex; - win->sizey = sizey; - win->posx = posx; - win->posy = posy; - /* debug prints */ if (G.debug & G_DEBUG_EVENTS) { const char *state_str; @@ -1659,8 +1658,6 @@ void wm_ghost_init(bContext *C) } GHOST_UseWindowFocus(wm_init_state.window_focus); - - WM_init_tablet_api(); } } @@ -1970,6 +1967,90 @@ bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Find Window Utility + * + * \{ */ +static void wm_window_desktop_pos_get(const wmWindow *win, + const int screen_pos[2], + int r_desk_pos[2]) +{ + /* To desktop space. */ + r_desk_pos[0] = screen_pos[0] + (int)(U.pixelsize * win->posx); + r_desk_pos[1] = screen_pos[1] + (int)(U.pixelsize * win->posy); +} + +static void wm_window_screen_pos_get(const wmWindow *win, + const int desktop_pos[2], + int r_scr_pos[2]) +{ + /* To window space. */ + r_scr_pos[0] = desktop_pos[0] - (int)(U.pixelsize * win->posx); + r_scr_pos[1] = desktop_pos[1] - (int)(U.pixelsize * win->posy); +} + +bool WM_window_find_under_cursor(const wmWindowManager *wm, + const wmWindow *win_ignore, + const wmWindow *win, + const int mval[2], + wmWindow **r_win, + int r_mval[2]) +{ + int desk_pos[2]; + wm_window_desktop_pos_get(win, mval, desk_pos); + + /* TODO: This should follow the order of the activated windows. + * The current solution is imperfect but usable in most cases. */ + LISTBASE_FOREACH (wmWindow *, win_iter, &wm->windows) { + if (win_iter == win_ignore) { + continue; + } + + if (win_iter->windowstate == GHOST_kWindowStateMinimized) { + continue; + } + + int scr_pos[2]; + wm_window_screen_pos_get(win_iter, desk_pos, scr_pos); + + if (scr_pos[0] >= 0 && win_iter->posy >= 0 && scr_pos[0] <= WM_window_pixels_x(win_iter) && + scr_pos[1] <= WM_window_pixels_y(win_iter)) { + + *r_win = win_iter; + copy_v2_v2_int(r_mval, scr_pos); + return true; + } + } + + return false; +} + +void WM_window_pixel_sample_read(const wmWindowManager *wm, + const wmWindow *win, + const int pos[2], + float r_col[3]) +{ + bool setup_context = wm->windrawable != win; + + if (setup_context) { + GHOST_ActivateWindowDrawingContext(win->ghostwin); + GPU_context_active_set(win->gpuctx); + } + + glReadBuffer(GL_FRONT); + glReadPixels(pos[0], pos[1], 1, 1, GL_RGB, GL_FLOAT, r_col); + glReadBuffer(GL_BACK); + + if (setup_context) { + if (wm->windrawable) { + GHOST_ActivateWindowDrawingContext(wm->windrawable->ghostwin); + GPU_context_active_set(wm->windrawable->gpuctx); + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Window Screen Shot Utility * * Include here since it can involve low level buffer switching. @@ -2152,8 +2233,7 @@ void WM_window_screen_rect_calc(const wmWindow *win, rcti *r_rect) screen_rect = window_rect; /* Subtract global areas from screen rectangle. */ - for (ScrArea *global_area = win->global_areas.areabase.first; global_area; - global_area = global_area->next) { + LISTBASE_FOREACH (ScrArea *, global_area, &win->global_areas.areabase) { int height = ED_area_global_size_y(global_area) - 1; if (global_area->global->flag & GLOBAL_AREA_IS_HIDDEN) { @@ -2201,7 +2281,7 @@ bool WM_window_is_maximized(const wmWindow *win) */ void WM_windows_scene_data_sync(const ListBase *win_lb, Scene *scene) { - for (wmWindow *win = win_lb->first; win; win = win->next) { + LISTBASE_FOREACH (wmWindow *, win, win_lb) { if (WM_window_get_active_scene(win) == scene) { ED_workspace_scene_data_sync(win->workspace_hook, scene); } @@ -2210,7 +2290,7 @@ void WM_windows_scene_data_sync(const ListBase *win_lb, Scene *scene) Scene *WM_windows_scene_get_from_screen(const wmWindowManager *wm, const bScreen *screen) { - for (wmWindow *win = wm->windows.first; win; win = win->next) { + LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { if (WM_window_get_active_screen(win) == screen) { return WM_window_get_active_scene(win); } @@ -2221,7 +2301,7 @@ Scene *WM_windows_scene_get_from_screen(const wmWindowManager *wm, const bScreen WorkSpace *WM_windows_workspace_get_from_screen(const wmWindowManager *wm, const bScreen *screen) { - for (wmWindow *win = wm->windows.first; win; win = win->next) { + LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { if (WM_window_get_active_screen(win) == screen) { return WM_window_get_active_workspace(win); } @@ -2249,7 +2329,7 @@ void WM_window_set_active_scene(Main *bmain, bContext *C, wmWindow *win, Scene * changed = true; } - for (wmWindow *win_child = wm->windows.first; win_child; win_child = win_child->next) { + LISTBASE_FOREACH (wmWindow *, win_child, &wm->windows) { if (win_child->parent == win_parent && win_child->scene != scene) { ED_screen_scene_change(C, win_child, scene); changed = true; @@ -2295,7 +2375,7 @@ void WM_window_set_active_view_layer(wmWindow *win, ViewLayer *view_layer) wmWindow *win_parent = (win->parent) ? win->parent : win; /* Set view layer in parent and child windows. */ - for (wmWindow *win_iter = wm->windows.first; win_iter; win_iter = win_iter->next) { + LISTBASE_FOREACH (wmWindow *, win_iter, &wm->windows) { if ((win_iter == win_parent) || (win_iter->parent == win_parent)) { STRNCPY(win_iter->view_layer_name, view_layer->name); bScreen *screen = BKE_workspace_active_screen_get(win_iter->workspace_hook); @@ -2327,7 +2407,7 @@ void WM_window_set_active_workspace(bContext *C, wmWindow *win, WorkSpace *works ED_workspace_change(workspace, C, wm, win); - for (wmWindow *win_child = wm->windows.first; win_child; win_child = win_child->next) { + LISTBASE_FOREACH (wmWindow *, win_child, &wm->windows) { if (win_child->parent == win_parent) { bScreen *screen = WM_window_get_active_screen(win_child); /* Don't change temporary screens, they only serve a single purpose. */ @@ -2346,7 +2426,7 @@ WorkSpaceLayout *WM_window_get_active_layout(const wmWindow *win) } void WM_window_set_active_layout(wmWindow *win, WorkSpace *workspace, WorkSpaceLayout *layout) { - BKE_workspace_hook_layout_for_workspace_set(win->workspace_hook, workspace, layout); + BKE_workspace_active_layout_set(win->workspace_hook, workspace, layout); } /** @@ -2441,24 +2521,3 @@ void WM_ghost_show_message_box(const char *title, GHOST_ShowMessageBox(g_system, title, message, help_label, continue_label, link, dialog_options); } /** \} */ - -#ifdef WIN32 -/* -------------------------------------------------------------------- */ -/** \name Direct DirectX Context Management - * \{ */ - -void *WM_directx_context_create(void) -{ - BLI_assert(GPU_framebuffer_active_get() == NULL); - return GHOST_CreateDirectXContext(g_system); -} - -void WM_directx_context_dispose(void *context) -{ - BLI_assert(GPU_framebuffer_active_get() == NULL); - GHOST_DisposeDirectXContext(g_system, context); -} - -/** \} */ - -#endif |