From def5999f9b04368aa21485b514c0931f6fb43d8e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 2 Apr 2014 18:42:08 +1100 Subject: UI: support for dragging popups title area --- source/blender/editors/include/ED_screen.h | 1 + .../blender/editors/interface/interface_handlers.c | 51 +++++++++++++++++++--- .../blender/editors/interface/interface_intern.h | 5 +++ source/blender/editors/screen/area.c | 29 +++++++++--- source/blender/windowmanager/intern/wm_subwindow.c | 14 ++++++ source/blender/windowmanager/wm_subwindow.h | 1 + 6 files changed, 89 insertions(+), 12 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 5e20734461b..1d1777afcd9 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -55,6 +55,7 @@ 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); void ED_region_set(const struct bContext *C, struct ARegion *ar); +void ED_region_update_rect(struct bContext *C, struct ARegion *ar); void ED_region_init(struct bContext *C, struct ARegion *ar); void ED_region_tag_redraw(struct ARegion *ar); void ED_region_tag_redraw_partial(struct ARegion *ar, struct rcti *rct); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 5a520a6df31..e7c9900c325 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -96,6 +96,9 @@ /* so we can avoid very small mouse-moves from jumping away from keyboard navigation [#34936] */ #define USE_KEYNAV_LIMIT +/* drag popups by their header */ +#define USE_DRAG_POPUP + /* proto */ static void ui_add_smart_controller(bContext *C, uiBut *from, uiBut *to); static void ui_add_link(bContext *C, uiBut *from, uiBut *to); @@ -7862,13 +7865,14 @@ static int ui_handle_menu_button(bContext *C, const wmEvent *event, uiPopupBlock } static int ui_handle_menu_event(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu, - int level, const bool is_parent_inside) + int level, const bool is_parent_inside, const bool is_floating) { ARegion *ar; uiBlock *block; uiBut *but, *bt; int mx, my, retval; bool inside; + bool inside_title; /* check for title dragging */ ar = menu->region; block = ar->uiblocks.first; @@ -7881,10 +7885,35 @@ static int ui_handle_menu_event(bContext *C, const wmEvent *event, uiPopupBlockH /* check if mouse is inside block */ inside = BLI_rctf_isect_pt(&block->rect, mx, my); + inside_title = inside && ((my + (UI_UNIT_Y * 1.5f)) > block->rect.xmax); /* if there's an active modal button, don't check events or outside, except for search menu */ but = ui_but_find_activated(ar); +#ifdef USE_DRAG_POPUP + if (menu->is_grab) { + if (event->type == LEFTMOUSE) { + menu->is_grab = false; + } + else { + if (event->type == MOUSEMOVE) { + int mdiff[2]; + + sub_v2_v2v2_int(mdiff, &event->x, menu->grab_xy_prev); + copy_v2_v2_int(menu->grab_xy_prev, &event->x); + + BLI_rcti_translate(&ar->winrct, UNPACK2(mdiff)); + + ED_region_update_rect(C, ar); + + ED_region_tag_redraw(ar); + } + + return retval; + } + } +#endif + if (but && button_modal_state(but->active->state)) { if (block->flag & UI_BLOCK_MOVEMOUSE_QUIT) { /* if a button is activated modal, always reset the start mouse @@ -8220,6 +8249,16 @@ static int ui_handle_menu_event(bContext *C, const wmEvent *event, uiPopupBlockH if (!ui_but_find_activated(ar)) menu->menuretval = UI_RETURN_CANCEL | UI_RETURN_POPUP_OK; } +#ifdef USE_DRAG_POPUP + else if ((event->type == LEFTMOUSE) && (event->val == KM_PRESS) && + (inside && is_floating && inside_title)) + { + if (!ui_but_find_activated(ar)) { + menu->is_grab = true; + copy_v2_v2_int(menu->grab_xy_prev, &event->x); + } + } +#endif else { /* check mouse moving outside of the menu */ @@ -8328,7 +8367,7 @@ static int ui_handle_menu_return_submenu(bContext *C, const wmEvent *event, uiPo } static int ui_handle_menus_recursive(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu, - int level, const bool is_parent_inside) + int level, const bool is_parent_inside, const bool is_floating) { uiBut *but; uiHandleButtonData *data; @@ -8354,7 +8393,7 @@ static int ui_handle_menus_recursive(bContext *C, const wmEvent *event, uiPopupB inside = BLI_rctf_isect_pt(&block->rect, mx, my); } - retval = ui_handle_menus_recursive(C, event, submenu, level + 1, is_parent_inside || inside); + retval = ui_handle_menus_recursive(C, event, submenu, level + 1, is_parent_inside || inside, false); } /* now handle events for our own menu */ @@ -8387,7 +8426,7 @@ static int ui_handle_menus_recursive(bContext *C, const wmEvent *event, uiPopupB } } else { - retval = ui_handle_menu_event(C, event, menu, level, is_parent_inside); + retval = ui_handle_menu_event(C, event, menu, level, is_parent_inside, is_floating); } } @@ -8484,7 +8523,7 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE /* handle events for menus and their buttons recursively, * this will handle events from the top to the bottom menu */ if (data->menu) - retval = ui_handle_menus_recursive(C, event, data->menu, 0, false); + retval = ui_handle_menus_recursive(C, event, data->menu, 0, false, false); /* handle events for the activated button */ if ((data->menu && (retval == WM_UI_HANDLER_CONTINUE)) || @@ -8530,7 +8569,7 @@ static int ui_handler_popup(bContext *C, const wmEvent *event, void *userdata) retval = WM_UI_HANDLER_CONTINUE; } - ui_handle_menus_recursive(C, event, menu, 0, false); + ui_handle_menus_recursive(C, event, menu, 0, false, true); /* free if done, does not free handle itself */ if (menu->menuretval) { diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 2c6486b587c..bb321353955 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -460,6 +460,11 @@ struct uiPopupBlockHandle { /* menu direction */ int direction; + +/* #ifdef USE_DRAG_POPUP */ + bool is_grab; + int grab_xy_prev[2]; +/* #endif */ }; uiBlock *ui_block_func_COLOR(struct bContext *C, uiPopupBlockHandle *handle, void *arg_but); diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index f62166d33b0..1efd3cc8ace 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -408,7 +408,7 @@ void ED_region_do_draw(bContext *C, ARegion *ar) /* see BKE_spacedata_draw_locks() */ if (at->do_lock) return; - + /* if no partial draw rect set, full rect */ if (ar->drawrct.xmin == ar->drawrct.xmax) { ar->drawrct = ar->winrct; @@ -1312,6 +1312,27 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa) } } +static void region_update_rect(ARegion *ar) +{ + ar->winx = BLI_rcti_size_x(&ar->winrct) + 1; + ar->winy = BLI_rcti_size_y(&ar->winrct) + 1; + + /* v2d mask is used to subtract scrollbars from a 2d view. Needs initialize here. */ + BLI_rcti_init(&ar->v2d.mask, 0, ar->winx - 1, 0, ar->winy -1); +} + +/** + * Call to move a popup window (keep OpenGL context free!) + */ +void ED_region_update_rect(bContext *C, ARegion *ar) +{ + wmWindow *win = CTX_wm_window(C); + + wm_subwindow_rect_set(win, ar->swinid, &ar->winrct); + + region_update_rect(ar); +} + /* externally called for floating regions like menus */ void ED_region_init(bContext *C, ARegion *ar) { @@ -1320,11 +1341,7 @@ void ED_region_init(bContext *C, ARegion *ar) /* refresh can be called before window opened */ region_subwindow(CTX_wm_window(C), ar); - ar->winx = BLI_rcti_size_x(&ar->winrct) + 1; - ar->winy = BLI_rcti_size_y(&ar->winrct) + 1; - - /* v2d mask is used to subtract scrollbars from a 2d view. Needs initialize here. */ - BLI_rcti_init(&ar->v2d.mask, 0, ar->winx - 1, 0, ar->winy -1); + region_update_rect(ar); /* UI convention */ wmOrtho2(-0.01f, ar->winx - 0.01f, -0.01f, ar->winy - 0.01f); diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c index 1c20fe34a90..ecf22fea454 100644 --- a/source/blender/windowmanager/intern/wm_subwindow.c +++ b/source/blender/windowmanager/intern/wm_subwindow.c @@ -180,6 +180,20 @@ void wm_subwindow_rect_get(wmWindow *win, int swinid, rcti *r_rect) } +static void wm_swin_rect_set(wmSubWindow *swin, const rcti *rect) +{ + swin->winrct = *rect; +} +void wm_subwindow_rect_set(wmWindow *win, int swinid, const rcti *rect) +{ + wmSubWindow *swin = swin_from_swinid(win, swinid); + + if (swin) { + wm_swin_rect_set(swin, rect); + } +} + + /* always sets pixel-precise 2D window/view matrices */ /* coords is in whole pixels. xmin = 15, xmax = 16: means window is 2 pix big */ int wm_subwindow_open(wmWindow *win, const rcti *winrct) diff --git a/source/blender/windowmanager/wm_subwindow.h b/source/blender/windowmanager/wm_subwindow.h index c1d0f9a9cac..bf7b99433c6 100644 --- a/source/blender/windowmanager/wm_subwindow.h +++ b/source/blender/windowmanager/wm_subwindow.h @@ -46,6 +46,7 @@ void wm_subwindow_size_get(wmWindow *win, int swinid, int *x, int *y); void wm_subwindow_origin_get(wmWindow *win, int swinid, int *x, int *y); void wm_subwindow_matrix_get(wmWindow *win, int swinid, float mat[4][4]); void wm_subwindow_rect_get(wmWindow *win, int swinid, struct rcti *r_rect); +void wm_subwindow_rect_set(wmWindow *win, int swinid, const rcti *rect); unsigned int index_to_framebuffer(int index); -- cgit v1.2.3