From ff3a346fc5b481c5fb026565018cbaa380eca3db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sat, 17 Jan 2004 23:12:12 +0000 Subject: [PATCH] Imported Matt Madia's changes to the Workspaces application (changed position calculation, new command line arguments [use --help for info]). Put a great effort into it cleaning and fixing it. Works around a bug in BeOS that affected the positioning algorithm - it's explained in WorkspacesWindow::FrameMoved() for those who want to know. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6120 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/prefs/workspaces/Workspaces.cpp | 232 +++++++++++++++++++--------- 1 file changed, 163 insertions(+), 69 deletions(-) diff --git a/src/prefs/workspaces/Workspaces.cpp b/src/prefs/workspaces/Workspaces.cpp index 1104c9073a..88ae30f0f5 100644 --- a/src/prefs/workspaces/Workspaces.cpp +++ b/src/prefs/workspaces/Workspaces.cpp @@ -1,14 +1,17 @@ /* - * Workspaces.cpp - * Open BeOS version alpha 1 by Francois Revol revol@free.fr + * Workspaces - OpenBeOS version by Francois Revol revol@free.fr + * This file is distributed under the terms of the OpenBeOS license. * * Workspaces window trick found by Michael "Minox" Paine. * (using B_ALL_WORKSPACES as flags in BWindow) * Found out that using 0xffffffff as Flags was causing the window not to close on Alt-W * hey Workspaces get Flags of Window 0 * gives 0x00008080 which makes it. + * + * Other authors: Axel Dörfler, Oliver "Madison" Kohl, Matt Madia */ + #include #include #include @@ -20,6 +23,18 @@ #include #include +#include +#include +#include + + +// here is the trick :) +#define B_WORKSPACES_WINDOW 0x00008000 + +static const char *kWorkspacesSignature = "application/x-vnd.Be-WORK"; +static const char *kWorkspacesSettingFile = "Workspace_data"; + +static const uint32 kScreenBorderOffset = 10; class WorkspacesPreferences { @@ -29,28 +44,31 @@ class WorkspacesPreferences { BRect WindowFrame() const { return fWindowFrame; } BRect ScreenFrame() const { return fScreenFrame; } + + void UpdateFramesForScreen(BRect screenFrame); void UpdateScreenFrame(); void SetWindowFrame(BRect); private: - static const char kWorkspacesSettingFile[]; - BRect fWindowFrame, fScreenFrame; + BRect fWindowFrame, fScreenFrame; }; class WorkspacesWindow : public BWindow { public: WorkspacesWindow(WorkspacesPreferences *fPreferences); virtual ~WorkspacesWindow(); - - virtual void ScreenChanged(BRect frame,color_space mode); + + virtual void ScreenChanged(BRect frame, color_space mode); virtual void FrameMoved(BPoint origin); virtual void FrameResized(float width, float height); virtual void Zoom(BPoint origin, float width, float height); + virtual void MessageReceived(BMessage *msg); virtual bool QuitRequested(void); private: WorkspacesPreferences *fPreferences; + BRect fPreviousFrame; }; class WorkspacesApp : public BApplication { @@ -61,51 +79,90 @@ class WorkspacesApp : public BApplication { virtual void AboutRequested(void); virtual void ArgvReceived(int32 argc, char **argv); virtual void ReadyToRun(void); - virtual bool WorkspacesApp::QuitRequested(void); + + void Usage(const char *programName); private: - static const char kWorkspacesAppSig[]; + BWindow *fWindow; }; -const char WorkspacesApp::kWorkspacesAppSig[] = "application/x-vnd.Be-WORK"; -const char WorkspacesPreferences::kWorkspacesSettingFile[] = "Workspace_data"; - WorkspacesPreferences::WorkspacesPreferences() { UpdateScreenFrame(); + bool settingsValid = false; BPath path; - if (find_directory(B_USER_SETTINGS_DIRECTORY,&path) == B_OK) { - path.Append(kWorkspacesSettingFile); + if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { + path.Append(kWorkspacesSettingFile); BFile file(path.Path(), B_READ_ONLY); - if (file.InitCheck() == B_OK && file.Read(&fWindowFrame, sizeof(BRect)) == sizeof(BRect)) { + if (file.InitCheck() == B_OK + && file.Read(&fWindowFrame, sizeof(BRect)) == sizeof(BRect)) { + // we now also store the frame of the screen to know + // in which context the window frame has been chosen BScreen screen; + BRect frame; + if (file.Read(&frame, sizeof(BRect)) == sizeof(BRect)) { + fScreenFrame = frame; + // 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()); + } + + // check if loaded values are valid if (screen.Frame().right >= fWindowFrame.right - && screen.Frame().bottom >= fWindowFrame.bottom) - return; + && screen.Frame().bottom >= fWindowFrame.bottom) + settingsValid = true; } } - fWindowFrame = fScreenFrame; - fWindowFrame.OffsetBy(-10, -10); - fWindowFrame.left = fWindowFrame.right - 160; - fWindowFrame.top = fWindowFrame.bottom - 120; + if (!settingsValid) { + // set to some usable defaults + fWindowFrame = fScreenFrame; + fWindowFrame.OffsetBy(-kScreenBorderOffset, -kScreenBorderOffset); + fWindowFrame.left = fWindowFrame.right - 160; + fWindowFrame.top = fWindowFrame.bottom - 120; + } } WorkspacesPreferences::~WorkspacesPreferences() { + // write settings file BPath path; - if (find_directory(B_USER_SETTINGS_DIRECTORY,&path) < B_OK) + if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) < B_OK) return; path.Append(kWorkspacesSettingFile); BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE); - if (file.InitCheck() == B_OK) + if (file.InitCheck() == B_OK) { file.Write(&fWindowFrame, sizeof(BRect)); + file.Write(&fScreenFrame, sizeof(BRect)); + } +} + + +void +WorkspacesPreferences::UpdateFramesForScreen(BRect newScreenFrame) +{ + // don't change the position if the screen frame hasn't changed + if (newScreenFrame == fScreenFrame) + return; + + // adjust horizontal position + if (fWindowFrame.right > fScreenFrame.right / 2) + fWindowFrame.OffsetTo(newScreenFrame.right + - (fScreenFrame.right - fWindowFrame.left), fWindowFrame.top); + + // adjust vertical position + if (fWindowFrame.bottom > fScreenFrame.bottom / 2) + fWindowFrame.OffsetTo(fWindowFrame.left, + newScreenFrame.bottom - (fScreenFrame.bottom - fWindowFrame.top)); + + fScreenFrame = newScreenFrame; } @@ -118,25 +175,21 @@ WorkspacesPreferences::UpdateScreenFrame() void -WorkspacesPreferences::SetWindowFrame(BRect f) +WorkspacesPreferences::SetWindowFrame(BRect frame) { - fWindowFrame = f; - - UpdateScreenFrame(); + fWindowFrame = frame; } // #pragma mark - -// here is the trick :) -#define B_WORKSPACES_WINDOW 0x00008000 - WorkspacesWindow::WorkspacesWindow(WorkspacesPreferences *preferences) : BWindow(preferences->WindowFrame(), "Workspaces", B_TITLED_WINDOW_LOOK, - B_NORMAL_WINDOW_FEEL, B_WORKSPACES_WINDOW | B_AVOID_FRONT, B_ALL_WORKSPACES) + B_NORMAL_WINDOW_FEEL, B_WORKSPACES_WINDOW | B_AVOID_FRONT, B_ALL_WORKSPACES), + fPreferences(preferences) { - fPreferences = preferences; + fPreviousFrame = Frame(); } @@ -147,24 +200,27 @@ WorkspacesWindow::~WorkspacesWindow() void -WorkspacesWindow::ScreenChanged(BRect frame,color_space mode) +WorkspacesWindow::ScreenChanged(BRect rect, color_space mode) { - BRect rect = fPreferences->WindowFrame(); - BRect old = fPreferences->ScreenFrame(); + fPreviousFrame = fPreferences->WindowFrame(); + // work-around for a bug in BeOS, see explanation in FrameMoved() - // adjust horizontal position - if (frame.right < rect.left || frame.right > rect.right && rect.left > old.right/2) - MoveTo(frame.right - (old.right - rect.left),rect.top); - - // adjust vertical position - if (frame.bottom < rect.top || frame.bottom > rect.bottom && rect.top > old.bottom/2) - MoveTo(Frame().left,frame.bottom - (old.bottom - rect.top)); + fPreferences->UpdateFramesForScreen(rect); + MoveTo(fPreferences->WindowFrame().LeftTop()); } void WorkspacesWindow::FrameMoved(BPoint origin) { + if (origin == fPreviousFrame.LeftTop()) { + // This works around a bug in BeOS; when you change the window + // position in WorkspaceActivated() or ScreenChanged(), it will + // send an old repositioning message *after* the FrameMoved() + // that originated your change has arrived + return; + } + fPreferences->SetWindowFrame(Frame()); } @@ -181,8 +237,8 @@ WorkspacesWindow::Zoom(BPoint origin, float width, float height) { BScreen screen; origin = screen.Frame().RightBottom(); - origin.x -= 10 + fPreferences->WindowFrame().Width(); - origin.y -= 10 + fPreferences->WindowFrame().Height(); + origin.x -= kScreenBorderOffset + fPreferences->WindowFrame().Width(); + origin.y -= kScreenBorderOffset + fPreferences->WindowFrame().Height(); MoveTo(origin); } @@ -191,7 +247,8 @@ WorkspacesWindow::Zoom(BPoint origin, float width, float height) void WorkspacesWindow::MessageReceived(BMessage *msg) { - if (msg->what == 'DATA') { // Drop from Tracker + if (msg->what == 'DATA') { + // Drop from Tracker entry_ref ref; for (int i = 0; (msg->FindRef("refs", i, &ref) == B_OK); i++) be_roster->Launch(&ref); @@ -211,8 +268,10 @@ WorkspacesWindow::QuitRequested(void) // #pragma mark - -WorkspacesApp::WorkspacesApp() : BApplication(kWorkspacesAppSig) -{ +WorkspacesApp::WorkspacesApp() + : BApplication(kWorkspacesSignature) +{ + fWindow = new WorkspacesWindow(new WorkspacesPreferences()); } @@ -226,22 +285,65 @@ WorkspacesApp::AboutRequested(void) { // blocking !! // the original does the same by the way =) - (new BAlert("about", "OpenBeOS Workspaces\n\tby François Revol, Axel Dörfler.\n\noriginal Be version by Robert Polic", "Big Deal"))->Go(); + (new BAlert("about", "OpenBeOS Workspaces\n" + "\tby François Revol, Axel Dörfler, Matt Madia.\n\n" + "original Be version by Robert Polic", "Big Deal"))->Go(); +} + + +void +WorkspacesApp::Usage(const char *programName) +{ + printf("Usage: %s [options] [workspace]\n" + "where \"options\" is one of:\n" + " --notitle\t\ttitle bar removed. border and resize kept.\n" + " --noborder\t\ttitle, border, and resize removed.\n" + " --acceptfirstclick\tforces workspace switch on first click.\n" + " --avoidfocus\t\tprevents the window from being the target of keyboard events.\n" + " --alwaysontop\t\tkeeps window on top\n" + " --help\t\tdisplay this help and exit\n" + "and \"workspace\" is the number of the Workspace to which to switch (0-31)\n", + programName); + + // quit only if we aren't running already + if (IsLaunching()) + Quit(); } void WorkspacesApp::ArgvReceived(int32 argc, char **argv) { - // we are told to switch to a specific workspace - if (argc > 1) { - // get it from the command line... - activate_workspace(atoi(argv[1])); - // if the app is running, don't quit - // but if it isn't, cancel the complete run, so it doesn't - // open any window - if (IsLaunching()) - Quit(); + for (int i = 1; i < argc; i++) { + if (argv[i][0] == '-' && argv[i][1] == '-') { + // evaluate --arguments + if (!strcmp(argv[i], "--notitle")) { + fWindow->SetLook(B_MODAL_WINDOW_LOOK); + fWindow->SetFlags(B_OUTLINE_RESIZE); + } else if (!strcmp(argv[i], "--noborder")) + fWindow->SetLook(B_NO_BORDER_WINDOW_LOOK); + else if (!strcmp(argv[i], "--acceptfirstclick")) + fWindow->SetFlags(B_WILL_ACCEPT_FIRST_CLICK); + else if (!strcmp(argv[i], "--avoidfocus")) + fWindow->SetFlags(B_AVOID_FOCUS); + else if (!strcmp(argv[i], "--alwaysontop")) + fWindow->SetFeel(B_FLOATING_ALL_WINDOW_FEEL); + else { + const char *programName = strrchr(argv[0], '/'); + programName = programName ? programName + 1 : argv[0]; + + Usage(programName); + } + } else if (isdigit(*argv[i])) { + // check for a numeric arg, if not already given + activate_workspace(atoi(argv[i])); + + // if the app is running, don't quit + // but if it isn't, cancel the complete run, so it doesn't + // open any window + if (IsLaunching()) + Quit(); + } } } @@ -249,14 +351,7 @@ WorkspacesApp::ArgvReceived(int32 argc, char **argv) void WorkspacesApp::ReadyToRun(void) { - (new WorkspacesWindow(new WorkspacesPreferences()))->Show(); -} - - -bool -WorkspacesApp::QuitRequested(void) -{ - return true; + fWindow->Show(); } @@ -264,11 +359,10 @@ WorkspacesApp::QuitRequested(void) int -main(int argc, char **argv) +main(int32 argc, char **argv) { - new WorkspacesApp(); - be_app->Run(); - delete be_app; + WorkspacesApp app; + app.Run(); + return 0; } -