diff options
-rw-r--r-- | source/blender/blenkernel/BKE_screen.h | 4 | ||||
-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 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_screen_types.h | 5 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_draw.c | 21 |
10 files changed, 153 insertions, 104 deletions
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 17cca92c1fc..36708cb11a4 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -140,8 +140,8 @@ typedef struct ARegionType { void (*exit)(struct wmWindowManager *, struct ARegion *); /* draw entirely, view changes should be handled here */ void (*draw)(const struct bContext *, struct ARegion *); - /* optional, refresh popup before drawing */ - void (*refresh)(const struct bContext *, struct ARegion *); + /* optional, compute button layout before drawing for dynamic size */ + void (*layout)(const struct bContext *, struct ARegion *); /* snap the size of the region (can be NULL for no snapping). */ int (*snap_size)(const struct ARegion *ar, int size, int axis); /* contextual changes should be handled here */ 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); diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 18986206b23..4274f348b2d 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -464,11 +464,6 @@ enum { * just big enough to show all its content (if enough space is available). * Note that only ED_region_header supports this right now. */ RGN_FLAG_DYNAMIC_SIZE = (1 << 2), - /* The region width stored in ARegion.sizex already has the DPI - * factor applied, skip applying it again (in region_rect_recursive). - * XXX Not nice at all. Leaving for now as temporary solution, but - * it might cause issues if we change how ARegion.sizex is used... */ - RGN_SIZEX_DPI_APPLIED = (1 << 3), }; /* region do_draw */ diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index f111bc3e2d1..685e6f7e216 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -489,12 +489,25 @@ GPUViewport *WM_draw_region_get_bound_viewport(ARegion *ar) static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo) { + wmWindowManager *wm = CTX_wm_manager(C); bScreen *screen = WM_window_get_active_screen(win); /* Draw screen areas into own frame buffer. */ ED_screen_areas_iter(win, screen, sa) { CTX_wm_area_set(C, sa); + /* Compute UI layouts for dynamically size regions. */ + for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->visible && ar->do_draw && ar->type && ar->type->layout) { + CTX_wm_region_set(C, ar); + ED_region_do_layout(C, ar); + CTX_wm_region_set(C, NULL); + } + } + + ED_area_update_region_sizes(wm, win, sa); + + /* Then do actual drawing of regions. */ for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { if (ar->visible && ar->do_draw) { CTX_wm_region_set(C, ar); @@ -539,11 +552,11 @@ static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo) if (ar->visible) { CTX_wm_menu_set(C, ar); - if (ar->type && ar->type->refresh) { - /* UI code reads the OpenGL state, but we have to - * refresh beforehand in case the menu size changes. */ + if (ar->type && ar->type->layout) { + /* UI code reads the OpenGL state, but we have to refesh + * the UI layout beforehand in case the menu size changes. */ wmViewport(&ar->winrct); - ar->type->refresh(C, ar); + ar->type->layout(C, ar); } wm_draw_region_buffer_create(ar, false, false); |