Tracker: Unselect all except clicked pose if >1 pose selected

... and we're not extending the selection or dragging.

Done on MouseUp() to allow for drag & drop. Fixes #20043.

More fixes included in this commit:
* Refactor BPoseView::MouseUp() code dealing with selection and
  popping menu. Don't consider fAllowPoseEditing for selection.
* Command **and Shift** extend selection.
* Create BPoseView::ExtendSelection() convenience method
  (also used in mouse down).
* List view/icon view loc "fix". Code worked before because index
  is 0 in icon mode but be explicit about pose location in list mode
  vs. icon mode anyway.
* Add ASSERT() for Window() and CurrentMessage() to BPoseView::MouseUp().
  We were already assuming they weren't NULL and it would have crashed
  if they were.
* Replace pose with clickedPose style fix (meaning is clearer).
* Comment update for "last_buttons" message param.

Change-Id: I3ecb035dbca8b343c230f1e6aee3070939a4a3f6
Reviewed-on: https://review.haiku-os.org/c/haiku/+/10814
Haiku-Format: Haiku-format Bot <[email protected]>
Reviewed-by: John Scipione <[email protected]>
Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
John Scipione
2026-04-26 20:54:09 +00:00
parent a682ccd899
commit 87dc1df680
2 changed files with 79 additions and 41 deletions
+64 -41
View File
@@ -7162,20 +7162,22 @@ BPoseView::ShowContextMenu(BPoint where)
// handle pose selection
int32 index;
BPose* pose = FindPose(where, &index);
if (pose != NULL) {
if (!pose->IsSelected()) {
BPose* clickedPose = FindPose(where, &index);
if (clickedPose != NULL) {
if (!clickedPose->IsSelected()) {
ClearSelection();
pose->Select(true);
fSelectionList->AddItem(pose);
DrawPose(pose, index, false);
clickedPose->Select(true);
fSelectionList->AddItem(clickedPose);
DrawPose(clickedPose, index, false);
}
} else
} else {
ClearSelection();
}
window->Activate();
window->UpdateIfNeeded();
window->ShowContextMenu(where, pose == NULL ? NULL : pose->TargetModel()->EntryRef());
const entry_ref* ref = (clickedPose == NULL ? NULL : clickedPose->TargetModel()->EntryRef());
window->ShowContextMenu(where, ref);
if (fSelectionChangedHook)
window->SelectionChanged();
@@ -7380,9 +7382,9 @@ BPoseView::MouseDragged(const BMessage* message)
bool extendSelection = (modifiers() & B_COMMAND_KEY) != 0 && fMultipleSelection;
int32 index;
BPose* pose = FindPose(where, &index);
if (pose != NULL)
DragSelectedPoses(pose, where, buttons);
BPose* clickedPose = FindPose(where, &index);
if (clickedPose != NULL)
DragSelectedPoses(clickedPose, where, buttons);
else if (buttons == B_PRIMARY_MOUSE_BUTTON)
_BeginSelectionRect(where, extendSelection);
}
@@ -7447,26 +7449,29 @@ BPoseView::MouseDown(BPoint where)
bool secondaryMouseButtonDown = SecondaryMouseButtonDown(mods, buttons);
fTrackRightMouseUp = secondaryMouseButtonDown;
fTrackMouseUp = !secondaryMouseButtonDown;
bool extendSelection = (mods & B_COMMAND_KEY) != 0 && fMultipleSelection;
bool extendSelection = ExtendSelection();
CommitActivePose();
int32 index;
BPose* pose = FindPose(where, &index);
if (pose != NULL) {
if (!pose->IsSelected() || !secondaryMouseButtonDown)
AddRemoveSelectionRange(where, extendSelection, pose);
BPose* clickedPose = FindPose(where, &index);
if (clickedPose != NULL) {
if (!clickedPose->IsSelected() || !secondaryMouseButtonDown)
AddRemoveSelectionRange(where, extendSelection, clickedPose);
if (fTextWidgetToCheck != NULL && (pose != fLastClickedPose || secondaryMouseButtonDown))
if (fTextWidgetToCheck != NULL
&& (clickedPose != fLastClickedPose || secondaryMouseButtonDown)) {
fTextWidgetToCheck->CancelWait();
}
if (!extendSelection && WasDoubleClick(pose, where) && buttons == B_PRIMARY_MOUSE_BUTTON
&& fLastClickButtons == B_PRIMARY_MOUSE_BUTTON && (mods & B_CONTROL_KEY) == 0) {
if (!extendSelection && WasDoubleClick(clickedPose, where)
&& buttons == B_PRIMARY_MOUSE_BUTTON && fLastClickButtons == B_PRIMARY_MOUSE_BUTTON
&& (mods & B_CONTROL_KEY) == 0) {
fTrackRightMouseUp = false;
fTrackMouseUp = false;
// special handling for path field double-clicks
if (!WasClickInPath(pose, index, where))
OpenSelection(pose, &index);
if (!WasClickInPath(clickedPose, index, where))
OpenSelection(clickedPose, &index);
}
} else {
// click was not in any pose
@@ -7502,35 +7507,53 @@ BPoseView::SetTextWidgetToCheck(BTextWidget* widget, BTextWidget* old)
void
BPoseView::MouseUp(BPoint where)
{
if (fSelectionRectInfo.isDragging)
ASSERT(Window() != NULL);
ASSERT(Window()->CurrentMessage() != NULL);
bool wasDragging = fDragMessage != NULL;
bool wasRectSelecting = fSelectionRectInfo.isDragging;
if (wasRectSelecting)
_EndSelectionRect();
// dispose of drag data from previous drag lazily
DragStop();
int32 index;
BPose* pose = FindPose(where, &index);
uint32 lastButtons = Window()->CurrentMessage()->FindInt32("last_buttons");
if (pose != NULL && fLastClickedPose != NULL && fAllowPoseEditing
&& !fTrackRightMouseUp) {
BPose* clickedPose = FindPose(where, &index);
if (clickedPose != NULL && fLastClickedPose != NULL) {
// This handy field has been added by the tracking filter.
// we need lastButtons for right button mouse-up tracking,
// because there's currently no way to know wich buttons were
// released in BView::MouseUp (unlike BView::KeyUp)
pose->MouseUp(BPoint(0, index * fListElemHeight), this, where, index);
}
// We need to know last buttons for context-click mouse up tracking,
// because there is no way to know which buttons were released in
// BView::MouseUp() (unlike BView::KeyUp()).
uint32 lastButtons = Window()->CurrentMessage()->FindInt32("last_buttons");
// Showing the pose context menu is done on mouse up (or long click)
// to make right button dragging possible
if (pose != NULL && fTrackRightMouseUp
&& (SecondaryMouseButtonDown(modifiers(), lastButtons))) {
if (!pose->IsSelected()) {
ClearSelection();
pose->Select(true);
fSelectionList->AddItem(pose);
DrawPose(pose, index, false);
if (!fTrackRightMouseUp) {
bool wasSelected = clickedPose->IsSelected();
BPoint loc;
if (ViewMode() == kListMode)
loc = BPoint(0, index * fListElemHeight);
else
loc = clickedPose->Location(this);
clickedPose->MouseUp(loc, this, where, index);
// reselect clicked pose
bool shouldSelect = wasSelected && !ExtendSelection();
bool dragging = wasDragging || wasRectSelecting;
if (shouldSelect && !dragging)
SelectPose(clickedPose, index);
} else if (SecondaryMouseButtonDown(modifiers(), lastButtons)) {
// Showing the pose context menu is done on mouse up (or long click)
// to make context-click (right-click) drag and drop possible.
if (!clickedPose->IsSelected()) {
ClearSelection();
clickedPose->Select(true);
fSelectionList->AddItem(clickedPose);
DrawPose(clickedPose, index, false);
}
ShowContextMenu(where);
}
ShowContextMenu(where);
}
if (fTrackMouseUp)
+15
View File
@@ -309,6 +309,8 @@ public:
void AddRemovePoseFromSelection(BPose* pose, int32 index,
bool select);
int32 CountSelected() const;
bool ExtendSelection() const;
bool SelectedVolumeIsReadOnly() const;
bool TargetVolumeIsReadOnly() const;
bool CanEditName() const;
@@ -925,12 +927,25 @@ BPoseView::SelectionList() const
return fSelectionList;
}
inline int32
BPoseView::CountSelected() const
{
return fSelectionList->CountItems();
}
inline bool
BPoseView::ExtendSelection() const
{
if (!fMultipleSelection)
return false;
uint32 mods = modifiers();
return (mods & B_COMMAND_KEY) != 0 || (mods & B_SHIFT_KEY) != 0;
}
inline BStringList*
BPoseView::MimeTypesInSelection()
{