Deskbar: Make Vulcan Death Grip work in mini-mode

Refactor so that ExpandoMenuBar and TeamMenu both call the menu item
TeamMenuItem::HandleMouseDown() method to do the actual work and then
send a message to cleanup.

Fixes #17761

Change-Id: I0e13e5fc6c90236936120ff0dda1246123576d37
Reviewed-on: https://review.haiku-os.org/c/haiku/+/6311
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
This commit is contained in:
John Scipione 2023-04-08 01:26:39 -04:00 committed by waddlesplash
parent 6347519ab1
commit 4f97a431b9
6 changed files with 197 additions and 75 deletions

View File

@ -71,9 +71,6 @@ All rights reserved.
#include "WindowMenuItem.h" #include "WindowMenuItem.h"
const uint32 kMinimizeTeam = 'mntm';
const uint32 kBringTeamToFront = 'bftm';
bool TExpandoMenuBar::sDoMonitor = false; bool TExpandoMenuBar::sDoMonitor = false;
thread_id TExpandoMenuBar::sMonThread = B_ERROR; thread_id TExpandoMenuBar::sMonThread = B_ERROR;
BLocker TExpandoMenuBar::sMonLocker("expando monitor"); BLocker TExpandoMenuBar::sMonLocker("expando monitor");
@ -222,8 +219,7 @@ TExpandoMenuBar::MessageReceived(BMessage* message)
break; break;
TShowHideMenuItem::TeamShowHideCommon(B_MINIMIZE_WINDOW, TShowHideMenuItem::TeamShowHideCommon(B_MINIMIZE_WINDOW,
item->Teams(), item->Teams(), item->Menu()->ConvertToScreen(item->Frame()),
item->Menu()->ConvertToScreen(item->Frame()),
true); true);
break; break;
} }
@ -251,80 +247,57 @@ TExpandoMenuBar::MessageReceived(BMessage* message)
void void
TExpandoMenuBar::MouseDown(BPoint where) TExpandoMenuBar::MouseDown(BPoint where)
{ {
BMessage* message = Window()->CurrentMessage(); if (fBarView == NULL || fBarView->Dragging())
BMenuItem* menuItem; return BMenuBar::MouseDown(where);
TTeamMenuItem* item = TeamItemAtPoint(where, &menuItem);
fLastClickedItem = item;
if (message == NULL || item == NULL || fBarView == NULL BMessage* message = Window()->CurrentMessage();
|| fBarView->Dragging()) { BMenuItem* item = ItemAtPoint(where);
BMenuBar::MouseDown(where); fLastClickedItem = item;
return; if (message == NULL || item == NULL)
} return BMenuBar::MouseDown(where);
int32 modifiers = 0; int32 modifiers = 0;
int32 buttons = 0; int32 buttons = 0;
message->FindInt32("modifiers", &modifiers); message->FindInt32("modifiers", &modifiers);
message->FindInt32("buttons", &buttons); message->FindInt32("buttons", &buttons);
// check for three finger salute, a.k.a. Vulcan Death Grip // close window item
if ((modifiers & B_COMMAND_KEY) != 0 if ((modifiers & B_SHIFT_KEY) != 0
&& (modifiers & B_CONTROL_KEY) != 0
&& (modifiers & B_SHIFT_KEY) != 0) {
const BList* teams = item->Teams();
int32 teamCount = teams->CountItems();
team_id teamID;
for (int32 team = 0; team < teamCount; team++) {
teamID = (addr_t)teams->ItemAt(team);
kill_team(teamID);
RemoveTeam(teamID, false);
// remove the team from display immediately
}
return;
// absorb the message
} else if (item != NULL
&& (modifiers & B_SHIFT_KEY) == 0
&& (buttons & B_TERTIARY_MOUSE_BUTTON) != 0) { && (buttons & B_TERTIARY_MOUSE_BUTTON) != 0) {
be_roster->Launch(item->Signature()); TWindowMenuItem* wItem = dynamic_cast<TWindowMenuItem*>(item);
return; if (wItem != NULL) {
// absorb the message // we have a window item
} else { BMessenger messenger;
TWindowMenuItem* wndItem = dynamic_cast<TWindowMenuItem*>(menuItem); client_window_info* info = get_window_info(wItem->ID());
if (wndItem != NULL if (info != NULL) {
&& (modifiers & B_SHIFT_KEY) != 0 BMessenger::Private(messenger).SetTo(info->team,
&& (buttons & B_TERTIARY_MOUSE_BUTTON) != 0) { info->client_port, info->client_token);
// close window messenger.SendMessage(B_QUIT_REQUESTED);
client_window_info* info; free(info);
BMessenger wnd; return;
info = get_window_info(wndItem->ID()); // absorb the message
if (info == NULL) return; }
BMessenger::Private(wnd).SetTo(
info->team, info->client_port, info->client_token);
free(info); info = NULL;
wnd.SendMessage(B_QUIT_REQUESTED);
return;
// absorb the message
} }
} }
// control click - show all/hide all shortcut // below depends on item being a team item
if ((modifiers & B_CONTROL_KEY) != 0) {
// show/hide item's teams TTeamMenuItem* teamItem = dynamic_cast<TTeamMenuItem*>(item);
BMessage showMessage((modifiers & B_SHIFT_KEY) != 0 if (teamItem == NULL)
? kMinimizeTeam : kBringTeamToFront); return BMenuBar::MouseDown(where);
showMessage.AddInt32("itemIndex", IndexOf(item));
Window()->PostMessage(&showMessage, this); // check for three finger salute, a.k.a. Vulcan Death Grip
if (teamItem->HandleMouseDown(where))
return; return;
// absorb the message // absorb the message
}
// check if within expander bounds to expand window items // check if within expander bounds to expand window items
if (Vertical() && static_cast<TBarApp*>(be_app)->Settings()->superExpando if (Vertical() && static_cast<TBarApp*>(be_app)->Settings()->superExpando
&& item->ExpanderBounds().Contains(where)) { && teamItem->ExpanderBounds().Contains(where)) {
// start the animation here, finish on mouse up // start the animation here, finish on mouse up
item->SetArrowDirection(BControlLook::B_RIGHT_DOWN_ARROW); teamItem->SetArrowDirection(BControlLook::B_RIGHT_DOWN_ARROW);
SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY); SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY);
Invalidate(item->ExpanderBounds()); Invalidate(teamItem->ExpanderBounds());
return; return;
// absorb the message // absorb the message
} }
@ -335,9 +308,8 @@ TExpandoMenuBar::MouseDown(BPoint where)
get_click_speed(&clickSpeed); get_click_speed(&clickSpeed);
bigtime_t delta = system_time() - fLastClickTime; bigtime_t delta = system_time() - fLastClickTime;
if (message->FindInt32("clicks", &clicks) == B_OK && clicks > 1 if (message->FindInt32("clicks", &clicks) == B_OK && clicks > 1
&& item == menuItem && item == fLastClickedItem && item == fLastClickedItem && delta <= clickSpeed) {
&& delta <= clickSpeed) { be_roster->ActivateApp((addr_t)teamItem->Teams()->ItemAt(0));
be_roster->ActivateApp((addr_t)item->Teams()->ItemAt(0));
// activate this team // activate this team
return; return;
// absorb the message // absorb the message
@ -489,15 +461,18 @@ TExpandoMenuBar::MouseMoved(BPoint where, uint32 code, const BMessage* message)
void void
TExpandoMenuBar::MouseUp(BPoint where) TExpandoMenuBar::MouseUp(BPoint where)
{ {
TTeamMenuItem* lastItem = dynamic_cast<TTeamMenuItem*>(fLastClickedItem);
fLastClickedItem = NULL;
if (fBarView != NULL && fBarView->Dragging()) { if (fBarView != NULL && fBarView->Dragging()) {
_FinishedDrag(true); _FinishedDrag(true);
return; return;
// absorb the message // absorb the message
} }
if (fLastClickedItem == NULL)
return BMenuBar::MouseUp(where);
TTeamMenuItem* lastItem = dynamic_cast<TTeamMenuItem*>(fLastClickedItem);
fLastClickedItem = NULL;
if (Vertical() && static_cast<TBarApp*>(be_app)->Settings()->superExpando if (Vertical() && static_cast<TBarApp*>(be_app)->Settings()->superExpando
&& lastItem != NULL && lastItem->ExpanderBounds().Contains(where)) { && lastItem != NULL && lastItem->ExpanderBounds().Contains(where)) {
lastItem->ToggleExpandState(true); lastItem->ToggleExpandState(true);
@ -507,6 +482,7 @@ TExpandoMenuBar::MouseUp(BPoint where)
Invalidate(lastItem->ExpanderBounds()); Invalidate(lastItem->ExpanderBounds());
} }
BMenuBar::MouseUp(where); BMenuBar::MouseUp(where);
} }
@ -626,6 +602,21 @@ TExpandoMenuBar::InDeskbarMenu(BPoint loc) const
} }
BMenuItem*
TExpandoMenuBar::ItemAtPoint(BPoint point)
{
int32 itemCount = CountItems();
for (int32 index = 0; index < itemCount; index++) {
BMenuItem* item = ItemAt(index);
if (item != NULL && item->Frame().Contains(point))
return item;
}
// no item found
return NULL;
}
/*! Returns the team menu item that belongs to the item under the /*! Returns the team menu item that belongs to the item under the
specified \a point. specified \a point.
If \a _item is given, it will return the exact menu item under If \a _item is given, it will return the exact menu item under
@ -637,13 +628,12 @@ TExpandoMenuBar::TeamItemAtPoint(BPoint point, BMenuItem** _item)
TTeamMenuItem* lastApp = NULL; TTeamMenuItem* lastApp = NULL;
int32 itemCount = CountItems(); int32 itemCount = CountItems();
for (int32 i = 0; i < itemCount; i++) { for (int32 index = 0; index < itemCount; index++) {
BMenuItem* item = ItemAt(i); BMenuItem* item = ItemAt(index);
if (item != NULL && item->Frame().Contains(point)) {
if (dynamic_cast<TTeamMenuItem*>(item) != NULL)
lastApp = (TTeamMenuItem*)item;
if (dynamic_cast<TTeamMenuItem*>(item) != NULL)
lastApp = (TTeamMenuItem*)item;
if (item && item->Frame().Contains(point)) {
if (_item != NULL) if (_item != NULL)
*_item = item; *_item = item;

View File

@ -83,6 +83,7 @@ public:
void BuildItems(); void BuildItems();
BMenuItem* ItemAtPoint(BPoint point);
TTeamMenuItem* TeamItemAtPoint(BPoint location, TTeamMenuItem* TeamItemAtPoint(BPoint location,
BMenuItem** _item = NULL); BMenuItem** _item = NULL);
bool InDeskbarMenu(BPoint) const; bool InDeskbarMenu(BPoint) const;

View File

@ -191,3 +191,64 @@ TTeamMenu::DetachedFromWindow()
BMessenger self(this); BMessenger self(this);
TBarApp::Unsubscribe(self); TBarApp::Unsubscribe(self);
} }
void
TTeamMenu::MessageReceived(BMessage* message)
{
TTeamMenuItem* item = NULL;
switch (message->what) {
case B_SOME_APP_QUIT:
case kRemoveTeam:
{
int32 itemIndex = -1;
message->FindInt32("itemIndex", &itemIndex);
team_id team = -1;
message->FindInt32("team", &team);
item = dynamic_cast<TTeamMenuItem*>(ItemAt(itemIndex));
if (item != NULL && item->Teams()->HasItem((void*)(addr_t)team)) {
item->Teams()->RemoveItem(team);
RemoveItem(itemIndex);
delete item;
}
break;
}
default:
BMenu::MessageReceived(message);
break;
}
}
void
TTeamMenu::MouseDown(BPoint where)
{
if (fBarView == NULL || fBarView->Dragging())
return BMenu::MouseDown(where);
BMenuItem* item = ItemAtPoint(where);
if (item == NULL)
return BMenu::MouseDown(where);
TTeamMenuItem* teamItem = dynamic_cast<TTeamMenuItem*>(item);
if (teamItem == NULL || !teamItem->HandleMouseDown(where))
BMenu::MouseDown(where);
}
BMenuItem*
TTeamMenu::ItemAtPoint(BPoint point)
{
int32 itemCount = CountItems();
for (int32 index = 0; index < itemCount; index++) {
BMenuItem* item = ItemAt(index);
if (item != NULL && item->Frame().Contains(point))
return item;
}
// no item found
return NULL;
}

View File

@ -50,8 +50,12 @@ class TTeamMenu : public BMenu {
public: public:
TTeamMenu(TBarView* barView = NULL); TTeamMenu(TBarView* barView = NULL);
void AttachedToWindow(); virtual void AttachedToWindow();
void DetachedFromWindow(); virtual void DetachedFromWindow();
virtual void MessageReceived(BMessage* message);
virtual void MouseDown(BPoint where);
BMenuItem* ItemAtPoint(BPoint point);
static int CompareByName(const void* first, static int CompareByName(const void* first,
const void* second); const void* second);

View File

@ -50,6 +50,7 @@ All rights reserved.
#include <Region.h> #include <Region.h>
#include <Roster.h> #include <Roster.h>
#include <Resources.h> #include <Resources.h>
#include <Window.h>
#include "BarApp.h" #include "BarApp.h"
#include "BarMenuBar.h" #include "BarMenuBar.h"
@ -94,6 +95,67 @@ TTeamMenuItem::~TTeamMenuItem()
} }
/*! Vulcan Death Grip and other team mouse button handling
\returns true if handled, false otherwise
*/
bool
TTeamMenuItem::HandleMouseDown(BPoint where)
{
BMenu* menu = Menu();
if (menu == NULL)
return false;
BWindow* window = menu->Window();
if (window == NULL)
return false;
BMessage* message = window->CurrentMessage();
if (message == NULL)
return false;
int32 modifiers = 0;
int32 buttons = 0;
message->FindInt32("modifiers", &modifiers);
message->FindInt32("buttons", &buttons);
// check for three finger salute, a.k.a. Vulcan Death Grip
if ((modifiers & B_COMMAND_KEY) != 0
&& (modifiers & B_CONTROL_KEY) != 0
&& (modifiers & B_SHIFT_KEY) != 0) {
BMessage appMessage(B_SOME_APP_QUIT);
int32 teamCount = fTeam->CountItems();
BMessage quitMessage(teamCount == 1 ? B_SOME_APP_QUIT : kRemoveTeam);
quitMessage.AddInt32("itemIndex", menu->IndexOf(this));
for (int32 index = 0; index < teamCount; index++) {
team_id team = (addr_t)fTeam->ItemAt(index);
appMessage.AddInt32("be:team", team);
quitMessage.AddInt32("team", team);
kill_team(team);
}
be_app->PostMessage(&appMessage);
TExpandoMenuBar* expando = dynamic_cast<TExpandoMenuBar*>(menu);
window->PostMessage(&quitMessage, expando != NULL ? expando : menu);
return true;
} else if ((modifiers & B_SHIFT_KEY) == 0
&& (buttons & B_TERTIARY_MOUSE_BUTTON) != 0) {
// launch new team
be_roster->Launch(Signature());
return true;
} else if ((modifiers & B_CONTROL_KEY) != 0) {
// control click - show all/hide all shortcut
BMessage showMessage((modifiers & B_SHIFT_KEY) != 0
? kMinimizeTeam : kBringTeamToFront);
showMessage.AddInt32("itemIndex", menu->IndexOf(this));
window->PostMessage(&showMessage, menu);
return true;
}
return false;
}
status_t status_t
TTeamMenuItem::Invoke(BMessage* message) TTeamMenuItem::Invoke(BMessage* message)
{ {

View File

@ -46,6 +46,9 @@ All rights reserved.
const float kSwitchWidth = 12.0f; const float kSwitchWidth = 12.0f;
const uint32 kMinimizeTeam = 'mntm';
const uint32 kBringTeamToFront = 'bftm';
class BBitmap; class BBitmap;
class TBarView; class TBarView;
@ -60,6 +63,7 @@ public:
float height = -1.0f); float height = -1.0f);
virtual ~TTeamMenuItem(); virtual ~TTeamMenuItem();
bool HandleMouseDown(BPoint where);
status_t Invoke(BMessage* message = NULL); status_t Invoke(BMessage* message = NULL);
void SetOverrideWidth(float width) void SetOverrideWidth(float width)