Changeset View
Changeset View
Standalone View
Standalone View
source/blender/windowmanager/intern/wm_window.c
| Show First 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | |||||
| #include "BLT_translation.h" | #include "BLT_translation.h" | ||||
| #include "BKE_blender.h" | #include "BKE_blender.h" | ||||
| #include "BKE_context.h" | #include "BKE_context.h" | ||||
| #include "BKE_icons.h" | #include "BKE_icons.h" | ||||
| #include "BKE_library.h" | #include "BKE_library.h" | ||||
| #include "BKE_global.h" | #include "BKE_global.h" | ||||
| #include "BKE_main.h" | #include "BKE_main.h" | ||||
| #include "BKE_screen.h" | |||||
| #include "BKE_workspace.h" | |||||
| #include "RNA_access.h" | #include "RNA_access.h" | ||||
| #include "RNA_define.h" | #include "RNA_define.h" | ||||
| #include "WM_api.h" | #include "WM_api.h" | ||||
| #include "WM_types.h" | #include "WM_types.h" | ||||
| #include "wm.h" | #include "wm.h" | ||||
| #include "wm_draw.h" | #include "wm_draw.h" | ||||
| #include "wm_window.h" | #include "wm_window.h" | ||||
| #include "wm_subwindow.h" | #include "wm_subwindow.h" | ||||
| #include "wm_event_system.h" | #include "wm_event_system.h" | ||||
| #include "ED_scene.h" | |||||
| #include "ED_screen.h" | #include "ED_screen.h" | ||||
| #include "ED_fileselect.h" | #include "ED_fileselect.h" | ||||
| #include "UI_interface.h" | #include "UI_interface.h" | ||||
| #include "UI_interface_icons.h" | #include "UI_interface_icons.h" | ||||
| #include "PIL_time.h" | #include "PIL_time.h" | ||||
| ▲ Show 20 Lines • Show All 134 Lines • ▼ Show 20 Lines | void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win) | ||||
| wm_event_free_all(win); | wm_event_free_all(win); | ||||
| wm_subwindows_free(win); | wm_subwindows_free(win); | ||||
| wm_draw_data_free(win); | wm_draw_data_free(win); | ||||
| wm_ghostwindow_destroy(win); | wm_ghostwindow_destroy(win); | ||||
| BKE_workspace_instance_hook_free(win->workspace_hook, G.main); | |||||
| MEM_freeN(win->stereo3d_format); | MEM_freeN(win->stereo3d_format); | ||||
| MEM_freeN(win); | MEM_freeN(win); | ||||
| } | } | ||||
| static int find_free_winid(wmWindowManager *wm) | static int find_free_winid(wmWindowManager *wm) | ||||
| { | { | ||||
| wmWindow *win; | wmWindow *win; | ||||
| int id = 1; | int id = 1; | ||||
| for (win = wm->windows.first; win; win = win->next) | for (win = wm->windows.first; win; win = win->next) | ||||
| if (id <= win->winid) | if (id <= win->winid) | ||||
| id = win->winid + 1; | id = win->winid + 1; | ||||
| return id; | return id; | ||||
| } | } | ||||
| /* don't change context itself */ | /* don't change context itself */ | ||||
| wmWindow *wm_window_new(bContext *C) | wmWindow *wm_window_new(bContext *C) | ||||
| { | { | ||||
| Main *bmain = CTX_data_main(C); | |||||
| wmWindowManager *wm = CTX_wm_manager(C); | wmWindowManager *wm = CTX_wm_manager(C); | ||||
| wmWindow *win = MEM_callocN(sizeof(wmWindow), "window"); | wmWindow *win = MEM_callocN(sizeof(wmWindow), "window"); | ||||
| BLI_addtail(&wm->windows, win); | BLI_addtail(&wm->windows, win); | ||||
| win->winid = find_free_winid(wm); | win->winid = find_free_winid(wm); | ||||
| win->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Stereo 3D Format (window)"); | win->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Stereo 3D Format (window)"); | ||||
| win->workspace_hook = BKE_workspace_instance_hook_create(bmain); | |||||
| return win; | return win; | ||||
| } | } | ||||
| /** | /** | ||||
| * A higher level version of copy that tests the new window can be added. | * A higher level version of copy that tests the new window can be added. | ||||
| */ | */ | ||||
| static wmWindow *wm_window_new_test(bContext *C) | static wmWindow *wm_window_new_test(bContext *C) | ||||
| Show All 9 Lines | static wmWindow *wm_window_new_test(bContext *C) | ||||
| else { | else { | ||||
| wmWindowManager *wm = CTX_wm_manager(C); | wmWindowManager *wm = CTX_wm_manager(C); | ||||
| wm_window_close(C, wm, win); | wm_window_close(C, wm, win); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| } | } | ||||
| /* part of wm_window.c api */ | /* part of wm_window.c api */ | ||||
| wmWindow *wm_window_copy(bContext *C, wmWindow *win_src) | wmWindow *wm_window_copy(bContext *C, wmWindow *win_src, const bool duplicate_layout) | ||||
| { | { | ||||
| wmWindow *win_dst = wm_window_new(C); | wmWindow *win_dst = wm_window_new(C); | ||||
| WorkSpace *workspace = WM_window_get_active_workspace(win_src); | |||||
| WorkSpaceLayout *layout_old = WM_window_get_active_layout(win_src); | |||||
| Scene *scene = WM_window_get_active_scene(win_src); | |||||
| WorkSpaceLayout *layout_new; | |||||
| bScreen *new_screen; | |||||
| win_dst->posx = win_src->posx + 10; | win_dst->posx = win_src->posx + 10; | ||||
| win_dst->posy = win_src->posy; | win_dst->posy = win_src->posy; | ||||
| win_dst->sizex = win_src->sizex; | win_dst->sizex = win_src->sizex; | ||||
| win_dst->sizey = win_src->sizey; | win_dst->sizey = win_src->sizey; | ||||
| /* duplicate assigns to window */ | win_dst->scene = scene; | ||||
| win_dst->screen = ED_screen_duplicate(win_dst, win_src->screen); | WM_window_set_active_workspace(win_dst, workspace); | ||||
| BLI_strncpy(win_dst->screenname, win_dst->screen->id.name + 2, sizeof(win_dst->screenname)); | layout_new = duplicate_layout ? ED_workspace_layout_duplicate(workspace, layout_old, win_dst) : layout_old; | ||||
| win_dst->screen->winid = win_dst->winid; | WM_window_set_active_layout(win_dst, workspace, layout_new); | ||||
| new_screen = WM_window_get_active_screen(win_dst); | |||||
| win_dst->screen->do_refresh = true; | BLI_strncpy(win_dst->screenname, new_screen->id.name + 2, sizeof(win_dst->screenname)); | ||||
| win_dst->screen->do_draw = true; | |||||
| win_dst->drawmethod = U.wmdrawmethod; | win_dst->drawmethod = U.wmdrawmethod; | ||||
| BLI_listbase_clear(&win_dst->drawdata); | BLI_listbase_clear(&win_dst->drawdata); | ||||
| *win_dst->stereo3d_format = *win_src->stereo3d_format; | *win_dst->stereo3d_format = *win_src->stereo3d_format; | ||||
| return win_dst; | return win_dst; | ||||
| } | } | ||||
| /** | /** | ||||
| * A higher level version of copy that tests the new window can be added. | * A higher level version of copy that tests the new window can be added. | ||||
| * (called from the operator directly) | * (called from the operator directly) | ||||
| */ | */ | ||||
| wmWindow *wm_window_copy_test(bContext *C, wmWindow *win_src) | wmWindow *wm_window_copy_test(bContext *C, wmWindow *win_src, const bool duplicate_layout) | ||||
| { | { | ||||
| wmWindowManager *wm = CTX_wm_manager(C); | wmWindowManager *wm = CTX_wm_manager(C); | ||||
| wmWindow *win_dst; | wmWindow *win_dst; | ||||
| win_dst = wm_window_copy(C, win_src); | win_dst = wm_window_copy(C, win_src, duplicate_layout); | ||||
| WM_check(C); | WM_check(C); | ||||
| if (win_dst->ghostwin) { | if (win_dst->ghostwin) { | ||||
| WM_event_add_notifier(C, NC_WINDOW | NA_ADDED, NULL); | WM_event_add_notifier(C, NC_WINDOW | NA_ADDED, NULL); | ||||
| return win_dst; | return win_dst; | ||||
| } | } | ||||
| else { | else { | ||||
| wm_window_close(C, wm, win_dst); | wm_window_close(C, wm, win_dst); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| } | } | ||||
| /* this is event from ghost, or exit-blender op */ | /* this is event from ghost, or exit-blender op */ | ||||
| void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) | void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) | ||||
| { | { | ||||
| wmWindow *tmpwin; | wmWindow *tmpwin; | ||||
| bool do_exit = false; | bool do_exit = false; | ||||
| /* first check if we have to quit (there are non-temp remaining windows) */ | /* first check if we have to quit (there are non-temp remaining windows) */ | ||||
| for (tmpwin = wm->windows.first; tmpwin; tmpwin = tmpwin->next) { | for (tmpwin = wm->windows.first; tmpwin; tmpwin = tmpwin->next) { | ||||
| if (tmpwin == win) | if (tmpwin == win) | ||||
| continue; | continue; | ||||
| if (tmpwin->screen->temp == 0) | if (WM_window_is_temp_screen(tmpwin) == false) | ||||
| break; | break; | ||||
| } | } | ||||
| if (tmpwin == NULL) | if (tmpwin == NULL) | ||||
| do_exit = 1; | do_exit = 1; | ||||
| if ((U.uiflag & USER_QUIT_PROMPT) && !wm->file_saved && !G.background) { | if ((U.uiflag & USER_QUIT_PROMPT) && !wm->file_saved && !G.background) { | ||||
| if (do_exit) { | if (do_exit) { | ||||
| if (!GHOST_confirmQuit(win->ghostwin)) | if (!GHOST_confirmQuit(win->ghostwin)) | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| /* let WM_exit do all freeing, for correct quit.blend save */ | /* let WM_exit do all freeing, for correct quit.blend save */ | ||||
| if (do_exit) { | if (do_exit) { | ||||
| WM_exit(C); | WM_exit(C); | ||||
| } | } | ||||
| else { | else { | ||||
| bScreen *screen = win->screen; | bScreen *screen = WM_window_get_active_screen(win); | ||||
| WorkSpace *workspace = WM_window_get_active_workspace(win); | |||||
| WorkSpaceLayout *layout = BKE_workspace_active_layout_get(win->workspace_hook); | |||||
| BLI_remlink(&wm->windows, win); | BLI_remlink(&wm->windows, win); | ||||
| wm_draw_window_clear(win); | wm_draw_window_clear(win); | ||||
| CTX_wm_window_set(C, win); /* needed by handlers */ | CTX_wm_window_set(C, win); /* needed by handlers */ | ||||
| WM_event_remove_handlers(C, &win->handlers); | WM_event_remove_handlers(C, &win->handlers); | ||||
| WM_event_remove_handlers(C, &win->modalhandlers); | WM_event_remove_handlers(C, &win->modalhandlers); | ||||
| /* for regular use this will _never_ be NULL, | /* for regular use this will _never_ be NULL, | ||||
| * however we may be freeing an improperly initialized window. */ | * however we may be freeing an improperly initialized window. */ | ||||
| if (win->screen) { | if (screen) { | ||||
| ED_screen_exit(C, win, win->screen); | ED_screen_exit(C, win, screen); | ||||
| } | } | ||||
| wm_window_free(C, wm, win); | wm_window_free(C, wm, win); | ||||
| /* if temp screen, delete it after window free (it stops jobs that can access it) */ | /* if temp screen, delete it after window free (it stops jobs that can access it) */ | ||||
| if (screen && screen->temp) { | if (screen && screen->temp) { | ||||
| Main *bmain = CTX_data_main(C); | Main *bmain = CTX_data_main(C); | ||||
| BKE_libblock_free(bmain, screen); | |||||
| BLI_assert(BKE_workspace_layout_screen_get(layout) == screen); | |||||
| BKE_workspace_layout_remove(workspace, layout, bmain); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| void wm_window_title(wmWindowManager *wm, wmWindow *win) | void wm_window_title(wmWindowManager *wm, wmWindow *win) | ||||
| { | { | ||||
| if (win->screen && win->screen->temp) { | if (WM_window_is_temp_screen(win)) { | ||||
| /* nothing to do for 'temp' windows, | /* nothing to do for 'temp' windows, | ||||
| * because WM_window_open_temp always sets window title */ | * because WM_window_open_temp always sets window title */ | ||||
| } | } | ||||
| else if (win->ghostwin) { | else if (win->ghostwin) { | ||||
| /* this is set to 1 if you don't have startup.blend open */ | /* this is set to 1 if you don't have startup.blend open */ | ||||
| if (G.save_over && G.main->name[0]) { | if (G.save_over && G.main->name[0]) { | ||||
| char str[sizeof(G.main->name) + 24]; | char str[sizeof(G.main->name) + 24]; | ||||
| BLI_snprintf(str, sizeof(str), "Blender%s [%s%s]", wm->file_saved ? "" : "*", G.main->name, | BLI_snprintf(str, sizeof(str), "Blender%s [%s%s]", wm->file_saved ? "" : "*", G.main->name, | ||||
| ▲ Show 20 Lines • Show All 275 Lines • ▼ Show 20 Lines | |||||
| * Uses `screen->temp` tag to define what to do, currently it limits | * Uses `screen->temp` tag to define what to do, currently it limits | ||||
| * to only one "temp" window for render out, preferences, filewindow, etc... | * to only one "temp" window for render out, preferences, filewindow, etc... | ||||
| * | * | ||||
| * \param type: WM_WINDOW_RENDER, WM_WINDOW_USERPREFS... | * \param type: WM_WINDOW_RENDER, WM_WINDOW_USERPREFS... | ||||
| * \return the window or NULL. | * \return the window or NULL. | ||||
| */ | */ | ||||
| wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, int type) | wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, int type) | ||||
| { | { | ||||
| Main *bmain = CTX_data_main(C); | |||||
| wmWindow *win_prev = CTX_wm_window(C); | wmWindow *win_prev = CTX_wm_window(C); | ||||
| wmWindow *win; | wmWindow *win; | ||||
| bScreen *screen; | |||||
| ScrArea *sa; | ScrArea *sa; | ||||
| Scene *scene = CTX_data_scene(C); | Scene *scene = CTX_data_scene(C); | ||||
| const char *title; | const char *title; | ||||
| /* convert to native OS window coordinates */ | /* convert to native OS window coordinates */ | ||||
| const float native_pixel_size = GHOST_GetNativePixelSize(win_prev->ghostwin); | const float native_pixel_size = GHOST_GetNativePixelSize(win_prev->ghostwin); | ||||
| x /= native_pixel_size; | x /= native_pixel_size; | ||||
| y /= native_pixel_size; | y /= native_pixel_size; | ||||
| sizex /= native_pixel_size; | sizex /= native_pixel_size; | ||||
| sizey /= native_pixel_size; | sizey /= native_pixel_size; | ||||
| /* calculate postition */ | /* calculate postition */ | ||||
| rcti rect; | rcti rect; | ||||
| rect.xmin = x + win_prev->posx - sizex / 2; | rect.xmin = x + win_prev->posx - sizex / 2; | ||||
| rect.ymin = y + win_prev->posy - sizey / 2; | rect.ymin = y + win_prev->posy - sizey / 2; | ||||
| rect.xmax = rect.xmin + sizex; | rect.xmax = rect.xmin + sizex; | ||||
| rect.ymax = rect.ymin + sizey; | rect.ymax = rect.ymin + sizey; | ||||
| /* changes rect to fit within desktop */ | /* changes rect to fit within desktop */ | ||||
| wm_window_check_position(&rect); | wm_window_check_position(&rect); | ||||
| /* test if we have a temp screen already */ | /* test if we have a temp screen already */ | ||||
| for (win = CTX_wm_manager(C)->windows.first; win; win = win->next) | for (win = CTX_wm_manager(C)->windows.first; win; win = win->next) | ||||
| if (win->screen->temp) | if (WM_window_is_temp_screen(win)) | ||||
| break; | break; | ||||
| /* add new window? */ | /* add new window? */ | ||||
| if (win == NULL) { | if (win == NULL) { | ||||
| win = wm_window_new(C); | win = wm_window_new(C); | ||||
| win->posx = rect.xmin; | win->posx = rect.xmin; | ||||
| win->posy = rect.ymin; | win->posy = rect.ymin; | ||||
| } | } | ||||
| screen = WM_window_get_active_screen(win); | |||||
| win->sizex = BLI_rcti_size_x(&rect); | win->sizex = BLI_rcti_size_x(&rect); | ||||
| win->sizey = BLI_rcti_size_y(&rect); | win->sizey = BLI_rcti_size_y(&rect); | ||||
| if (win->ghostwin) { | if (win->ghostwin) { | ||||
| wm_window_set_size(win, win->sizex, win->sizey); | wm_window_set_size(win, win->sizex, win->sizey); | ||||
| wm_window_raise(win); | wm_window_raise(win); | ||||
| } | } | ||||
| if (win->screen == NULL) { | if (WM_window_get_active_workspace(win) == NULL) { | ||||
| /* add new screen */ | WorkSpace *workspace = WM_window_get_active_workspace(win_prev); | ||||
| win->screen = ED_screen_add(win, scene, "temp"); | WM_window_set_active_workspace(win, workspace); | ||||
| } | } | ||||
| else { | |||||
| /* switch scene for rendering */ | if (screen == NULL) { | ||||
| if (win->screen->scene != scene) | /* add new screen layout */ | ||||
| ED_screen_set_scene(C, win->screen, scene); | WorkSpace *workspace = WM_window_get_active_workspace(win); | ||||
| WorkSpaceLayout *layout = ED_workspace_layout_add(workspace, win, "temp"); | |||||
| screen = BKE_workspace_layout_screen_get(layout); | |||||
| WM_window_set_active_layout(win, workspace, layout); | |||||
| } | |||||
| if (WM_window_get_active_scene(win) != scene) { | |||||
| WM_window_change_active_scene(bmain, C, win, scene); | |||||
| } | } | ||||
| win->screen->temp = 1; | screen->temp = 1; | ||||
| /* make window active, and validate/resize */ | /* make window active, and validate/resize */ | ||||
| CTX_wm_window_set(C, win); | CTX_wm_window_set(C, win); | ||||
| WM_check(C); | WM_check(C); | ||||
| /* It's possible `win->ghostwin == NULL`. | /* It's possible `win->ghostwin == NULL`. | ||||
| * instead of attempting to cleanup here (in a half finished state), | * instead of attempting to cleanup here (in a half finished state), | ||||
| * finish setting up the screen, then free it at the end of the function, | * finish setting up the screen, then free it at the end of the function, | ||||
| * to avoid having to take into account a partially-created window. | * to avoid having to take into account a partially-created window. | ||||
| */ | */ | ||||
| /* ensure it shows the right spacetype editor */ | /* ensure it shows the right spacetype editor */ | ||||
| sa = win->screen->areabase.first; | sa = screen->areabase.first; | ||||
| CTX_wm_area_set(C, sa); | CTX_wm_area_set(C, sa); | ||||
| if (type == WM_WINDOW_RENDER) { | if (type == WM_WINDOW_RENDER) { | ||||
| ED_area_newspace(C, sa, SPACE_IMAGE, false); | ED_area_newspace(C, sa, SPACE_IMAGE, false); | ||||
| } | } | ||||
| else { | else { | ||||
| ED_area_newspace(C, sa, SPACE_USERPREF, false); | ED_area_newspace(C, sa, SPACE_USERPREF, false); | ||||
| } | } | ||||
| ED_screen_set(C, win->screen); | ED_screen_change(C, screen); | ||||
| ED_screen_refresh(CTX_wm_manager(C), win); /* test scale */ | ED_screen_refresh(CTX_wm_manager(C), win); /* test scale */ | ||||
| if (sa->spacetype == SPACE_IMAGE) | if (sa->spacetype == SPACE_IMAGE) | ||||
| title = IFACE_("Blender Render"); | title = IFACE_("Blender Render"); | ||||
| else if (ELEM(sa->spacetype, SPACE_OUTLINER, SPACE_USERPREF)) | else if (ELEM(sa->spacetype, SPACE_OUTLINER, SPACE_USERPREF)) | ||||
| title = IFACE_("Blender User Preferences"); | title = IFACE_("Blender User Preferences"); | ||||
| else if (sa->spacetype == SPACE_FILE) | else if (sa->spacetype == SPACE_FILE) | ||||
| title = IFACE_("Blender File View"); | title = IFACE_("Blender File View"); | ||||
| Show All 19 Lines | |||||
| int wm_window_close_exec(bContext *C, wmOperator *UNUSED(op)) | int wm_window_close_exec(bContext *C, wmOperator *UNUSED(op)) | ||||
| { | { | ||||
| wmWindowManager *wm = CTX_wm_manager(C); | wmWindowManager *wm = CTX_wm_manager(C); | ||||
| wmWindow *win = CTX_wm_window(C); | wmWindow *win = CTX_wm_window(C); | ||||
| wm_window_close(C, wm, win); | wm_window_close(C, wm, win); | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| static WorkSpaceLayout *wm_window_new_find_layout(wmOperator *op, WorkSpace *workspace) | |||||
| { | |||||
| ListBase *listbase = BKE_workspace_layouts_get(workspace); | |||||
| const int layout_id = RNA_enum_get(op->ptr, "screen"); | |||||
| int i = 0; | |||||
| BKE_workspace_layout_iter_begin(layout, listbase->first) | |||||
| { | |||||
| if (i++ == layout_id) { | |||||
| return layout; | |||||
| } | |||||
| } | |||||
| BKE_workspace_layout_iter_end; | |||||
| BLI_assert(0); | |||||
| return NULL; | |||||
| } | |||||
| /* new window operator callback */ | /* new window operator callback */ | ||||
| int wm_window_new_exec(bContext *C, wmOperator *op) | int wm_window_new_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| Main *bmain = CTX_data_main(C); | |||||
| wmWindow *win_src = CTX_wm_window(C); | wmWindow *win_src = CTX_wm_window(C); | ||||
| const int screen_id = RNA_enum_get(op->ptr, "screen"); | WorkSpace *workspace = WM_window_get_active_workspace(win_src); | ||||
| bScreen *screen = BLI_findlink(&bmain->screen, screen_id); | WorkSpaceLayout *layout_new = wm_window_new_find_layout(op, workspace); | ||||
| bScreen *screen_new = BKE_workspace_layout_screen_get(layout_new); | |||||
| wmWindow *win_dst; | wmWindow *win_dst; | ||||
| if (screen->winid) { | if ((win_dst = wm_window_new_test(C))) { | ||||
| /* Screen is already used, duplicate window and screen */ | if (screen_new->winid) { | ||||
| win_dst = wm_window_copy_test(C, win_src); | /* layout/screen is already used, duplicate it */ | ||||
| } | layout_new = ED_workspace_layout_duplicate(workspace, layout_new, win_dst); | ||||
| else if ((win_dst = wm_window_new_test(C))) { | screen_new = BKE_workspace_layout_screen_get(layout_new); | ||||
| /* New window with a different screen */ | } | ||||
| win_dst->screen = screen; | /* New window with a different screen but same workspace */ | ||||
| screen->winid = win_dst->winid; | WM_window_set_active_workspace(win_dst, workspace); | ||||
| WM_window_set_active_screen(win_dst, workspace, screen_new); | |||||
| win_dst->scene = win_src->scene; | |||||
| screen_new->winid = win_dst->winid; | |||||
| CTX_wm_window_set(C, win_dst); | CTX_wm_window_set(C, win_dst); | ||||
| ED_screen_refresh(CTX_wm_manager(C), win_dst); | ED_screen_refresh(CTX_wm_manager(C), win_dst); | ||||
| } | } | ||||
| return (win_dst != NULL) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; | return (win_dst != NULL) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; | ||||
| } | } | ||||
| int wm_window_new_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) | int wm_window_new_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) | ||||
| { | { | ||||
| Main *bmain = CTX_data_main(C); | wmWindow *win = CTX_wm_window(C); | ||||
| WorkSpace *workspace = WM_window_get_active_workspace(win); | |||||
| ListBase *listbase = BKE_workspace_layouts_get(workspace); | |||||
| if (BLI_listbase_count_ex(&bmain->screen, 2) == 1) { | if (BLI_listbase_count_ex(listbase, 2) == 1) { | ||||
| RNA_enum_set(op->ptr, "screen", 0); | RNA_enum_set(op->ptr, "screen", 0); | ||||
| return wm_window_new_exec(C, op); | return wm_window_new_exec(C, op); | ||||
| } | } | ||||
| else { | else { | ||||
| return WM_enum_search_invoke_previews(C, op, 6, 2); | return WM_enum_search_invoke_previews(C, op, 6, 2); | ||||
| } | } | ||||
| } | } | ||||
| struct EnumPropertyItem *wm_window_new_screen_itemf( | struct EnumPropertyItem *wm_window_new_screen_itemf( | ||||
| bContext *C, struct PointerRNA *UNUSED(ptr), struct PropertyRNA *UNUSED(prop), bool *r_free) | bContext *C, struct PointerRNA *UNUSED(ptr), struct PropertyRNA *UNUSED(prop), bool *r_free) | ||||
| { | { | ||||
| Main *bmain = CTX_data_main(C); | wmWindow *win = CTX_wm_window(C); | ||||
| WorkSpace *workspace = WM_window_get_active_workspace(win); | |||||
| ListBase *listbase = BKE_workspace_layouts_get(workspace); | |||||
| EnumPropertyItem *item = NULL; | EnumPropertyItem *item = NULL; | ||||
| EnumPropertyItem tmp = {0, "", 0, "", ""}; | EnumPropertyItem tmp = {0, "", 0, "", ""}; | ||||
| int value = 0, totitem = 0; | int value = 0, totitem = 0; | ||||
| int count_act_screens = 0; | int count_act_screens = 0; | ||||
| /* XXX setting max number of windows to 20. We'd need support | /* XXX setting max number of windows to 20. We'd need support | ||||
| * for dynamic strings in EnumPropertyItem.name to avoid this. */ | * for dynamic strings in EnumPropertyItem.name to avoid this. */ | ||||
| static char active_screens[20][MAX_NAME + 12]; | static char active_screens[20][MAX_NAME + 12]; | ||||
| for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) { | BKE_workspace_layout_iter_begin(layout, listbase->first) | ||||
| { | |||||
| bScreen *screen = BKE_workspace_layout_screen_get(layout); | |||||
| const char *layout_name = BKE_workspace_layout_name_get(layout); | |||||
| if (screen->winid) { | if (screen->winid) { | ||||
| BLI_snprintf(active_screens[count_act_screens], sizeof(*active_screens), "%s (Duplicate)", | BLI_snprintf(active_screens[count_act_screens], sizeof(*active_screens), "%s (Duplicate)", layout_name); | ||||
| screen->id.name + 2); | |||||
| tmp.name = active_screens[count_act_screens++]; | tmp.name = active_screens[count_act_screens++]; | ||||
| } | } | ||||
| else { | else { | ||||
| tmp.name = screen->id.name + 2; | tmp.name = layout_name; | ||||
| } | } | ||||
| tmp.value = value; | tmp.value = value; | ||||
| tmp.identifier = screen->id.name; | tmp.identifier = layout_name; | ||||
| UI_id_icon_render(C, CTX_data_scene(C), &screen->id, true, false); | UI_id_icon_render(C, CTX_data_scene(C), &screen->id, true, false); | ||||
| tmp.icon = BKE_icon_id_ensure(&screen->id); | tmp.icon = BKE_icon_id_ensure(&screen->id); | ||||
| RNA_enum_item_add(&item, &totitem, &tmp); | RNA_enum_item_add(&item, &totitem, &tmp); | ||||
| value++; | value++; | ||||
| } | } | ||||
| BKE_workspace_layout_iter_end; | |||||
| RNA_enum_item_end(&item, &totitem); | RNA_enum_item_end(&item, &totitem); | ||||
| *r_free = true; | *r_free = true; | ||||
| return item; | return item; | ||||
| } | } | ||||
| /* fullscreen operator callback */ | /* fullscreen operator callback */ | ||||
| ▲ Show 20 Lines • Show All 292 Lines • ▼ Show 20 Lines | #undef USE_WIN_ACTIVATE | ||||
| case GHOST_kEventWindowMove: | case GHOST_kEventWindowMove: | ||||
| { | { | ||||
| GHOST_TWindowState state; | GHOST_TWindowState state; | ||||
| state = GHOST_GetWindowState(win->ghostwin); | state = GHOST_GetWindowState(win->ghostwin); | ||||
| win->windowstate = state; | win->windowstate = state; | ||||
| /* stop screencast if resize */ | /* stop screencast if resize */ | ||||
| if (type == GHOST_kEventWindowSize) { | if (type == GHOST_kEventWindowSize) { | ||||
| WM_jobs_stop(wm, win->screen, NULL); | WM_jobs_stop(wm, WM_window_get_active_screen(win), NULL); | ||||
| } | } | ||||
| wm_window_set_dpi(win); | wm_window_set_dpi(win); | ||||
| /* win32: gives undefined window size when minimized */ | /* win32: gives undefined window size when minimized */ | ||||
| if (state != GHOST_kWindowStateMinimized) { | if (state != GHOST_kWindowStateMinimized) { | ||||
| GHOST_RectangleHandle client_rect; | GHOST_RectangleHandle client_rect; | ||||
| int l, t, r, b, scr_w, scr_h; | int l, t, r, b, scr_w, scr_h; | ||||
| Show All 18 Lines | #undef USE_WIN_ACTIVATE | ||||
| * It might be good to eventually do that at Ghost level, but that is for | * It might be good to eventually do that at Ghost level, but that is for | ||||
| * another time. | * another time. | ||||
| */ | */ | ||||
| if (win->sizex != sizex || | if (win->sizex != sizex || | ||||
| win->sizey != sizey || | win->sizey != sizey || | ||||
| win->posx != posx || | win->posx != posx || | ||||
| win->posy != posy) | win->posy != posy) | ||||
| { | { | ||||
| const bScreen *screen = WM_window_get_active_screen(win); | |||||
| win->sizex = sizex; | win->sizex = sizex; | ||||
| win->sizey = sizey; | win->sizey = sizey; | ||||
| win->posx = posx; | win->posx = posx; | ||||
| win->posy = posy; | win->posy = posy; | ||||
| /* debug prints */ | /* debug prints */ | ||||
| if (G.debug & G_DEBUG_EVENTS) { | if (G.debug & G_DEBUG_EVENTS) { | ||||
| const char *state_str; | const char *state_str; | ||||
| Show All 20 Lines | #undef USE_WIN_ACTIVATE | ||||
| if (type != GHOST_kEventWindowSize) { | if (type != GHOST_kEventWindowSize) { | ||||
| printf("win move event pos %d %d size %d %d\n", | printf("win move event pos %d %d size %d %d\n", | ||||
| win->posx, win->posy, win->sizex, win->sizey); | win->posx, win->posy, win->sizex, win->sizey); | ||||
| } | } | ||||
| } | } | ||||
| wm_window_make_drawable(wm, win); | wm_window_make_drawable(wm, win); | ||||
| wm_draw_window_clear(win); | wm_draw_window_clear(win); | ||||
| BKE_icon_changed(win->screen->id.icon_id); | BKE_icon_changed(screen->id.icon_id); | ||||
| WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); | WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); | ||||
| WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL); | WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL); | ||||
| #if defined(__APPLE__) || defined(WIN32) | #if defined(__APPLE__) || defined(WIN32) | ||||
| /* OSX and Win32 don't return to the mainloop while resize */ | /* OSX and Win32 don't return to the mainloop while resize */ | ||||
| wm_event_do_notifiers(C); | wm_event_do_notifiers(C); | ||||
| wm_draw_update(C); | wm_draw_update(C); | ||||
| ▲ Show 20 Lines • Show All 96 Lines • ▼ Show 20 Lines | #endif | ||||
| } | } | ||||
| case GHOST_kEventNativeResolutionChange: | case GHOST_kEventNativeResolutionChange: | ||||
| { | { | ||||
| // only update if the actual pixel size changes | // only update if the actual pixel size changes | ||||
| float prev_pixelsize = U.pixelsize; | float prev_pixelsize = U.pixelsize; | ||||
| wm_window_set_dpi(win); | wm_window_set_dpi(win); | ||||
| if (U.pixelsize != prev_pixelsize) { | if (U.pixelsize != prev_pixelsize) { | ||||
| BKE_icon_changed(win->screen->id.icon_id); | BKE_icon_changed(WM_window_get_active_screen(win)->id.icon_id); | ||||
| // close all popups since they are positioned with the pixel | // close all popups since they are positioned with the pixel | ||||
| // size baked in and it's difficult to correct them | // size baked in and it's difficult to correct them | ||||
| wmWindow *oldWindow = CTX_wm_window(C); | wmWindow *oldWindow = CTX_wm_window(C); | ||||
| CTX_wm_window_set(C, win); | CTX_wm_window_set(C, win); | ||||
| UI_popup_handlers_remove_all(C, &win->modalhandlers); | UI_popup_handlers_remove_all(C, &win->modalhandlers); | ||||
| CTX_wm_window_set(C, oldWindow); | CTX_wm_window_set(C, oldWindow); | ||||
| ▲ Show 20 Lines • Show All 490 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| bool WM_window_is_fullscreen(wmWindow *win) | bool WM_window_is_fullscreen(wmWindow *win) | ||||
| { | { | ||||
| return win->windowstate == GHOST_kWindowStateFullScreen; | return win->windowstate == GHOST_kWindowStateFullScreen; | ||||
| } | } | ||||
| /** | |||||
| * Some editor data may need to be synced with scene data (3D View camera and layers). | |||||
| * This function ensures data is synced for editors in visible workspaces and their visible layouts. | |||||
| */ | |||||
| void WM_windows_scene_data_sync(const ListBase *win_lb, Scene *scene) | |||||
| { | |||||
| for (wmWindow *win = win_lb->first; win; win = win->next) { | |||||
| if (WM_window_get_active_scene(win) == scene) { | |||||
| ED_workspace_scene_data_sync(win->workspace_hook, scene); | |||||
| } | |||||
| } | |||||
| } | |||||
| Scene *WM_windows_scene_get_from_screen(const wmWindowManager *wm, const bScreen *screen) | |||||
| { | |||||
| for (wmWindow *win = wm->windows.first; win; win = win->next) { | |||||
| if (WM_window_get_active_screen(win) == screen) { | |||||
| return WM_window_get_active_scene(win); | |||||
| } | |||||
| } | |||||
| return NULL; | |||||
| } | |||||
| Scene *WM_window_get_active_scene(const wmWindow *win) | |||||
| { | |||||
| return win->scene; | |||||
| } | |||||
| /** | |||||
| * \warning Only call outside of area/region loops | |||||
| */ | |||||
| void WM_window_change_active_scene(Main *bmain, bContext *C, wmWindow *win, Scene *scene_new) | |||||
| { | |||||
| const bScreen *screen = WM_window_get_active_screen(win); | |||||
| ED_scene_exit(C); | |||||
| win->scene = scene_new; | |||||
| ED_scene_changed_update(bmain, C, scene_new, screen); | |||||
| } | |||||
| WorkSpace *WM_window_get_active_workspace(const wmWindow *win) | |||||
| { | |||||
| return BKE_workspace_active_get(win->workspace_hook); | |||||
| } | |||||
| void WM_window_set_active_workspace(wmWindow *win, WorkSpace *workspace) | |||||
| { | |||||
| BKE_workspace_active_set(win->workspace_hook, workspace); | |||||
| } | |||||
| WorkSpaceLayout *WM_window_get_active_layout(const wmWindow *win) | |||||
| { | |||||
| const WorkSpace *workspace = WM_window_get_active_workspace(win); | |||||
| return (LIKELY(workspace != NULL) ? BKE_workspace_active_layout_get(win->workspace_hook): NULL); | |||||
| } | |||||
| void WM_window_set_active_layout(wmWindow *win, WorkSpace *workspace, WorkSpaceLayout *layout) | |||||
| { | |||||
| BKE_workspace_hook_layout_for_workspace_set(win->workspace_hook, workspace, layout); | |||||
| } | |||||
| /** | |||||
| * Get the active screen of the active workspace in \a win. | |||||
| */ | |||||
| bScreen *WM_window_get_active_screen(const wmWindow *win) | |||||
| { | |||||
| const WorkSpace *workspace = WM_window_get_active_workspace(win); | |||||
| /* May be NULL in rare cases like closing Blender */ | |||||
| return (LIKELY(workspace != NULL) ? BKE_workspace_active_screen_get(win->workspace_hook) : NULL); | |||||
| } | |||||
| void WM_window_set_active_screen(wmWindow *win, WorkSpace *workspace, bScreen *screen) | |||||
| { | |||||
| BKE_workspace_active_screen_set(win->workspace_hook, workspace, screen); | |||||
| } | |||||
| bool WM_window_is_temp_screen(const wmWindow *win) | |||||
| { | |||||
| const bScreen *screen = WM_window_get_active_screen(win); | |||||
| return (screen && screen->temp != 0); | |||||
| } | |||||
| #ifdef WITH_INPUT_IME | #ifdef WITH_INPUT_IME | ||||
| /* note: keep in mind wm_window_IME_begin is also used to reposition the IME window */ | /* note: keep in mind wm_window_IME_begin is also used to reposition the IME window */ | ||||
| void wm_window_IME_begin(wmWindow *win, int x, int y, int w, int h, bool complete) | void wm_window_IME_begin(wmWindow *win, int x, int y, int w, int h, bool complete) | ||||
| { | { | ||||
| BLI_assert(win); | BLI_assert(win); | ||||
| GHOST_BeginIME(win->ghostwin, x, win->sizey - y, w, h, complete); | GHOST_BeginIME(win->ghostwin, x, win->sizey - y, w, h, complete); | ||||
| Show All 10 Lines | |||||