Fix T52999: floating (popup) panels/menus could jump around screen in some cases.

Would happen during panel's refresh drawing, if drawing code had to adjust
final panel position compared to the initial one computed based on the
mouse coordinates, and user had dragged the floating panel around.

Issue fixed by adjusting stored mouse coordinates once final panel
position is known, such that they would directly generate those
coordinates. that way, the basic offset applied to those stored mouse
coordinates during panel dragging is valid, and recreating panel based
on those won't make it jump in screen.

Note that panel will still jump in case user dragged it partially out of
view - we could prevent that, but imho it's better to keep that
behavior, since redraw can generate a popup of different size, which
could end up with a totally out-of-view one...

Hopefully this fix does not break anything else!
This commit is contained in:
Bastien Montagne 2017-10-12 14:43:45 +02:00
parent b29e37ed81
commit 3b4f6996a8
Notes: blender-bot 2023-02-14 06:32:27 +01:00
Referenced by issue #52999, invoke_props_dialog() window changes position on redraw if the window has sufficient vertical height
3 changed files with 18 additions and 10 deletions

View File

@ -439,7 +439,7 @@ void UI_popup_block_close(struct bContext *C, struct wmWindow *win, uiBlock *blo
* */
uiBlock *UI_block_begin(const struct bContext *C, struct ARegion *region, const char *name, short dt);
void UI_block_end_ex(const struct bContext *C, uiBlock *block, const int xy[2]);
void UI_block_end_ex(const struct bContext *C, uiBlock *block, const int xy[2], int r_xy[2]);
void UI_block_end(const struct bContext *C, uiBlock *block);
void UI_block_draw(const struct bContext *C, struct uiBlock *block);
void UI_block_update_from_old(const struct bContext *C, struct uiBlock *block);

View File

@ -366,10 +366,10 @@ static void ui_block_bounds_calc_centered_pie(uiBlock *block)
static void ui_block_bounds_calc_popup(
wmWindow *window, uiBlock *block,
eBlockBoundsCalc bounds_calc, const int xy[2])
eBlockBoundsCalc bounds_calc, const int xy[2], int r_xy[2])
{
int width, height, oldwidth, oldheight;
int oldbounds, xmax, ymax;
int oldbounds, xmax, ymax, raw_x, raw_y;
const int margin = UI_SCREEN_MARGIN;
rcti rect, rect_bounds;
int ofs_dummy[2];
@ -407,8 +407,8 @@ static void ui_block_bounds_calc_popup(
/* offset block based on mouse position, user offset is scaled
* along in case we resized the block in ui_block_bounds_calc_text */
rect.xmin = xy[0] + block->rect.xmin + (block->mx * width) / oldwidth;
rect.ymin = xy[1] + block->rect.ymin + (block->my * height) / oldheight;
raw_x = rect.xmin = xy[0] + block->rect.xmin + (block->mx * width) / oldwidth;
raw_y = rect.ymin = xy[1] + block->rect.ymin + (block->my * height) / oldheight;
rect.xmax = rect.xmin + width;
rect.ymax = rect.ymin + height;
@ -422,6 +422,13 @@ static void ui_block_bounds_calc_popup(
/* now recompute bounds and safety */
ui_block_bounds_calc(block);
/* If given, adjust input coordinates such that they would generate real final popup position.
* Needed to handle correctly floating panels once they have been dragged around, see T52999. */
if (r_xy) {
r_xy[0] = xy[0] + block->rect.xmin - raw_x;
r_xy[1] = xy[1] + block->rect.ymin - raw_y;
}
}
/* used for various cases */
@ -1231,7 +1238,7 @@ void UI_block_update_from_old(const bContext *C, uiBlock *block)
block->oldblock = NULL;
}
void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2])
void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_xy[2])
{
wmWindow *window = CTX_wm_window(C);
Scene *scene = CTX_data_scene(C);
@ -1299,7 +1306,7 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2])
/* fallback */
case UI_BLOCK_BOUNDS_POPUP_MOUSE:
case UI_BLOCK_BOUNDS_POPUP_MENU:
ui_block_bounds_calc_popup(window, block, block->bounds_type, xy);
ui_block_bounds_calc_popup(window, block, block->bounds_type, xy, r_xy);
break;
}
@ -1317,7 +1324,7 @@ void UI_block_end(const bContext *C, uiBlock *block)
{
wmWindow *window = CTX_wm_window(C);
UI_block_end_ex(C, block, &window->eventstate->x);
UI_block_end_ex(C, block, &window->eventstate->x, NULL);
}
/* ************** BLOCK DRAWING FUNCTION ************* */

View File

@ -1869,8 +1869,9 @@ uiBlock *ui_popup_block_refresh(
/* defer this until blocks are translated (below) */
block->oldblock = NULL;
if (!block->endblock)
UI_block_end_ex(C, block, handle->popup_create_vars.event_xy);
if (!block->endblock) {
UI_block_end_ex(C, block, handle->popup_create_vars.event_xy, handle->popup_create_vars.event_xy);
}
/* if this is being created from a button */
if (but) {