Deskbar: Reimplement auto-raise/implement auto-lower

This changes auto-raise so that when the mouse moves over the screen edge
within the Deskbar window it raises Deskbar up and when the mouse leaves
the Deskbar window it lowers it back down again as described in #13304.

Activate Deskbar on click only if not in auto-raise mode and not in
always-on-top mode. In auto-raise mode click activates through foreground
windows, which we don't want. We don't ever want to activate Deskbar in
always-on-top mode because Deskbar is already on top and we don't want to
change the active window.

However, if a menu is opened on click in auto-raise Deskbar is raised and
stays on top as long as a menu remains open. Once menu is closed Deskbar
lowers back down again. Only lower Deskbar on menu close in auto-raise mode
if there isn't another menu open.

Don't raise/lower Deskbar if window has been dragged from the outside in
auto-raise mode.

Change bool fShowingMenu to int32 fMenusShown and use it to store a
reference count of open menus. In the previous design menus could be
opened from multiple locations clobbering the bool.

Add an fBarWindow member to BarView and initialize it in AttachedToWindow()
Use this throughout the class so that we don't have to keep getting it over
and over again. Also add an fBarApp member to BarWindow and use that
instead of creating it again and again.

Change order of methods in BarView to MouseDown(), MouseMoved(), then
MouseUp() because that order is both logical and alphabetical.

Fixes #15678, #13304

Change-Id: I076a452b26250d9eb9a4eccb4a6aa6f939e11d34
Reviewed-on: https://review.haiku-os.org/c/haiku/+/2281
Reviewed-by: Sergei Reznikov <diver@gelios.net>
Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
Reviewed-by: humdinger <humdingerb@gmail.com>
This commit is contained in:
John Scipione 2020-02-25 21:58:43 -05:00 committed by Adrien Destugues
parent a8cd19b641
commit 74ceffa889
4 changed files with 130 additions and 89 deletions

View File

