diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-04-29 13:24:08 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-04-29 23:11:12 +0300 |
commit | 7a9f64e6657a231289f56b0a8c9949c8f7a23c59 (patch) | |
tree | efee3c4ac1988ad96d743f1d82e7a677096ca0c3 /source/blender/editors | |
parent | 0c512a6f951e36e29d2f6865cc975f7e40c4d31d (diff) |
UI: better support for dynamically sized regions in topbar.
Dynamically sized regions in the topbar were flickering due to only updating
their size after redraws. Now there is an optional layout() callback for
all regions in an area to do UI layout first, then refresh the region layout,
and then do the actual drawing for each region.
Task T54753
Diffstat (limited to 'source/blender/editors')
-rw-r--r-- | source/blender/editors/include/ED_screen.h | 4 | ||||
-rw-r--r-- | source/blender/editors/include/UI_interface.h | 2 | ||||
-rw-r--r-- | source/blender/editors/interface/interface.c | 63 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_region_popup.c | 2 | ||||
-rw-r--r-- | source/blender/editors/screen/area.c | 107 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_edit.c | 33 | ||||
-rw-r--r-- | source/blender/editors/space_topbar/space_topbar.c | 16 |
7 files changed, 134 insertions, 93 deletions
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index b5f1d947076..a1c429043cc 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -65,6 +65,7 @@ struct wmMsgSubscribeValue; void ED_region_do_listen( struct bScreen *sc, struct ScrArea *sa, struct ARegion *ar, struct wmNotifier *note, const Scene *scene); +void ED_region_do_layout(struct bContext *C, struct ARegion *ar); void ED_region_do_draw(struct bContext *C, struct ARegion *ar); void ED_region_exit(struct bContext *C, struct ARegion *ar); void ED_region_pixelspace(struct ARegion *ar); @@ -81,6 +82,8 @@ void ED_region_panels( const bool vertical); void ED_region_header_init(struct ARegion *ar); void ED_region_header(const struct bContext *C, struct ARegion *ar); +void ED_region_header_layout(const struct bContext *C, struct ARegion *ar); +void ED_region_header_draw(const struct bContext *C, struct ARegion *ar); void ED_region_cursor_set(struct wmWindow *win, struct ScrArea *sa, struct ARegion *ar); void ED_region_toggle_hidden(struct bContext *C, struct ARegion *ar); void ED_region_visibility_change_update(struct bContext *C, struct ARegion *ar); @@ -135,6 +138,7 @@ int ED_area_headersize(void); int ED_area_global_size_y(const ScrArea *area); bool ED_area_is_global(const ScrArea *area); int ED_region_global_size_y(void); +void ED_area_update_region_sizes(struct wmWindowManager *wm, struct wmWindow *win, struct ScrArea *area); ScrArea *ED_screen_areas_iter_first(const struct wmWindow *win, const bScreen *screen); ScrArea *ED_screen_areas_iter_next(const bScreen *screen, const ScrArea *area); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 7fd48ce081c..20c4552e6b2 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -475,6 +475,8 @@ uiBlock *UI_block_begin(const struct bContext *C, struct ARegion *region, const void UI_block_end_ex(const struct bContext *C, uiBlock *block, const int xy[2], int r_xy[2]); void UI_block_end(const struct bContext *C, uiBlock *block); void UI_block_draw(const struct bContext *C, struct uiBlock *block); +void UI_blocklist_update_window_matrix(const struct bContext *C, const struct ListBase *lb); +void UI_blocklist_draw(const struct bContext *C, const struct ListBase *lb); void UI_block_update_from_old(const struct bContext *C, struct uiBlock *block); uiBlock *UI_block_find_in_region(const char *name, struct ARegion *ar); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index eb69ccef2e4..99387a47670 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -224,6 +224,26 @@ void ui_region_to_window(const ARegion *ar, int *x, int *y) *y += ar->winrct.ymin; } +static void ui_update_window_matrix(const wmWindow *window, const ARegion *region, uiBlock *block) +{ + /* window matrix and aspect */ + if (region && region->visible) { + /* Get projection matrix which includes View2D translation and zoom. */ + gpuGetProjectionMatrix(block->winmat); + block->aspect = 2.0f / fabsf(region->winx * block->winmat[0][0]); + } + else { + /* No subwindow created yet, for menus for example, so we use the main + * window instead, since buttons are created there anyway. */ + int width = WM_window_pixels_x(window); + int height = WM_window_pixels_y(window); + rcti winrct = {0, width - 1, 0, height - 1}; + + wmGetProjectionMatrix(block->winmat, &winrct); + block->aspect = 2.0f / fabsf(width * block->winmat[0][0]); + } +} + /** * Popups will add a margin to #ARegion.winrct for shadow, * for interactivity (point-inside tests for eg), we want the winrct without the margin added. @@ -2670,6 +2690,27 @@ void UI_block_free(const bContext *C, uiBlock *block) MEM_freeN(block); } +void UI_blocklist_update_window_matrix(const bContext *C, const ListBase *lb) +{ + ARegion *region = CTX_wm_region(C); + wmWindow *window = CTX_wm_window(C); + + for (uiBlock *block = lb->first; block; block = block->next) { + if (block->active) { + ui_update_window_matrix(window, region, block); + } + } +} + +void UI_blocklist_draw(const bContext *C, const ListBase *lb) +{ + for (uiBlock *block = lb->first; block; block = block->next) { + if (block->active) { + UI_block_draw(C, block); + } + } +} + /* can be called with C==NULL */ void UI_blocklist_free(const bContext *C, ListBase *lb) { @@ -2755,25 +2796,13 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, sh if (region) UI_block_region_set(block, region); - /* window matrix and aspect */ - if (region && region->visible) { - gpuGetProjectionMatrix(block->winmat); + /* Set window matrix and aspect for region and OpenGL state. */ + ui_update_window_matrix(window, region, block); - block->aspect = 2.0f / fabsf(region->winx * block->winmat[0][0]); - } - else { - /* no subwindow created yet, for menus for example, so we - * use the main window instead, since buttons are created - * there anyway */ - int width = WM_window_pixels_x(window); - int height = WM_window_pixels_y(window); - rcti winrct = {0, width -1, 0, height - 1}; - - wmGetProjectionMatrix(block->winmat, &winrct); - - block->aspect = 2.0f / fabsf(width * block->winmat[0][0]); + /* Tag as popup menu if not created within a region. */ + if (!(region && region->visible)) { block->auto_open = true; - block->flag |= UI_BLOCK_LOOP; /* tag as menu */ + block->flag |= UI_BLOCK_LOOP; } return block; diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c index f397c62920b..4f8e9090a4a 100644 --- a/source/blender/editors/interface/interface_region_popup.c +++ b/source/blender/editors/interface/interface_region_popup.c @@ -682,7 +682,7 @@ uiPopupBlockHandle *ui_popup_block_create( memset(&type, 0, sizeof(ARegionType)); type.draw = ui_block_region_draw; - type.refresh = ui_block_region_refresh; + type.layout = ui_block_region_refresh; type.regionid = RGN_TYPE_TEMPORARY; ar->type = &type; diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 6e45b184478..5e68ad1218d 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -501,6 +501,27 @@ void ED_area_do_msg_notify_tag_refresh( } /* only exported for WM */ +void ED_region_do_layout(bContext *C, ARegion *ar) +{ + /* This is optional, only needed for dynamically sized regions. */ + ScrArea *sa = CTX_wm_area(C); + ARegionType *at = ar->type; + + if (!at->layout) { + return; + } + + if (at->do_lock) { + return; + } + + ar->do_draw |= RGN_DRAWING; + + UI_SetTheme(sa ? sa->spacetype : 0, at->regionid); + at->layout(C, ar); +} + +/* only exported for WM */ void ED_region_do_draw(bContext *C, ARegion *ar) { wmWindow *win = CTX_wm_window(C); @@ -1187,9 +1208,8 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti if (ar->next == NULL && alignment != RGN_ALIGN_QSPLIT) alignment = RGN_ALIGN_NONE; - /* prefsize, for header we stick to exception (prevent dpi rounding error) */ - const float sizex_dpi_fac = (ar->flag & RGN_SIZEX_DPI_APPLIED) ? 1.0f : UI_DPI_FAC; - prefsizex = sizex_dpi_fac * ((ar->sizex > 1) ? ar->sizex + 0.5f : ar->type->prefsizex); + /* prefsize, taking into account DPI */ + prefsizex = UI_DPI_FAC * ((ar->sizex > 1) ? ar->sizex + 0.5f : ar->type->prefsizex); if (ar->regiontype == RGN_TYPE_HEADER) { prefsizey = ED_area_headersize(); @@ -1514,8 +1534,12 @@ static void ed_default_handlers(wmWindowManager *wm, ScrArea *sa, ListBase *hand } } -void screen_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, ScrArea *area) +void ED_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, ScrArea *area) { + 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; @@ -1898,6 +1922,23 @@ static ThemeColorID region_background_color_id(const bContext *C, const ARegion } } +static void region_clear_color(const bContext *C, const ARegion *ar, ThemeColorID colorid) +{ + if (ar->overlap) { + /* view should be in pixelspace */ + UI_view2d_view_restore(C); + + float back[4]; + UI_GetThemeColor4fv(colorid, back); + glClearColor(back[3] * back[0], back[3] * back[1], back[3] * back[2], back[3]); + glClear(GL_COLOR_BUFFER_BIT); + } + else { + UI_ThemeClearColor(colorid); + glClear(GL_COLOR_BUFFER_BIT); + } +} + void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int contextnr, const bool vertical) { const WorkSpace *workspace = CTX_wm_workspace(C); @@ -2124,20 +2165,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c } } - /* clear */ - if (ar->overlap) { - /* view should be in pixelspace */ - UI_view2d_view_restore(C); - - float back[4]; - UI_GetThemeColor4fv((ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK, back); - glClearColor(back[3] * back[0], back[3] * back[1], back[3] * back[2], back[3]); - glClear(GL_COLOR_BUFFER_BIT); - } - else { - UI_ThemeClearColor((ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK); - glClear(GL_COLOR_BUFFER_BIT); - } + region_clear_color(C, ar, (ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK); /* reset line width for drawing tabs */ glLineWidth(1.0f); @@ -2171,7 +2199,7 @@ void ED_region_panels_init(wmWindowManager *wm, ARegion *ar) WM_event_add_keymap_handler(&ar->handlers, keymap); } -void ED_region_header(const bContext *C, ARegion *ar) +void ED_region_header_layout(const bContext *C, ARegion *ar) { uiStyle *style = UI_style_get_dpi(); uiBlock *block; @@ -2183,10 +2211,6 @@ void ED_region_header(const bContext *C, ARegion *ar) const int start_ofs = 0.4f * UI_UNIT_X; bool region_layout_based = ar->flag & RGN_FLAG_DYNAMIC_SIZE; - /* clear */ - UI_ThemeClearColor(region_background_color_id(C, ar)); - glClear(GL_COLOR_BUFFER_BIT); - /* set view2d view matrix for scrolling (without scrollers) */ UI_view2d_view_ortho(&ar->v2d); @@ -2221,27 +2245,50 @@ void ED_region_header(const bContext *C, ARegion *ar) if (xco > maxco) maxco = xco; - if (region_layout_based && (ar->sizex != (maxco + start_ofs))) { + int new_sizex = (maxco + start_ofs) / UI_DPI_FAC; + + if (region_layout_based && (ar->sizex != new_sizex)) { /* region size is layout based and needs to be updated */ ScrArea *sa = CTX_wm_area(C); - ar->sizex = maxco + start_ofs; - UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->sizex, ar->winy); - + ar->sizex = new_sizex; sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE; - ar->flag |= RGN_SIZEX_DPI_APPLIED; } + UI_block_end(C, block); - UI_block_draw(C, block); } /* always as last */ UI_view2d_totRect_set(&ar->v2d, maxco + (region_layout_based ? 0 : UI_UNIT_X + 80), headery); - /* restore view matrix? */ + /* restore view matrix */ + UI_view2d_view_restore(C); +} + +void ED_region_header_draw(const bContext *C, ARegion *ar) +{ + UI_view2d_view_ortho(&ar->v2d); + + /* clear */ + region_clear_color(C, ar, region_background_color_id(C, ar)); + + /* View2D matrix might have changed due to dynamic sized regions. */ + UI_blocklist_update_window_matrix(C, &ar->uiblocks); + + /* draw blocks */ + UI_blocklist_draw(C, &ar->uiblocks); + + /* restore view matrix */ UI_view2d_view_restore(C); } +void ED_region_header(const bContext *C, ARegion *ar) +{ + /* TODO: remove? */ + ED_region_header_layout(C, ar); + ED_region_header_draw(C, ar); +} + void ED_region_header_init(ARegion *ar) { UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy); diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index c7d1605cbbf..1cadefadd5c 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -835,36 +835,6 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win) screen->context = ed_screen_context; } -static bool screen_regions_need_size_refresh( - const wmWindow *win, const bScreen *screen) -{ - ED_screen_areas_iter(win, screen, area) { - if (area->flag & AREA_FLAG_REGION_SIZE_UPDATE) { - return true; - } - } - - return false; -} - -static void screen_refresh_region_sizes_only( - wmWindowManager *wm, wmWindow *win, - bScreen *screen) -{ - 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); - - screen_vertices_scale(win, screen, window_size_x, window_size_y, screen_size_x, screen_size_y); - - ED_screen_areas_iter(win, screen, area) { - screen_area_update_region_sizes(wm, win, area); - /* XXX hack to force drawing */ - ED_area_tag_redraw(area); - } -} - /* file read, set all screens, ... */ void ED_screens_initialize(wmWindowManager *wm) { @@ -887,9 +857,6 @@ void ED_screen_ensure_updated(wmWindowManager *wm, wmWindow *win, bScreen *scree if (screen->do_refresh) { ED_screen_refresh(wm, win); } - else if (screen_regions_need_size_refresh(win, screen)) { - screen_refresh_region_sizes_only(wm, win, screen); - } } diff --git a/source/blender/editors/space_topbar/space_topbar.c b/source/blender/editors/space_topbar/space_topbar.c index f2824b3bf70..fc76fd9c638 100644 --- a/source/blender/editors/space_topbar/space_topbar.c +++ b/source/blender/editors/space_topbar/space_topbar.c @@ -132,11 +132,6 @@ static void topbar_main_region_init(wmWindowManager *wm, ARegion *region) WM_event_add_keymap_handler(®ion->handlers, keymap); } -static void topbar_main_region_draw(const bContext *C, ARegion *region) -{ - ED_region_header(C, region); -} - static void topbar_operatortypes(void) { @@ -156,11 +151,6 @@ static void topbar_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar) ED_region_header_init(ar); } -static void topbar_header_region_draw(const bContext *C, ARegion *ar) -{ - ED_region_header(C, ar); -} - static void topbar_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn, const Scene *UNUSED(scene)) { @@ -263,7 +253,8 @@ void ED_spacetype_topbar(void) art = MEM_callocN(sizeof(ARegionType), "spacetype topbar main region"); art->regionid = RGN_TYPE_WINDOW; art->init = topbar_main_region_init; - art->draw = topbar_main_region_draw; + art->layout = ED_region_header_layout; + art->draw = ED_region_header_draw; art->listener = topbar_main_region_listener; art->prefsizex = UI_UNIT_X * 5; /* Mainly to avoid glitches */ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER; @@ -279,7 +270,8 @@ void ED_spacetype_topbar(void) art->listener = topbar_header_listener; art->message_subscribe = topbar_header_region_message_subscribe; art->init = topbar_header_region_init; - art->draw = topbar_header_region_draw; + art->layout = ED_region_header_layout; + art->draw = ED_region_header_draw; BLI_addhead(&st->regiontypes, art); |