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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user