From 6f20fcd5984a47baee9ff440e9e59584fccd1e59 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 23 May 2018 22:38:25 +0200 Subject: UI: Global "Status-bar" Area (WIP) * Add horizontal bar at bottom of all non-temp windows, similar to the Top-bar. * Status-bar is hidden in UI-less fullscreen mode * Current contents are preliminary and based on T54861: ** Left: Current file-path if needed. "(Modified)" note if file was changed. ** Center: Scene statistics (like in 2.7 Info Editor). ** Right: Progress-bars and reports * Internally managed as own "STATUSBAR" editor-type (hidden in UI). * Like with the Top-bar, Status-bar data and SDNA writing is disabled. * Most changes in low-level screen/area code are to support layout bounds that differ from window bounds. Design task: T54861 Main changes approved by @brecht. --- build_files/cmake/macros.cmake | 1 + release/scripts/startup/bl_ui/__init__.py | 1 + release/scripts/startup/bl_ui/space_statusbar.py | 84 +++++++++ release/scripts/startup/bl_ui/space_topbar.py | 20 -- source/blender/blenloader/intern/writefile.c | 11 +- source/blender/editors/CMakeLists.txt | 1 + source/blender/editors/include/ED_screen.h | 3 - source/blender/editors/include/ED_space_api.h | 1 + source/blender/editors/screen/area.c | 27 ++- source/blender/editors/screen/screen_edit.c | 209 +++++++++++---------- source/blender/editors/screen/screen_intern.h | 4 +- source/blender/editors/screen/screen_ops.c | 57 +++--- .../blender/editors/screen/workspace_layout_edit.c | 10 +- source/blender/editors/space_api/spacetypes.c | 3 +- .../blender/editors/space_statusbar/CMakeLists.txt | 45 +++++ .../editors/space_statusbar/space_statusbar.c | 200 ++++++++++++++++++++ source/blender/makesdna/DNA_screen_types.h | 9 +- source/blender/makesdna/DNA_space_types.h | 23 ++- source/blender/makesrna/intern/rna_screen.c | 4 +- source/blender/makesrna/intern/rna_space.c | 7 +- source/blender/windowmanager/WM_api.h | 4 +- source/blender/windowmanager/intern/wm_window.c | 39 +++- 22 files changed, 568 insertions(+), 195 deletions(-) create mode 100644 release/scripts/startup/bl_ui/space_statusbar.py create mode 100644 source/blender/editors/space_statusbar/CMakeLists.txt create mode 100644 source/blender/editors/space_statusbar/space_statusbar.c diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index 3bb435fa892..a38a6805274 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -581,6 +581,7 @@ function(SETUP_BLENDER_SORTED_LIBS) bf_editor_space_outliner bf_editor_space_script bf_editor_space_sequencer + bf_editor_space_statusbar bf_editor_space_text bf_editor_space_time bf_editor_space_topbar diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py index 0de0e8ad72d..dd99195f12a 100644 --- a/release/scripts/startup/bl_ui/__init__.py +++ b/release/scripts/startup/bl_ui/__init__.py @@ -81,6 +81,7 @@ _modules = [ "space_outliner", "space_properties", "space_sequencer", + "space_statusbar", "space_text", "space_time", "space_topbar", diff --git a/release/scripts/startup/bl_ui/space_statusbar.py b/release/scripts/startup/bl_ui/space_statusbar.py new file mode 100644 index 00000000000..983b474d18b --- /dev/null +++ b/release/scripts/startup/bl_ui/space_statusbar.py @@ -0,0 +1,84 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# +import bpy +from bpy.types import Header + + +class STATUSBAR_HT_header(Header): + bl_space_type = 'STATUSBAR' + + def draw(self, context): + area = context.area + region = context.region + + if region.alignment == 'RIGHT': + if region == area.regions[0]: + self.draw_right(context) + else: + self.draw_center(context) + else: + self.draw_left(context) + + def draw_left(self, context): + layout = self.layout + + row = layout.row(align=True) + if (bpy.data.filepath): + row.label(text=bpy.data.filepath, translate=False) + if bpy.data.is_dirty: + row.label("(Modified)") + + def draw_center(self, context): + layout = self.layout + + scene = context.scene + view_layer = context.view_layer + + layout.label(text=scene.statistics(view_layer), translate=False) + + def draw_right(self, context): + layout = self.layout + + layout.template_running_jobs() + layout.template_reports_banner() + + row = layout.row(align=True) + if bpy.app.autoexec_fail is True and bpy.app.autoexec_fail_quiet is False: + row.label("Auto-run disabled", icon='ERROR') + if bpy.data.is_saved: + props = row.operator("wm.revert_mainfile", icon='SCREEN_BACK', text="Reload Trusted") + props.use_scripts = True + + row.operator("script.autoexec_warn_clear", text="Ignore") + + # include last so text doesn't push buttons out of the header + row.label(bpy.app.autoexec_fail_message) + return + + + +classes = ( + STATUSBAR_HT_header, +) + +if __name__ == "__main__": # only for live edit. + from bpy.utils import register_class + for cls in classes: + register_class(cls) diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py index 1c4e5493e24..4eabf2bf327 100644 --- a/release/scripts/startup/bl_ui/space_topbar.py +++ b/release/scripts/startup/bl_ui/space_topbar.py @@ -57,26 +57,6 @@ class TOPBAR_HT_upper_bar(Header): text="Back to Previous", ) - layout.separator() - - layout.template_running_jobs() - - layout.template_reports_banner() - - row = layout.row(align=True) - - if bpy.app.autoexec_fail is True and bpy.app.autoexec_fail_quiet is False: - row.label("Auto-run disabled", icon='ERROR') - if bpy.data.is_saved: - props = row.operator("wm.revert_mainfile", icon='SCREEN_BACK', text="Reload Trusted") - props.use_scripts = True - - row.operator("script.autoexec_warn_clear", text="Ignore") - - # include last so text doesn't push buttons out of the header - row.label(bpy.app.autoexec_fail_message) - return - def draw_right(self, context): layout = self.layout diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index d94fe790c9d..f3042dc84db 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2879,10 +2879,13 @@ static void write_area_regions(WriteData *wd, ScrArea *area) } writestruct(wd, DATA, SpaceConsole, 1, sl); } -#ifdef WITH_TOPBAR_WRITING +#ifdef WITH_GLOBAL_AREA_WRITING else if (sl->spacetype == SPACE_TOPBAR) { writestruct(wd, DATA, SpaceTopBar, 1, sl); } + else if (sl->spacetype == SPACE_STATUSBAR) { + writestruct(wd, DATA, SpaceStatusBar, 1, sl); + } #endif else if (sl->spacetype == SPACE_USERPREF) { writestruct(wd, DATA, SpaceUserPref, 1, sl); @@ -2905,7 +2908,7 @@ static void write_area_map(WriteData *wd, ScrAreaMap *area_map) writestruct(wd, DATA, ScrArea, 1, area); -#ifdef WITH_TOPBAR_WRITING +#ifdef WITH_GLOBAL_AREA_WRITING writestruct(wd, DATA, ScrGlobalAreaData, 1, area->global); #endif @@ -2921,7 +2924,7 @@ static void write_windowmanager(WriteData *wd, wmWindowManager *wm) write_iddata(wd, &wm->id); for (wmWindow *win = wm->windows.first; win; win = win->next) { -#ifndef WITH_TOPBAR_WRITING +#ifndef WITH_GLOBAL_AREA_WRITING /* Don't write global areas yet, while we make changes to them. */ ScrAreaMap global_areas = win->global_areas; memset(&win->global_areas, 0, sizeof(win->global_areas)); @@ -2934,7 +2937,7 @@ static void write_windowmanager(WriteData *wd, wmWindowManager *wm) writestruct(wd, DATA, WorkSpaceInstanceHook, 1, win->workspace_hook); writestruct(wd, DATA, Stereo3dFormat, 1, win->stereo3d_format); -#ifdef WITH_TOPBAR_WRITING +#ifdef WITH_GLOBAL_AREA_WRITING write_area_map(wd, &win->global_areas); #else win->global_areas = global_areas; diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt index 358f82499c2..2b30382f4a4 100644 --- a/source/blender/editors/CMakeLists.txt +++ b/source/blender/editors/CMakeLists.txt @@ -54,6 +54,7 @@ if(WITH_BLENDER) add_subdirectory(space_outliner) add_subdirectory(space_script) add_subdirectory(space_sequencer) + add_subdirectory(space_statusbar) add_subdirectory(space_text) add_subdirectory(space_topbar) add_subdirectory(space_userpref) diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index c30aaf8df0a..749d1347eb3 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -119,9 +119,6 @@ int ED_area_header_switchbutton(const struct bContext *C, struct uiBlock *bl void ED_area_initialize(struct wmWindowManager *wm, struct wmWindow *win, struct ScrArea *sa); void ED_area_exit(struct bContext *C, struct ScrArea *sa); int ED_screen_area_active(const struct bContext *C); -void ED_screen_global_topbar_area_create( - struct wmWindow *win, - const struct bScreen *screen); void ED_screen_global_areas_create( struct wmWindow *win); void ED_area_do_listen(struct bScreen *sc, ScrArea *sa, struct wmNotifier *note, Scene *scene, diff --git a/source/blender/editors/include/ED_space_api.h b/source/blender/editors/include/ED_space_api.h index 0cb23514867..77539bff252 100644 --- a/source/blender/editors/include/ED_space_api.h +++ b/source/blender/editors/include/ED_space_api.h @@ -57,6 +57,7 @@ void ED_spacetype_logic(void); void ED_spacetype_console(void); void ED_spacetype_userpref(void); void ED_spacetype_clip(void); +void ED_spacetype_statusbar(void); void ED_spacetype_topbar(void); /* calls for instancing and freeing spacetype static data diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index dc5c9be04c8..e8192c4ce90 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -1259,7 +1259,7 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti region_rect_recursive(win, sa, ar->next, remainder, overlap_remainder, quad); } -static void area_calc_totrct(ScrArea *sa, int window_size_x, int window_size_y) +static void area_calc_totrct(ScrArea *sa, const rcti *window_rect) { short px = (short)U.pixelsize; @@ -1269,16 +1269,16 @@ static void area_calc_totrct(ScrArea *sa, int window_size_x, int window_size_y) sa->totrct.ymax = sa->v2->vec.y; /* scale down totrct by 1 pixel on all sides not matching window borders */ - if (sa->totrct.xmin > 0) { + if (sa->totrct.xmin > window_rect->xmin) { sa->totrct.xmin += px; } - if (sa->totrct.xmax < (window_size_x - 1)) { + if (sa->totrct.xmax < (window_rect->xmax - 1)) { sa->totrct.xmax -= px; } - if (sa->totrct.ymin > 0) { + if (sa->totrct.ymin > window_rect->ymin) { sa->totrct.ymin += px; } - if (sa->totrct.ymax < (window_size_y - 1)) { + if (sa->totrct.ymax < (window_rect->ymax - 1)) { sa->totrct.ymax -= px; } /* Although the following asserts are correct they lead to a very unstable Blender. @@ -1373,15 +1373,15 @@ static void ed_default_handlers(wmWindowManager *wm, ScrArea *sa, ListBase *hand void ED_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, ScrArea *area) { + rcti rect, overlap_rect; + rcti window_rect; + if (!(area->flag & AREA_FLAG_REGION_SIZE_UPDATE)) { return; } - const int size_x = WM_window_pixels_x(win); - const int size_y = WM_window_pixels_y(win); - rcti rect, overlap_rect; - - area_calc_totrct(area, size_x, size_y); + WM_window_rect_calc(win, &window_rect); + area_calc_totrct(area, &window_rect); /* region rect sizes */ rect = area->totrct; @@ -1406,15 +1406,14 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa) WorkSpace *workspace = WM_window_get_active_workspace(win); const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook); Scene *scene = WM_window_get_active_scene(win); - - const int window_size_x = WM_window_pixels_x(win); - const int window_size_y = WM_window_pixels_y(win); ARegion *ar; rcti rect, overlap_rect; + rcti window_rect; if (ED_area_is_global(sa) && (sa->global->flag & GLOBAL_AREA_IS_HIDDEN)) { return; } + WM_window_rect_calc(win, &window_rect); /* set typedefinitions */ sa->type = BKE_spacetype_from_id(sa->spacetype); @@ -1428,7 +1427,7 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa) ar->type = BKE_regiontype_from_id(sa->type, ar->regiontype); /* area sizes */ - area_calc_totrct(sa, window_size_x, window_size_y); + area_calc_totrct(sa, &window_rect); /* region rect sizes */ rect = sa->totrct; diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 4208f3f6233..c7578741d24 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -111,10 +111,12 @@ bool scredge_is_horizontal(ScrEdge *se) return (se->v1->vec.y == se->v2->vec.y); } -/* need win size to make sure not to include edges along screen edge */ +/** + * \param bounds_rect: Either window or screen bounds. Used to exclude edges along window/screen edges. + */ ScrEdge *screen_area_map_find_active_scredge( const ScrAreaMap *area_map, - const int winsize_x, const int winsize_y, + const rcti *bounds_rect, const int mx, const int my) { int safety = U.widget_unit / 10; @@ -123,7 +125,7 @@ ScrEdge *screen_area_map_find_active_scredge( for (ScrEdge *se = area_map->edgebase.first; se; se = se->next) { if (scredge_is_horizontal(se)) { - if (se->v1->vec.y > 0 && se->v1->vec.y < winsize_y - 1) { + if ((se->v1->vec.y > bounds_rect->ymin) && (se->v1->vec.y < (bounds_rect->ymax - 1))) { short min, max; min = MIN2(se->v1->vec.x, se->v2->vec.x); max = MAX2(se->v1->vec.x, se->v2->vec.x); @@ -133,7 +135,7 @@ ScrEdge *screen_area_map_find_active_scredge( } } else { - if (se->v1->vec.x > 0 && se->v1->vec.x < winsize_x - 1) { + if ((se->v1->vec.x > bounds_rect->xmin) && (se->v1->vec.x < (bounds_rect->xmax - 1))) { short min, max; min = MIN2(se->v1->vec.y, se->v2->vec.y); max = MAX2(se->v1->vec.y, se->v2->vec.y); @@ -153,13 +155,17 @@ ScrEdge *screen_find_active_scredge( const int mx, const int my) { /* Use layout size (screen excluding global areas) for screen-layout area edges */ - const int screen_x = WM_window_screen_pixels_x(win), screen_y = WM_window_screen_pixels_y(win); - ScrEdge *se = screen_area_map_find_active_scredge(AREAMAP_FROM_SCREEN(screen), screen_x, screen_y, mx, my); + rcti screen_rect; + ScrEdge *se; + + WM_window_screen_rect_calc(win, &screen_rect); + se = screen_area_map_find_active_scredge(AREAMAP_FROM_SCREEN(screen), &screen_rect, mx, my); if (!se) { /* Use entire window size (screen including global areas) for global area edges */ - const int win_x = WM_window_pixels_x(win), win_y = WM_window_pixels_y(win); - se = screen_area_map_find_active_scredge(&win->global_areas, win_x, win_y, mx, my); + rcti win_rect; + WM_window_rect_calc(win, &win_rect); + se = screen_area_map_find_active_scredge(&win->global_areas, &win_rect, mx, my); } return se; } @@ -334,7 +340,7 @@ ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge) /** * Empty screen, with 1 dummy area without spacedata. Uses window size. */ -bScreen *screen_add(const char *name, const int winsize_x, const int winsize_y) +bScreen *screen_add(const char *name, const rcti *rect) { bScreen *sc; ScrVert *sv1, *sv2, *sv3, *sv4; @@ -343,10 +349,10 @@ bScreen *screen_add(const char *name, const int winsize_x, const int winsize_y) sc->do_refresh = true; sc->redraws_flag = TIME_ALL_3D_WIN | TIME_ALL_ANIM_WIN; - sv1 = screen_addvert(sc, 0, 0); - sv2 = screen_addvert(sc, 0, winsize_y - 1); - sv3 = screen_addvert(sc, winsize_x - 1, winsize_y - 1); - sv4 = screen_addvert(sc, winsize_x - 1, 0); + sv1 = screen_addvert(sc, rect->xmin, rect->ymin); + sv2 = screen_addvert(sc, rect->xmin, rect->ymax - 1); + sv3 = screen_addvert(sc, rect->xmax - 1, rect->ymax - 1); + sv4 = screen_addvert(sc, rect->xmax - 1, rect->ymin); screen_addedge(sc, sv1, sv2); screen_addedge(sc, sv2, sv3); @@ -546,34 +552,29 @@ void select_connected_scredge(const wmWindow *win, ScrEdge *edge) */ static void screen_vertices_scale( const wmWindow *win, bScreen *sc, - int window_size_x, int window_size_y, - int screen_size_x, int screen_size_y) + const rcti *window_rect, const rcti *screen_rect) { /* clamp Y size of header sized areas when expanding windows * avoids annoying empty space around file menu */ #define USE_HEADER_SIZE_CLAMP const int headery_init = ED_area_headersize(); + const int screen_size_x = BLI_rcti_size_x(screen_rect); + const int screen_size_y = BLI_rcti_size_y(screen_rect); ScrVert *sv = NULL; ScrArea *sa; int screen_size_x_prev, screen_size_y_prev; - float facx, facy, tempf, min[2], max[2]; - + float min[2], max[2]; + /* calculate size */ min[0] = min[1] = 20000.0f; max[0] = max[1] = 0.0f; - + for (sv = sc->vertbase.first; sv; sv = sv->next) { const float fv[2] = {(float)sv->vec.x, (float)sv->vec.y}; minmax_v2v2_v2(min, max, fv); } - - /* always make 0.0 left under */ - for (sv = sc->vertbase.first; sv; sv = sv->next) { - sv->vec.x -= min[0]; - sv->vec.y -= min[1]; - } - + screen_size_x_prev = (max[0] - min[0]) + 1; screen_size_y_prev = (max[1] - min[1]) + 1; @@ -590,12 +591,12 @@ static void screen_vertices_scale( sa->temp = 0; if (ar && !(ar->flag & RGN_FLAG_HIDDEN)) { - if (sa->v2->vec.y == screen_size_y_prev) { + if (sa->v2->vec.y == max[1]) { if ((sa->v2->vec.y - sa->v1->vec.y) < headery_margin_max) { sa->temp = TEMP_TOP; } } - else if (sa->v1->vec.y == 0) { + else if (sa->v1->vec.y == min[1]) { if ((sa->v2->vec.y - sa->v1->vec.y) < headery_margin_max) { sa->temp = TEMP_BOTTOM; } @@ -607,26 +608,16 @@ static void screen_vertices_scale( if (screen_size_x_prev != screen_size_x || screen_size_y_prev != screen_size_y) { - facx = ((float)screen_size_x - 1) / ((float)screen_size_x_prev - 1); - facy = ((float)screen_size_y) / ((float)screen_size_y_prev); - + const float facx = ((float)screen_size_x - 1) / ((float)screen_size_x_prev - 1); + const float facy = ((float)screen_size_y) / ((float)screen_size_y_prev); + /* make sure it fits! */ for (sv = sc->vertbase.first; sv; sv = sv->next) { - /* FIXME, this re-sizing logic is no good when re-sizing the window + redrawing [#24428] - * need some way to store these as floats internally and re-apply from there. */ - tempf = ((float)sv->vec.x) * facx; - sv->vec.x = (short)(tempf + 0.5f); - //sv->vec.x += AREAGRID - 1; - //sv->vec.x -= (sv->vec.x % AREAGRID); - - CLAMP(sv->vec.x, 0, screen_size_x - 1); - - tempf = ((float)sv->vec.y) * facy; - sv->vec.y = (short)(tempf + 0.5f); - //sv->vec.y += AREAGRID - 1; - //sv->vec.y -= (sv->vec.y % AREAGRID); + sv->vec.x = screen_rect->xmin + round_fl_to_short((sv->vec.x - min[0]) * facx); + CLAMP(sv->vec.x, screen_rect->xmin, screen_rect->xmax - 1); - CLAMP(sv->vec.y, 0, screen_size_y); + sv->vec.y = screen_rect->ymin + round_fl_to_short((sv->vec.y - min[1]) * facy); + CLAMP(sv->vec.y, screen_rect->ymin, screen_rect->ymax); } } @@ -688,23 +679,22 @@ static void screen_vertices_scale( /* make each window at least ED_area_headersize() high */ for (sa = sc->areabase.first; sa; sa = sa->next) { int headery = headery_init; - + /* adjust headery if verts are along the edge of window */ - if (sa->v1->vec.y > 0) + if (sa->v1->vec.y > window_rect->ymin) headery += U.pixelsize; - if (sa->v2->vec.y < screen_size_y) + if (sa->v2->vec.y < window_rect->ymax) headery += U.pixelsize; - + if (sa->v2->vec.y - sa->v1->vec.y + 1 < headery) { /* lower edge */ ScrEdge *se = BKE_screen_find_edge(sc, sa->v4, sa->v1); if (se && sa->v1 != sa->v2) { - int yval; - + const int yval = sa->v2->vec.y - headery + 1; + select_connected_scredge(win, se); - + /* all selected vertices get the right offset */ - yval = sa->v2->vec.y - headery + 1; for (sv = sc->vertbase.first; sv; sv = sv->next) { /* if is a collapsed area */ if (sv != sa->v2 && sv != sa->v3) { @@ -717,18 +707,25 @@ static void screen_vertices_scale( } } - /* Global areas have a fixed size that only changes with the DPI. Here we ensure that exactly this size is set. - * TODO Assumes global area to be top-aligned. Should be made more generic */ + /* Global areas have a fixed size that only changes with the DPI. Here we ensure that exactly this size is set. */ for (ScrArea *area = win->global_areas.areabase.first; area; area = area->next) { if (area->global->flag & GLOBAL_AREA_IS_HIDDEN) { continue; } /* width */ - area->v1->vec.x = area->v2->vec.x = 0; - area->v3->vec.x = area->v4->vec.x = window_size_x - 1; + area->v1->vec.x = area->v2->vec.x = window_rect->xmin; + area->v3->vec.x = area->v4->vec.x = window_rect->xmax - 1; /* height */ - area->v2->vec.y = area->v3->vec.y = window_size_y - 1; - area->v1->vec.y = area->v4->vec.y = area->v2->vec.y - ED_area_global_size_y(area); + area->v1->vec.y = area->v4->vec.y = window_rect->ymin; + area->v2->vec.y = area->v3->vec.y = window_rect->ymax - 1; + switch (area->global->align) { + case GLOBAL_AREA_ALIGN_TOP: + area->v1->vec.y = area->v4->vec.y = area->v2->vec.y - ED_area_global_size_y(area); + break; + case GLOBAL_AREA_ALIGN_BOTTOM: + area->v2->vec.y = area->v3->vec.y = area->v1->vec.y + ED_area_global_size_y(area); + break; + } } } @@ -802,18 +799,16 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win) /* exception for bg mode, we only need the screen context */ if (!G.background) { - WM_window_set_dpi(win); - - /* Get window pixels __after__ updating window DPI! */ - const int window_size_x = WM_window_pixels_x(win); - const int window_size_y = WM_window_pixels_y(win); - const int screen_size_x = WM_window_screen_pixels_x(win); - const int screen_size_y = WM_window_screen_pixels_y(win); + rcti window_rect, screen_rect; /* header size depends on DPI, let's verify */ + WM_window_set_dpi(win); screen_refresh_headersizes(); - screen_vertices_scale(win, screen, window_size_x, window_size_y, screen_size_x, screen_size_y); + WM_window_rect_calc(win, &window_rect); + WM_window_screen_rect_calc(win, &screen_rect); /* Get screen bounds __after__ updating window DPI! */ + + screen_vertices_scale(win, screen, &window_rect, &screen_rect); ED_screen_areas_iter(win, screen, area) { /* set spacetype and region callbacks, calls init() */ @@ -921,8 +916,6 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen) { wmWindowManager *wm = CTX_wm_manager(C); wmWindow *prevwin = CTX_wm_window(C); - ScrArea *sa; - ARegion *ar; CTX_wm_window_set(C, window); @@ -933,13 +926,14 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen) screen->active_region = NULL; - for (ar = screen->regionbase.first; ar; ar = ar->next) { + for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) { ED_region_exit(C, ar); } - for (sa = screen->areabase.first; sa; sa = sa->next) { + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { ED_area_exit(C, sa); } - for (sa = window->global_areas.areabase.first; sa; sa = sa->next) { + /* Don't use ED_screen_areas_iter here, it skips hidden areas. */ + for (ScrArea *sa = window->global_areas.areabase.first; sa; sa = sa->next) { ED_area_exit(C, sa); } @@ -1113,39 +1107,56 @@ static ScrArea *screen_area_create_with_geometry( return screen_addarea_ex(area_map, bottom_left, top_left, top_right, bottom_right, spacetype); } -void ED_screen_global_topbar_area_create(wmWindow *win, const bScreen *screen) +static void screen_global_area_create( + wmWindow *win, eSpace_Type space_type, GlobalAreaAlign align, const rcti *rect, + const short height_cur, const short height_min, const short height_max) { - if (screen->temp == 0) { - const short size_y = 2.25 * HEADERY; - SpaceType *st; - SpaceLink *sl; - ScrArea *sa; - rcti rect; - - BLI_rcti_init(&rect, 0, WM_window_pixels_x(win) - 1, 0, WM_window_pixels_y(win) - 1); - rect.ymin = rect.ymax - size_y; - - sa = screen_area_create_with_geometry(&win->global_areas, &rect, SPACE_TOPBAR); - st = BKE_spacetype_from_id(SPACE_TOPBAR); - sl = st->new(sa, WM_window_get_active_scene(win)); - sa->regionbase = sl->regionbase; - - /* Data specific to global areas. */ - sa->global = MEM_callocN(sizeof(*sa->global), __func__); - sa->global->cur_fixed_height = size_y; - sa->global->size_max = size_y; - sa->global->size_min = HEADERY; - - BLI_addhead(&sa->spacedata, sl); - BLI_listbase_clear(&sl->regionbase); - } - /* Do not create more area types here! Function is called on file load (wm_window_ghostwindows_ensure). TODO */ + ScrArea *area = screen_area_create_with_geometry(&win->global_areas, rect, space_type); + SpaceType *stype = BKE_spacetype_from_id(space_type); + SpaceLink *slink = stype->new(area, WM_window_get_active_scene(win)); + + area->regionbase = slink->regionbase; + + /* Data specific to global areas. */ + area->global = MEM_callocN(sizeof(*area->global), __func__); + area->global->cur_fixed_height = height_cur; + area->global->size_max = height_max; + area->global->size_min = height_min; + area->global->align = align; + + BLI_addhead(&area->spacedata, slink); + BLI_listbase_clear(&slink->regionbase); +} + +static void screen_global_topbar_area_create(wmWindow *win) +{ + const short size_y = 2.25 * HEADERY; + rcti rect; + + BLI_rcti_init(&rect, 0, WM_window_pixels_x(win) - 1, 0, WM_window_pixels_y(win) - 1); + rect.ymin = rect.ymax - size_y; + + screen_global_area_create(win, SPACE_TOPBAR, GLOBAL_AREA_ALIGN_TOP, &rect, size_y, HEADERY, size_y); +} + +static void screen_global_statusbar_area_create(wmWindow *win) +{ + const short size_y = HEADERY; + rcti rect; + + BLI_rcti_init(&rect, 0, WM_window_pixels_x(win) - 1, 0, WM_window_pixels_y(win) - 1); + rect.ymax = rect.ymin + size_y; + + screen_global_area_create(win, SPACE_STATUSBAR, GLOBAL_AREA_ALIGN_BOTTOM, &rect, size_y, size_y, size_y); } void ED_screen_global_areas_create(wmWindow *win) { - const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook); - ED_screen_global_topbar_area_create(win, screen); + bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook); + if (screen->temp == 0) { + screen_global_topbar_area_create(win); + screen_global_statusbar_area_create(win); + } } diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h index 045e5ee6b48..b54a5e04571 100644 --- a/source/blender/editors/screen/screen_intern.h +++ b/source/blender/editors/screen/screen_intern.h @@ -48,7 +48,7 @@ void screen_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, void region_toggle_hidden(struct bContext *C, ARegion *ar, const bool do_fade); /* screen_edit.c */ -bScreen *screen_add(const char *name, const int winsize_x, const int winsize_y); +bScreen *screen_add(const char *name, const rcti *rect); void screen_data_copy(bScreen *to, bScreen *from); void screen_new_activate_prepare(const wmWindow *win, bScreen *screen_new); void screen_change_update(struct bContext *C, wmWindow *win, bScreen *sc); @@ -61,7 +61,7 @@ void select_connected_scredge(const wmWindow *win, ScrEdge *edge); bool scredge_is_horizontal(ScrEdge *se); ScrEdge *screen_area_map_find_active_scredge( const struct ScrAreaMap *area_map, - const int winsize_x, const int winsize_y, + const rcti *bounds_rect, const int mx, const int my); ScrEdge *screen_find_active_scredge( const wmWindow *win, const bScreen *screen, diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 0c13ac03d1b..2063191658b 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -842,11 +842,8 @@ static int actionzone_invoke(bContext *C, wmOperator *op, const wmEvent *event) static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event) { - wmWindow *win = CTX_wm_window(C); bScreen *sc = CTX_wm_screen(C); sActionzoneData *sad = op->customdata; - const int screen_size_x = WM_window_screen_pixels_x(win); - const int screen_size_y = WM_window_screen_pixels_y(win); switch (event->type) { case MOUSEMOVE: @@ -867,11 +864,15 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event) sad->gesture_dir = 'w'; if (sad->az->type == AZONE_AREA) { + const wmWindow *win = CTX_wm_window(C); + rcti screen_rect; + + WM_window_screen_rect_calc(win, &screen_rect); /* once we drag outside the actionzone, register a gesture * check we're not on an edge so join finds the other area */ is_gesture = ((is_in_area_actionzone(sad->sa1, &event->x) != sad->az) && (screen_area_map_find_active_scredge( - AREAMAP_FROM_SCREEN(sc), screen_size_x, screen_size_y, event->x, event->y) == NULL)); + AREAMAP_FROM_SCREEN(sc), &screen_rect, event->x, event->y) == NULL)); } else { const int delta_min = 1; @@ -1186,10 +1187,10 @@ typedef struct sAreaMoveData { } sAreaMoveData; /* helper call to move area-edge, sets limits - * need window size in order to get correct limits */ + * need window bounds in order to get correct limits */ static void area_move_set_limits( wmWindow *win, bScreen *sc, int dir, - const int winsize_x, const int winsize_y, + const rcti *screen_rect, int *bigger, int *smaller, bool *use_bigger_smaller_snap) { @@ -1242,9 +1243,9 @@ static void area_move_set_limits( int y1; areamin = areaminy; - if (sa->v1->vec.y > 0) + if (sa->v1->vec.y > screen_rect->ymin) areamin += U.pixelsize; - if (sa->v2->vec.y < winsize_y - 1) + if (sa->v2->vec.y < (screen_rect->ymax - 1)) areamin += U.pixelsize; y1 = sa->v2->vec.y - sa->v1->vec.y + 1 - areamin; @@ -1259,9 +1260,9 @@ static void area_move_set_limits( int x1; areamin = AREAMINX; - if (sa->v1->vec.x > 0) + if (sa->v1->vec.x > screen_rect->xmin) areamin += U.pixelsize; - if (sa->v4->vec.x < winsize_x - 1) + if (sa->v4->vec.x < (screen_rect->xmax - 1)) areamin += U.pixelsize; x1 = sa->v4->vec.x - sa->v1->vec.x + 1 - areamin; @@ -1283,8 +1284,7 @@ static int area_move_init(bContext *C, wmOperator *op) wmWindow *win = CTX_wm_window(C); ScrEdge *actedge; sAreaMoveData *md; - const int screen_size_x = WM_window_screen_pixels_x(win); - const int screen_size_y = WM_window_screen_pixels_y(win); + rcti screen_rect; int x, y; /* required properties */ @@ -1308,8 +1308,10 @@ static int area_move_init(bContext *C, wmOperator *op) v1->editflag = v1->flag; } + WM_window_screen_rect_calc(win, &screen_rect); + bool use_bigger_smaller_snap = false; - area_move_set_limits(win, sc, md->dir, screen_size_x, screen_size_y, + area_move_set_limits(win, sc, md->dir, &screen_rect, &md->bigger, &md->smaller, &use_bigger_smaller_snap); @@ -1772,14 +1774,15 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event) wmWindow *win = CTX_wm_window(C); bScreen *sc = CTX_wm_screen(C); sAreaSplitData *sd; - const int screen_size_x = WM_window_screen_pixels_x(win); - const int screen_size_y = WM_window_screen_pixels_y(win); + rcti screen_rect; int dir; /* no full window splitting allowed */ if (sc->state != SCREENNORMAL) return OPERATOR_CANCELLED; - + + WM_window_screen_rect_calc(win, &screen_rect); + if (event->type == EVT_ACTIONZONE_AREA) { sActionzoneData *sad = event->customdata; @@ -1825,8 +1828,8 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event) y = RNA_int_get(op->ptr, "mouse_y"); else y = event->x; - - actedge = screen_area_map_find_active_scredge(AREAMAP_FROM_SCREEN(sc), screen_size_x, screen_size_y, x, y); + + actedge = screen_area_map_find_active_scredge(AREAMAP_FROM_SCREEN(sc), &screen_rect, x, y); if (actedge == NULL) return OPERATOR_CANCELLED; @@ -1846,8 +1849,8 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event) /* do the split */ if (area_split_apply(C, op)) { - area_move_set_limits(win, sc, dir, screen_size_x, screen_size_y, &sd->bigger, &sd->smaller, NULL); - + area_move_set_limits(win, sc, dir, &screen_rect, &sd->bigger, &sd->smaller, NULL); + /* add temp handler for edge move or cancel */ WM_event_add_modal_handler(C, op); @@ -2731,7 +2734,8 @@ static int screen_maximize_area_poll(bContext *C) const bScreen *screen = CTX_wm_screen(C); const ScrArea *area = CTX_wm_area(C); return ED_operator_areaactive(C) && - ((screen->state != SCREENNORMAL) || (area->spacetype != SPACE_TOPBAR)); + /* Don't allow maximizing global areas but allow minimizing from them. */ + ((screen->state != SCREENNORMAL) || !ED_area_is_global(area)); } static void SCREEN_OT_screen_full_area(wmOperatorType *ot) @@ -3047,17 +3051,16 @@ static void SCREEN_OT_area_join(wmOperatorType *ot) static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - wmWindow *win = CTX_wm_window(C); - bScreen *sc = CTX_wm_screen(C); + const wmWindow *win = CTX_wm_window(C); + const bScreen *sc = CTX_wm_screen(C); uiPopupMenu *pup; uiLayout *layout; PointerRNA ptr; ScrEdge *actedge; - const int screen_size_x = WM_window_screen_pixels_x(win); - const int screen_size_y = WM_window_screen_pixels_y(win); + rcti screen_rect; - actedge = screen_area_map_find_active_scredge( - AREAMAP_FROM_SCREEN(sc), screen_size_x, screen_size_y, event->x, event->y); + WM_window_screen_rect_calc(win, &screen_rect); + actedge = screen_area_map_find_active_scredge(AREAMAP_FROM_SCREEN(sc), &screen_rect, event->x, event->y); if (actedge == NULL) return OPERATOR_CANCELLED; diff --git a/source/blender/editors/screen/workspace_layout_edit.c b/source/blender/editors/screen/workspace_layout_edit.c index a6f991d4bbe..6285f031836 100644 --- a/source/blender/editors/screen/workspace_layout_edit.c +++ b/source/blender/editors/screen/workspace_layout_edit.c @@ -50,13 +50,13 @@ WorkSpaceLayout *ED_workspace_layout_add( wmWindow *win, const char *name) { - const int screen_size_x = WM_window_screen_pixels_x(win); - const int screen_size_y = WM_window_screen_pixels_y(win); + bScreen *screen; + rcti screen_rect; - bScreen *screen = screen_add(name, screen_size_x, screen_size_y); - WorkSpaceLayout *layout = BKE_workspace_layout_add(workspace, screen, name); + WM_window_screen_rect_calc(win, &screen_rect); + screen = screen_add(name, &screen_rect); - return layout; + return BKE_workspace_layout_add(workspace, screen, name); } WorkSpaceLayout *ED_workspace_layout_duplicate( diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 12f16f1fe42..4d4bcf4dffc 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -97,9 +97,10 @@ void ED_spacetypes_init(void) ED_spacetype_console(); ED_spacetype_userpref(); ED_spacetype_clip(); + ED_spacetype_statusbar(); ED_spacetype_topbar(); // ... - + /* register operator types for screen and all spaces */ ED_operatortypes_workspace(); ED_operatortypes_scene(); diff --git a/source/blender/editors/space_statusbar/CMakeLists.txt b/source/blender/editors/space_statusbar/CMakeLists.txt new file mode 100644 index 00000000000..31439942397 --- /dev/null +++ b/source/blender/editors/space_statusbar/CMakeLists.txt @@ -0,0 +1,45 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# Contributor(s): Jacques Beaurain. +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + ../include + ../../blenkernel + ../../blenlib + ../../blenloader + ../../blentranslation + ../../gpu + ../../makesdna + ../../makesrna + ../../windowmanager + ../../../../intern/guardedalloc + ../../../../intern/glew-mx +) + +set(INC_SYS + ${GLEW_INCLUDE_PATH} +) + +set(SRC + space_statusbar.c +) + +add_definitions(${GL_DEFINITIONS}) + +blender_add_lib(bf_editor_space_statusbar "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/space_statusbar/space_statusbar.c b/source/blender/editors/space_statusbar/space_statusbar.c new file mode 100644 index 00000000000..4c6a2eea469 --- /dev/null +++ b/source/blender/editors/space_statusbar/space_statusbar.c @@ -0,0 +1,200 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_statusbar/space_statusbar.c + * \ingroup spstatusbar + */ + + +#include +#include + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" + +#include "BKE_context.h" +#include "BKE_screen.h" + +#include "ED_screen.h" +#include "ED_space_api.h" + +#include "RNA_access.h" + +#include "UI_interface.h" +#include "UI_view2d.h" + +#include "WM_api.h" +#include "WM_types.h" +#include "WM_message.h" + + +/* ******************** default callbacks for statusbar space ******************** */ + +static SpaceLink *statusbar_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) +{ + ARegion *ar; + SpaceStatusBar *sstatusbar; + + sstatusbar = MEM_callocN(sizeof(*sstatusbar), "init statusbar"); + sstatusbar->spacetype = SPACE_STATUSBAR; + + /* header regions */ + /* *** NOTE: *** + * Python layout code (space_statusbar.py) depends on the list order of + * these! Not nice at all, but the only way to identify the correct header + * to draw to is using alignment + list position. It can't use alignment + * only since code below has to set two right aligned regions - XXX. */ + ar = MEM_callocN(sizeof(*ar), "right aligned header for statusbar"); + BLI_addtail(&sstatusbar->regionbase, ar); + ar->regiontype = RGN_TYPE_HEADER; + ar->alignment = RGN_ALIGN_RIGHT; + ar = MEM_callocN(sizeof(*ar), "center header for statusbar"); + BLI_addtail(&sstatusbar->regionbase, ar); + ar->regiontype = RGN_TYPE_HEADER; + ar->alignment = RGN_ALIGN_RIGHT; /* Right aligned too, so region layout code scales it correctly. */ + ar = MEM_callocN(sizeof(*ar), "left aligned header for statusbar"); + BLI_addtail(&sstatusbar->regionbase, ar); + ar->regiontype = RGN_TYPE_HEADER; + ar->alignment = RGN_ALIGN_NONE; + + return (SpaceLink *)sstatusbar; +} + +/* not spacelink itself */ +static void statusbar_free(SpaceLink *UNUSED(sl)) +{ + +} + + +/* spacetype; init callback */ +static void statusbar_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa)) +{ + +} + +static SpaceLink *statusbar_duplicate(SpaceLink *sl) +{ + SpaceStatusBar *sstatusbarn = MEM_dupallocN(sl); + + /* clear or remove stuff from old */ + + return (SpaceLink *)sstatusbarn; +} + + + +/* add handlers, stuff you only do once or on area/region changes */ +static void statusbar_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region) +{ + if (ELEM(region->alignment, RGN_ALIGN_RIGHT)) { + region->flag |= RGN_FLAG_DYNAMIC_SIZE; + } + ED_region_header_init(region); +} + +static void statusbar_operatortypes(void) +{ + +} + +static void statusbar_keymap(struct wmKeyConfig *UNUSED(keyconf)) +{ + +} + +static void statusbar_header_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) +{ + /* context changes */ + switch (wmn->category) { + case NC_SCREEN: + if (ELEM(wmn->data, ND_LAYER, ND_SCREENCAST, ND_ANIMPLAY)) { + ED_region_tag_redraw(ar); + } + break; + case NC_WM: + if (wmn->data == ND_JOB) + ED_region_tag_redraw(ar); + break; + case NC_SCENE: + if (wmn->data == ND_RENDER_RESULT) + ED_region_tag_redraw(ar); + break; + case NC_SPACE: + if (wmn->data == ND_SPACE_INFO) + ED_region_tag_redraw(ar); + break; + case NC_ID: + if (wmn->action == NA_RENAME) + ED_region_tag_redraw(ar); + break; + } +} + +static void statusbar_header_region_message_subscribe( + const bContext *UNUSED(C), + WorkSpace *UNUSED(workspace), Scene *UNUSED(scene), + bScreen *UNUSED(screen), ScrArea *UNUSED(sa), ARegion *ar, + struct wmMsgBus *mbus) +{ + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { + .owner = ar, + .user_data = ar, + .notify = ED_region_do_msg_notify_tag_redraw, + }; + + WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_region_tag_redraw); + WM_msg_subscribe_rna_anon_prop(mbus, ViewLayer, name, &msg_sub_value_region_tag_redraw); +} + +/* only called once, from space/spacetypes.c */ +void ED_spacetype_statusbar(void) +{ + SpaceType *st = MEM_callocN(sizeof(*st), "spacetype statusbar"); + ARegionType *art; + + st->spaceid = SPACE_STATUSBAR; + strncpy(st->name, "Status Bar", BKE_ST_MAXNAME); + + st->new = statusbar_new; + st->free = statusbar_free; + st->init = statusbar_init; + st->duplicate = statusbar_duplicate; + st->operatortypes = statusbar_operatortypes; + st->keymap = statusbar_keymap; + + /* regions: header window */ + art = MEM_callocN(sizeof(*art), "spacetype statusbar header region"); + art->regionid = RGN_TYPE_HEADER; + art->prefsizey = HEADERY; + art->prefsizex = UI_UNIT_X * 5; /* Mainly to avoid glitches */ + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER; + art->init = statusbar_header_region_init; + art->layout = ED_region_header_layout; + art->draw = ED_region_header_draw; + art->listener = statusbar_header_region_listener; + art->message_subscribe = statusbar_header_region_message_subscribe; + BLI_addhead(&st->regiontypes, art); + + BKE_spacetype_register(st); +} diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 1f14bb58e78..ef0dbceef38 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -227,7 +227,7 @@ typedef struct uiPreview { /* some preview UI data need to be saved in } uiPreview; /* These two lines with # tell makesdna this struct can be excluded. - * Should be: #ifndef WITH_TOPBAR_WRITING */ + * Should be: #ifndef WITH_GLOBAL_AREA_WRITING */ # # typedef struct ScrGlobalAreaData { @@ -240,14 +240,21 @@ typedef struct ScrGlobalAreaData { * if they are 'collapsed' or not. Value is set on area creation and not * touched afterwards. */ short size_min, size_max; + short align; /* GlobalAreaAlign */ short flag; /* GlobalAreaFlag */ + short pad; } ScrGlobalAreaData; enum GlobalAreaFlag { GLOBAL_AREA_IS_HIDDEN = (1 << 0), }; +typedef enum GlobalAreaAlign { + GLOBAL_AREA_ALIGN_TOP, + GLOBAL_AREA_ALIGN_BOTTOM, +} GlobalAreaAlign; + typedef struct ScrArea_Runtime { struct bToolRef *tool; char is_tool_set; diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 588d90fae8d..3bc5118c996 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -67,9 +67,9 @@ struct MovieClipScopes; struct Mask; struct BLI_mempool; -/* TODO 2.8: We don't write the topbar to files currently. Uncomment this +/* TODO 2.8: We don't write the global areas to files currently. Uncomment * define to enable writing (should become the default in a bit). */ -//#define WITH_TOPBAR_WRITING +//#define WITH_GLOBAL_AREA_WRITING /* SpaceLink (Base) ==================================== */ @@ -1327,7 +1327,7 @@ typedef enum eSpaceClip_GPencil_Source { /* Top Bar ======================================= */ /* These two lines with # tell makesdna this struct can be excluded. - * Should be: #ifndef WITH_TOPBAR_WRITING */ + * Should be: #ifndef WITH_GLOBAL_AREA_WRITING */ # # typedef struct SpaceTopBar { @@ -1338,6 +1338,20 @@ typedef struct SpaceTopBar { int pad; } SpaceTopBar; +/* Status Bar ======================================= */ + +/* These two lines with # tell makesdna this struct can be excluded. + * Should be: #ifndef WITH_GLOBAL_AREA_WRITING */ +# +# +typedef struct SpaceStatusBar { + SpaceLink *next, *prev; + ListBase regionbase; /* storage of regions for inactive spaces */ + int spacetype; + + int pad; +} SpaceStatusBar; + /* **************** SPACE DEFINES ********************* */ @@ -1369,8 +1383,9 @@ typedef enum eSpace_Type { SPACE_USERPREF = 19, SPACE_CLIP = 20, SPACE_TOPBAR = 21, + SPACE_STATUSBAR = 22, - SPACE_TYPE_LAST = SPACE_TOPBAR + SPACE_TYPE_LAST = SPACE_STATUSBAR } eSpace_Type; /* use for function args */ diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c index 83d8e730e3e..b8c7eff6241 100644 --- a/source/blender/makesrna/intern/rna_screen.c +++ b/source/blender/makesrna/intern/rna_screen.c @@ -145,7 +145,7 @@ static const EnumPropertyItem *rna_Area_type_itemf(bContext *UNUSED(C), PointerR /* +1 to skip SPACE_EMPTY */ for (const EnumPropertyItem *item_from = rna_enum_space_type_items + 1; item_from->identifier; item_from++) { - if (ELEM(item_from->value, SPACE_TOPBAR)) { + if (ELEM(item_from->value, SPACE_TOPBAR, SPACE_STATUSBAR)) { continue; } RNA_enum_item_add(&item, &totitem, item_from); @@ -166,7 +166,7 @@ static int rna_Area_type_get(PointerRNA *ptr) static void rna_Area_type_set(PointerRNA *ptr, int value) { - if (ELEM(value, SPACE_TOPBAR)) { + if (ELEM(value, SPACE_TOPBAR, SPACE_STATUSBAR)) { /* Special case: An area can not be set to show the top-bar editor (or * other global areas). However it should still be possible to identify * its type from Python. */ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index fa4eb2f4962..e555c2ae52a 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -90,8 +90,11 @@ const EnumPropertyItem rna_enum_space_type_items[] = { "advanced editing and script development"}, {SPACE_INFO, "INFO", ICON_INFO, "Info", "Main menu bar and list of error messages " "(drag down to expand and display)"}, - /* Special case: Top-bar isn't supposed to be a regular editor for the user. */ - {SPACE_TOPBAR, "TOPBAR", ICON_NONE, "Top Bar", "Global bar at the top of the screen for global per-window settings"}, + /* Special case: Top-bar and Status-bar aren't supposed to be a regular editor for the user. */ + {SPACE_TOPBAR, "TOPBAR", ICON_NONE, "Top Bar", "Global bar at the top of the screen for " + "global per-window settings"}, + {SPACE_STATUSBAR, "STATUSBAR", ICON_NONE, "Status Bar", "Global bar at the bottom of the " + "screen for general status information"}, /* Data */ {0, "", ICON_NONE, "Data", ""}, diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 9e47179c615..d941ef02ee0 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -102,8 +102,8 @@ void WM_check (struct bContext *C); int WM_window_pixels_x(const struct wmWindow *win); int WM_window_pixels_y(const struct wmWindow *win); -int WM_window_screen_pixels_x(const struct wmWindow *win); -int WM_window_screen_pixels_y(const struct wmWindow *win); +void WM_window_rect_calc(const struct wmWindow *win, struct rcti *r_rect); +void WM_window_screen_rect_calc(const struct wmWindow *win, struct rcti *r_rect); bool WM_window_is_fullscreen(struct wmWindow *win); void WM_windows_scene_data_sync(const ListBase *win_lb, struct Scene *scene) ATTR_NONNULL(); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index ef1e4d24e7f..0c3d2544bb4 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -2135,23 +2135,44 @@ int WM_window_pixels_y(const wmWindow *win) } /** - * Get the total pixels that are usable by the screen-layouts, excluding global areas. + * Get boundaries usable by all window contents, including global areas. */ -int WM_window_screen_pixels_x(const wmWindow *win) +void WM_window_rect_calc(const wmWindow *win, rcti *r_rect) { - return WM_window_pixels_x(win); + BLI_rcti_init(r_rect, 0, WM_window_pixels_x(win), 0, WM_window_pixels_y(win)); } -int WM_window_screen_pixels_y(const wmWindow *win) +/** + * Get boundaries usable by screen-layouts, excluding global areas. + * \note Depends on U.dpi_fac. Should that be outdated, call #WM_window_set_dpi first. + */ +void WM_window_screen_rect_calc(const wmWindow *win, rcti *r_rect) { - short screen_size_y = WM_window_pixels_y(win); + rcti rect; - for (ScrArea *sa = win->global_areas.areabase.first; sa; sa = sa->next) { - if ((sa->global->flag & GLOBAL_AREA_IS_HIDDEN) == 0) { - screen_size_y -= ED_area_global_size_y(sa); + BLI_rcti_init(&rect, 0, WM_window_pixels_x(win), 0, WM_window_pixels_y(win)); + + /* Substract global areas from screen rectangle. */ + for (ScrArea *global_area = win->global_areas.areabase.first; global_area; global_area = global_area->next) { + if (global_area->global->flag & GLOBAL_AREA_IS_HIDDEN) { + continue; + } + + switch (global_area->global->align) { + case GLOBAL_AREA_ALIGN_TOP: + rect.ymax -= ED_area_global_size_y(global_area); + break; + case GLOBAL_AREA_ALIGN_BOTTOM: + rect.ymin += ED_area_global_size_y(global_area); + break; + default: + BLI_assert(0); + break; } } - return screen_size_y; + BLI_assert(rect.xmin < rect.xmax); + BLI_assert(rect.ymin < rect.ymax); + *r_rect = rect; } bool WM_window_is_fullscreen(wmWindow *win) -- cgit v1.2.3