fix [#35346] Python: still UI issue with popup and dropdown list

This commit is contained in:
Campbell Barton
2013-06-13 09:12:53 +00:00
parent 8b4bca6cf0
commit 815a87a652
3 changed files with 76 additions and 45 deletions

View File

@@ -138,15 +138,11 @@ void ui_block_to_window(const ARegion *ar, uiBlock *block, int *x, int *y)
*y = (int)(fy + 0.5f);
}
void ui_block_to_window_rct(const ARegion *ar, uiBlock *block, const rctf *graph, rcti *winr)
void ui_block_to_window_rctf(const ARegion *ar, uiBlock *block, rctf *rct_dst, const rctf *rct_src)
{
rctf tmpr;
tmpr = *graph;
ui_block_to_window_fl(ar, block, &tmpr.xmin, &tmpr.ymin);
ui_block_to_window_fl(ar, block, &tmpr.xmax, &tmpr.ymax);
BLI_rcti_rctf_copy(winr, &tmpr);
*rct_dst = *rct_src;
ui_block_to_window_fl(ar, block, &rct_dst->xmin, &rct_dst->ymin);
ui_block_to_window_fl(ar, block, &rct_dst->xmax, &rct_dst->ymax);
}
void ui_window_to_block_fl(const ARegion *ar, uiBlock *block, float *x, float *y) /* for mouse cursor */
@@ -1023,11 +1019,10 @@ void ui_fontscale(short *points, float aspect)
/* project button or block (but==NULL) to pixels in regionspace */
static void ui_but_to_pixelrect(rcti *rect, const ARegion *ar, uiBlock *block, uiBut *but)
{
rctf rectf = (but) ? but->rect : block->rect;
ui_block_to_window_fl(ar, block, &rectf.xmin, &rectf.ymin);
ui_block_to_window_fl(ar, block, &rectf.xmax, &rectf.ymax);
rctf rectf;
ui_block_to_window_rctf(ar, block, &rectf, (but) ? &but->rect : &block->rect);
rectf.xmin -= ar->winrct.xmin;
rectf.ymin -= ar->winrct.ymin;
rectf.xmax -= ar->winrct.xmin;

View File

@@ -108,6 +108,9 @@ static bool ui_mouse_motion_keynav_test(struct uiKeyNavLock *keynav, const wmEve
/* pixels to move the cursor to get out of keyboard navigation */
#define BUTTON_KEYNAV_PX_LIMIT 4
#define MENU_TOWARDS_MARGIN 20 /* margin in pixels */
#define MENU_TOWARDS_WIGGLE_ROOM 64 /* tolerance in pixels */
typedef enum uiButtonActivateType {
BUTTON_ACTIVATE_OVER,
BUTTON_ACTIVATE,
@@ -6554,12 +6557,12 @@ static void ui_handle_button_return_submenu(bContext *C, const wmEvent *event, u
* - only for 1 second
*/
static void ui_mouse_motion_towards_init(uiPopupBlockHandle *menu, int mx, int my, const bool force)
static void ui_mouse_motion_towards_init_ex(uiPopupBlockHandle *menu, const int xy[2], const bool force)
{
if (!menu->dotowards || force) {
menu->dotowards = true;
menu->towardsx = mx;
menu->towardsy = my;
menu->towards_xy[0] = xy[0];
menu->towards_xy[1] = xy[1];
if (force)
menu->towardstime = DBL_MAX; /* unlimited time */
@@ -6568,38 +6571,62 @@ static void ui_mouse_motion_towards_init(uiPopupBlockHandle *menu, int mx, int m
}
}
static bool ui_mouse_motion_towards_check(uiBlock *block, uiPopupBlockHandle *menu, int mx, int my)
static void ui_mouse_motion_towards_init(uiPopupBlockHandle *menu, const int xy[2])
{
float p1[2], p2[2], p3[2], p4[2], oldp[2], newp[2];
ui_mouse_motion_towards_init_ex(menu, xy, false);
}
static void ui_mouse_motion_towards_reinit(uiPopupBlockHandle *menu, const int xy[2])
{
ui_mouse_motion_towards_init_ex(menu, xy, true);
}
static bool ui_mouse_motion_towards_check(uiBlock *block, uiPopupBlockHandle *menu, const int xy[2])
{
float p1[2], p2[2], p3[2], p4[2];
float oldp[2] = {menu->towards_xy[0], menu->towards_xy[1]};
const float newp[2] = {xy[0], xy[1]};
bool closer;
const float margin = MENU_TOWARDS_MARGIN;
rctf rect_px;
if (!menu->dotowards) {
return 0;
return false;
}
if (len_squared_v2v2(oldp, newp) < (4.0f * 4.0f))
return menu->dotowards;
/* verify that we are moving towards one of the edges of the
* menu block, in other words, in the triangle formed by the
* initial mouse location and two edge points. */
p1[0] = block->rect.xmin - 20;
p1[1] = block->rect.ymin - 20;
ui_block_to_window_rctf(menu->region, block, &rect_px, &block->rect);
p2[0] = block->rect.xmax + 20;
p2[1] = block->rect.ymin - 20;
p1[0] = rect_px.xmin - margin;
p1[1] = rect_px.ymin - margin;
p2[0] = rect_px.xmax + margin;
p2[1] = rect_px.ymin - margin;
p3[0] = block->rect.xmax + 20;
p3[1] = block->rect.ymax + 20;
p3[0] = rect_px.xmax + margin;
p3[1] = rect_px.ymax + margin;
p4[0] = block->rect.xmin - 20;
p4[1] = block->rect.ymax + 20;
p4[0] = rect_px.xmin - margin;
p4[1] = rect_px.ymax + margin;
oldp[0] = menu->towardsx;
oldp[1] = menu->towardsy;
/* allow for some wiggle room, if the user moves a few pixels away,
* don't immediately quit */
{
const float cent[2] = {
BLI_rctf_cent_x(&rect_px),
BLI_rctf_cent_y(&rect_px)};
float delta[2];
newp[0] = mx;
newp[1] = my;
if (len_squared_v2v2(oldp, newp) < (4.0f * 4.0f))
return menu->dotowards;
sub_v2_v2v2(delta, oldp, cent);
normalize_v2(delta);
mul_v2_fl(delta, MENU_TOWARDS_WIGGLE_ROOM);
add_v2_v2(oldp, delta);
}
closer = (isect_point_tri_v2(newp, oldp, p1, p2) ||
isect_point_tri_v2(newp, oldp, p2, p3) ||
@@ -6789,7 +6816,7 @@ static int ui_handle_menu_event(bContext *C, const wmEvent *event, uiPopupBlockH
/* if a button is activated modal, always reset the start mouse
* position of the towards mechanism to avoid loosing focus,
* and don't handle events */
ui_mouse_motion_towards_init(menu, mx, my, true);
ui_mouse_motion_towards_reinit(menu, &event->x);
}
else if (event->type == TIMER) {
if (event->customdata == menu->scrolltimer)
@@ -6798,7 +6825,7 @@ static int ui_handle_menu_event(bContext *C, const wmEvent *event, uiPopupBlockH
else {
/* for ui_mouse_motion_towards_block */
if (event->type == MOUSEMOVE) {
ui_mouse_motion_towards_init(menu, mx, my, false);
ui_mouse_motion_towards_init(menu, &event->x);
/* add menu scroll timer, if needed */
if (ui_menu_scroll_test(block, my))
@@ -7103,7 +7130,7 @@ static int ui_handle_menu_event(bContext *C, const wmEvent *event, uiPopupBlockH
menu->menuretval = UI_RETURN_CANCEL | UI_RETURN_POPUP_OK;
}
else {
ui_mouse_motion_towards_check(block, menu, mx, my);
ui_mouse_motion_towards_check(block, menu, &event->x);
/* check mouse moving outside of the menu */
if (inside == 0 && (block->flag & UI_BLOCK_MOVEMOUSE_QUIT)) {
@@ -7166,7 +7193,6 @@ static int ui_handle_menu_return_submenu(bContext *C, const wmEvent *event, uiPo
uiBlock *block;
uiHandleButtonData *data;
uiPopupBlockHandle *submenu;
int mx, my, update;
ar = menu->region;
block = ar->uiblocks.first;
@@ -7176,6 +7202,8 @@ static int ui_handle_menu_return_submenu(bContext *C, const wmEvent *event, uiPo
submenu = data->menu;
if (submenu->menuretval) {
bool update;
/* first decide if we want to close our own menu cascading, if
* so pass on the sub menu return value to our own menu handle */
if ((submenu->menuretval & UI_RETURN_OK) || (submenu->menuretval & UI_RETURN_CANCEL)) {
@@ -7185,7 +7213,7 @@ static int ui_handle_menu_return_submenu(bContext *C, const wmEvent *event, uiPo
}
}
update = (submenu->menuretval & UI_RETURN_UPDATE);
update = (submenu->menuretval & UI_RETURN_UPDATE) != 0;
/* now let activated button in this menu exit, which
* will actually close the submenu too */
@@ -7197,10 +7225,7 @@ static int ui_handle_menu_return_submenu(bContext *C, const wmEvent *event, uiPo
/* for cases where close does not cascade, allow the user to
* move the mouse back towards the menu without closing */
mx = event->x;
my = event->y;
ui_window_to_block(ar, block, &mx, &my);
ui_mouse_motion_towards_init(menu, mx, my, true);
ui_mouse_motion_towards_reinit(menu, &event->x);
if (menu->menuretval)
return WM_UI_HANDLER_CONTINUE;
@@ -7214,6 +7239,7 @@ static int ui_handle_menus_recursive(bContext *C, const wmEvent *event, uiPopupB
uiHandleButtonData *data;
uiPopupBlockHandle *submenu;
int retval = WM_UI_HANDLER_CONTINUE;
bool do_towards_reinit = false;
/* check if we have a submenu, and handle events for it first */
but = ui_but_find_activated(menu->region);
@@ -7241,12 +7267,22 @@ static int ui_handle_menus_recursive(bContext *C, const wmEvent *event, uiPopupB
if (do_but_search) {
retval = ui_handle_menu_button(C, event, menu);
/* when there is a active search button and we close it,
* we need to reinit the mouse coords [#35346] */
if (ui_but_find_activated(menu->region) != but) {
do_towards_reinit = true;
}
}
else {
retval = ui_handle_menu_event(C, event, menu, level);
}
}
if (do_towards_reinit) {
ui_mouse_motion_towards_reinit(menu, &event->x);
}
return retval;
}

View File

@@ -369,7 +369,7 @@ void ui_fontscale(short *points, float aspect);
extern bool ui_block_is_menu(const uiBlock *block);
extern void ui_block_to_window_fl(const struct ARegion *ar, uiBlock *block, float *x, float *y);
extern void ui_block_to_window(const struct ARegion *ar, uiBlock *block, int *x, int *y);
extern void ui_block_to_window_rct(const struct ARegion *ar, uiBlock *block, const rctf *graph, rcti *winr);
extern void ui_block_to_window_rctf(const struct ARegion *ar, uiBlock *block, rctf *rct_dst, const rctf *rct_src);
extern void ui_window_to_block_fl(const struct ARegion *ar, uiBlock *block, float *x, float *y);
extern void ui_window_to_block(const struct ARegion *ar, uiBlock *block, int *x, int *y);
extern void ui_window_to_region(const ARegion *ar, int *x, int *y);
@@ -426,7 +426,7 @@ struct uiKeyNavLock {
struct uiPopupBlockHandle {
/* internal */
struct ARegion *region;
int towardsx, towardsy;
float towards_xy[2];
double towardstime;
bool dotowards;