Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/editors/include/ED_screen.h1
-rw-r--r--source/blender/editors/interface/interface_dropboxes.cc8
-rw-r--r--source/blender/editors/screen/area_query.c45
-rw-r--r--source/blender/windowmanager/WM_types.h31
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.c77
5 files changed, 116 insertions, 46 deletions
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index 08b6c02a8d0..ef3ff7874df 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -439,6 +439,7 @@ bool ED_region_panel_category_gutter_calc_rect(const ARegion *region, rcti *r_re
bool ED_region_panel_category_gutter_isect_xy(const ARegion *region, const int event_xy[2]);
bool ED_region_contains_xy(const struct ARegion *region, const int event_xy[2]);
+ARegion *ED_area_find_region_xy_visual(const ScrArea *area, int regiontype, const int event_xy[2]);
/* interface_region_hud.c */
struct ARegionType *ED_area_type_hud(int space_type);
diff --git a/source/blender/editors/interface/interface_dropboxes.cc b/source/blender/editors/interface/interface_dropboxes.cc
index 81a1354cbe7..369efa7c52e 100644
--- a/source/blender/editors/interface/interface_dropboxes.cc
+++ b/source/blender/editors/interface/interface_dropboxes.cc
@@ -39,12 +39,12 @@ static bool ui_tree_view_drop_poll(bContext *C, wmDrag *drag, const wmEvent *eve
return false;
}
- if (drag->free_disabled_info) {
- MEM_SAFE_FREE(drag->disabled_info);
+ if (drag->drop_state.free_disabled_info) {
+ MEM_SAFE_FREE(drag->drop_state.disabled_info);
}
- drag->free_disabled_info = false;
- return UI_tree_view_item_can_drop(hovered_tree_item, drag, &drag->disabled_info);
+ drag->drop_state.free_disabled_info = false;
+ return UI_tree_view_item_can_drop(hovered_tree_item, drag, &drag->drop_state.disabled_info);
}
static char *ui_tree_view_drop_tooltip(bContext *C,
diff --git a/source/blender/editors/screen/area_query.c b/source/blender/editors/screen/area_query.c
index fd4f3964398..30e744ca174 100644
--- a/source/blender/editors/screen/area_query.c
+++ b/source/blender/editors/screen/area_query.c
@@ -140,6 +140,10 @@ bool ED_region_overlap_isect_xy_with_margin(const ARegion *region,
ED_region_overlap_isect_y_with_margin(region, event_xy[1], margin));
}
+/**
+ * \note: This may return true for multiple overlapping regions. If it matters, check overlapped
+ * regions first (#ARegion.overlap).
+ */
bool ED_region_contains_xy(const ARegion *region, const int event_xy[2])
{
/* Only use the margin when inside the region. */
@@ -188,3 +192,44 @@ bool ED_region_contains_xy(const ARegion *region, const int event_xy[2])
}
return false;
}
+
+/**
+ * Similar to #BKE_area_find_region_xy() but when \a event_xy intersects an overlapping region,
+ * this returns the region that is visually under the cursor. E.g. when over the
+ * transparent part of the region, it returns the region underneath.
+ *
+ * The overlapping region is determined using the #ED_region_contains_xy() query.
+ */
+ARegion *ED_area_find_region_xy_visual(const ScrArea *area,
+ const int regiontype,
+ const int event_xy[2])
+{
+ if (!area) {
+ return NULL;
+ }
+
+ /* Check overlapped regions first. */
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+ if (!region->overlap) {
+ continue;
+ }
+ if (ELEM(regiontype, RGN_TYPE_ANY, region->regiontype)) {
+ if (ED_region_contains_xy(region, event_xy)) {
+ return region;
+ }
+ }
+ }
+ /* Now non-overlapping ones. */
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+ if (region->overlap) {
+ continue;
+ }
+ if (ELEM(regiontype, RGN_TYPE_ANY, region->regiontype)) {
+ if (ED_region_contains_xy(region, event_xy)) {
+ return region;
+ }
+ }
+ }
+
+ return NULL;
+}
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index 9f427a90353..27c8aa532f2 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -1030,6 +1030,27 @@ typedef char *(*WMDropboxTooltipFunc)(struct bContext *,
const int xy[2],
struct wmDropBox *drop);
+typedef struct wmDragActiveDropState {
+ /** Informs which dropbox is activated with the drag item.
+ * When this value changes, the #draw_activate and #draw_deactivate dropbox callbacks are
+ * triggered.
+ */
+ struct wmDropBox *active_dropbox;
+
+ /** If `active_dropbox` is set, the area it successfully polled in. To restore the context of it
+ * as needed. */
+ struct ScrArea *area_from;
+ /** If `active_dropbox` is set, the region it successfully polled in. To restore the context of
+ * it as needed. */
+ struct ARegion *region_from;
+
+ /** Text to show when a dropbox poll succeeds (so the dropbox itself is available) but the
+ * operator poll fails. Typically the message the operator set with
+ * CTX_wm_operator_poll_msg_set(). */
+ const char *disabled_info;
+ bool free_disabled_info;
+} wmDragActiveDropState;
+
typedef struct wmDrag {
struct wmDrag *next, *prev;
@@ -1045,15 +1066,7 @@ typedef struct wmDrag {
float scale;
int sx, sy;
- /** Informs which dropbox is activated with the drag item.
- * When this value changes, the #draw_activate and #draw_deactivate dropbox callbacks are
- * triggered.
- */
- struct wmDropBox *active_dropbox;
- /* Text to show when the operator poll fails. Typically the message the
- * operator set with CTX_wm_operator_poll_msg_set(). */
- const char *disabled_info;
- bool free_disabled_info;
+ wmDragActiveDropState drop_state;
unsigned int flags;
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
index 37a101cc31d..85378ffd7c7 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.c
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -51,6 +51,7 @@
#include "BLO_readfile.h"
#include "ED_asset.h"
+#include "ED_screen.h"
#include "GPU_shader.h"
#include "GPU_state.h"
@@ -217,7 +218,7 @@ void wm_drags_exit(wmWindowManager *wm, wmWindow *win)
{
bool any_active = false;
LISTBASE_FOREACH (const wmDrag *, drag, &wm->drags) {
- if (drag->active_dropbox) {
+ if (drag->drop_state.active_dropbox) {
any_active = true;
break;
}
@@ -260,14 +261,14 @@ void WM_drag_data_free(int dragtype, void *poin)
void WM_drag_free(wmDrag *drag)
{
- if (drag->active_dropbox && drag->active_dropbox->draw_deactivate) {
- drag->active_dropbox->draw_deactivate(drag->active_dropbox, drag);
+ if (drag->drop_state.active_dropbox && drag->drop_state.active_dropbox->draw_deactivate) {
+ drag->drop_state.active_dropbox->draw_deactivate(drag->drop_state.active_dropbox, drag);
}
if (drag->flags & WM_DRAG_FREE_DATA) {
WM_drag_data_free(drag->type, drag->poin);
}
- if (drag->free_disabled_info) {
- MEM_SAFE_FREE(drag->disabled_info);
+ if (drag->drop_state.free_disabled_info) {
+ MEM_SAFE_FREE(drag->drop_state.disabled_info);
}
BLI_freelistN(&drag->ids);
LISTBASE_FOREACH_MUTABLE (wmDragAssetListItem *, asset_item, &drag->asset_items) {
@@ -306,10 +307,10 @@ static wmDropBox *dropbox_active(bContext *C,
wmDrag *drag,
const wmEvent *event)
{
- if (drag->free_disabled_info) {
- MEM_SAFE_FREE(drag->disabled_info);
+ if (drag->drop_state.free_disabled_info) {
+ MEM_SAFE_FREE(drag->drop_state.disabled_info);
}
- drag->disabled_info = NULL;
+ drag->drop_state.disabled_info = NULL;
LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) {
if (handler_base->type == WM_HANDLER_TYPE_DROPBOX) {
@@ -332,8 +333,8 @@ static wmDropBox *dropbox_active(bContext *C,
bool free_disabled_info = false;
const char *disabled_hint = CTX_wm_operator_poll_msg_get(C, &free_disabled_info);
if (disabled_hint) {
- drag->disabled_info = disabled_hint;
- drag->free_disabled_info = free_disabled_info;
+ drag->drop_state.disabled_info = disabled_hint;
+ drag->drop_state.free_disabled_info = free_disabled_info;
}
}
}
@@ -373,7 +374,7 @@ static void wm_drop_update_active(bContext *C, wmDrag *drag, const wmEvent *even
return;
}
- wmDropBox *drop_prev = drag->active_dropbox;
+ wmDropBox *drop_prev = drag->drop_state.active_dropbox;
wmDropBox *drop = wm_dropbox_active(C, drag, event);
if (drop != drop_prev) {
if (drop_prev && drop_prev->draw_deactivate) {
@@ -383,7 +384,9 @@ static void wm_drop_update_active(bContext *C, wmDrag *drag, const wmEvent *even
if (drop && drop->draw_activate) {
drop->draw_activate(drop, drag);
}
- drag->active_dropbox = drop;
+ drag->drop_state.active_dropbox = drop;
+ drag->drop_state.area_from = drop ? CTX_wm_area(C) : NULL;
+ drag->drop_state.region_from = drop ? CTX_wm_region(C) : NULL;
}
}
@@ -408,7 +411,7 @@ void wm_drags_check_ops(bContext *C, const wmEvent *event)
LISTBASE_FOREACH (wmDrag *, drag, &wm->drags) {
wm_drop_update_active(C, drag, event);
- if (drag->active_dropbox) {
+ if (drag->drop_state.active_dropbox) {
any_active = true;
}
}
@@ -819,14 +822,14 @@ static void wm_drag_draw_tooltip(bContext *C, wmWindow *win, wmDrag *drag, const
int iconsize = UI_DPI_ICON_SIZE;
int padding = 4 * UI_DPI_FAC;
- const char *tooltip = NULL;
- bool free_tooltip = false;
- if (drag->active_dropbox) {
- tooltip = dropbox_tooltip(C, drag, xy, drag->active_dropbox);
- free_tooltip = true;
+ char *tooltip = NULL;
+ if (drag->drop_state.active_dropbox) {
+ tooltip = dropbox_tooltip(C, drag, xy, drag->drop_state.active_dropbox);
}
- if (!tooltip && !drag->disabled_info) {
+ const bool has_disabled_info = drag->drop_state.disabled_info &&
+ drag->drop_state.disabled_info[0];
+ if (!tooltip && !has_disabled_info) {
return;
}
@@ -855,12 +858,10 @@ static void wm_drag_draw_tooltip(bContext *C, wmWindow *win, wmDrag *drag, const
if (tooltip) {
wm_drop_operator_draw(tooltip, x, y);
- if (free_tooltip) {
- MEM_freeN((void *)tooltip);
- }
+ MEM_freeN(tooltip);
}
- else if (drag->disabled_info) {
- wm_drop_redalert_draw(drag->disabled_info, x, y);
+ else if (has_disabled_info) {
+ wm_drop_redalert_draw(drag->drop_state.disabled_info, x, y);
}
}
@@ -905,22 +906,32 @@ void wm_drags_draw(bContext *C, wmWindow *win)
}
bScreen *screen = CTX_wm_screen(C);
+ /* To start with, use the area and region under the mouse cursor, just like event handling. The
+ * operator context may still override it. */
ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, UNPACK2(xy));
- ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_ANY, UNPACK2(xy));
- if (region) {
- BLI_assert(!CTX_wm_area(C) && !CTX_wm_region(C));
- CTX_wm_area_set(C, area);
- CTX_wm_region_set(C, region);
- }
+ ARegion *region = ED_area_find_region_xy_visual(area, RGN_TYPE_ANY, xy);
+ /* Will be overridden and unset eventually. */
+ BLI_assert(!CTX_wm_area(C) && !CTX_wm_region(C));
wmWindowManager *wm = CTX_wm_manager(C);
/* Should we support multi-line drag draws? Maybe not, more types mixed won't work well. */
GPU_blend(GPU_BLEND_ALPHA);
LISTBASE_FOREACH (wmDrag *, drag, &wm->drags) {
- if (drag->active_dropbox && drag->active_dropbox->draw) {
- drag->active_dropbox->draw(C, win, drag, xy);
- continue;
+ if (drag->drop_state.active_dropbox) {
+ CTX_wm_area_set(C, drag->drop_state.area_from);
+ CTX_wm_region_set(C, drag->drop_state.region_from);
+
+ /* Drawing should be allowed to assume the context from handling and polling (that's why we
+ * restore it above). */
+ if (drag->drop_state.active_dropbox->draw) {
+ drag->drop_state.active_dropbox->draw(C, win, drag, xy);
+ continue;
+ }
+ }
+ else if (region) {
+ CTX_wm_area_set(C, area);
+ CTX_wm_region_set(C, region);
}
wm_drag_draw_default(C, win, drag, xy);