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:
parent
a8cd19b641
commit
74ceffa889
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user