Skip to content

frontend: Clean up and adjustments to SceneTree - #13622

Open
Warchamp7 wants to merge 5 commits into
obsproject:masterfrom
Warchamp7:scene-tree-drag-tweak
Open

Warchamp7 wants to merge 5 commits into
obsproject:masterfrom
Warchamp7:scene-tree-drag-tweak

Conversation

@Warchamp7

@Warchamp7 Warchamp7 commented Jul 4, 2026 •

Copy link
Copy Markdown
Member

Description

A medley of clean up to the SceneTree widget.

Pile o' commits:

  • Split out scene tree grid calculation
    • Moved this logic into it's own function rather than the hacky approach of forcing a resizeEvent which might have other side effects
  • Remove empty eventFilter
    • Function is empty and always has been since it was added? Perhaps a misunderstanding of Qt from years ago.
  • Remove deferred scenesReordered signal
  • Block signals while updating the grid list
    • This also fixes a bug where reordering the grid list caused OBS to swap to the scene at the target index and then immediately swap back to the scene being dragged. Visually this bug was invisible until libobs: Fix interrupted transitions #13088 fixed interrupted transitions.
  • Restore old safety guard on selectionChanged
    • An old QTBUG allowed the scene to be deselected by clicking in the empty area of the QList. This was (allegedly) fixed at some point, however it is still possible to deselect the scene by clicking and dragging in the empty area now sooo we need this guard again.
  • Simplify grid reordering logic
    • There's a lot going on here and I will type it up later.
  • Adjust style refresh logic
    • Polish the widget instead of setting/clearing a stylesheet.
  • Codestyle cleanup

Motivation and Context

Originally I was trying to chase down a UI deadlock a friend ran into when changing scenes. In the DMP I received from them, the main thread was stuck inside the SceneTree's drag event. I have yet to determine if the SceneTree was actually responsible in any way for that lock up, but looking around at what could have potentially caused it led me to the resizeEvent stuff.

How Has This Been Tested?

Tested all the functionality I changed. Reordered scenes in grid mode, adjusted the scene tree styling locally. Resized the dock before and after reordering items. Ensured Multiview behaved correctly in list and grid mode when making changes.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • Tweak (non-breaking change to improve existing functionality)
  • Code cleanup (non-breaking change which makes code smaller or more readable)

Checklist:

  • I have read the contributing document.
  • My code has been run through clang-format.
  • My code follows the project's style guidelines
  • My code has been tested.
  • All commit messages are properly formatted and commits squashed where appropriate.
  • I have included updates to all appropriate documentation.

@Warchamp7 Warchamp7 added kind/bug Categorizes issue or PR as related to a bug. kind/cleanup Non-breaking change which makes code smaller or more readable area/ui-ux Anything to do with changes or additions to UI/UX elements. kind/tech-debt labels Jul 4, 2026
Comment thread frontend/components/SceneTree.cpp Resolved
Comment thread frontend/components/SceneTree.hpp Resolved
@RytoEX
RytoEX requested a review from PatTheMav August 25, 2026 17:18
Comment thread frontend/components/SceneTree.cpp Resolved
scrollWid = 0;
} else {
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
QListWidgetItem *draggedItem = takeItem(selectedIndexes().first().row());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

This is in context of commit 4dbc053. As stated in our contribution guidelines, all commits need to be "atomic" and represent a whole unit of change.

Just so I understand the logic right:

  • You first take a pointer to the first of all selected items (because one could select multiple non-consecutive items and drag them).
    • What is the order of items in the list returned by selectedIndexes()? Is it order of actual selection or ordered by their row numbers in the original data model?
  • Then you insert just this single item after the lastTargetRow, which will be -1 by default, thus representing the top of the list.
  • Then you set the inserted item as the "current" item (so it is selected by default, which will also trigger a whole lot of other "selection changed" events, scene changes, etc.)

At a cursory glance (and proven by testing this code change), this leads to an endless loop: There is always a selected item in the scene list, so you take the current item and reinsert it at the first position.

This triggers the resizeEvent again, which... reinserts the same item and triggers the resizeEvent, and on and on it goes until it corrupts the stack pointer.

At the same time this also triggers scene switch events over and over again. With just two scenes I get this in my log:

info: User switched to scene 'Scene 2'
info: User switched to scene 'Scene'
info: User switched to scene 'Scene 2'
info: User switched to scene 'Scene'
info: User switched to scene 'Scene 2'
info: User switched to scene 'Scene'

And that's just from switching to "Grid Mode" without any reordering involved.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The signal blocker should be preventing that sort of recursion. I'll investigate.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, but it looks like commit 4dbc053 leaves the project in a broken state because only a later commit introduces the signal blocker changes. So you'd have to squash these commits to ensure that you still end up in a working state e.g. during bisecting.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah okay, are you saying that commit has these issues or the PR as a whole exhibits this infinite loop? I was probably gonna squash the commits.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah okay, are you saying that commit has these issues or the PR as a whole exhibits this infinite loop? I was probably gonna squash the commits.

Yeah squashing them in the right way will probably resolve this automatically. But per our contribution guidelines I'm checking code commit by commit as that's the expectation for initial (and final) reviews.

@Warchamp7 Warchamp7 Sep 2, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In regards to the actual problem itself:

At a cursory glance (and proven by testing this code change), this leads to an endless loop: There is always a selected item in the scene list, so you take the current item and reinsert it at the first position.

Welcome to the wonderful world of Current Behaviour! We were getting lucky before by offloading this logic into the resizeEvent. Reordering scenes in grid mode on stable actually switches to the scene in the index after the dragged item, and then immediately back to the dragged item. Code that works vs code that doesn't break etc.

Commits have been squashed and should be properly atomic now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will give it another quick spin, though IIRC it all worked on the last commit before.

@Warchamp7
Warchamp7 force-pushed the scene-tree-drag-tweak branch 3 times, most recently from 45ddfed to 2410de9 Compare September 2, 2026 19:14
@github-project-automation github-project-automation Bot moved this to Ready For Review in Next Release Tracker (33.2) Sep 4, 2026
@Warchamp7 Warchamp7 moved this from Ready For Review to Ready For Merge in Next Release Tracker (33.2) Sep 4, 2026
@Warchamp7 Warchamp7 added this to the OBS Studio 33.2 milestone Nov 9, 2026
Moves the grid recalculation behaviour into a dedicated function
instead of performing it as part of resizeEvent and manually triggering
resizeEvents. This event is not always fired when you might expect, and
triggering a resizeEvent manually can have unintended side effects.

This blocks signals during the recalculation to ensure there is no
potential for recursive resizeEvent churn.

Fixes an issue on stable where reordering scenes in grid mode actually
switches to the scene at the index after the dragged item, and then
immediately back to the dragged item, when dropping the dragged item.
This eventFilter is empty and does nothing. I am unsure what it's
purpose was as it has always been empty.
An old QTBUG allowed the scene to be deselected by clicking in the empty
area of the QList. This was fixed at some point, however it is still
possible to deselect the scene by clicking and dragging in the empty
area now sooo we need this guard again.
Polish the widget instead of setting/clearing a stylesheet.
@Warchamp7
Warchamp7 force-pushed the scene-tree-drag-tweak branch from 2410de9 to 4c87c38 Compare November 10, 2026 15:37

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/ui-ux Anything to do with changes or additions to UI/UX elements. kind/bug Categorizes issue or PR as related to a bug. kind/cleanup Non-breaking change which makes code smaller or more readable kind/tech-debt

Projects

Status: Ready For Merge

Development

Successfully merging this pull request may close these issues.

3 participants