Workspaces: fix the auto-raise functionality
- Remove hardcoded decorator border size, and get it from the system. - Move the window at the right place when using the "zoom" button (if the auto-raise setting is enabled). - Make the auto-raise work even when the mouse is above the window borders, not the active area. This works similarly to LaunchBox auto-raise feature. fixes #8188, #8194. Manual rework of patches by Daniel Devine which were never merged and didn't apply cleanly anymore.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2012, Haiku, Inc. All rights reserved.
|
* Copyright 2002-2016, Haiku, Inc. All rights reserved.
|
||||||
* Copyright 2002, François Revol, [email protected].
|
* Copyright 2002, François Revol, [email protected].
|
||||||
* This file is distributed under the terms of the MIT License.
|
* This file is distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
* Axel Dörfler, [email protected]
|
* Axel Dörfler, [email protected]
|
||||||
* Oliver "Madison" Kohl,
|
* Oliver "Madison" Kohl,
|
||||||
* Matt Madia
|
* Matt Madia
|
||||||
|
* Daniel Devine, [email protected]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -56,7 +57,6 @@ static const uint32 kMsgToggleAlwaysOnTop = 'tgAT';
|
|||||||
static const uint32 kMsgToggleLiveInDeskbar = 'tgDb';
|
static const uint32 kMsgToggleLiveInDeskbar = 'tgDb';
|
||||||
static const uint32 kMsgToggleSwitchOnWheel = 'tgWh';
|
static const uint32 kMsgToggleSwitchOnWheel = 'tgWh';
|
||||||
|
|
||||||
static const float kScreenBorderOffset = 10.0;
|
|
||||||
|
|
||||||
extern "C" _EXPORT BView* instantiate_deskbar_item();
|
extern "C" _EXPORT BView* instantiate_deskbar_item();
|
||||||
|
|
||||||
@@ -73,6 +73,7 @@ class WorkspacesSettings {
|
|||||||
bool HasTitle() const { return fHasTitle; }
|
bool HasTitle() const { return fHasTitle; }
|
||||||
bool HasBorder() const { return fHasBorder; }
|
bool HasBorder() const { return fHasBorder; }
|
||||||
bool SwitchOnWheel() const { return fSwitchOnWheel; }
|
bool SwitchOnWheel() const { return fSwitchOnWheel; }
|
||||||
|
bool SettingsLoaded() const { return fLoaded; }
|
||||||
|
|
||||||
void UpdateFramesForScreen(BRect screenFrame);
|
void UpdateFramesForScreen(BRect screenFrame);
|
||||||
void UpdateScreenFrame();
|
void UpdateScreenFrame();
|
||||||
@@ -94,6 +95,7 @@ class WorkspacesSettings {
|
|||||||
bool fHasTitle;
|
bool fHasTitle;
|
||||||
bool fHasBorder;
|
bool fHasBorder;
|
||||||
bool fSwitchOnWheel;
|
bool fSwitchOnWheel;
|
||||||
|
bool fLoaded;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WorkspacesView : public BView {
|
class WorkspacesView : public BView {
|
||||||
@@ -139,14 +141,19 @@ class WorkspacesWindow : public BWindow {
|
|||||||
virtual bool QuitRequested();
|
virtual bool QuitRequested();
|
||||||
|
|
||||||
void SetAutoRaise(bool enable);
|
void SetAutoRaise(bool enable);
|
||||||
bool IsAutoRaising() const { return fAutoRaising; }
|
bool IsAutoRaising() const { return fSettings->AutoRaising(); }
|
||||||
void SetSwitchOnWheel(bool enable);
|
void SetSwitchOnWheel(bool enable);
|
||||||
bool SwitchOnWheel() const { return fSwitchOnWheel; }
|
bool SwitchOnWheel() const { return fSwitchOnWheel; }
|
||||||
|
|
||||||
|
float GetTabHeight() { return fSettings->HasTitle() ? fTabHeight : 0; }
|
||||||
|
float GetBorderWidth() { return fBorderWidth; }
|
||||||
|
float GetScreenBorderOffset() { return 2.0 * fBorderWidth; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WorkspacesSettings *fSettings;
|
WorkspacesSettings *fSettings;
|
||||||
bool fAutoRaising;
|
|
||||||
bool fSwitchOnWheel;
|
bool fSwitchOnWheel;
|
||||||
|
float fTabHeight;
|
||||||
|
float fBorderWidth;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WorkspacesApp : public BApplication {
|
class WorkspacesApp : public BApplication {
|
||||||
@@ -171,11 +178,11 @@ WorkspacesSettings::WorkspacesSettings()
|
|||||||
fAlwaysOnTop(false),
|
fAlwaysOnTop(false),
|
||||||
fHasTitle(true),
|
fHasTitle(true),
|
||||||
fHasBorder(true),
|
fHasBorder(true),
|
||||||
fSwitchOnWheel(false)
|
fSwitchOnWheel(false),
|
||||||
|
fLoaded(false)
|
||||||
{
|
{
|
||||||
UpdateScreenFrame();
|
UpdateScreenFrame();
|
||||||
|
|
||||||
bool loaded = false;
|
|
||||||
BScreen screen;
|
BScreen screen;
|
||||||
|
|
||||||
BFile file;
|
BFile file;
|
||||||
@@ -184,7 +191,7 @@ WorkspacesSettings::WorkspacesSettings()
|
|||||||
if (settings.Unflatten(&file) == B_OK) {
|
if (settings.Unflatten(&file) == B_OK) {
|
||||||
if (settings.FindRect("window", &fWindowFrame) == B_OK
|
if (settings.FindRect("window", &fWindowFrame) == B_OK
|
||||||
&& settings.FindRect("screen", &fScreenFrame) == B_OK)
|
&& settings.FindRect("screen", &fScreenFrame) == B_OK)
|
||||||
loaded = true;
|
fLoaded = true;
|
||||||
|
|
||||||
settings.FindBool("auto-raise", &fAutoRaising);
|
settings.FindBool("auto-raise", &fAutoRaising);
|
||||||
settings.FindBool("always on top", &fAlwaysOnTop);
|
settings.FindBool("always on top", &fAlwaysOnTop);
|
||||||
@@ -212,53 +219,17 @@ WorkspacesSettings::WorkspacesSettings()
|
|||||||
else
|
else
|
||||||
fScreenFrame = screen.Frame();
|
fScreenFrame = screen.Frame();
|
||||||
|
|
||||||
loaded = true;
|
fLoaded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loaded) {
|
if (fLoaded) {
|
||||||
// if the current screen frame is different from the one
|
// if the current screen frame is different from the one
|
||||||
// just loaded, we need to alter the window frame accordingly
|
// just loaded, we need to alter the window frame accordingly
|
||||||
if (fScreenFrame != screen.Frame())
|
if (fScreenFrame != screen.Frame())
|
||||||
UpdateFramesForScreen(screen.Frame());
|
UpdateFramesForScreen(screen.Frame());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!loaded
|
|
||||||
|| !(screen.Frame().right + 5 >= fWindowFrame.right
|
|
||||||
&& screen.Frame().bottom + 5 >= fWindowFrame.bottom
|
|
||||||
&& screen.Frame().left - 5 <= fWindowFrame.left
|
|
||||||
&& screen.Frame().top - 5 <= fWindowFrame.top)) {
|
|
||||||
// set to some usable defaults
|
|
||||||
float screenWidth = screen.Frame().Width();
|
|
||||||
float screenHeight = screen.Frame().Height();
|
|
||||||
float aspectRatio = screenWidth / screenHeight;
|
|
||||||
|
|
||||||
uint32 columns, rows;
|
|
||||||
BPrivate::get_workspaces_layout(&columns, &rows);
|
|
||||||
|
|
||||||
// default size of ~1/10 of screen width
|
|
||||||
float workspaceWidth = screenWidth / 10;
|
|
||||||
float workspaceHeight = workspaceWidth / aspectRatio;
|
|
||||||
|
|
||||||
float width = floor(workspaceWidth * columns);
|
|
||||||
float height = floor(workspaceHeight * rows);
|
|
||||||
|
|
||||||
float tabHeight = 20;
|
|
||||||
// TODO: find tabHeight without being a window
|
|
||||||
|
|
||||||
// shrink to fit more
|
|
||||||
while (width + 2 * kScreenBorderOffset > screenWidth
|
|
||||||
|| height + 2 * kScreenBorderOffset + tabHeight > screenHeight) {
|
|
||||||
width = floor(0.95 * width);
|
|
||||||
height = floor(0.95 * height);
|
|
||||||
}
|
|
||||||
|
|
||||||
fWindowFrame = fScreenFrame;
|
|
||||||
fWindowFrame.OffsetBy(-kScreenBorderOffset, -kScreenBorderOffset);
|
|
||||||
fWindowFrame.left = fWindowFrame.right - width;
|
|
||||||
fWindowFrame.top = fWindowFrame.bottom - height;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -564,11 +535,19 @@ WorkspacesView::MouseMoved(BPoint where, uint32 transit,
|
|||||||
|
|
||||||
where = ConvertToScreen(where);
|
where = ConvertToScreen(where);
|
||||||
BScreen screen(window);
|
BScreen screen(window);
|
||||||
BRect frame = screen.Frame();
|
BRect screenFrame = screen.Frame();
|
||||||
if (where.x == frame.left || where.x == frame.right
|
BRect windowFrame = window->Frame();
|
||||||
|| where.y == frame.top || where.y == frame.bottom) {
|
float tabHeight = window->GetTabHeight();
|
||||||
|
float borderWidth = window->GetBorderWidth();
|
||||||
|
|
||||||
|
if (where.x == screenFrame.left || where.x == screenFrame.right
|
||||||
|
|| where.y == screenFrame.top || where.y == screenFrame.bottom) {
|
||||||
// cursor is on screen edge
|
// cursor is on screen edge
|
||||||
if (window->Frame().Contains(where))
|
|
||||||
|
// Stretch frame to also accept mouse moves over the window borders
|
||||||
|
windowFrame.InsetBy(-borderWidth, -(tabHeight + borderWidth));
|
||||||
|
|
||||||
|
if (windowFrame.Contains(where))
|
||||||
window->Activate();
|
window->Activate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -673,21 +652,75 @@ WorkspacesView::MouseDown(BPoint where)
|
|||||||
|
|
||||||
WorkspacesWindow::WorkspacesWindow(WorkspacesSettings *settings)
|
WorkspacesWindow::WorkspacesWindow(WorkspacesSettings *settings)
|
||||||
:
|
:
|
||||||
BWindow(settings->WindowFrame(), B_TRANSLATE_SYSTEM_NAME("Workspaces"),
|
BWindow(settings->WindowFrame(), B_TRANSLATE_SYSTEM_NAME("Workspaces"),
|
||||||
B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
|
B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
|
||||||
B_AVOID_FRONT | B_WILL_ACCEPT_FIRST_CLICK | B_CLOSE_ON_ESCAPE,
|
B_AVOID_FRONT | B_WILL_ACCEPT_FIRST_CLICK | B_CLOSE_ON_ESCAPE,
|
||||||
B_ALL_WORKSPACES),
|
B_ALL_WORKSPACES),
|
||||||
fSettings(settings),
|
fSettings(settings),
|
||||||
fAutoRaising(false),
|
|
||||||
fSwitchOnWheel(false)
|
fSwitchOnWheel(false)
|
||||||
{
|
{
|
||||||
AddChild(new WorkspacesView(Bounds()));
|
// Turn window decor on to grab decor widths.
|
||||||
|
BMessage windowSettings;
|
||||||
|
float borderWidth = 0;
|
||||||
|
|
||||||
|
SetLook(B_TITLED_WINDOW_LOOK);
|
||||||
|
if (GetDecoratorSettings(&windowSettings) == B_OK) {
|
||||||
|
BRect tabFrame = windowSettings.FindRect("tab frame");
|
||||||
|
borderWidth = windowSettings.FindFloat("border width");
|
||||||
|
fTabHeight = tabFrame.Height();
|
||||||
|
fBorderWidth = borderWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fSettings->SettingsLoaded()) {
|
||||||
|
// No settings, compute a reasonable default frame.
|
||||||
|
// We aim for previews at 10% of actual screen size, and matching the
|
||||||
|
// aspect ratio. We then scale that down, until it fits the screen.
|
||||||
|
// Finally, we put the window on the bottom right of the screen so the
|
||||||
|
// auto-raise mode can be used.
|
||||||
|
|
||||||
|
BScreen screen;
|
||||||
|
|
||||||
|
float screenWidth = screen.Frame().Width();
|
||||||
|
float screenHeight = screen.Frame().Height();
|
||||||
|
float aspectRatio = screenWidth / screenHeight;
|
||||||
|
|
||||||
|
uint32 columns, rows;
|
||||||
|
BPrivate::get_workspaces_layout(&columns, &rows);
|
||||||
|
|
||||||
|
// default size of ~1/10 of screen width
|
||||||
|
float workspaceWidth = screenWidth / 10;
|
||||||
|
float workspaceHeight = workspaceWidth / aspectRatio;
|
||||||
|
|
||||||
|
float width = floor(workspaceWidth * columns);
|
||||||
|
float height = floor(workspaceHeight * rows);
|
||||||
|
|
||||||
|
// If you have too many workspaces to fit on the screen, shrink until they fit.
|
||||||
|
while (width + 2 * borderWidth > screenWidth
|
||||||
|
|| height + 2 * borderWidth + GetTabHeight() > screenHeight) {
|
||||||
|
width = floor(0.95 * width);
|
||||||
|
height = floor(0.95 * height);
|
||||||
|
}
|
||||||
|
|
||||||
|
BRect frame = fSettings->ScreenFrame();
|
||||||
|
frame.OffsetBy(-2.0 * borderWidth, -2.0 * borderWidth);
|
||||||
|
frame.left = frame.right - width;
|
||||||
|
frame.top = frame.bottom - height;
|
||||||
|
ResizeTo(frame.Width(), frame.Height());
|
||||||
|
|
||||||
|
// Put it in bottom corner by default.
|
||||||
|
MoveTo(screenWidth - frame.Width() - borderWidth,
|
||||||
|
screenHeight - frame.Height() - borderWidth);
|
||||||
|
|
||||||
|
fSettings->SetWindowFrame(frame);
|
||||||
|
}
|
||||||
|
|
||||||
if (!fSettings->HasBorder())
|
if (!fSettings->HasBorder())
|
||||||
SetLook(B_NO_BORDER_WINDOW_LOOK);
|
SetLook(B_NO_BORDER_WINDOW_LOOK);
|
||||||
else if (!fSettings->HasTitle())
|
else if (!fSettings->HasTitle())
|
||||||
SetLook(B_MODAL_WINDOW_LOOK);
|
SetLook(B_MODAL_WINDOW_LOOK);
|
||||||
|
|
||||||
|
AddChild(new WorkspacesView(Bounds()));
|
||||||
|
|
||||||
if (fSettings->AlwaysOnTop())
|
if (fSettings->AlwaysOnTop())
|
||||||
SetFeel(B_FLOATING_ALL_WINDOW_FEEL);
|
SetFeel(B_FLOATING_ALL_WINDOW_FEEL);
|
||||||
else
|
else
|
||||||
@@ -762,15 +795,25 @@ WorkspacesWindow::Zoom(BPoint origin, float width, float height)
|
|||||||
width = floor(workspaceWidth * columns);
|
width = floor(workspaceWidth * columns);
|
||||||
height = floor(workspaceHeight * rows);
|
height = floor(workspaceHeight * rows);
|
||||||
|
|
||||||
float tabHeight = Frame().top - DecoratorFrame().top;
|
while (width + 2 * GetScreenBorderOffset() > screenWidth
|
||||||
|
|| height + 2 * GetScreenBorderOffset() + GetTabHeight() > screenHeight) {
|
||||||
while (width + 2 * kScreenBorderOffset > screenWidth
|
|
||||||
|| height + 2 * kScreenBorderOffset + tabHeight > screenHeight) {
|
|
||||||
width = floor(0.95 * width);
|
width = floor(0.95 * width);
|
||||||
height = floor(0.95 * height);
|
height = floor(0.95 * height);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResizeTo(width, height);
|
ResizeTo(width, height);
|
||||||
|
|
||||||
|
if (fSettings->AutoRaising())
|
||||||
|
{
|
||||||
|
// The auto-raising mode makes sense only if the window is positionned
|
||||||
|
// exactly in the bottom-right corner. If the setting is enabled, move
|
||||||
|
// the window there.
|
||||||
|
origin = screen.Frame().RightBottom();
|
||||||
|
origin.x -= GetScreenBorderOffset() + width;
|
||||||
|
origin.y -= GetScreenBorderOffset() + height;
|
||||||
|
|
||||||
|
MoveTo(origin);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -821,8 +864,7 @@ WorkspacesWindow::MessageReceived(BMessage *message)
|
|||||||
else
|
else
|
||||||
SetLook(B_MODAL_WINDOW_LOOK);
|
SetLook(B_MODAL_WINDOW_LOOK);
|
||||||
|
|
||||||
// No matter what the setting for title,
|
// No matter what the setting for title, we must force the border on
|
||||||
// we must force the border on
|
|
||||||
fSettings->SetHasBorder(true);
|
fSettings->SetHasBorder(true);
|
||||||
fSettings->SetHasTitle(enable);
|
fSettings->SetHasTitle(enable);
|
||||||
break;
|
break;
|
||||||
@@ -883,10 +925,6 @@ WorkspacesWindow::QuitRequested()
|
|||||||
void
|
void
|
||||||
WorkspacesWindow::SetAutoRaise(bool enable)
|
WorkspacesWindow::SetAutoRaise(bool enable)
|
||||||
{
|
{
|
||||||
if (enable == fAutoRaising)
|
|
||||||
return;
|
|
||||||
|
|
||||||
fAutoRaising = enable;
|
|
||||||
fSettings->SetAutoRaising(enable);
|
fSettings->SetAutoRaising(enable);
|
||||||
|
|
||||||
if (enable)
|
if (enable)
|
||||||
|
|||||||
Reference in New Issue
Block a user