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
This commit is contained in:
Axel Dörfler
2004-01-17 23:12:12 +00:00
parent 43c4c1eead
commit ff3a346fc5
+163 -69
View File
@@ -1,14 +1,17 @@
/* /*
* Workspaces.cpp * Workspaces - OpenBeOS version by Francois Revol [email protected]
* Open BeOS version alpha 1 by Francois Revol [email protected] * This file is distributed under the terms of the OpenBeOS license.
* *
* Workspaces window trick found by Michael "Minox" Paine. * Workspaces window trick found by Michael "Minox" Paine.
* (using B_ALL_WORKSPACES as flags in BWindow) * (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 * Found out that using 0xffffffff as Flags was causing the window not to close on Alt-W
* hey Workspaces get Flags of Window 0 * hey Workspaces get Flags of Window 0
* gives 0x00008080 which makes it. * gives 0x00008080 which makes it.
*
* Other authors: Axel Dörfler, Oliver "Madison" Kohl, Matt Madia
*/ */
#include <Application.h> #include <Application.h>
#include <Alert.h> #include <Alert.h>
#include <File.h> #include <File.h>
@@ -20,6 +23,18 @@
#include <FindDirectory.h> #include <FindDirectory.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
// 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 { class WorkspacesPreferences {
@@ -29,28 +44,31 @@ class WorkspacesPreferences {
BRect WindowFrame() const { return fWindowFrame; } BRect WindowFrame() const { return fWindowFrame; }
BRect ScreenFrame() const { return fScreenFrame; } BRect ScreenFrame() const { return fScreenFrame; }
void UpdateFramesForScreen(BRect screenFrame);
void UpdateScreenFrame(); void UpdateScreenFrame();
void SetWindowFrame(BRect); void SetWindowFrame(BRect);
private: private:
static const char kWorkspacesSettingFile[]; BRect fWindowFrame, fScreenFrame;
BRect fWindowFrame, fScreenFrame;
}; };
class WorkspacesWindow : public BWindow { class WorkspacesWindow : public BWindow {
public: public:
WorkspacesWindow(WorkspacesPreferences *fPreferences); WorkspacesWindow(WorkspacesPreferences *fPreferences);
virtual ~WorkspacesWindow(); 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 FrameMoved(BPoint origin);
virtual void FrameResized(float width, float height); virtual void FrameResized(float width, float height);
virtual void Zoom(BPoint origin, float width, float height); virtual void Zoom(BPoint origin, float width, float height);
virtual void MessageReceived(BMessage *msg); virtual void MessageReceived(BMessage *msg);
virtual bool QuitRequested(void); virtual bool QuitRequested(void);
private: private:
WorkspacesPreferences *fPreferences; WorkspacesPreferences *fPreferences;
BRect fPreviousFrame;
}; };
class WorkspacesApp : public BApplication { class WorkspacesApp : public BApplication {
@@ -61,51 +79,90 @@ class WorkspacesApp : public BApplication {
virtual void AboutRequested(void); virtual void AboutRequested(void);
virtual void ArgvReceived(int32 argc, char **argv); virtual void ArgvReceived(int32 argc, char **argv);
virtual void ReadyToRun(void); virtual void ReadyToRun(void);
virtual bool WorkspacesApp::QuitRequested(void);
void Usage(const char *programName);
private: private:
static const char kWorkspacesAppSig[]; BWindow *fWindow;
}; };
const char WorkspacesApp::kWorkspacesAppSig[] = "application/x-vnd.Be-WORK";
const char WorkspacesPreferences::kWorkspacesSettingFile[] = "Workspace_data";
WorkspacesPreferences::WorkspacesPreferences() WorkspacesPreferences::WorkspacesPreferences()
{ {
UpdateScreenFrame(); UpdateScreenFrame();
bool settingsValid = false;
BPath path; 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); 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; 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 if (screen.Frame().right >= fWindowFrame.right
&& screen.Frame().bottom >= fWindowFrame.bottom) && screen.Frame().bottom >= fWindowFrame.bottom)
return; settingsValid = true;
} }
} }
fWindowFrame = fScreenFrame; if (!settingsValid) {
fWindowFrame.OffsetBy(-10, -10); // set to some usable defaults
fWindowFrame.left = fWindowFrame.right - 160; fWindowFrame = fScreenFrame;
fWindowFrame.top = fWindowFrame.bottom - 120; fWindowFrame.OffsetBy(-kScreenBorderOffset, -kScreenBorderOffset);
fWindowFrame.left = fWindowFrame.right - 160;
fWindowFrame.top = fWindowFrame.bottom - 120;
}
} }
WorkspacesPreferences::~WorkspacesPreferences() WorkspacesPreferences::~WorkspacesPreferences()
{ {
// write settings file
BPath path; BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY,&path) < B_OK) if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) < B_OK)
return; return;
path.Append(kWorkspacesSettingFile); path.Append(kWorkspacesSettingFile);
BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE); 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(&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 void
WorkspacesPreferences::SetWindowFrame(BRect f) WorkspacesPreferences::SetWindowFrame(BRect frame)
{ {
fWindowFrame = f; fWindowFrame = frame;
UpdateScreenFrame();
} }
// #pragma mark - // #pragma mark -
// here is the trick :)
#define B_WORKSPACES_WINDOW 0x00008000
WorkspacesWindow::WorkspacesWindow(WorkspacesPreferences *preferences) WorkspacesWindow::WorkspacesWindow(WorkspacesPreferences *preferences)
: BWindow(preferences->WindowFrame(), "Workspaces", B_TITLED_WINDOW_LOOK, : 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 void
WorkspacesWindow::ScreenChanged(BRect frame,color_space mode) WorkspacesWindow::ScreenChanged(BRect rect, color_space mode)
{ {
BRect rect = fPreferences->WindowFrame(); fPreviousFrame = fPreferences->WindowFrame();
BRect old = fPreferences->ScreenFrame(); // work-around for a bug in BeOS, see explanation in FrameMoved()
// adjust horizontal position fPreferences->UpdateFramesForScreen(rect);
if (frame.right < rect.left || frame.right > rect.right && rect.left > old.right/2) MoveTo(fPreferences->WindowFrame().LeftTop());
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));
} }
void void
WorkspacesWindow::FrameMoved(BPoint origin) 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()); fPreferences->SetWindowFrame(Frame());
} }
@@ -181,8 +237,8 @@ WorkspacesWindow::Zoom(BPoint origin, float width, float height)
{ {
BScreen screen; BScreen screen;
origin = screen.Frame().RightBottom(); origin = screen.Frame().RightBottom();
origin.x -= 10 + fPreferences->WindowFrame().Width(); origin.x -= kScreenBorderOffset + fPreferences->WindowFrame().Width();
origin.y -= 10 + fPreferences->WindowFrame().Height(); origin.y -= kScreenBorderOffset + fPreferences->WindowFrame().Height();
MoveTo(origin); MoveTo(origin);
} }
@@ -191,7 +247,8 @@ WorkspacesWindow::Zoom(BPoint origin, float width, float height)
void void
WorkspacesWindow::MessageReceived(BMessage *msg) WorkspacesWindow::MessageReceived(BMessage *msg)
{ {
if (msg->what == 'DATA') { // Drop from Tracker if (msg->what == 'DATA') {
// Drop from Tracker
entry_ref ref; entry_ref ref;
for (int i = 0; (msg->FindRef("refs", i, &ref) == B_OK); i++) for (int i = 0; (msg->FindRef("refs", i, &ref) == B_OK); i++)
be_roster->Launch(&ref); be_roster->Launch(&ref);
@@ -211,8 +268,10 @@ WorkspacesWindow::QuitRequested(void)
// #pragma mark - // #pragma mark -
WorkspacesApp::WorkspacesApp() : BApplication(kWorkspacesAppSig) WorkspacesApp::WorkspacesApp()
{ : BApplication(kWorkspacesSignature)
{
fWindow = new WorkspacesWindow(new WorkspacesPreferences());
} }
@@ -226,22 +285,65 @@ WorkspacesApp::AboutRequested(void)
{ {
// blocking !! // blocking !!
// the original does the same by the way =) // 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 void
WorkspacesApp::ArgvReceived(int32 argc, char **argv) WorkspacesApp::ArgvReceived(int32 argc, char **argv)
{ {
// we are told to switch to a specific workspace for (int i = 1; i < argc; i++) {
if (argc > 1) { if (argv[i][0] == '-' && argv[i][1] == '-') {
// get it from the command line... // evaluate --arguments
activate_workspace(atoi(argv[1])); if (!strcmp(argv[i], "--notitle")) {
// if the app is running, don't quit fWindow->SetLook(B_MODAL_WINDOW_LOOK);
// but if it isn't, cancel the complete run, so it doesn't fWindow->SetFlags(B_OUTLINE_RESIZE);
// open any window } else if (!strcmp(argv[i], "--noborder"))
if (IsLaunching()) fWindow->SetLook(B_NO_BORDER_WINDOW_LOOK);
Quit(); 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 void
WorkspacesApp::ReadyToRun(void) WorkspacesApp::ReadyToRun(void)
{ {
(new WorkspacesWindow(new WorkspacesPreferences()))->Show(); fWindow->Show();
}
bool
WorkspacesApp::QuitRequested(void)
{
return true;
} }
@@ -264,11 +359,10 @@ WorkspacesApp::QuitRequested(void)
int int
main(int argc, char **argv) main(int32 argc, char **argv)
{ {
new WorkspacesApp(); WorkspacesApp app;
be_app->Run(); app.Run();
delete be_app;
return 0; return 0;
} }