Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2018-04-29 13:24:08 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2018-04-29 23:11:12 +0300
commit7a9f64e6657a231289f56b0a8c9949c8f7a23c59 (patch)
treeefee3c4ac1988ad96d743f1d82e7a677096ca0c3 /source
parent0c512a6f951e36e29d2f6865cc975f7e40c4d31d (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')
-rw-r--r--source/blender/blenkernel/BKE_screen.h4
-rw-r--r--source/blender/editors/include/ED_screen.h4
-rw-r--r--source/blender/editors/include/UI_interface.h2
-rw-r--r--source/blender/editors/interface/interface.c63
-rw-r--r--source/blender/editors/interface/interface_region_popup.c2
-rw-r--r--source/blender/editors/screen/area.c107
-rw-r--r--source/blender/editors/screen/screen_edit.c33
-rw-r--r--source/blender/editors/space_topbar/space_topbar.c16
-rw-r--r--source/blender/makesdna/DNA_screen_types.h5
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c21
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(&region->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);