UI: Fix potential race condition for hover items

The graphics thread should not be accessing any Qt objects that aren't
guaranteed to exist.  Instead, store the currently hovering list/preview
scene items in the preview class.
master
jp9000 2019-02-11 15:27:38 -08:00
parent 7068e61fd9
commit 1b8ecae3b9
4 changed files with 25 additions and 25 deletions

View File

@ -1270,14 +1270,21 @@ void SourceTree::dropEvent(QDropEvent *event)
void SourceTree::mouseMoveEvent(QMouseEvent *event)
{
QPoint pos = event->pos();
SourceTreeItem *item = qobject_cast<SourceTreeItem *>
(childAt(pos));
SourceTreeItem *item = qobject_cast<SourceTreeItem *>(childAt(pos));
currentHover = item;
OBSBasicPreview *preview = OBSBasicPreview::Get();
preview->hoveredListItem = !!item ? item->sceneitem : nullptr;
QListView::mouseMoveEvent(event);
}
void SourceTree::leaveEvent(QEvent *event)
{
OBSBasicPreview *preview = OBSBasicPreview::Get();
preview->hoveredListItem = nullptr;
QListView::leaveEvent(event);
}
void SourceTree::selectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected)

View File

@ -142,8 +142,6 @@ class SourceTree : public QListView {
return reinterpret_cast<SourceTreeModel *>(model());
}
SourceTreeItem *currentHover;
public:
inline SourceTreeItem *GetItemWidget(int idx)
{
@ -151,14 +149,6 @@ public:
return reinterpret_cast<SourceTreeItem *>(widget);
}
inline SourceTreeItem *GetHoveredItem()
{
if (underMouse()) {
return currentHover;
}
return nullptr;
}
explicit SourceTree(QWidget *parent = nullptr);
inline bool IgnoreReorder() const {return ignoreReorder;}
@ -186,6 +176,7 @@ protected:
virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
virtual void dropEvent(QDropEvent *event) override;
virtual void mouseMoveEvent(QMouseEvent *event) override;
virtual void leaveEvent(QEvent *event) override;
virtual void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) override;
};

View File

@ -616,7 +616,7 @@ void OBSBasicPreview::mouseReleaseEvent(QMouseEvent *event)
cropping = false;
OBSSceneItem item = GetItemAtPos(pos, true);
hovered = item;
hoveredPreviewItem = item;
}
}
@ -1163,7 +1163,7 @@ void OBSBasicPreview::mouseMoveEvent(QMouseEvent *event)
return;
if (mouseDown) {
hovered = nullptr;
hoveredPreviewItem = nullptr;
vec2 pos = GetMouseEventPos(event);
@ -1205,13 +1205,13 @@ void OBSBasicPreview::mouseMoveEvent(QMouseEvent *event)
vec2 pos = GetMouseEventPos(event);
OBSSceneItem item = GetItemAtPos(pos, true);
hovered = item;
hoveredPreviewItem = item;
}
}
void OBSBasicPreview::leaveEvent(QEvent *event)
{
hovered = nullptr;
hoveredPreviewItem = nullptr;
UNUSED_PARAMETER(event);
}
@ -1408,16 +1408,14 @@ bool OBSBasicPreview::DrawSelectedItem(obs_scene_t *scene,
gs_matrix_pop();
}
OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow());
OBSBasicPreview *prev = reinterpret_cast<OBSBasicPreview*>(param);
OBSBasic *main = OBSBasic::Get();
SourceTreeItem *hovItem = main->ui->sources->GetHoveredItem();
SourceTreeItem *curItem = main->GetItemWidgetFromSceneItem(item);
bool hover = (curItem && hovItem == curItem) || prev->hovered == item;
bool hovered = prev->hoveredPreviewItem == item ||
prev->hoveredListItem == item;
bool selected = obs_sceneitem_selected(item);
if (!selected && !hover)
if (!selected && !hovered)
return true;
matrix4 boxTransform;
@ -1466,7 +1464,7 @@ bool OBSBasicPreview::DrawSelectedItem(obs_scene_t *scene,
if (info.bounds_type == OBS_BOUNDS_NONE && crop_enabled(&crop)) {
#define DRAW_SIDE(side, x1, y1, x2, y2) \
if (hover && !selected) \
if (hovered && !selected) \
gs_effect_set_vec4(colParam, &blue); \
else if (crop.side > 0) \
gs_effect_set_vec4(colParam, &green); \

View File

@ -31,6 +31,8 @@ enum class ItemHandle : uint32_t {
class OBSBasicPreview : public OBSQTDisplay {
Q_OBJECT
friend class SourceTree;
private:
obs_sceneitem_crop startCrop;
vec2 startItemPos;
@ -56,10 +58,12 @@ private:
bool locked = false;
bool scrollMode = false;
bool fixedScaling = false;
OBSSceneItem hovered = nullptr;
int32_t scalingLevel = 0;
float scalingAmount = 1.0f;
obs_sceneitem_t *hoveredPreviewItem = nullptr;
obs_sceneitem_t *hoveredListItem = nullptr;
static vec2 GetMouseEventPos(QMouseEvent *event);
static bool DrawSelectedOverflow(obs_scene_t *scene,
obs_sceneitem_t *item, void *param);