UI: support for dragging popups title area

This commit is contained in:
Campbell Barton 2014-04-02 18:42:08 +11:00
parent 442f2df736
commit def5999f9b
6 changed files with 89 additions and 12 deletions

View File

@ -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);

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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);