fix [#35346] Python: still UI issue with popup and dropdown list
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user