2005-07-05 22:14:24 +04:00
|
|
|
/*
|
|
|
|
* Copyright 2001-2005, Haiku.
|
|
|
|
* Distributed under the terms of the MIT License.
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Adrian Oanca <adioanca@cotty.iren.ro>
|
|
|
|
* Stephan Aßmus <superstippi@gmx.de>
|
|
|
|
* Axel Dörfler, axeld@pinc-software.de
|
|
|
|
*/
|
|
|
|
|
|
|
|
/** Class used to encapsulate desktop management */
|
|
|
|
|
|
|
|
|
* the new input event dispatcher is now actually used, although it doesn't
distribute any messages to the clients yet.
* removed the working thread from RootLayer - for now, its event handlers are
still called using input filters in the new event dispatcher, though (to
get things started).
* ServerApp is now using a BMessenger to identify its client, and no longer
stores the port/token separately.
* the input_server handshake is a bit simpler now, as it can now just reply
to the app_server message, removed unused code from ServerProtocol.h
* calmed down the MultiLocker (it always printed thread statistics on startup,
because it's compiled in debug mode).
* removed the cursor thread stuff from AppServer.cpp
* the new event dispatcher now uses a cursor thread when supported (only in
native mode, not in the test environment), although it improves cursor
movement under Qemu, the effect is not as good as expected - this might
need some more investigations (might just be a thread priority problem).
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15012 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-18 14:30:06 +03:00
|
|
|
#include "Desktop.h"
|
2005-07-05 22:14:24 +04:00
|
|
|
|
2004-01-22 03:32:07 +03:00
|
|
|
#include "AppServer.h"
|
* the new input event dispatcher is now actually used, although it doesn't
distribute any messages to the clients yet.
* removed the working thread from RootLayer - for now, its event handlers are
still called using input filters in the new event dispatcher, though (to
get things started).
* ServerApp is now using a BMessenger to identify its client, and no longer
stores the port/token separately.
* the input_server handshake is a bit simpler now, as it can now just reply
to the app_server message, removed unused code from ServerProtocol.h
* calmed down the MultiLocker (it always printed thread statistics on startup,
because it's compiled in debug mode).
* removed the cursor thread stuff from AppServer.cpp
* the new event dispatcher now uses a cursor thread when supported (only in
native mode, not in the test environment), although it improves cursor
movement under Qemu, the effect is not as good as expected - this might
need some more investigations (might just be a thread priority problem).
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15012 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-18 14:30:06 +03:00
|
|
|
#include "DesktopSettingsPrivate.h"
|
2005-11-04 18:54:16 +03:00
|
|
|
#include "DrawingEngine.h"
|
* the new input event dispatcher is now actually used, although it doesn't
distribute any messages to the clients yet.
* removed the working thread from RootLayer - for now, its event handlers are
still called using input filters in the new event dispatcher, though (to
get things started).
* ServerApp is now using a BMessenger to identify its client, and no longer
stores the port/token separately.
* the input_server handshake is a bit simpler now, as it can now just reply
to the app_server message, removed unused code from ServerProtocol.h
* calmed down the MultiLocker (it always printed thread statistics on startup,
because it's compiled in debug mode).
* removed the cursor thread stuff from AppServer.cpp
* the new event dispatcher now uses a cursor thread when supported (only in
native mode, not in the test environment), although it improves cursor
movement under Qemu, the effect is not as good as expected - this might
need some more investigations (might just be a thread priority problem).
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15012 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-18 14:30:06 +03:00
|
|
|
#include "HWInterface.h"
|
|
|
|
#include "InputManager.h"
|
|
|
|
#include "ServerApp.h"
|
2004-01-22 03:32:07 +03:00
|
|
|
#include "ServerConfig.h"
|
|
|
|
#include "ServerScreen.h"
|
|
|
|
#include "ServerWindow.h"
|
2005-11-24 20:45:26 +03:00
|
|
|
#include "WindowLayer.h"
|
2004-01-12 01:12:55 +03:00
|
|
|
#include "Workspace.h"
|
2005-12-09 19:20:01 +03:00
|
|
|
#include "WorkspacesLayer.h"
|
2005-07-17 20:25:48 +04:00
|
|
|
|
* the new input event dispatcher is now actually used, although it doesn't
distribute any messages to the clients yet.
* removed the working thread from RootLayer - for now, its event handlers are
still called using input filters in the new event dispatcher, though (to
get things started).
* ServerApp is now using a BMessenger to identify its client, and no longer
stores the port/token separately.
* the input_server handshake is a bit simpler now, as it can now just reply
to the app_server message, removed unused code from ServerProtocol.h
* calmed down the MultiLocker (it always printed thread statistics on startup,
because it's compiled in debug mode).
* removed the cursor thread stuff from AppServer.cpp
* the new event dispatcher now uses a cursor thread when supported (only in
native mode, not in the test environment), although it improves cursor
movement under Qemu, the effect is not as good as expected - this might
need some more investigations (might just be a thread priority problem).
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15012 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-18 14:30:06 +03:00
|
|
|
#include <WindowInfo.h>
|
|
|
|
#include <ServerProtocol.h>
|
2003-02-12 14:24:26 +03:00
|
|
|
|
2005-11-18 16:51:32 +03:00
|
|
|
#include <Entry.h>
|
* the new input event dispatcher is now actually used, although it doesn't
distribute any messages to the clients yet.
* removed the working thread from RootLayer - for now, its event handlers are
still called using input filters in the new event dispatcher, though (to
get things started).
* ServerApp is now using a BMessenger to identify its client, and no longer
stores the port/token separately.
* the input_server handshake is a bit simpler now, as it can now just reply
to the app_server message, removed unused code from ServerProtocol.h
* calmed down the MultiLocker (it always printed thread statistics on startup,
because it's compiled in debug mode).
* removed the cursor thread stuff from AppServer.cpp
* the new event dispatcher now uses a cursor thread when supported (only in
native mode, not in the test environment), although it improves cursor
movement under Qemu, the effect is not as good as expected - this might
need some more investigations (might just be a thread priority problem).
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15012 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-18 14:30:06 +03:00
|
|
|
#include <Message.h>
|
|
|
|
#include <MessageFilter.h>
|
|
|
|
#include <Region.h>
|
2005-06-24 03:46:17 +04:00
|
|
|
|
* the new input event dispatcher is now actually used, although it doesn't
distribute any messages to the clients yet.
* removed the working thread from RootLayer - for now, its event handlers are
still called using input filters in the new event dispatcher, though (to
get things started).
* ServerApp is now using a BMessenger to identify its client, and no longer
stores the port/token separately.
* the input_server handshake is a bit simpler now, as it can now just reply
to the app_server message, removed unused code from ServerProtocol.h
* calmed down the MultiLocker (it always printed thread statistics on startup,
because it's compiled in debug mode).
* removed the cursor thread stuff from AppServer.cpp
* the new event dispatcher now uses a cursor thread when supported (only in
native mode, not in the test environment), although it improves cursor
movement under Qemu, the effect is not as good as expected - this might
need some more investigations (might just be a thread priority problem).
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15012 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-18 14:30:06 +03:00
|
|
|
#include <stdio.h>
|
2005-06-24 03:46:17 +04:00
|
|
|
|
* the new input event dispatcher is now actually used, although it doesn't
distribute any messages to the clients yet.
* removed the working thread from RootLayer - for now, its event handlers are
still called using input filters in the new event dispatcher, though (to
get things started).
* ServerApp is now using a BMessenger to identify its client, and no longer
stores the port/token separately.
* the input_server handshake is a bit simpler now, as it can now just reply
to the app_server message, removed unused code from ServerProtocol.h
* calmed down the MultiLocker (it always printed thread statistics on startup,
because it's compiled in debug mode).
* removed the cursor thread stuff from AppServer.cpp
* the new event dispatcher now uses a cursor thread when supported (only in
native mode, not in the test environment), although it improves cursor
movement under Qemu, the effect is not as good as expected - this might
need some more investigations (might just be a thread priority problem).
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15012 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-18 14:30:06 +03:00
|
|
|
#if TEST_MODE
|
|
|
|
# include "EventStream.h"
|
|
|
|
#endif
|
2005-06-24 03:46:17 +04:00
|
|
|
|
2004-01-22 03:32:07 +03:00
|
|
|
//#define DEBUG_DESKTOP
|
|
|
|
#ifdef DEBUG_DESKTOP
|
2005-07-05 22:38:12 +04:00
|
|
|
# define STRACE(a) printf(a)
|
2004-01-22 03:32:07 +03:00
|
|
|
#else
|
* the new input event dispatcher is now actually used, although it doesn't
distribute any messages to the clients yet.
* removed the working thread from RootLayer - for now, its event handlers are
still called using input filters in the new event dispatcher, though (to
get things started).
* ServerApp is now using a BMessenger to identify its client, and no longer
stores the port/token separately.
* the input_server handshake is a bit simpler now, as it can now just reply
to the app_server message, removed unused code from ServerProtocol.h
* calmed down the MultiLocker (it always printed thread statistics on startup,
because it's compiled in debug mode).
* removed the cursor thread stuff from AppServer.cpp
* the new event dispatcher now uses a cursor thread when supported (only in
native mode, not in the test environment), although it improves cursor
movement under Qemu, the effect is not as good as expected - this might
need some more investigations (might just be a thread priority problem).
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15012 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-18 14:30:06 +03:00
|
|
|
# define STRACE(a) ;
|
2004-01-22 03:32:07 +03:00
|
|
|
#endif
|
2003-02-14 14:04:01 +03:00
|
|
|
|
2005-04-25 18:14:09 +04:00
|
|
|
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
class KeyboardFilter : public EventFilter {
|
2005-11-18 16:51:32 +03:00
|
|
|
public:
|
|
|
|
KeyboardFilter(Desktop* desktop);
|
|
|
|
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
virtual filter_result Filter(BMessage* message, EventTarget** _target,
|
|
|
|
int32* _viewToken);
|
2005-11-18 16:51:32 +03:00
|
|
|
|
|
|
|
private:
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
Desktop* fDesktop;
|
|
|
|
EventTarget* fLastFocus;
|
|
|
|
bigtime_t fTimestamp;
|
2005-11-18 16:51:32 +03:00
|
|
|
};
|
|
|
|
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
class MouseFilter : public EventFilter {
|
|
|
|
public:
|
|
|
|
MouseFilter(Desktop* desktop);
|
|
|
|
|
|
|
|
virtual filter_result Filter(BMessage* message, EventTarget** _target,
|
|
|
|
int32* _viewToken);
|
|
|
|
|
|
|
|
private:
|
|
|
|
Desktop* fDesktop;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
2005-11-18 16:51:32 +03:00
|
|
|
|
|
|
|
KeyboardFilter::KeyboardFilter(Desktop* desktop)
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
:
|
|
|
|
fDesktop(desktop),
|
|
|
|
fLastFocus(NULL),
|
|
|
|
fTimestamp(0)
|
2005-11-18 16:51:32 +03:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
filter_result
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
KeyboardFilter::Filter(BMessage* message, EventTarget** _target,
|
|
|
|
int32* /*_viewToken*/)
|
2005-11-18 16:51:32 +03:00
|
|
|
{
|
|
|
|
int32 key;
|
|
|
|
int32 modifiers;
|
|
|
|
|
|
|
|
if (message->what != B_KEY_DOWN
|
|
|
|
|| message->FindInt32("key", &key) != B_OK
|
|
|
|
|| message->FindInt32("modifiers", &modifiers) != B_OK)
|
|
|
|
return B_DISPATCH_MESSAGE;
|
|
|
|
|
|
|
|
// Check for safe video mode (F12 + l-cmd + l-ctrl + l-shift)
|
|
|
|
if (key == 0x0d
|
|
|
|
&& (modifiers & (B_LEFT_COMMAND_KEY
|
|
|
|
| B_LEFT_CONTROL_KEY | B_LEFT_SHIFT_KEY)) != 0)
|
|
|
|
{
|
|
|
|
// TODO: Set to Safe Mode in KeyboardEventHandler:B_KEY_DOWN.
|
|
|
|
STRACE(("Safe Video Mode invoked - code unimplemented\n"));
|
|
|
|
return B_SKIP_MESSAGE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key > 0x01 && key < 0x0e) {
|
|
|
|
// workspace change, F1-F12
|
|
|
|
|
|
|
|
#if !TEST_MODE
|
|
|
|
if (modifiers & B_COMMAND_KEY)
|
|
|
|
#else
|
|
|
|
if (modifiers & B_CONTROL_KEY)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
STRACE(("Set Workspace %ld\n", key - 1));
|
|
|
|
|
2005-11-29 02:36:59 +03:00
|
|
|
fDesktop->SetWorkspace(key - 2);
|
2005-11-18 16:51:32 +03:00
|
|
|
return B_SKIP_MESSAGE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: this should be moved client side!
|
|
|
|
// (that's how it is done in BeOS, clients could need this key for
|
|
|
|
// different purposes - also, it's preferrable to let the client
|
|
|
|
// write the dump within his own environment)
|
|
|
|
if (key == 0xe) {
|
|
|
|
// screen dump, PrintScreen
|
|
|
|
char filename[128];
|
|
|
|
BEntry entry;
|
|
|
|
|
|
|
|
int32 index = 1;
|
|
|
|
do {
|
|
|
|
sprintf(filename, "/boot/home/screen%ld.png", index++);
|
|
|
|
entry.SetTo(filename);
|
|
|
|
} while(entry.Exists());
|
|
|
|
|
|
|
|
fDesktop->GetDrawingEngine()->DumpToFile(filename);
|
|
|
|
return B_SKIP_MESSAGE;
|
|
|
|
}
|
|
|
|
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
bigtime_t now = system_time();
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
if (!fDesktop->LockSingleWindow())
|
2005-12-10 16:47:13 +03:00
|
|
|
return B_DISPATCH_MESSAGE;
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
|
|
|
|
EventTarget* focus = NULL;
|
2005-12-08 15:41:19 +03:00
|
|
|
if (fDesktop->FocusWindow() != NULL)
|
|
|
|
focus = &fDesktop->FocusWindow()->EventTarget();
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
|
|
|
|
// TODO: this is a try to not steal focus from the current window
|
|
|
|
// in case you enter some text and a window pops up you haven't
|
|
|
|
// triggered yourself (like a pop-up window in your browser while
|
|
|
|
// you're typing a password in another window) - maybe this should
|
|
|
|
// be done differently, though (using something like B_LOCK_WINDOW_FOCUS)
|
2005-11-29 20:00:08 +03:00
|
|
|
// (at least B_WINDOW_ACTIVATED must be postponed)
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
|
|
|
|
if (focus != fLastFocus && now - fTimestamp > 100000) {
|
|
|
|
// if the time span between the key presses is very short
|
|
|
|
// we keep our previous focus alive - this is save even
|
|
|
|
// if the target doesn't exist anymore, as we don't reset
|
|
|
|
// it, and the event focus passed in is always valid (or NULL)
|
|
|
|
*_target = focus;
|
|
|
|
fLastFocus = focus;
|
|
|
|
}
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
fDesktop->UnlockSingleWindow();
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
|
|
|
|
// we always allow to switch focus after the enter key has pressed
|
|
|
|
if (key == B_ENTER)
|
|
|
|
fTimestamp = 0;
|
|
|
|
else
|
|
|
|
fTimestamp = now;
|
|
|
|
|
|
|
|
return B_DISPATCH_MESSAGE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
|
|
|
MouseFilter::MouseFilter(Desktop* desktop)
|
|
|
|
:
|
|
|
|
fDesktop(desktop)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
filter_result
|
|
|
|
MouseFilter::Filter(BMessage* message, EventTarget** _target, int32* _viewToken)
|
|
|
|
{
|
|
|
|
BPoint where;
|
|
|
|
if (message->FindPoint("where", &where) != B_OK)
|
|
|
|
return B_DISPATCH_MESSAGE;
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
if (!fDesktop->LockAllWindows())
|
2005-12-10 16:47:13 +03:00
|
|
|
return B_DISPATCH_MESSAGE;
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
WindowLayer* window = fDesktop->MouseEventWindow();
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
if (window == NULL)
|
2005-12-08 15:41:19 +03:00
|
|
|
window = fDesktop->WindowAt(where);
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
|
|
|
|
if (window != NULL) {
|
|
|
|
// dispatch event in the window layers
|
|
|
|
switch (message->what) {
|
|
|
|
case B_MOUSE_DOWN:
|
|
|
|
window->MouseDown(message, where, _viewToken);
|
|
|
|
break;
|
2005-12-08 15:41:19 +03:00
|
|
|
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
case B_MOUSE_UP:
|
|
|
|
window->MouseUp(message, where, _viewToken);
|
2005-12-08 15:41:19 +03:00
|
|
|
fDesktop->SetMouseEventWindow(NULL);
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
break;
|
2005-12-08 15:41:19 +03:00
|
|
|
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
case B_MOUSE_MOVED:
|
|
|
|
window->MouseMoved(message, where, _viewToken);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*_viewToken != B_NULL_TOKEN)
|
2005-12-08 15:41:19 +03:00
|
|
|
*_target = &window->EventTarget();
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
else
|
|
|
|
*_target = NULL;
|
|
|
|
} else
|
|
|
|
*_target = NULL;
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
fDesktop->UnlockAllWindows();
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
|
2005-11-18 16:51:32 +03:00
|
|
|
return B_DISPATCH_MESSAGE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
2005-11-30 18:47:01 +03:00
|
|
|
static inline uint32
|
|
|
|
workspace_to_workspaces(int32 index)
|
|
|
|
{
|
|
|
|
return 1UL << index;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline bool
|
2005-12-09 16:28:28 +03:00
|
|
|
workspace_in_workspaces(int32 index, uint32 workspaces)
|
2005-11-30 18:47:01 +03:00
|
|
|
{
|
|
|
|
return (workspaces & (1UL << index)) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
2005-10-31 22:35:46 +03:00
|
|
|
Desktop::Desktop(uid_t userID)
|
2005-07-24 21:14:17 +04:00
|
|
|
: MessageLooper("desktop"),
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2005-10-31 22:35:46 +03:00
|
|
|
fUserID(userID),
|
2005-07-17 20:25:48 +04:00
|
|
|
fSettings(new DesktopSettings::Private()),
|
2005-12-08 15:41:19 +03:00
|
|
|
fApplicationsLock("application list"),
|
2005-07-26 01:08:34 +04:00
|
|
|
fShutdownSemaphore(-1),
|
2005-12-08 15:41:19 +03:00
|
|
|
fAllWindows(kAllWindowList),
|
2005-12-09 16:17:43 +03:00
|
|
|
fSubsetWindows(kSubsetList),
|
2005-12-09 19:20:01 +03:00
|
|
|
fWorkspacesLayer(NULL),
|
2005-08-21 14:28:40 +04:00
|
|
|
fActiveScreen(NULL),
|
2005-12-08 15:41:19 +03:00
|
|
|
fWindowLock("window lock")
|
2004-01-22 03:32:07 +03:00
|
|
|
{
|
2005-07-24 21:14:17 +04:00
|
|
|
char name[B_OS_NAME_LENGTH];
|
2005-11-17 17:56:12 +03:00
|
|
|
Desktop::_GetLooperName(name, sizeof(name));
|
2005-07-24 21:14:17 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
for (int32 i = 0; i < kMaxWorkspaces; i++) {
|
2005-12-09 16:17:43 +03:00
|
|
|
_Windows(i).SetIndex(i);
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
2005-07-24 21:14:17 +04:00
|
|
|
fMessagePort = create_port(DEFAULT_MONITOR_PORT_SIZE, name);
|
|
|
|
if (fMessagePort < B_OK)
|
|
|
|
return;
|
2005-07-26 01:08:34 +04:00
|
|
|
|
|
|
|
fLink.SetReceiverPort(fMessagePort);
|
2005-11-03 20:03:36 +03:00
|
|
|
gFontManager->AttachUser(fUserID);
|
2003-01-24 18:19:27 +03:00
|
|
|
}
|
2004-01-22 03:32:07 +03:00
|
|
|
|
2005-04-25 18:14:09 +04:00
|
|
|
|
2005-06-24 03:46:17 +04:00
|
|
|
Desktop::~Desktop()
|
2004-01-22 03:32:07 +03:00
|
|
|
{
|
2005-07-17 20:25:48 +04:00
|
|
|
delete fSettings;
|
2005-07-24 21:14:17 +04:00
|
|
|
|
|
|
|
delete_port(fMessagePort);
|
2005-11-03 20:03:36 +03:00
|
|
|
gFontManager->DetachUser(fUserID);
|
2003-01-24 18:19:27 +03:00
|
|
|
}
|
2004-01-13 03:56:36 +03:00
|
|
|
|
2005-03-29 19:39:08 +04:00
|
|
|
|
|
|
|
void
|
2005-06-24 03:46:17 +04:00
|
|
|
Desktop::Init()
|
2004-01-22 03:32:07 +03:00
|
|
|
{
|
2005-07-17 20:25:48 +04:00
|
|
|
fVirtualScreen.RestoreConfiguration(*this, fSettings->WorkspacesMessage(0));
|
2005-04-25 18:14:09 +04:00
|
|
|
|
2005-07-15 16:45:23 +04:00
|
|
|
// TODO: temporary workaround, fActiveScreen will be removed
|
|
|
|
fActiveScreen = fVirtualScreen.ScreenAt(0);
|
2005-04-25 18:14:09 +04:00
|
|
|
|
2005-11-15 22:59:53 +03:00
|
|
|
#if TEST_MODE
|
* the new input event dispatcher is now actually used, although it doesn't
distribute any messages to the clients yet.
* removed the working thread from RootLayer - for now, its event handlers are
still called using input filters in the new event dispatcher, though (to
get things started).
* ServerApp is now using a BMessenger to identify its client, and no longer
stores the port/token separately.
* the input_server handshake is a bit simpler now, as it can now just reply
to the app_server message, removed unused code from ServerProtocol.h
* calmed down the MultiLocker (it always printed thread statistics on startup,
because it's compiled in debug mode).
* removed the cursor thread stuff from AppServer.cpp
* the new event dispatcher now uses a cursor thread when supported (only in
native mode, not in the test environment), although it improves cursor
movement under Qemu, the effect is not as good as expected - this might
need some more investigations (might just be a thread priority problem).
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15012 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-18 14:30:06 +03:00
|
|
|
gInputManager->AddStream(new InputServerStream);
|
2005-11-15 22:59:53 +03:00
|
|
|
#endif
|
* the new input event dispatcher is now actually used, although it doesn't
distribute any messages to the clients yet.
* removed the working thread from RootLayer - for now, its event handlers are
still called using input filters in the new event dispatcher, though (to
get things started).
* ServerApp is now using a BMessenger to identify its client, and no longer
stores the port/token separately.
* the input_server handshake is a bit simpler now, as it can now just reply
to the app_server message, removed unused code from ServerProtocol.h
* calmed down the MultiLocker (it always printed thread statistics on startup,
because it's compiled in debug mode).
* removed the cursor thread stuff from AppServer.cpp
* the new event dispatcher now uses a cursor thread when supported (only in
native mode, not in the test environment), although it improves cursor
movement under Qemu, the effect is not as good as expected - this might
need some more investigations (might just be a thread priority problem).
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15012 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-18 14:30:06 +03:00
|
|
|
fEventDispatcher.SetTo(gInputManager->GetStream());
|
|
|
|
fEventDispatcher.SetHWInterface(fVirtualScreen.HWInterface());
|
|
|
|
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
fEventDispatcher.SetMouseFilter(new MouseFilter(this));
|
2005-11-18 16:51:32 +03:00
|
|
|
fEventDispatcher.SetKeyboardFilter(new KeyboardFilter(this));
|
2005-07-18 04:22:08 +04:00
|
|
|
|
|
|
|
// take care of setting the default cursor
|
2005-08-21 14:28:40 +04:00
|
|
|
ServerCursor *cursor = fCursorManager.GetCursor(B_CURSOR_DEFAULT);
|
2005-07-18 04:22:08 +04:00
|
|
|
if (cursor)
|
|
|
|
fVirtualScreen.HWInterface()->SetCursor(cursor);
|
2005-11-18 16:21:07 +03:00
|
|
|
|
|
|
|
fVirtualScreen.HWInterface()->MoveCursorTo(fVirtualScreen.Frame().Width() / 2,
|
|
|
|
fVirtualScreen.Frame().Height() / 2);
|
* the new input event dispatcher is now actually used, although it doesn't
distribute any messages to the clients yet.
* removed the working thread from RootLayer - for now, its event handlers are
still called using input filters in the new event dispatcher, though (to
get things started).
* ServerApp is now using a BMessenger to identify its client, and no longer
stores the port/token separately.
* the input_server handshake is a bit simpler now, as it can now just reply
to the app_server message, removed unused code from ServerProtocol.h
* calmed down the MultiLocker (it always printed thread statistics on startup,
because it's compiled in debug mode).
* removed the cursor thread stuff from AppServer.cpp
* the new event dispatcher now uses a cursor thread when supported (only in
native mode, not in the test environment), although it improves cursor
movement under Qemu, the effect is not as good as expected - this might
need some more investigations (might just be a thread priority problem).
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15012 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-18 14:30:06 +03:00
|
|
|
fVirtualScreen.HWInterface()->SetCursorVisible(true);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
// draw the background
|
|
|
|
|
|
|
|
fScreenRegion = fVirtualScreen.Frame();
|
|
|
|
|
|
|
|
BRegion stillAvailableOnScreen;
|
|
|
|
_RebuildClippingForAllWindows(stillAvailableOnScreen);
|
|
|
|
_SetBackground(stillAvailableOnScreen);
|
2003-01-24 18:19:27 +03:00
|
|
|
}
|
2004-01-22 03:32:07 +03:00
|
|
|
|
2005-04-25 18:14:09 +04:00
|
|
|
|
2005-07-24 21:14:17 +04:00
|
|
|
void
|
|
|
|
Desktop::_GetLooperName(char* name, size_t length)
|
|
|
|
{
|
|
|
|
snprintf(name, length, "d:%d:%s", /*id*/0, /*name*/"baron");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-26 01:08:34 +04:00
|
|
|
void
|
|
|
|
Desktop::_PrepareQuit()
|
|
|
|
{
|
|
|
|
// let's kill all remaining applications
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
fApplicationsLock.Lock();
|
2005-07-26 01:08:34 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
int32 count = fApplications.CountItems();
|
2005-07-26 01:08:34 +04:00
|
|
|
for (int32 i = 0; i < count; i++) {
|
2005-12-08 15:41:19 +03:00
|
|
|
ServerApp *app = fApplications.ItemAt(i);
|
2005-07-26 01:08:34 +04:00
|
|
|
team_id clientTeam = app->ClientTeam();
|
|
|
|
|
|
|
|
app->Quit();
|
|
|
|
kill_team(clientTeam);
|
|
|
|
}
|
|
|
|
|
|
|
|
// wait for the last app to die
|
|
|
|
if (count > 0)
|
|
|
|
acquire_sem_etc(fShutdownSemaphore, fShutdownCount, B_RELATIVE_TIMEOUT, 250000);
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
fApplicationsLock.Unlock();
|
2005-07-26 01:08:34 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
Desktop::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
|
|
|
{
|
|
|
|
switch (code) {
|
|
|
|
case AS_CREATE_APP:
|
|
|
|
{
|
|
|
|
// Create the ServerApp to node monitor a new BApplication
|
|
|
|
|
|
|
|
// Attached data:
|
|
|
|
// 1) port_id - receiver port of a regular app
|
|
|
|
// 2) port_id - client looper port - for sending messages to the client
|
|
|
|
// 2) team_id - app's team ID
|
|
|
|
// 3) int32 - handler token of the regular app
|
|
|
|
// 4) char * - signature of the regular app
|
|
|
|
|
|
|
|
// Find the necessary data
|
|
|
|
team_id clientTeamID = -1;
|
|
|
|
port_id clientLooperPort = -1;
|
|
|
|
port_id clientReplyPort = -1;
|
|
|
|
int32 htoken = B_NULL_TOKEN;
|
|
|
|
char *appSignature = NULL;
|
|
|
|
|
|
|
|
link.Read<port_id>(&clientReplyPort);
|
|
|
|
link.Read<port_id>(&clientLooperPort);
|
|
|
|
link.Read<team_id>(&clientTeamID);
|
|
|
|
link.Read<int32>(&htoken);
|
|
|
|
if (link.ReadString(&appSignature) != B_OK)
|
|
|
|
break;
|
|
|
|
|
|
|
|
ServerApp *app = new ServerApp(this, clientReplyPort,
|
|
|
|
clientLooperPort, clientTeamID, htoken, appSignature);
|
|
|
|
if (app->InitCheck() == B_OK
|
|
|
|
&& app->Run()) {
|
|
|
|
// add the new ServerApp to the known list of ServerApps
|
2005-12-08 15:41:19 +03:00
|
|
|
fApplicationsLock.Lock();
|
|
|
|
fApplications.AddItem(app);
|
|
|
|
fApplicationsLock.Unlock();
|
2005-07-26 01:08:34 +04:00
|
|
|
} else {
|
|
|
|
delete app;
|
|
|
|
|
|
|
|
// if everything went well, ServerApp::Run() will notify
|
|
|
|
// the client - but since it didn't, we do it here
|
|
|
|
BPrivate::LinkSender reply(clientReplyPort);
|
|
|
|
reply.StartMessage(SERVER_FALSE);
|
|
|
|
reply.Flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is necessary because BPortLink::ReadString allocates memory
|
|
|
|
free(appSignature);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case AS_DELETE_APP:
|
|
|
|
{
|
|
|
|
// Delete a ServerApp. Received only from the respective ServerApp when a
|
|
|
|
// BApplication asks it to quit.
|
|
|
|
|
|
|
|
// Attached Data:
|
|
|
|
// 1) thread_id - thread ID of the ServerApp to be deleted
|
|
|
|
|
|
|
|
thread_id thread = -1;
|
|
|
|
if (link.Read<thread_id>(&thread) < B_OK)
|
|
|
|
break;
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
fApplicationsLock.Lock();
|
2005-07-26 01:08:34 +04:00
|
|
|
|
|
|
|
// Run through the list of apps and nuke the proper one
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
int32 count = fApplications.CountItems();
|
2005-07-26 01:08:34 +04:00
|
|
|
ServerApp *removeApp = NULL;
|
|
|
|
|
|
|
|
for (int32 i = 0; i < count; i++) {
|
2005-12-08 15:41:19 +03:00
|
|
|
ServerApp *app = fApplications.ItemAt(i);
|
2005-07-26 01:08:34 +04:00
|
|
|
|
|
|
|
if (app != NULL && app->Thread() == thread) {
|
2005-12-08 15:41:19 +03:00
|
|
|
fApplications.RemoveItemAt(i);
|
2005-07-26 01:08:34 +04:00
|
|
|
removeApp = app;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
fApplicationsLock.Unlock();
|
2005-07-26 01:08:34 +04:00
|
|
|
|
|
|
|
if (removeApp != NULL)
|
|
|
|
removeApp->Quit(fShutdownSemaphore);
|
|
|
|
|
|
|
|
if (fQuitting && count <= 1) {
|
|
|
|
// wait for the last app to die
|
|
|
|
acquire_sem_etc(fShutdownSemaphore, fShutdownCount, B_RELATIVE_TIMEOUT, 500000);
|
|
|
|
PostMessage(kMsgQuitLooper);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-10-31 22:35:46 +03:00
|
|
|
case AS_ACTIVATE_APP:
|
|
|
|
{
|
|
|
|
// Someone is requesting to activation of a certain app.
|
|
|
|
|
|
|
|
// Attached data:
|
|
|
|
// 1) port_id reply port
|
|
|
|
// 2) team_id team
|
|
|
|
|
|
|
|
status_t status;
|
|
|
|
|
|
|
|
// get the parameters
|
|
|
|
port_id replyPort;
|
|
|
|
team_id team;
|
|
|
|
if (link.Read(&replyPort) == B_OK
|
|
|
|
&& link.Read(&team) == B_OK)
|
|
|
|
status = _ActivateApp(team);
|
|
|
|
else
|
|
|
|
status = B_ERROR;
|
|
|
|
|
|
|
|
// send the reply
|
|
|
|
BPrivate::PortLink replyLink(replyPort);
|
|
|
|
replyLink.StartMessage(status);
|
|
|
|
replyLink.Flush();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case AS_SET_SYSCURSOR_DEFAULTS:
|
|
|
|
{
|
|
|
|
GetCursorManager().SetDefaults();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-07-26 01:08:34 +04:00
|
|
|
case B_QUIT_REQUESTED:
|
|
|
|
// We've been asked to quit, so (for now) broadcast to all
|
|
|
|
// test apps to quit. This situation will occur only when the server
|
|
|
|
// is compiled as a regular Be application.
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
fApplicationsLock.Lock();
|
2005-07-26 01:08:34 +04:00
|
|
|
fShutdownSemaphore = create_sem(0, "desktop shutdown");
|
2005-12-08 15:41:19 +03:00
|
|
|
fShutdownCount = fApplications.CountItems();
|
|
|
|
fApplicationsLock.Unlock();
|
2005-07-26 01:08:34 +04:00
|
|
|
|
|
|
|
fQuitting = true;
|
|
|
|
BroadcastToAllApps(AS_QUIT_APP);
|
|
|
|
|
|
|
|
// We now need to process the remaining AS_DELETE_APP messages and
|
|
|
|
// wait for the kMsgShutdownServer message.
|
|
|
|
// If an application does not quit as asked, the picasso thread
|
|
|
|
// will send us this message in 2-3 seconds.
|
|
|
|
|
|
|
|
// if there are no apps to quit, shutdown directly
|
|
|
|
if (fShutdownCount == 0)
|
|
|
|
PostMessage(kMsgQuitLooper);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
printf("Desktop %d:%s received unexpected code %ld\n", 0, "baron", code);
|
|
|
|
|
|
|
|
if (link.NeedsReply()) {
|
|
|
|
// the client is now blocking and waiting for a reply!
|
|
|
|
fLink.StartMessage(B_ERROR);
|
|
|
|
fLink.Flush();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-10-31 22:35:46 +03:00
|
|
|
/*!
|
|
|
|
\brief activate one of the app's windows.
|
|
|
|
*/
|
|
|
|
status_t
|
|
|
|
Desktop::_ActivateApp(team_id team)
|
|
|
|
{
|
|
|
|
status_t status = B_BAD_TEAM_ID;
|
|
|
|
|
|
|
|
// search for an unhidden window to give focus to
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
for (WindowLayer* window = fAllWindows.FirstWindow(); window != NULL;
|
|
|
|
window = window->NextWindow(kAllWindowList)) {
|
|
|
|
// if window is a normal window of the team, and not hidden,
|
|
|
|
// we've found our target
|
|
|
|
if (!window->IsHidden() && window->IsNormal()
|
|
|
|
&& window->ServerWindow()->ClientTeam() == team) {
|
|
|
|
ActivateWindow(window);
|
2005-11-29 02:36:59 +03:00
|
|
|
return B_OK;
|
2005-10-31 22:35:46 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-26 01:08:34 +04:00
|
|
|
/*!
|
|
|
|
\brief Send a quick (no attachments) message to all applications
|
|
|
|
|
|
|
|
Quite useful for notification for things like server shutdown, system
|
|
|
|
color changes, etc.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
Desktop::BroadcastToAllApps(int32 code)
|
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
BAutolock locker(fApplicationsLock);
|
2005-07-26 01:08:34 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
for (int32 i = 0; i < fApplications.CountItems(); i++) {
|
|
|
|
fApplications.ItemAt(i)->PostMessage(code);
|
2005-07-26 01:08:34 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
Desktop::UpdateWorkspaces()
|
|
|
|
{
|
|
|
|
// TODO: maybe this should be replaced by a SetWorkspacesCount() method
|
|
|
|
|
2005-12-09 19:20:01 +03:00
|
|
|
_WindowChanged(NULL);
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-11-29 02:36:59 +03:00
|
|
|
void
|
|
|
|
Desktop::SetWorkspace(int32 index)
|
|
|
|
{
|
2005-12-12 13:41:31 +03:00
|
|
|
LockAllWindows();
|
2005-11-29 02:36:59 +03:00
|
|
|
DesktopSettings settings(this);
|
|
|
|
|
2005-12-10 16:47:13 +03:00
|
|
|
if (index < 0 || index >= settings.WorkspacesCount() || index == fCurrentWorkspace) {
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockAllWindows();
|
2005-11-29 02:36:59 +03:00
|
|
|
return;
|
2005-12-10 16:47:13 +03:00
|
|
|
}
|
2005-12-08 17:45:42 +03:00
|
|
|
|
2005-11-30 18:47:01 +03:00
|
|
|
int32 previousIndex = fCurrentWorkspace;
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2005-12-08 17:45:42 +03:00
|
|
|
if (fMouseEventWindow != NULL) {
|
2005-12-09 16:17:43 +03:00
|
|
|
if (!fMouseEventWindow->InWorkspace(index)) {
|
|
|
|
// the window currently being dragged will follow us to this workspace
|
|
|
|
// if it's not already on it
|
|
|
|
if (fMouseEventWindow->IsNormal()) {
|
|
|
|
// but only normal windows are following
|
2005-12-15 19:42:12 +03:00
|
|
|
uint32 oldWorkspaces = fMouseEventWindow->Workspaces();
|
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
_Windows(index).AddWindow(fMouseEventWindow);
|
|
|
|
_Windows(previousIndex).RemoveWindow(fMouseEventWindow);
|
2005-12-15 19:42:12 +03:00
|
|
|
|
|
|
|
// send B_WORKSPACES_CHANGED message
|
|
|
|
fMouseEventWindow->WorkspacesChanged(oldWorkspaces,
|
|
|
|
fMouseEventWindow->Workspaces());
|
2005-12-09 16:17:43 +03:00
|
|
|
}
|
2005-12-08 17:45:42 +03:00
|
|
|
} else {
|
|
|
|
// make sure it's frontmost
|
2005-12-09 16:17:43 +03:00
|
|
|
_Windows(index).RemoveWindow(fMouseEventWindow);
|
|
|
|
_Windows(index).AddWindow(fMouseEventWindow,
|
|
|
|
fMouseEventWindow->Frontmost(_Windows(index).FirstWindow(), index));
|
2005-12-08 17:45:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
fMouseEventWindow->Anchor(index).position = fMouseEventWindow->Frame().LeftTop();
|
|
|
|
}
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// build region of windows that are no longer visible in the new workspace
|
|
|
|
|
|
|
|
BRegion dirty;
|
2005-12-09 16:17:43 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
for (WindowLayer* window = _CurrentWindows().FirstWindow();
|
|
|
|
window != NULL; window = window->NextWindow(previousIndex)) {
|
2005-12-09 16:17:43 +03:00
|
|
|
// store current position in Workspace anchor
|
2005-12-08 15:41:19 +03:00
|
|
|
window->Anchor(previousIndex).position = window->Frame().LeftTop();
|
|
|
|
|
2005-12-15 19:42:12 +03:00
|
|
|
window->WorkspaceActivated(previousIndex, false);
|
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
if (window->InWorkspace(index))
|
2005-12-08 15:41:19 +03:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!window->IsHidden()) {
|
|
|
|
// this window will no longer be visible
|
|
|
|
dirty.Include(&window->VisibleRegion());
|
|
|
|
}
|
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
window->SetCurrentWorkspace(-1);
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
2005-11-30 18:47:01 +03:00
|
|
|
fCurrentWorkspace = index;
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// show windows, and include them in the changed region - but only
|
|
|
|
// those that were not visible before (or whose position changed)
|
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
for (WindowLayer* window = _Windows(index).FirstWindow();
|
2005-12-08 15:41:19 +03:00
|
|
|
window != NULL; window = window->NextWindow(index)) {
|
|
|
|
BPoint position = window->Anchor(index).position;
|
|
|
|
|
|
|
|
window->SetCurrentWorkspace(index);
|
|
|
|
|
|
|
|
if (window->IsHidden())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (position == kInvalidWindowPosition) {
|
|
|
|
// if you enter a workspace for the first time, the position
|
|
|
|
// of the window in the previous workspace is adopted
|
|
|
|
position = window->Frame().LeftTop();
|
|
|
|
// TODO: make sure the window is still on-screen if it
|
|
|
|
// was before!
|
|
|
|
}
|
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
if (!window->InWorkspace(previousIndex)) {
|
2005-12-08 15:41:19 +03:00
|
|
|
// this window was not visible before
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (window->Frame().LeftTop() != position) {
|
|
|
|
// the window was visible before, but its on-screen location changed
|
|
|
|
BPoint offset = position - window->Frame().LeftTop();
|
|
|
|
MoveWindowBy(window, offset.x, offset.y);
|
|
|
|
// TODO: be a bit smarter than this...
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BRegion stillAvailableOnScreen;
|
|
|
|
_RebuildClippingForAllWindows(stillAvailableOnScreen);
|
|
|
|
_SetBackground(stillAvailableOnScreen);
|
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
for (WindowLayer* window = _Windows(index).FirstWindow(); window != NULL;
|
2005-12-08 15:41:19 +03:00
|
|
|
window = window->NextWindow(index)) {
|
2005-12-15 19:42:12 +03:00
|
|
|
// send B_WORKSPACE_ACTIVATED message
|
|
|
|
window->WorkspaceActivated(index, true);
|
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
if (window->InWorkspace(previousIndex) || window == fMouseEventWindow) {
|
2005-12-08 15:41:19 +03:00
|
|
|
// this window was visible before, and is already handled in the above loop
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
dirty.Include(&window->VisibleRegion());
|
|
|
|
}
|
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
_UpdateFronts(false);
|
|
|
|
_UpdateFloating(previousIndex, index);
|
|
|
|
|
2005-12-09 17:23:51 +03:00
|
|
|
// Set new focus to the front window, but keep focus to a floating
|
|
|
|
// window if still visible
|
|
|
|
if (!_Windows(index).HasWindow(FocusWindow()) || !FocusWindow()->IsFloating())
|
|
|
|
SetFocusWindow(FrontWindow());
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2005-12-09 19:20:01 +03:00
|
|
|
_WindowChanged(NULL);
|
2005-12-08 15:41:19 +03:00
|
|
|
MarkDirty(dirty);
|
2005-12-08 17:45:42 +03:00
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockAllWindows();
|
2005-11-29 02:36:59 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-11-26 19:56:52 +03:00
|
|
|
void
|
|
|
|
Desktop::ScreenChanged(Screen* screen)
|
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
// TODO: confirm that everywhere this is used,
|
|
|
|
// the Window WriteLock is held
|
|
|
|
|
|
|
|
// the entire screen is dirty, because we're actually
|
|
|
|
// operating on an all new buffer in memory
|
|
|
|
BRegion dirty(screen->Frame());
|
|
|
|
// update our cached screen region
|
|
|
|
fScreenRegion.Set(screen->Frame());
|
|
|
|
|
|
|
|
BRegion background;
|
|
|
|
_RebuildClippingForAllWindows(background);
|
|
|
|
|
|
|
|
fBackgroundRegion.MakeEmpty();
|
|
|
|
// makes sure that the complete background is redrawn
|
|
|
|
_SetBackground(background);
|
|
|
|
|
|
|
|
// figure out dirty region
|
|
|
|
dirty.Exclude(&background);
|
|
|
|
_TriggerWindowRedrawing(dirty);
|
|
|
|
|
|
|
|
// send B_SCREEN_CHANGED to windows on that screen
|
2005-11-26 19:56:52 +03:00
|
|
|
BMessage update(B_SCREEN_CHANGED);
|
|
|
|
update.AddInt64("when", real_time_clock_usecs());
|
|
|
|
update.AddRect("frame", screen->Frame());
|
|
|
|
update.AddInt32("mode", screen->ColorSpace());
|
|
|
|
|
|
|
|
// TODO: currently ignores the screen argument!
|
2005-12-08 15:41:19 +03:00
|
|
|
for (WindowLayer* window = fAllWindows.FirstWindow(); window != NULL;
|
|
|
|
window = window->NextWindow(kAllWindowList)) {
|
|
|
|
window->ServerWindow()->SendMessageToClient(&update);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// #pragma mark - Methods for WindowLayer manipulation
|
|
|
|
|
|
|
|
|
|
|
|
WindowList&
|
|
|
|
Desktop::_CurrentWindows()
|
|
|
|
{
|
|
|
|
return fWorkspaces[fCurrentWorkspace].Windows();
|
|
|
|
}
|
2005-11-26 19:56:52 +03:00
|
|
|
|
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
WindowList&
|
|
|
|
Desktop::_Windows(int32 index)
|
|
|
|
{
|
|
|
|
return fWorkspaces[index].Windows();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
Desktop::_UpdateFloating(int32 previousWorkspace, int32 nextWorkspace)
|
|
|
|
{
|
|
|
|
if (fFront == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (previousWorkspace == -1)
|
|
|
|
previousWorkspace = fCurrentWorkspace;
|
|
|
|
if (nextWorkspace == -1)
|
|
|
|
nextWorkspace = previousWorkspace;
|
|
|
|
|
|
|
|
for (WindowLayer* floating = fSubsetWindows.FirstWindow(); floating != NULL;
|
|
|
|
floating = floating->NextWindow(kSubsetList)) {
|
|
|
|
// we only care about app/subset floating windows
|
|
|
|
if (floating->Feel() != B_FLOATING_SUBSET_WINDOW_FEEL
|
|
|
|
&& floating->Feel() != B_FLOATING_APP_WINDOW_FEEL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (fFront->IsNormal() && floating->HasInSubset(fFront)) {
|
|
|
|
// is now visible
|
|
|
|
if (_Windows(previousWorkspace).HasWindow(floating)
|
|
|
|
&& previousWorkspace != nextWorkspace) {
|
|
|
|
// but no longer on the previous workspace
|
|
|
|
_Windows(previousWorkspace).RemoveWindow(floating);
|
|
|
|
floating->SetCurrentWorkspace(-1);
|
|
|
|
}
|
|
|
|
if (!_Windows(nextWorkspace).HasWindow(floating)) {
|
|
|
|
// but wasn't before
|
|
|
|
_Windows(nextWorkspace).AddWindow(floating,
|
|
|
|
floating->Frontmost(_Windows(nextWorkspace).FirstWindow(), nextWorkspace));
|
|
|
|
floating->SetCurrentWorkspace(nextWorkspace);
|
|
|
|
_ShowWindow(floating);
|
|
|
|
|
|
|
|
// TODO:
|
|
|
|
// put the floating last in the floating window list to preserve
|
|
|
|
// the on screen window order
|
|
|
|
}
|
|
|
|
} else if (_Windows(previousWorkspace).HasWindow(floating)) {
|
|
|
|
// was visible, but is no longer
|
|
|
|
_Windows(previousWorkspace).RemoveWindow(floating);
|
|
|
|
floating->SetCurrentWorkspace(-1);
|
|
|
|
_HideWindow(floating);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Search the visible windows for a valid back window
|
2005-12-08 15:41:19 +03:00
|
|
|
(only normal windows can be back windows)
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
Desktop::_UpdateBack()
|
|
|
|
{
|
|
|
|
fBack = NULL;
|
|
|
|
|
|
|
|
for (WindowLayer* window = _CurrentWindows().FirstWindow();
|
|
|
|
window != NULL; window = window->NextWindow(fCurrentWorkspace)) {
|
|
|
|
if (window->IsHidden() || !window->SupportsFront())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
fBack = window;
|
|
|
|
break;
|
2005-11-26 19:56:52 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
/*!
|
|
|
|
Search the visible windows for a valid front window
|
|
|
|
(only normal and modal windows can be front windows)
|
|
|
|
|
|
|
|
The only place where you don't want to update floating windows is
|
|
|
|
during a workspace change - because then you'll call _UpdateFloating()
|
|
|
|
yourself.
|
2005-12-08 15:41:19 +03:00
|
|
|
*/
|
|
|
|
void
|
2005-12-09 16:17:43 +03:00
|
|
|
Desktop::_UpdateFront(bool updateFloating)
|
2005-12-08 15:41:19 +03:00
|
|
|
{
|
|
|
|
fFront = NULL;
|
|
|
|
|
|
|
|
for (WindowLayer* window = _CurrentWindows().LastWindow();
|
|
|
|
window != NULL; window = window->PreviousWindow(fCurrentWorkspace)) {
|
2005-12-09 16:17:43 +03:00
|
|
|
if (window->IsHidden() || window->IsFloating() || !window->SupportsFront())
|
2005-12-08 15:41:19 +03:00
|
|
|
continue;
|
|
|
|
|
|
|
|
fFront = window;
|
|
|
|
break;
|
|
|
|
}
|
2005-12-09 16:17:43 +03:00
|
|
|
|
|
|
|
if (updateFloating)
|
|
|
|
_UpdateFloating();
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
2004-01-22 03:32:07 +03:00
|
|
|
|
2005-04-25 18:14:09 +04:00
|
|
|
|
|
|
|
void
|
2005-12-09 16:17:43 +03:00
|
|
|
Desktop::_UpdateFronts(bool updateFloating)
|
2005-02-28 23:23:51 +03:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
_UpdateBack();
|
2005-12-09 16:17:43 +03:00
|
|
|
_UpdateFront(updateFloating);
|
2005-02-28 23:23:51 +03:00
|
|
|
}
|
|
|
|
|
2005-04-25 18:14:09 +04:00
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
bool
|
|
|
|
Desktop::_WindowHasModal(WindowLayer* window)
|
|
|
|
{
|
|
|
|
if (window == NULL || window->IsFloating())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (WindowLayer* modal = fSubsetWindows.FirstWindow(); modal != NULL;
|
|
|
|
modal = modal->NextWindow(kSubsetList)) {
|
|
|
|
// only visible modal windows count
|
|
|
|
if (!modal->IsModal() || modal->IsHidden())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (modal->HasInSubset(window))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2005-12-09 19:20:01 +03:00
|
|
|
void
|
|
|
|
Desktop::_WindowChanged(WindowLayer* window)
|
|
|
|
{
|
|
|
|
if (fWorkspacesLayer == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
fWorkspacesLayer->WindowChanged(window);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-04-25 18:14:09 +04:00
|
|
|
void
|
2005-12-08 15:41:19 +03:00
|
|
|
Desktop::SetFocusWindow(WindowLayer* focus)
|
2004-01-22 03:32:07 +03:00
|
|
|
{
|
2005-12-12 13:41:31 +03:00
|
|
|
if (!LockAllWindows())
|
2005-12-08 15:41:19 +03:00
|
|
|
return;
|
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
bool hasModal = _WindowHasModal(focus);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
// TODO: test for FFM and B_LOCK_WINDOW_FOCUS
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
if (focus == fFocus && focus != NULL && (focus->Flags() & B_AVOID_FOCUS) == 0
|
|
|
|
&& !hasModal) {
|
|
|
|
// the window that is supposed to get focus already has focus
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockAllWindows();
|
2005-12-09 16:17:43 +03:00
|
|
|
return;
|
|
|
|
}
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2005-12-09 17:23:51 +03:00
|
|
|
if (focus == NULL || hasModal) {
|
2005-12-09 16:17:43 +03:00
|
|
|
focus = FrontWindow();
|
2005-12-09 17:23:51 +03:00
|
|
|
if (focus == NULL) {
|
|
|
|
// there might be no front window in case of only a single
|
|
|
|
// window with B_FLOATING_ALL_WINDOW_FEEL
|
|
|
|
focus = _CurrentWindows().LastWindow();
|
|
|
|
}
|
|
|
|
}
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
// make sure no window is chosen that doesn't want focus or cannot have it
|
|
|
|
while (focus != NULL
|
2005-12-09 17:23:51 +03:00
|
|
|
&& ((focus->Flags() & B_AVOID_FOCUS) != 0
|
|
|
|
|| _WindowHasModal(focus)
|
|
|
|
|| focus->IsHidden())) {
|
2005-12-09 16:17:43 +03:00
|
|
|
focus = focus->PreviousWindow(fCurrentWorkspace);
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
2005-12-09 16:17:43 +03:00
|
|
|
|
|
|
|
if (fFocus != NULL)
|
|
|
|
fFocus->SetFocus(false);
|
|
|
|
|
|
|
|
fFocus = focus;
|
|
|
|
|
|
|
|
if (focus != NULL)
|
|
|
|
focus->SetFocus(true);
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockAllWindows();
|
2005-11-29 02:36:59 +03:00
|
|
|
}
|
2005-02-28 23:23:51 +03:00
|
|
|
|
|
|
|
|
2005-11-30 13:45:01 +03:00
|
|
|
void
|
2005-12-08 15:41:19 +03:00
|
|
|
Desktop::_BringWindowsToFront(WindowList& windows, int32 list,
|
|
|
|
bool wereVisible)
|
|
|
|
{
|
|
|
|
// we don't need to redraw what is currently
|
|
|
|
// visible of the window
|
|
|
|
BRegion clean;
|
|
|
|
|
|
|
|
for (WindowLayer* window = windows.FirstWindow(); window != NULL;
|
|
|
|
window = window->NextWindow(list)) {
|
|
|
|
if (wereVisible)
|
|
|
|
clean.Include(&window->VisibleRegion());
|
|
|
|
|
|
|
|
_CurrentWindows().AddWindow(window,
|
|
|
|
window->Frontmost(_CurrentWindows().FirstWindow(),
|
|
|
|
fCurrentWorkspace));
|
2005-12-09 19:20:01 +03:00
|
|
|
|
|
|
|
_WindowChanged(window);
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
BRegion dummy;
|
|
|
|
_RebuildClippingForAllWindows(dummy);
|
|
|
|
|
|
|
|
// redraw what became visible of the window(s)
|
|
|
|
|
|
|
|
BRegion dirty;
|
|
|
|
for (WindowLayer* window = windows.FirstWindow(); window != NULL;
|
|
|
|
window = window->NextWindow(list)) {
|
|
|
|
dirty.Include(&window->VisibleRegion());
|
|
|
|
}
|
|
|
|
|
|
|
|
dirty.Exclude(&clean);
|
|
|
|
MarkDirty(dirty);
|
|
|
|
|
|
|
|
_UpdateFront();
|
|
|
|
|
|
|
|
if (windows.FirstWindow() == fBack || fBack == NULL)
|
|
|
|
_UpdateBack();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief Tries to move the specified window to the front of the screen,
|
|
|
|
and make it the focus window.
|
|
|
|
|
|
|
|
If there are any modal windows on this screen, it might not actually
|
|
|
|
become the frontmost window, though, as modal windows stay in front
|
|
|
|
of their subset.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
Desktop::ActivateWindow(WindowLayer* window)
|
2005-11-30 13:45:01 +03:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
// printf("ActivateWindow(%p, %s)\n", window, window ? window->Title() : "<none>");
|
|
|
|
|
|
|
|
if (window == NULL) {
|
|
|
|
fBack = NULL;
|
|
|
|
fFront = NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
// TODO: support B_NO_WORKSPACE_ACTIVATION
|
|
|
|
// TODO: support B_NOT_ANCHORED_ON_ACTIVATE
|
2005-12-08 15:41:19 +03:00
|
|
|
// TODO: take care about floating windows
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
if (!LockAllWindows())
|
2005-11-30 13:45:01 +03:00
|
|
|
return;
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
if (window == FrontWindow()) {
|
|
|
|
SetFocusWindow(window);
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockAllWindows();
|
2005-12-09 16:17:43 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// we don't need to redraw what is currently
|
|
|
|
// visible of the window
|
|
|
|
BRegion clean(window->VisibleRegion());
|
|
|
|
WindowList windows(kWorkingList);
|
|
|
|
|
|
|
|
WindowLayer* frontmost = window->Frontmost();
|
|
|
|
|
|
|
|
_CurrentWindows().RemoveWindow(window);
|
|
|
|
windows.AddWindow(window);
|
|
|
|
|
|
|
|
if (frontmost != NULL && frontmost->IsModal()) {
|
|
|
|
// all modal windows follow their subsets to the front
|
|
|
|
// (ie. they are staying in front of them, but they are
|
|
|
|
// not supposed to change their order because of that)
|
|
|
|
|
|
|
|
WindowLayer* nextModal;
|
|
|
|
for (WindowLayer* modal = frontmost; modal != NULL; modal = nextModal) {
|
|
|
|
// get the next modal window
|
|
|
|
nextModal = modal->NextWindow(fCurrentWorkspace);
|
|
|
|
while (nextModal != NULL && !nextModal->IsModal()) {
|
|
|
|
nextModal = nextModal->NextWindow(fCurrentWorkspace);
|
|
|
|
}
|
|
|
|
if (nextModal != NULL && !nextModal->HasInSubset(window))
|
|
|
|
nextModal = NULL;
|
|
|
|
|
|
|
|
_CurrentWindows().RemoveWindow(modal);
|
|
|
|
windows.AddWindow(modal);
|
|
|
|
}
|
2005-11-30 18:47:01 +03:00
|
|
|
}
|
2005-11-30 13:45:01 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
_BringWindowsToFront(windows, kWorkingList, true);
|
2005-12-09 16:17:43 +03:00
|
|
|
SetFocusWindow(window);
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockAllWindows();
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
Desktop::SendWindowBehind(WindowLayer* window, WindowLayer* behindOf)
|
|
|
|
{
|
2005-12-12 13:41:31 +03:00
|
|
|
if (window == BackWindow() || !LockAllWindows())
|
2005-12-08 15:41:19 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
// Is this a valid behindOf window?
|
|
|
|
if (behindOf != NULL && window->HasInSubset(behindOf))
|
|
|
|
behindOf = NULL;
|
|
|
|
|
|
|
|
// what is currently visible of the window
|
|
|
|
// might be dirty after the window is send to back
|
|
|
|
BRegion dirty(window->VisibleRegion());
|
|
|
|
|
|
|
|
// detach window and re-attach at desired position
|
|
|
|
WindowLayer* backmost = window->Backmost(behindOf);
|
|
|
|
|
|
|
|
_CurrentWindows().RemoveWindow(window);
|
|
|
|
_CurrentWindows().AddWindow(window, backmost
|
|
|
|
? backmost->NextWindow(fCurrentWorkspace) : BackWindow());
|
|
|
|
|
|
|
|
BRegion dummy;
|
|
|
|
_RebuildClippingForAllWindows(dummy);
|
|
|
|
|
|
|
|
// mark everything dirty that is no longer visible
|
|
|
|
BRegion clean(window->VisibleRegion());
|
|
|
|
dirty.Exclude(&clean);
|
|
|
|
MarkDirty(dirty);
|
|
|
|
|
|
|
|
// TODO: if this window has any floating windows, remove them here
|
|
|
|
|
|
|
|
_UpdateFronts();
|
|
|
|
SetFocusWindow(FrontWindow());
|
|
|
|
//_WindowsChanged();
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockAllWindows();
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
Desktop::ShowWindow(WindowLayer* window)
|
|
|
|
{
|
|
|
|
if (!window->IsHidden())
|
|
|
|
return;
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
LockAllWindows();
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
window->SetHidden(false);
|
2005-12-08 16:32:54 +03:00
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
if (window->InWorkspace(fCurrentWorkspace)) {
|
2005-12-08 16:32:54 +03:00
|
|
|
_ShowWindow(window, true);
|
2005-12-09 16:17:43 +03:00
|
|
|
_UpdateSubsetWorkspaces(window);
|
2005-12-08 16:32:54 +03:00
|
|
|
ActivateWindow(window);
|
|
|
|
} else {
|
|
|
|
// then we don't need to send the fake mouse event either
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockAllWindows();
|
2005-12-08 16:32:54 +03:00
|
|
|
return;
|
|
|
|
}
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2005-12-09 19:20:01 +03:00
|
|
|
if (WorkspacesLayer* layer = dynamic_cast<WorkspacesLayer*>(window->TopLayer()))
|
|
|
|
fWorkspacesLayer = layer;
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockAllWindows();
|
2005-11-30 13:45:01 +03:00
|
|
|
|
|
|
|
// If the mouse cursor is directly over the newly visible window,
|
|
|
|
// we'll send a fake mouse moved message to the window, so that
|
|
|
|
// it knows the mouse is over it.
|
|
|
|
|
|
|
|
BPoint where;
|
|
|
|
int32 buttons;
|
|
|
|
EventDispatcher().GetMouse(where, buttons);
|
|
|
|
|
|
|
|
int32 viewToken = B_NULL_TOKEN;
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
LockAllWindows();
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
if (WindowAt(where) == window) {
|
|
|
|
ViewLayer* view = window->ViewAt(where);
|
|
|
|
if (view != NULL)
|
|
|
|
viewToken = view->Token();
|
2005-11-30 13:45:01 +03:00
|
|
|
}
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockAllWindows();
|
2005-11-30 13:45:01 +03:00
|
|
|
|
|
|
|
if (viewToken != B_NULL_TOKEN)
|
2005-12-08 15:41:19 +03:00
|
|
|
EventDispatcher().SendFakeMouseMoved(window->EventTarget(), viewToken);
|
2005-11-30 13:45:01 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
Desktop::HideWindow(WindowLayer* window)
|
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
if (window->IsHidden())
|
2005-11-30 18:47:01 +03:00
|
|
|
return;
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
if (!LockAllWindows())
|
2005-12-08 15:41:19 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
window->SetHidden(true);
|
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
if (window->InWorkspace(fCurrentWorkspace)) {
|
|
|
|
_UpdateSubsetWorkspaces(window);
|
2005-12-08 16:32:54 +03:00
|
|
|
_HideWindow(window);
|
|
|
|
_UpdateFronts();
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2005-12-08 16:32:54 +03:00
|
|
|
if (FocusWindow() == window)
|
|
|
|
SetFocusWindow(FrontWindow());
|
|
|
|
}
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2005-12-09 19:20:01 +03:00
|
|
|
if (dynamic_cast<WorkspacesLayer*>(window->TopLayer()) != NULL)
|
|
|
|
fWorkspacesLayer = NULL;
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockAllWindows();
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Shows the window on the screen - it does this independently of the
|
|
|
|
WindowLayer::IsHidden() state.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
Desktop::_ShowWindow(WindowLayer* window, bool affectsOtherWindows)
|
|
|
|
{
|
|
|
|
BRegion background;
|
|
|
|
_RebuildClippingForAllWindows(background);
|
|
|
|
_SetBackground(background);
|
2005-12-09 19:20:01 +03:00
|
|
|
_WindowChanged(window);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
BRegion dirty(window->VisibleRegion());
|
|
|
|
|
|
|
|
if (!affectsOtherWindows) {
|
|
|
|
// everything that is now visible in the
|
|
|
|
// window needs a redraw, but other windows
|
|
|
|
// are not affected, we can call ProcessDirtyRegion()
|
|
|
|
// of the window, and don't have to use MarkDirty()
|
|
|
|
window->ProcessDirtyRegion(dirty);
|
|
|
|
} else
|
|
|
|
MarkDirty(dirty);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Hides the window from the screen - it does this independently of the
|
|
|
|
WindowLayer::IsHidden() state.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
Desktop::_HideWindow(WindowLayer* window)
|
|
|
|
{
|
|
|
|
// after rebuilding the clipping,
|
|
|
|
// this window will not have a visible
|
|
|
|
// region anymore, so we need to remember
|
|
|
|
// it now
|
|
|
|
// (actually that's not true, since
|
|
|
|
// hidden windows are excluded from the
|
|
|
|
// clipping calculation, but anyways)
|
|
|
|
BRegion dirty(window->VisibleRegion());
|
|
|
|
|
|
|
|
BRegion background;
|
|
|
|
_RebuildClippingForAllWindows(background);
|
|
|
|
_SetBackground(background);
|
2005-12-09 19:20:01 +03:00
|
|
|
_WindowChanged(window);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
MarkDirty(dirty);
|
2005-11-30 13:45:01 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-01 13:31:30 +03:00
|
|
|
void
|
|
|
|
Desktop::MoveWindowBy(WindowLayer* window, float x, float y)
|
|
|
|
{
|
2005-12-12 13:41:31 +03:00
|
|
|
if (!LockAllWindows())
|
2005-12-08 15:41:19 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
// the dirty region starts with the visible area of the window being moved
|
|
|
|
BRegion newDirtyRegion(window->VisibleRegion());
|
|
|
|
|
|
|
|
window->MoveBy(x, y);
|
|
|
|
|
|
|
|
BRegion background;
|
|
|
|
_RebuildClippingForAllWindows(background);
|
|
|
|
|
|
|
|
// construct the region that is possible to be blitted
|
|
|
|
// to move the contents of the window
|
|
|
|
BRegion copyRegion(window->VisibleRegion());
|
|
|
|
copyRegion.OffsetBy(-x, -y);
|
|
|
|
copyRegion.IntersectWith(&newDirtyRegion);
|
|
|
|
|
|
|
|
// include the the new visible region of the window being
|
|
|
|
// moved into the dirty region (for now)
|
|
|
|
newDirtyRegion.Include(&window->VisibleRegion());
|
|
|
|
|
2005-12-20 00:18:23 +03:00
|
|
|
GetDrawingEngine()->CopyRegion(©Region, x, y);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2005-12-20 00:18:23 +03:00
|
|
|
// in the dirty region, exclude the parts that we
|
|
|
|
// could move by blitting
|
|
|
|
copyRegion.OffsetBy(x, y);
|
|
|
|
newDirtyRegion.Exclude(©Region);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
MarkDirty(newDirtyRegion);
|
|
|
|
_SetBackground(background);
|
2005-12-09 19:20:01 +03:00
|
|
|
_WindowChanged(window);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockAllWindows();
|
2005-12-01 13:31:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
Desktop::ResizeWindowBy(WindowLayer* window, float x, float y)
|
|
|
|
{
|
2005-12-12 13:41:31 +03:00
|
|
|
if (!LockAllWindows())
|
2005-12-08 15:41:19 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
BRegion newDirtyRegion;
|
|
|
|
BRegion previouslyOccupiedRegion(window->VisibleRegion());
|
|
|
|
|
|
|
|
window->ResizeBy(x, y, &newDirtyRegion);
|
|
|
|
|
|
|
|
BRegion background;
|
|
|
|
_RebuildClippingForAllWindows(background);
|
|
|
|
|
|
|
|
previouslyOccupiedRegion.Exclude(&window->VisibleRegion());
|
|
|
|
|
|
|
|
newDirtyRegion.IntersectWith(&window->VisibleRegion());
|
|
|
|
newDirtyRegion.Include(&previouslyOccupiedRegion);
|
|
|
|
|
|
|
|
MarkDirty(newDirtyRegion);
|
|
|
|
_SetBackground(background);
|
2005-12-09 19:20:01 +03:00
|
|
|
_WindowChanged(window);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockAllWindows();
|
2005-12-01 13:31:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
/*!
|
|
|
|
Updates the workspaces of all subset windows with regard to the
|
|
|
|
specifed window.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
Desktop::_UpdateSubsetWorkspaces(WindowLayer* window)
|
|
|
|
{
|
|
|
|
// if the window is hidden, the subset windows are up-to-date already
|
|
|
|
if (!window->IsNormal() || window->IsHidden())
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (WindowLayer* subset = fSubsetWindows.FirstWindow(); subset != NULL;
|
|
|
|
subset = subset->NextWindow(kSubsetList)) {
|
|
|
|
if (subset->Feel() == B_MODAL_ALL_WINDOW_FEEL
|
|
|
|
|| subset->Feel() == B_FLOATING_ALL_WINDOW_FEEL) {
|
|
|
|
// These windows are always visible on all workspaces,
|
|
|
|
// no need to update them.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (subset->IsFloating()) {
|
|
|
|
// Floating windows are inserted and removed to the current
|
|
|
|
// workspace as the need arises - they are not handled here
|
|
|
|
// but in _UpdateFront()
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (subset->HasInSubset(window)) {
|
|
|
|
// adopt the workspace change
|
|
|
|
SetWindowWorkspaces(subset, subset->SubsetWorkspaces());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-11-30 18:47:01 +03:00
|
|
|
/*!
|
|
|
|
\brief Adds or removes the window to or from the workspaces it's on.
|
|
|
|
*/
|
2005-11-29 02:36:59 +03:00
|
|
|
void
|
2005-11-30 18:47:01 +03:00
|
|
|
Desktop::_ChangeWindowWorkspaces(WindowLayer* window, uint32 oldWorkspaces,
|
|
|
|
uint32 newWorkspaces)
|
2005-11-29 02:36:59 +03:00
|
|
|
{
|
2005-12-08 17:45:42 +03:00
|
|
|
// apply changes to the workspaces' window lists
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
LockAllWindows();
|
2005-11-30 18:47:01 +03:00
|
|
|
|
|
|
|
for (int32 i = 0; i < kMaxWorkspaces; i++) {
|
2005-12-09 16:28:28 +03:00
|
|
|
if (workspace_in_workspaces(i, oldWorkspaces)) {
|
2005-11-30 18:47:01 +03:00
|
|
|
// window is on this workspace, is it anymore?
|
2005-12-09 16:28:28 +03:00
|
|
|
if (!workspace_in_workspaces(i, newWorkspaces)) {
|
2005-12-09 16:17:43 +03:00
|
|
|
_Windows(i).RemoveWindow(window);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
if (i == CurrentWorkspace()) {
|
|
|
|
// remove its appearance from the current workspace
|
|
|
|
window->SetCurrentWorkspace(-1);
|
|
|
|
|
|
|
|
if (!window->IsHidden())
|
|
|
|
_HideWindow(window);
|
|
|
|
}
|
2005-11-30 18:47:01 +03:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// window was not on this workspace, is it now?
|
2005-12-09 16:28:28 +03:00
|
|
|
if (workspace_in_workspaces(i, newWorkspaces)) {
|
2005-12-09 16:17:43 +03:00
|
|
|
_Windows(i).AddWindow(window,
|
|
|
|
window->Frontmost(_Windows(i).FirstWindow(), i));
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
if (i == CurrentWorkspace()) {
|
2005-12-09 16:17:43 +03:00
|
|
|
// make the window visible in current workspace
|
|
|
|
window->SetCurrentWorkspace(fCurrentWorkspace);
|
|
|
|
|
|
|
|
if (!window->IsHidden()) {
|
|
|
|
// this only affects other windows if this windows has floating or
|
|
|
|
// modal windows that need to be shown as well
|
|
|
|
// TODO: take care of this
|
|
|
|
_ShowWindow(window, FrontWindow() == window);
|
|
|
|
}
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
2005-11-30 18:47:01 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-12-08 17:45:42 +03:00
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
// take care about modals and floating windows
|
|
|
|
_UpdateSubsetWorkspaces(window);
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockAllWindows();
|
2005-11-30 18:47:01 +03:00
|
|
|
}
|
2004-06-19 17:04:50 +04:00
|
|
|
|
2005-02-28 23:23:51 +03:00
|
|
|
|
2005-11-30 18:47:01 +03:00
|
|
|
void
|
|
|
|
Desktop::SetWindowWorkspaces(WindowLayer* window, uint32 workspaces)
|
|
|
|
{
|
2005-12-12 13:41:31 +03:00
|
|
|
LockAllWindows();
|
2005-12-08 17:45:42 +03:00
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
if (window->IsNormal() && workspaces == B_CURRENT_WORKSPACE)
|
2005-11-30 18:47:01 +03:00
|
|
|
workspaces = workspace_to_workspaces(CurrentWorkspace());
|
2005-02-28 23:23:51 +03:00
|
|
|
|
2005-12-15 19:42:12 +03:00
|
|
|
window->WorkspacesChanged(window->Workspaces(), workspaces);
|
2005-11-30 18:47:01 +03:00
|
|
|
_ChangeWindowWorkspaces(window, window->Workspaces(), workspaces);
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockAllWindows();
|
2005-02-28 23:23:51 +03:00
|
|
|
}
|
|
|
|
|
2005-04-25 18:14:09 +04:00
|
|
|
|
|
|
|
void
|
2005-11-30 18:47:01 +03:00
|
|
|
Desktop::AddWindow(WindowLayer *window)
|
2005-02-28 23:23:51 +03:00
|
|
|
{
|
2005-12-12 13:41:31 +03:00
|
|
|
LockAllWindows();
|
2005-02-28 23:23:51 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
fAllWindows.AddWindow(window);
|
2005-12-09 16:17:43 +03:00
|
|
|
if (!window->IsNormal())
|
|
|
|
fSubsetWindows.AddWindow(window);
|
2005-11-30 18:47:01 +03:00
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
if (window->IsNormal()) {
|
|
|
|
if (window->Workspaces() == B_CURRENT_WORKSPACE)
|
|
|
|
window->SetWorkspaces(workspace_to_workspaces(CurrentWorkspace()));
|
|
|
|
} else {
|
|
|
|
// subset windows are visible on all workspaces their subset is on
|
|
|
|
window->SetWorkspaces(window->SubsetWorkspaces());
|
|
|
|
}
|
2005-11-29 02:36:59 +03:00
|
|
|
|
2005-11-30 18:47:01 +03:00
|
|
|
_ChangeWindowWorkspaces(window, 0, window->Workspaces());
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockAllWindows();
|
2004-01-12 01:12:55 +03:00
|
|
|
}
|
2004-01-22 03:32:07 +03:00
|
|
|
|
2005-04-25 18:14:09 +04:00
|
|
|
|
|
|
|
void
|
2005-11-30 18:47:01 +03:00
|
|
|
Desktop::RemoveWindow(WindowLayer *window)
|
2004-01-22 03:32:07 +03:00
|
|
|
{
|
2005-12-12 13:41:31 +03:00
|
|
|
LockAllWindows();
|
2005-11-30 18:47:01 +03:00
|
|
|
|
2005-12-09 17:23:51 +03:00
|
|
|
if (!window->IsHidden())
|
|
|
|
HideWindow(window);
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
fAllWindows.RemoveWindow(window);
|
2005-12-09 16:17:43 +03:00
|
|
|
if (!window->IsNormal())
|
|
|
|
fSubsetWindows.RemoveWindow(window);
|
|
|
|
|
2005-11-30 18:47:01 +03:00
|
|
|
_ChangeWindowWorkspaces(window, window->Workspaces(), 0);
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockAllWindows();
|
2005-11-30 18:47:01 +03:00
|
|
|
|
|
|
|
// make sure this window won't get any events anymore
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
EventDispatcher().RemoveTarget(window->EventTarget());
|
2005-11-30 18:47:01 +03:00
|
|
|
}
|
2005-11-29 02:36:59 +03:00
|
|
|
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
bool
|
|
|
|
Desktop::AddWindowToSubset(WindowLayer* subset, WindowLayer* window)
|
|
|
|
{
|
|
|
|
if (!subset->AddToSubset(window))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
_ChangeWindowWorkspaces(subset, subset->Workspaces(), subset->SubsetWorkspaces());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
Desktop::RemoveWindowFromSubset(WindowLayer* subset, WindowLayer* window)
|
|
|
|
{
|
|
|
|
subset->RemoveFromSubset(window);
|
|
|
|
_ChangeWindowWorkspaces(subset, subset->Workspaces(), subset->SubsetWorkspaces());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-11-30 18:47:01 +03:00
|
|
|
void
|
2005-12-08 15:41:19 +03:00
|
|
|
Desktop::SetWindowLook(WindowLayer *window, window_look newLook)
|
2005-11-30 18:47:01 +03:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
if (window->Look() == newLook)
|
|
|
|
return;
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
if (!LockAllWindows())
|
2005-12-08 15:41:19 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
BRegion dirty;
|
|
|
|
window->SetLook(newLook, &dirty);
|
|
|
|
// TODO: test what happens when the window
|
|
|
|
// finds out it needs to resize itself...
|
|
|
|
|
|
|
|
BRegion stillAvailableOnScreen;
|
|
|
|
_RebuildClippingForAllWindows(stillAvailableOnScreen);
|
|
|
|
_SetBackground(stillAvailableOnScreen);
|
2005-12-09 19:20:01 +03:00
|
|
|
_WindowChanged(window);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
_TriggerWindowRedrawing(dirty);
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockAllWindows();
|
2003-08-31 21:38:34 +04:00
|
|
|
}
|
2004-01-22 03:32:07 +03:00
|
|
|
|
2005-04-25 18:14:09 +04:00
|
|
|
|
|
|
|
void
|
2005-12-08 15:41:19 +03:00
|
|
|
Desktop::SetWindowFeel(WindowLayer *window, window_feel newFeel)
|
2005-04-21 22:57:34 +04:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
if (window->Feel() == newFeel)
|
|
|
|
return;
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
LockAllWindows();
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
bool wasNormal = window->IsNormal();
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
window->SetFeel(newFeel);
|
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
// move the window out of or into the subset window list as needed
|
|
|
|
if (window->IsNormal() && !wasNormal)
|
|
|
|
fSubsetWindows.RemoveWindow(window);
|
|
|
|
else if (!window->IsNormal() && wasNormal)
|
|
|
|
fSubsetWindows.AddWindow(window);
|
|
|
|
|
|
|
|
// A normal window that was once a floating or modal window will
|
|
|
|
// adopt the window's current workspaces
|
|
|
|
|
|
|
|
if (!window->IsNormal())
|
|
|
|
_ChangeWindowWorkspaces(window, window->Workspaces(), window->SubsetWorkspaces());
|
|
|
|
|
2005-12-09 16:28:28 +03:00
|
|
|
// make sure the window has the correct position in the window lists
|
2005-12-09 16:17:43 +03:00
|
|
|
// (ie. all floating windows have to be on the top, ...)
|
|
|
|
|
2005-12-09 16:28:28 +03:00
|
|
|
for (int32 i = 0; i < kMaxWorkspaces; i++) {
|
|
|
|
if (!workspace_in_workspaces(i, window->Workspaces()))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
WindowLayer* frontmost = window->Frontmost(_Windows(i).FirstWindow(), i);
|
|
|
|
if (frontmost == NULL)
|
|
|
|
continue;
|
2005-12-09 17:03:00 +03:00
|
|
|
|
2005-12-09 16:28:28 +03:00
|
|
|
// check if the frontmost window is really in front of it
|
2005-12-09 17:03:00 +03:00
|
|
|
|
2005-12-09 16:28:28 +03:00
|
|
|
WindowLayer* next = window->NextWindow(i);
|
|
|
|
while (next != NULL) {
|
|
|
|
if (next == frontmost)
|
|
|
|
break;
|
|
|
|
|
|
|
|
next = next->NextWindow(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (next == NULL) {
|
|
|
|
// need to reinsert window behind its frontmost window
|
|
|
|
_Windows(i).RemoveWindow(window);
|
|
|
|
_Windows(i).AddWindow(window, frontmost);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
_UpdateFronts();
|
2005-12-09 16:30:47 +03:00
|
|
|
|
|
|
|
if (window == FocusWindow() && !window->IsVisible())
|
|
|
|
SetFocusWindow(FrontWindow());
|
2005-12-10 16:47:13 +03:00
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockAllWindows();
|
2005-12-01 16:59:04 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2005-12-08 15:41:19 +03:00
|
|
|
Desktop::SetWindowFlags(WindowLayer *window, uint32 newFlags)
|
2005-12-01 16:59:04 +03:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
if (window->Flags() == newFlags)
|
|
|
|
return;
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
if (!LockAllWindows())
|
2005-12-08 15:41:19 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
BRegion dirty;
|
|
|
|
window->SetFlags(newFlags, &dirty);
|
|
|
|
// TODO: test what happens when the window
|
|
|
|
// finds out it needs to resize itself...
|
|
|
|
|
|
|
|
BRegion stillAvailableOnScreen;
|
|
|
|
_RebuildClippingForAllWindows(stillAvailableOnScreen);
|
|
|
|
_SetBackground(stillAvailableOnScreen);
|
2005-12-09 19:20:01 +03:00
|
|
|
_WindowChanged(window);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
_TriggerWindowRedrawing(dirty);
|
|
|
|
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockAllWindows();
|
2005-04-21 22:57:34 +04:00
|
|
|
}
|
|
|
|
|
2005-04-25 18:14:09 +04:00
|
|
|
|
2005-12-09 01:15:12 +03:00
|
|
|
void
|
|
|
|
Desktop::SetWindowTitle(WindowLayer *window, const char* title)
|
|
|
|
{
|
2005-12-12 13:41:31 +03:00
|
|
|
if (!LockAllWindows())
|
2005-12-09 01:15:12 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
BRegion dirty;
|
|
|
|
window->SetTitle(title, dirty);
|
|
|
|
|
|
|
|
if (window->IsVisible() && dirty.CountRects() > 0) {
|
|
|
|
BRegion stillAvailableOnScreen;
|
|
|
|
_RebuildClippingForAllWindows(stillAvailableOnScreen);
|
|
|
|
_SetBackground(stillAvailableOnScreen);
|
|
|
|
|
|
|
|
_TriggerWindowRedrawing(dirty);
|
|
|
|
}
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockAllWindows();
|
2005-12-09 01:15:12 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-10 16:47:13 +03:00
|
|
|
/*!
|
|
|
|
Returns the window under the mouse cursor.
|
|
|
|
You need to have the window write lock acquired when calling this method.
|
|
|
|
*/
|
2005-12-08 15:41:19 +03:00
|
|
|
WindowLayer*
|
|
|
|
Desktop::WindowAt(BPoint where)
|
2005-02-28 23:23:51 +03:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
for (WindowLayer* window = _CurrentWindows().LastWindow(); window;
|
|
|
|
window = window->PreviousWindow(fCurrentWorkspace)) {
|
|
|
|
if (window->VisibleRegion().Contains(where))
|
|
|
|
return window;
|
2005-02-28 23:23:51 +03:00
|
|
|
}
|
2005-04-25 18:14:09 +04:00
|
|
|
|
2005-07-05 22:14:24 +04:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
Desktop::SetMouseEventWindow(WindowLayer* window)
|
2005-10-31 22:35:46 +03:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
fMouseEventWindow = window;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
WindowLayer *
|
|
|
|
Desktop::FindWindowLayerByClientToken(int32 token, team_id teamID)
|
|
|
|
{
|
2005-12-12 13:41:31 +03:00
|
|
|
LockSingleWindow();
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
for (WindowLayer *window = fAllWindows.FirstWindow(); window != NULL;
|
|
|
|
window = window->NextWindow(kAllWindowList)) {
|
|
|
|
if (window->ServerWindow()->ClientToken() == token
|
2005-12-10 16:47:13 +03:00
|
|
|
&& window->ServerWindow()->ClientTeam() == teamID) {
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockSingleWindow();
|
2005-12-08 15:41:19 +03:00
|
|
|
return window;
|
2005-12-10 16:47:13 +03:00
|
|
|
}
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
2005-10-31 22:35:46 +03:00
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockSingleWindow();
|
2005-12-08 15:41:19 +03:00
|
|
|
return NULL;
|
2005-10-31 22:35:46 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-05 22:14:24 +04:00
|
|
|
void
|
|
|
|
Desktop::WriteWindowList(team_id team, BPrivate::LinkSender& sender)
|
|
|
|
{
|
2005-12-10 16:47:13 +03:00
|
|
|
BAutolock locker(fWindowLock);
|
2005-07-05 22:14:24 +04:00
|
|
|
|
|
|
|
// compute the number of windows
|
|
|
|
|
|
|
|
int32 count = 0;
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
for (WindowLayer *window = fAllWindows.FirstWindow(); window != NULL;
|
|
|
|
window = window->NextWindow(kAllWindowList)) {
|
|
|
|
if (team < B_OK || window->ServerWindow()->ClientTeam() == team)
|
|
|
|
count++;
|
|
|
|
}
|
2005-07-05 22:14:24 +04:00
|
|
|
|
|
|
|
// write list
|
|
|
|
|
2005-11-30 22:56:44 +03:00
|
|
|
sender.StartMessage(B_OK);
|
2005-07-05 22:14:24 +04:00
|
|
|
sender.Attach<int32>(count);
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
for (WindowLayer *window = fAllWindows.FirstWindow(); window != NULL;
|
|
|
|
window = window->NextWindow(kAllWindowList)) {
|
|
|
|
if (team >= B_OK && window->ServerWindow()->ClientTeam() != team)
|
2005-07-05 22:14:24 +04:00
|
|
|
continue;
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
sender.Attach<int32>(window->ServerWindow()->ServerToken());
|
2005-07-05 22:14:24 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
sender.Flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
Desktop::WriteWindowInfo(int32 serverToken, BPrivate::LinkSender& sender)
|
|
|
|
{
|
2005-12-10 16:47:13 +03:00
|
|
|
BAutolock locker(fWindowLock);
|
2005-07-05 22:14:24 +04:00
|
|
|
BAutolock tokenLocker(BPrivate::gDefaultTokens);
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
::ServerWindow* window;
|
2005-07-05 22:14:24 +04:00
|
|
|
if (BPrivate::gDefaultTokens.GetToken(serverToken,
|
|
|
|
B_SERVER_TOKEN, (void**)&window) != B_OK) {
|
|
|
|
sender.StartMessage(B_ENTRY_NOT_FOUND);
|
|
|
|
sender.Flush();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
window_info info;
|
|
|
|
window->GetInfo(info);
|
|
|
|
|
|
|
|
int32 length = window->Title() ? strlen(window->Title()) : 0;
|
|
|
|
|
|
|
|
sender.StartMessage(B_OK);
|
|
|
|
sender.Attach<int32>(sizeof(window_info) + length + 1);
|
|
|
|
sender.Attach(&info, sizeof(window_info));
|
|
|
|
if (length > 0)
|
|
|
|
sender.Attach(window->Title(), length + 1);
|
|
|
|
else
|
|
|
|
sender.Attach<char>('\0');
|
|
|
|
sender.Flush();
|
2003-01-24 18:19:27 +03:00
|
|
|
}
|
2004-01-22 03:32:07 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
void
|
|
|
|
Desktop::MarkDirty(BRegion& region)
|
|
|
|
{
|
|
|
|
if (region.CountRects() == 0)
|
|
|
|
return;
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
if (LockAllWindows()) {
|
2005-12-08 15:41:19 +03:00
|
|
|
// send redraw messages to all windows intersecting the dirty region
|
|
|
|
_TriggerWindowRedrawing(region);
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
UnlockAllWindows();
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
Desktop::_RebuildClippingForAllWindows(BRegion& stillAvailableOnScreen)
|
|
|
|
{
|
|
|
|
// the available region on screen starts with the entire screen area
|
|
|
|
// each window on the screen will take a portion from that area
|
|
|
|
|
|
|
|
// figure out what the entire screen area is
|
|
|
|
stillAvailableOnScreen = fScreenRegion;
|
|
|
|
|
|
|
|
// set clipping of each window
|
|
|
|
for (WindowLayer* window = _CurrentWindows().LastWindow(); window != NULL;
|
|
|
|
window = window->PreviousWindow(fCurrentWorkspace)) {
|
|
|
|
if (!window->IsHidden()) {
|
|
|
|
window->SetClipping(&stillAvailableOnScreen);
|
|
|
|
// that windows region is not available on screen anymore
|
|
|
|
stillAvailableOnScreen.Exclude(&window->VisibleRegion());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
Desktop::_TriggerWindowRedrawing(BRegion& newDirtyRegion)
|
|
|
|
{
|
|
|
|
// send redraw messages to all windows intersecting the dirty region
|
|
|
|
for (WindowLayer* window = _CurrentWindows().LastWindow(); window != NULL;
|
|
|
|
window = window->PreviousWindow(fCurrentWorkspace)) {
|
|
|
|
if (!window->IsHidden()
|
|
|
|
&& newDirtyRegion.Intersects(window->VisibleRegion().Frame()))
|
|
|
|
window->ProcessDirtyRegion(newDirtyRegion);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
Desktop::_SetBackground(BRegion& background)
|
|
|
|
{
|
|
|
|
// NOTE: the drawing operation is caried out
|
|
|
|
// in the clipping region rebuild, but it is
|
|
|
|
// ok actually, because it also avoids trails on
|
|
|
|
// moving windows
|
|
|
|
|
|
|
|
// remember the region not covered by any windows
|
|
|
|
// and redraw the dirty background
|
|
|
|
BRegion dirtyBackground(background);
|
|
|
|
dirtyBackground.Exclude(&fBackgroundRegion);
|
|
|
|
dirtyBackground.IntersectWith(&background);
|
|
|
|
fBackgroundRegion = background;
|
|
|
|
if (dirtyBackground.Frame().IsValid()) {
|
|
|
|
if (GetDrawingEngine()->Lock()) {
|
|
|
|
GetDrawingEngine()->ConstrainClippingRegion(NULL);
|
|
|
|
GetDrawingEngine()->FillRegion(dirtyBackground,
|
|
|
|
fWorkspaces[fCurrentWorkspace].Color());
|
|
|
|
|
|
|
|
GetDrawingEngine()->Unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|