@ -133,10 +133,13 @@ TBarView::TBarView(BRect frame, bool vertical, bool left, bool top,
:
BView(frame, "BarView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW),
fBarApp(static_cast<TBarApp*>(be_app)),
fBarWindow(NULL),
fInlineScrollView(NULL),
fBarMenuBar(NULL),
fExpandoMenuBar(NULL),
fTrayLocation(1),
fIsRaised(false),
fMouseDownOutside(false),
fVertical(vertical),
fTop(top),
fLeft(left),
@ -205,6 +208,8 @@ TBarView::AttachedToWindow()
{
BView::AttachedToWindow();
fBarWindow = dynamic_cast<TBarWindow*>(Window());
SetViewUIColor(B_MENU_BACKGROUND_COLOR);
SetFont(be_plain_font);
@ -297,6 +302,59 @@ TBarView::MessageReceived(BMessage* message)
}
void
TBarView::MouseDown(BPoint where)
{
// exit if menu or calendar is showing
if (fBarWindow == NULL || fBarWindow->IsShowingMenu()
|| fReplicantTray->fTime->IsShowingCalendar()) {
return BView::MouseDown(where);
}
// where is relative to status tray while mouse is over it so pull
// the screen point out of the message instead
BMessage* currentMessage = Window()->CurrentMessage();
if (currentMessage == NULL)
return BView::MouseDown(where);
desk_settings* settings = fBarApp->Settings();
bool alwaysOnTop = settings->alwaysOnTop;
bool autoRaise = settings->autoRaise;
bool autoHide = settings->autoHide;
BPoint whereScreen = currentMessage->GetPoint("screen_where",
ConvertToScreen(where));
fMouseDownOutside = !Window()->Frame().Contains(whereScreen);
if (fMouseDownOutside) {
// lower Deskbar
if (!alwaysOnTop && autoRaise && fIsRaised)
RaiseDeskbar(false);
// hide Deskbar
if (autoHide && !IsHidden())
HideDeskbar(true);
} else {
// Activate Deskbar on click only if not in auto-raise mode and not
// in always-on-top mode. In auto-raise mode click activates through
// foreground windows, which we don't want. We don't ever want to
// activate Deskbar in always-on-top mode because Deskbar is
// already on top and we don't want to change the active window.
if (!autoRaise && !alwaysOnTop)
Window()->Activate(true);
if ((modifiers() & (B_CONTROL_KEY | B_COMMAND_KEY | B_OPTION_KEY
| B_SHIFT_KEY)) == (B_CONTROL_KEY | B_COMMAND_KEY)) {
// The window key was pressed - enter dragging code
fDragRegion->MouseDown(fDragRegion->DragRegion().LeftTop());
return BView::MouseDown(where);
}
}
BView::MouseDown(where);
}
void
TBarView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
{
@ -316,12 +374,16 @@ TBarView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
SetEventMask(0);
return BView::MouseMoved(where, transit, dragMessage);
} else {
} else if (EventMask() != B_POINTER_EVENTS) {
// track mouse outside view
SetEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY);
}
bool isTopMost = Window()->Feel() == B_FLOATING_ALL_WINDOW_FEEL;
// exit if menu or calendar is showing
if (fBarWindow == NULL || fBarWindow->IsShowingMenu()
|| fReplicantTray->fTime->IsShowingCalendar()) {
return BView::MouseMoved(where, transit, dragMessage);
}
// where is relative to status tray while mouse is over it so pull
// the screen point out of the message instead
@ -332,32 +394,15 @@ TBarView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
BPoint whereScreen = currentMessage->GetPoint("screen_where",
ConvertToScreen(where));
BRect screenFrame = (BScreen(Window())).Frame();
bool onScreenEdge = whereScreen.x == screenFrame.left
|| whereScreen.x == screenFrame.right
|| whereScreen.y == screenFrame.top
|| whereScreen.y == screenFrame.bottom;
// Auto-Raise and Auto-Hide
if ((whereScreen.x == screenFrame.left
|| whereScreen.x == screenFrame.right
|| whereScreen.y == screenFrame.top
|| whereScreen.y == screenFrame.bottom)
&& Window()->Frame().Contains(whereScreen)) {
// cursor is on a screen edge within the window frame
// raise Deskbar
if (!alwaysOnTop && autoRaise && !isTopMost)
RaiseDeskbar(true);
// show Deskbar
if (autoHide && IsHidden())
HideDeskbar(false);
} else {
// stop if menu is showing or calendar is showing
TBarWindow* window = dynamic_cast<TBarWindow*>(Window());
if ((window != NULL && window->IsShowingMenu())
|| fReplicantTray->fTime->IsShowingCalendar()) {
return BView::MouseMoved(where, transit, dragMessage);
}
if (!Window()->Frame().Contains(whereScreen)) {
// lower Deskbar
if (!alwaysOnTop && autoRaise && isTopMost)
if (!alwaysOnTop && autoRaise && fIsRaised && !fMouseDownOutside)
RaiseDeskbar(false);
// check if cursor to bar distance is below threshold
@ -368,6 +413,16 @@ TBarView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
// hide Deskbar
HideDeskbar(true);
}
} else if (onScreenEdge) {
// cursor is on a screen edge within the window frame
// raise Deskbar
if (!alwaysOnTop && autoRaise && !fIsRaised && !fMouseDownOutside)
RaiseDeskbar(true);
// show Deskbar
if (autoHide && IsHidden())
HideDeskbar(false);
}
BView::MouseMoved(where, transit, dragMessage);
@ -375,53 +430,11 @@ TBarView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
void
TBarView::MouseDown(BPoint where)
TBarView::MouseUp(BPoint where)
{
// where is relative to status tray while mouse is over it so pull
// the screen point out of the message instead
BMessage* currentMessage = Window()->CurrentMessage();
if (currentMessage == NULL)
return BView::MouseDown(where);
fMouseDownOutside = false;
desk_settings* settings = fBarApp->Settings();
bool alwaysOnTop = settings->alwaysOnTop;
bool autoRaise = settings->autoRaise;
bool autoHide = settings->autoHide;
bool isTopMost = Window()->Feel() == B_FLOATING_ALL_WINDOW_FEEL;
BPoint whereScreen = currentMessage->GetPoint("screen_where",
ConvertToScreen(where));
if (Window()->Frame().Contains(whereScreen)) {
// don't activate window if calendar is showing
if (!fReplicantTray->fTime->IsShowingCalendar()
&& (alwaysOnTop || (autoRaise && isTopMost))) {
Window()->Activate();
}
if ((modifiers() & (B_CONTROL_KEY | B_COMMAND_KEY | B_OPTION_KEY
| B_SHIFT_KEY)) == (B_CONTROL_KEY | B_COMMAND_KEY)) {
// The window key was pressed - enter dragging code
fDragRegion->MouseDown(fDragRegion->DragRegion().LeftTop());
return BView::MouseDown(where);
}
} else {
// stop if menu is showing or calendar is showing
TBarWindow* window = dynamic_cast<TBarWindow*>(Window());
if ((window != NULL && window->IsShowingMenu())
|| fReplicantTray->fTime->IsShowingCalendar()) {
return BView::MouseDown(where);
}
// lower deskbar
if (!alwaysOnTop && autoRaise && isTopMost)
RaiseDeskbar(false);
// hide deskbar
if (autoHide && !IsHidden())
HideDeskbar(true);
}
BView::MouseDown(where);
BView::MouseUp(where);
}
@ -799,10 +812,14 @@ TBarView::_ChangeState(BMessage* message)
void
TBarView::RaiseDeskbar(bool raise)
{
if (raise)
fIsRaised = raise;
// raise or lower Deskbar without changing the active window
if (raise) {
Window()->SetFeel(B_FLOATING_ALL_WINDOW_FEEL);
else
Window()->SetFeel(B_NORMAL_WINDOW_FEEL);
} else
Window()->SendBehind(Window());
}
@ -810,19 +827,18 @@ void
TBarView::HideDeskbar(bool hide)
{
BRect screenFrame = (BScreen(Window())).Frame();
TBarWindow* barWindow = dynamic_cast<TBarWindow*>(Window());
if (hide) {
Hide();
if (barWindow != NULL)
barWindow->SetSizeLimits();
if (fBarWindow != NULL)
fBarWindow->SetSizeLimits();
PositionWindow(screenFrame);
SizeWindow(screenFrame);
} else {
Show();
if (barWindow != NULL)
barWindow->SetSizeLimits();
if (fBarWindow != NULL)
fBarWindow->SetSizeLimits();
SizeWindow(screenFrame);
PositionWindow(screenFrame);

View File

@ -69,6 +69,7 @@ const float kMaxPreventHidingDist = 80.0f;
class BShelf;
class TBarApp;
class TBarMenuBar;
class TBarWindow;
class TExpandoMenuBar;
class TReplicantTray;
class TDragRegion;
@ -89,9 +90,10 @@ public:
virtual void MessageReceived(BMessage* message);
virtual void MouseDown(BPoint where);
virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage);
virtual void MouseDown(BPoint where);
virtual void MouseUp(BPoint where);
void SaveSettings();
@ -186,6 +188,7 @@ private:
void _ChangeState(BMessage* message);
TBarApp* fBarApp;
TBarWindow* fBarWindow;
TInlineScrollView* fInlineScrollView;
TBarMenuBar* fBarMenuBar;
TExpandoMenuBar* fExpandoMenuBar;
@ -195,6 +198,9 @@ private:
TResizeControl* fResizeControl;
TReplicantTray* fReplicantTray;
bool fIsRaised : 1;
bool fMouseDownOutside : 1;
bool fVertical : 1;
bool fTop : 1;
bool fLeft : 1;

View File

@ -90,9 +90,11 @@ TBarWindow::TBarWindow()
| B_NOT_MINIMIZABLE | B_NOT_MOVABLE | B_NOT_V_RESIZABLE
| B_AVOID_FRONT | B_ASYNCHRONOUS_CONTROLS,
B_ALL_WORKSPACES),
fShowingMenu(false)
fBarApp(static_cast<TBarApp*>(be_app)),
fBarView(NULL),
fMenusShown(0)
{
desk_settings* settings = ((TBarApp*)be_app)->Settings();
desk_settings* settings = fBarApp->Settings();
if (settings->alwaysOnTop)
SetFeel(B_FLOATING_ALL_WINDOW_FEEL);
@ -132,9 +134,16 @@ TBarWindow::MenusBeginning()
return;
}
// raise Deskbar on menu open in auto-raise mode unless always-on-top
desk_settings* settings = fBarApp->Settings();
bool alwaysOnTop = settings->alwaysOnTop;
bool autoRaise = settings->autoRaise;
if (!alwaysOnTop && autoRaise)
fBarView->RaiseDeskbar(true);
sDeskbarMenu->ResetTargets();
fShowingMenu = true;
fMenusShown++;
BWindow::MenusBeginning();
}
@ -142,9 +151,17 @@ TBarWindow::MenusBeginning()
void
TBarWindow::MenusEnded()
{
fShowingMenu = false;
fMenusShown--;
BWindow::MenusEnded();
// lower Deskbar back down again on menu close in auto-raise mode
// unless another menu is open or always-on-top.
desk_settings* settings = fBarApp->Settings();
bool alwaysOnTop = settings->alwaysOnTop;
bool autoRaise = settings->autoRaise;
if (!alwaysOnTop && autoRaise && fMenusShown <= 0)
fBarView->RaiseDeskbar(false);
if (sDeskbarMenu->LockLooper()) {
sDeskbarMenu->ForceRebuild();
sDeskbarMenu->UnlockLooper();
@ -230,7 +247,7 @@ TBarWindow::FrameResized(float width, float height)
if (!fBarView->Vertical())
return BWindow::FrameResized(width, height);
bool setToHiddenSize = static_cast<TBarApp*>(be_app)->Settings()->autoHide
bool setToHiddenSize = fBarApp->Settings()->autoHide
&& fBarView->IsHidden() && !fBarView->DragRegion()->IsDragging();
if (!setToHiddenSize) {
// constrain within limits
@ -242,10 +259,10 @@ TBarWindow::FrameResized(float width, float height)
else
newWidth = width;
float oldWidth = static_cast<TBarApp*>(be_app)->Settings()->width;
float oldWidth = fBarApp->Settings()->width;
// update width setting
static_cast<TBarApp*>(be_app)->Settings()->width = newWidth;
fBarApp->Settings()->width = newWidth;
if (oldWidth != newWidth) {
fBarView->ResizeTo(width, fBarView->Bounds().Height());
@ -646,7 +663,7 @@ TBarWindow::GetIconFrame(BMessage* message)
bool
TBarWindow::IsShowingMenu() const
{
return fShowingMenu;
return fMenusShown > 0;
}
@ -654,7 +671,7 @@ void
TBarWindow::SetSizeLimits()
{
BRect screenFrame = (BScreen(this)).Frame();
bool setToHiddenSize = static_cast<TBarApp*>(be_app)->Settings()->autoHide
bool setToHiddenSize = fBarApp->Settings()->autoHide
&& fBarView->IsHidden() && !fBarView->DragRegion()->IsDragging();
if (setToHiddenSize) {

View File

@ -40,8 +40,9 @@ All rights reserved.
#include <Window.h>
class TDeskbarMenu;
class TBarApp;
class TBarView;
class TDeskbarMenu;
class TBarWindow : public BWindow {
public:
@ -94,8 +95,9 @@ private:
private:
static TDeskbarMenu* sDeskbarMenu;
TBarApp* fBarApp;
TBarView* fBarView;
bool fShowingMenu;
int32 fMenusShown;
};