UI: support for dragging popups title area
This commit is contained in:
parent
442f2df736
commit
def5999f9b
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue