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:
parent
fa3f84b78c
commit
43caca9680
@ -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, revol@free.fr.
|
||||
* This file is distributed under the terms of the MIT License.
|
||||
*
|
||||
@ -8,6 +8,7 @@
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
* Oliver "Madison" Kohl,
|
||||
* Matt Madia
|
||||
* Daniel Devine, devine@ddevnet.net
|
||||
*/
|
||||
|
||||
|
||||
@ -56,7 +57,6 @@ static const uint32 kMsgToggleAlwaysOnTop = 'tgAT';
|
||||
static const uint32 kMsgToggleLiveInDeskbar = 'tgDb';
|
||||
static const uint32 kMsgToggleSwitchOnWheel = 'tgWh';
|
||||
|
||||
static const float kScreenBorderOffset = 10.0;
|
||||
|
||||
extern "C" _EXPORT BView* instantiate_deskbar_item();
|
||||
|
||||
@ -73,6 +73,7 @@ class WorkspacesSettings {
|
||||
bool HasTitle() const { return fHasTitle; }
|
||||
bool HasBorder() const { return fHasBorder; }
|
||||
bool SwitchOnWheel() const { return fSwitchOnWheel; }
|
||||
bool SettingsLoaded() const { return fLoaded; }
|
||||
|
||||
void UpdateFramesForScreen(BRect screenFrame);
|
||||
void UpdateScreenFrame();
|
||||
@ -94,6 +95,7 @@ class WorkspacesSettings {
|
||||
bool fHasTitle;
|
||||
bool fHasBorder;
|
||||
bool fSwitchOnWheel;
|
||||
bool fLoaded;
|
||||
};
|
||||
|
||||
class WorkspacesView : public BView {
|
||||
@ -139,14 +141,19 @@ class WorkspacesWindow : public BWindow {
|
||||
virtual bool QuitRequested();
|
||||
|
||||
void SetAutoRaise(bool enable);
|
||||
bool IsAutoRaising() const { return fAutoRaising; }
|
||||
bool IsAutoRaising() const { return fSettings->AutoRaising(); }
|
||||
void SetSwitchOnWheel(bool enable);
|
||||
bool SwitchOnWheel() const { return fSwitchOnWheel; }
|
||||
|
||||
float GetTabHeight() { return fSettings->HasTitle() ? fTabHeight : 0; }
|
||||
float GetBorderWidth() { return fBorderWidth; }
|
||||
float GetScreenBorderOffset() { return 2.0 * fBorderWidth; }
|
||||
|
||||
private:
|
||||
WorkspacesSettings *fSettings;
|
||||
bool fAutoRaising;
|
||||
bool fSwitchOnWheel;
|
||||
float fTabHeight;
|
||||
float fBorderWidth;
|
||||
};
|
||||
|
||||
class WorkspacesApp : public BApplication {
|
||||
@ -171,11 +178,11 @@ WorkspacesSettings::WorkspacesSettings()
|
||||
fAlwaysOnTop(false),
|
||||
fHasTitle(true),
|
||||
fHasBorder(true),
|
||||
fSwitchOnWheel(false)
|
||||
fSwitchOnWheel(false),
|
||||
fLoaded(false)
|
||||
{
|
||||
UpdateScreenFrame();
|
||||
|
||||
bool loaded = false;
|
||||
BScreen screen;
|
||||
|
||||
BFile file;
|
||||
@ -184,7 +191,7 @@ WorkspacesSettings::WorkspacesSettings()
|
||||
if (settings.Unflatten(&file) == B_OK) {
|
||||
if (settings.FindRect("window", &fWindowFrame) == B_OK
|
||||
&& settings.FindRect("screen", &fScreenFrame) == B_OK)
|
||||
loaded = true;
|
||||
fLoaded = true;
|
||||
|
||||
settings.FindBool("auto-raise", &fAutoRaising);
|
||||
settings.FindBool("always on top", &fAlwaysOnTop);
|
||||
@ -212,53 +219,17 @@ WorkspacesSettings::WorkspacesSettings()
|
||||
else
|
||||
fScreenFrame = screen.Frame();
|
||||
|
||||
loaded = true;
|
||||
fLoaded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (loaded) {
|
||||
if (fLoaded) {
|
||||
// if the current screen frame is different from the one
|
||||
// just loaded, we need to alter the window frame accordingly
|
||||
if (fScreenFrame != 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);
|
||||
BScreen screen(window);
|
||||
BRect frame = screen.Frame();
|
||||
if (where.x == frame.left || where.x == frame.right
|
||||
|| where.y == frame.top || where.y == frame.bottom) {
|
||||
BRect screenFrame = screen.Frame();
|
||||
BRect windowFrame = window->Frame();
|
||||
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
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -673,21 +652,75 @@ WorkspacesView::MouseDown(BPoint where)
|
||||
|
||||
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_AVOID_FRONT | B_WILL_ACCEPT_FIRST_CLICK | B_CLOSE_ON_ESCAPE,
|
||||
B_ALL_WORKSPACES),
|
||||
fSettings(settings),
|
||||
fAutoRaising(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())
|
||||
SetLook(B_NO_BORDER_WINDOW_LOOK);
|
||||
else if (!fSettings->HasTitle())
|
||||
SetLook(B_MODAL_WINDOW_LOOK);
|
||||
|
||||
AddChild(new WorkspacesView(Bounds()));
|
||||
|
||||
if (fSettings->AlwaysOnTop())
|
||||
SetFeel(B_FLOATING_ALL_WINDOW_FEEL);
|
||||
else
|
||||
@ -762,15 +795,25 @@ WorkspacesWindow::Zoom(BPoint origin, float width, float height)
|
||||
width = floor(workspaceWidth * columns);
|
||||
height = floor(workspaceHeight * rows);
|
||||
|
||||
float tabHeight = Frame().top - DecoratorFrame().top;
|
||||
|
||||
while (width + 2 * kScreenBorderOffset > screenWidth
|
||||
|| height + 2 * kScreenBorderOffset + tabHeight > screenHeight) {
|
||||
while (width + 2 * GetScreenBorderOffset() > screenWidth
|
||||
|| height + 2 * GetScreenBorderOffset() + GetTabHeight() > screenHeight) {
|
||||
width = floor(0.95 * width);
|
||||
height = floor(0.95 * 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
|
||||
SetLook(B_MODAL_WINDOW_LOOK);
|
||||
|
||||
// No matter what the setting for title,
|
||||
// we must force the border on
|
||||
// No matter what the setting for title, we must force the border on
|
||||
fSettings->SetHasBorder(true);
|
||||
fSettings->SetHasTitle(enable);
|
||||
break;
|
||||
@ -883,10 +925,6 @@ WorkspacesWindow::QuitRequested()
|
||||
void
|
||||
WorkspacesWindow::SetAutoRaise(bool enable)
|
||||
{
|
||||
if (enable == fAutoRaising)
|
||||
return;
|
||||
|
||||
fAutoRaising = enable;
|
||||
fSettings->SetAutoRaising(enable);
|
||||
|
||||
if (enable)
|
||||
|
Loading…
x
Reference in New Issue
Block a user