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:
parent
6347519ab1
commit
4f97a431b9
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user