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"
|
2004-01-12 01:12:55 +03:00
|
|
|
#include "Layer.h"
|
2004-01-22 03:32:07 +03:00
|
|
|
#include "RootLayer.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 "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-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();
|
|
|
|
|
|
|
|
::RootLayer* rootLayer = fDesktop->RootLayer();
|
|
|
|
rootLayer->Lock();
|
|
|
|
|
|
|
|
EventTarget* focus = NULL;
|
|
|
|
if (rootLayer->Focus() != NULL)
|
|
|
|
focus = &rootLayer->Focus()->Window()->EventTarget();
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
rootLayer->Unlock();
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
|
|
|
::RootLayer* rootLayer = fDesktop->RootLayer();
|
|
|
|
|
|
|
|
rootLayer->Lock();
|
|
|
|
|
|
|
|
WindowLayer* window = rootLayer->MouseEventWindow();
|
|
|
|
if (window == NULL)
|
|
|
|
window = rootLayer->WindowAt(where);
|
|
|
|
|
|
|
|
if (window != NULL) {
|
|
|
|
// dispatch event in the window layers
|
|
|
|
switch (message->what) {
|
|
|
|
case B_MOUSE_DOWN:
|
|
|
|
window->MouseDown(message, where, _viewToken);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case B_MOUSE_UP:
|
|
|
|
window->MouseUp(message, where, _viewToken);
|
|
|
|
rootLayer->SetMouseEventWindow(NULL);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case B_MOUSE_MOVED:
|
|
|
|
window->MouseMoved(message, where, _viewToken);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*_viewToken != B_NULL_TOKEN)
|
|
|
|
*_target = &window->Window()->EventTarget();
|
|
|
|
else
|
|
|
|
*_target = NULL;
|
|
|
|
} else
|
|
|
|
*_target = NULL;
|
|
|
|
|
|
|
|
rootLayer->Unlock();
|
|
|
|
|
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
|
|
|
|
workspaces_on_workspace(int32 index, uint32 workspaces)
|
|
|
|
{
|
|
|
|
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-10-31 22:35:46 +03:00
|
|
|
fUserID(userID),
|
2005-07-17 20:25:48 +04:00
|
|
|
fSettings(new DesktopSettings::Private()),
|
2005-07-26 01:08:34 +04:00
|
|
|
fAppListLock("application list"),
|
|
|
|
fShutdownSemaphore(-1),
|
2005-11-24 20:45:26 +03:00
|
|
|
fWindowLayerList(64),
|
2005-08-21 14:28:40 +04:00
|
|
|
fActiveScreen(NULL),
|
|
|
|
fCursorManager()
|
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
|
|
|
|
|
|
|
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-11-24 20:45:26 +03:00
|
|
|
// root layer only knows the visible WindowLayers, so we delete them all over here
|
|
|
|
for (int32 i = 0; WindowLayer *border = (WindowLayer *)fWindowLayerList.ItemAt(i); i++)
|
2005-04-25 18:14:09 +04:00
|
|
|
delete border;
|
2005-01-17 00:35:02 +03:00
|
|
|
|
2005-07-15 16:45:23 +04:00
|
|
|
delete fRootLayer;
|
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-07-15 16:45:23 +04:00
|
|
|
// TODO: add user identity to the name
|
|
|
|
char name[32];
|
|
|
|
sprintf(name, "RootLayer %d", 1);
|
2005-11-29 02:36:59 +03:00
|
|
|
fRootLayer = new ::RootLayer(name, this, GetDrawingEngine());
|
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);
|
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
|
|
|
|
|
|
|
|
fAppListLock.Lock();
|
|
|
|
|
|
|
|
int32 count = fAppList.CountItems();
|
|
|
|
for (int32 i = 0; i < count; i++) {
|
|
|
|
ServerApp *app = (ServerApp*)fAppList.ItemAt(i);
|
|
|
|
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);
|
|
|
|
|
|
|
|
fAppListLock.Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
fAppListLock.Lock();
|
|
|
|
fAppList.AddItem(app);
|
|
|
|
fAppListLock.Unlock();
|
|
|
|
} 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;
|
|
|
|
|
|
|
|
fAppListLock.Lock();
|
|
|
|
|
|
|
|
// Run through the list of apps and nuke the proper one
|
|
|
|
|
|
|
|
int32 count = fAppList.CountItems();
|
|
|
|
ServerApp *removeApp = NULL;
|
|
|
|
|
|
|
|
for (int32 i = 0; i < count; i++) {
|
|
|
|
ServerApp *app = (ServerApp *)fAppList.ItemAt(i);
|
|
|
|
|
|
|
|
if (app != NULL && app->Thread() == thread) {
|
|
|
|
fAppList.RemoveItem(i);
|
|
|
|
removeApp = app;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fAppListLock.Unlock();
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
fAppListLock.Lock();
|
|
|
|
fShutdownSemaphore = create_sem(0, "desktop shutdown");
|
|
|
|
fShutdownCount = fAppList.CountItems();
|
|
|
|
fAppListLock.Unlock();
|
|
|
|
|
|
|
|
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
|
|
|
|
int32 windowCount = WindowList().CountItems();
|
|
|
|
for (int32 i = 0; i < windowCount; ++i) {
|
2005-11-24 20:45:26 +03:00
|
|
|
// is this layer in fact a WindowLayer?
|
2005-11-29 02:36:59 +03:00
|
|
|
WindowLayer *windowLayer = WindowList().ItemAt(i);
|
2005-10-31 22:35:46 +03:00
|
|
|
|
|
|
|
// if winBorder is valid and not hidden, then we've found our target
|
2005-11-29 02:36:59 +03:00
|
|
|
if (windowLayer != NULL && !windowLayer->IsHidden()
|
|
|
|
&& windowLayer->App()->ClientTeam() == team) {
|
|
|
|
fRootLayer->ActivateWindow(windowLayer);
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
BAutolock locker(fAppListLock);
|
|
|
|
|
|
|
|
for (int32 i = 0; i < fAppList.CountItems(); i++) {
|
|
|
|
ServerApp *app = (ServerApp *)fAppList.ItemAt(i);
|
|
|
|
|
|
|
|
app->PostMessage(code);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-11-29 02:36:59 +03:00
|
|
|
void
|
|
|
|
Desktop::SetWorkspace(int32 index)
|
|
|
|
{
|
|
|
|
BAutolock _(this);
|
|
|
|
DesktopSettings settings(this);
|
|
|
|
|
2005-11-30 18:47:01 +03:00
|
|
|
if (index < 0 || index >= settings.WorkspacesCount() || index == fCurrentWorkspace)
|
2005-11-29 02:36:59 +03:00
|
|
|
return;
|
|
|
|
|
2005-11-30 18:47:01 +03:00
|
|
|
int32 previousIndex = fCurrentWorkspace;
|
|
|
|
fCurrentWorkspace = index;
|
|
|
|
|
|
|
|
fRootLayer->SetWorkspace(index, fWorkspaces[previousIndex],
|
|
|
|
fWorkspaces[index]);
|
2005-11-29 02:36:59 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-11-26 19:56:52 +03:00
|
|
|
void
|
|
|
|
Desktop::ScreenChanged(Screen* screen)
|
|
|
|
{
|
|
|
|
BMessage update(B_SCREEN_CHANGED);
|
|
|
|
update.AddInt64("when", real_time_clock_usecs());
|
|
|
|
update.AddRect("frame", screen->Frame());
|
|
|
|
update.AddInt32("mode", screen->ColorSpace());
|
|
|
|
|
|
|
|
BAutolock locker(this);
|
|
|
|
|
|
|
|
// send B_SCREEN_CHANGED to windows on that screen
|
|
|
|
// TODO: currently ignores the screen argument!
|
|
|
|
|
|
|
|
for (int32 i = fWindowLayerList.CountItems(); i-- > 0;) {
|
|
|
|
WindowLayer* layer = fWindowLayerList.ItemAt(i);
|
|
|
|
ServerWindow* window = layer->Window();
|
|
|
|
|
|
|
|
window->SendMessageToClient(&update);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-11-24 20:45:26 +03:00
|
|
|
// #pragma mark - Methods for WindowLayer manipulation
|
2004-01-22 03:32:07 +03:00
|
|
|
|
2005-04-25 18:14:09 +04:00
|
|
|
|
|
|
|
void
|
2005-11-29 02:36:59 +03:00
|
|
|
Desktop::ActivateWindow(WindowLayer* windowLayer)
|
2005-02-28 23:23:51 +03:00
|
|
|
{
|
2005-11-29 02:36:59 +03:00
|
|
|
fRootLayer->ActivateWindow(windowLayer);
|
2005-02-28 23:23:51 +03:00
|
|
|
}
|
|
|
|
|
2005-04-25 18:14:09 +04:00
|
|
|
|
|
|
|
void
|
2005-11-29 02:36:59 +03:00
|
|
|
Desktop::SendBehindWindow(WindowLayer* windowLayer, WindowLayer* front)
|
2004-01-22 03:32:07 +03:00
|
|
|
{
|
2005-11-29 02:36:59 +03:00
|
|
|
fRootLayer->SendBehindWindow(windowLayer, front);
|
|
|
|
}
|
2005-02-28 23:23:51 +03:00
|
|
|
|
|
|
|
|
2005-11-30 13:45:01 +03:00
|
|
|
void
|
|
|
|
Desktop::ShowWindow(WindowLayer* window)
|
|
|
|
{
|
2005-11-30 18:47:01 +03:00
|
|
|
if (!window->IsHidden() || window->Parent() == NULL) {
|
|
|
|
window->Show(false);
|
2005-11-30 13:45:01 +03:00
|
|
|
return;
|
2005-11-30 18:47:01 +03:00
|
|
|
}
|
2005-11-30 13:45:01 +03:00
|
|
|
|
2005-12-02 18:06:14 +03:00
|
|
|
fRootLayer->ShowWindow(window);
|
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;
|
|
|
|
|
|
|
|
fRootLayer->Lock();
|
|
|
|
if (fRootLayer->WindowAt(where) == window) {
|
|
|
|
Layer* layer = window->LayerAt(where);
|
|
|
|
if (layer != NULL && layer != window)
|
|
|
|
viewToken = layer->ViewToken();
|
|
|
|
}
|
|
|
|
fRootLayer->Unlock();
|
|
|
|
|
|
|
|
if (viewToken != B_NULL_TOKEN)
|
|
|
|
EventDispatcher().SendFakeMouseMoved(window->Window()->EventTarget(), viewToken);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
Desktop::HideWindow(WindowLayer* window)
|
|
|
|
{
|
2005-11-30 18:47:01 +03:00
|
|
|
if (window->IsHidden() || window->Parent() == NULL) {
|
|
|
|
window->Hide(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-12-02 18:06:14 +03:00
|
|
|
fRootLayer->HideWindow(window);
|
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)
|
|
|
|
{
|
|
|
|
fRootLayer->MoveWindowBy(window, x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
Desktop::ResizeWindowBy(WindowLayer* window, float x, float y)
|
|
|
|
{
|
|
|
|
fRootLayer->ResizeWindowBy(window, x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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-11-30 18:47:01 +03:00
|
|
|
// apply changes to the workspaces' window list
|
|
|
|
// (and RootLayer, for the current workspace)
|
|
|
|
|
|
|
|
for (int32 i = 0; i < kMaxWorkspaces; i++) {
|
|
|
|
if (workspaces_on_workspace(i, oldWorkspaces)) {
|
|
|
|
// window is on this workspace, is it anymore?
|
|
|
|
if (!workspaces_on_workspace(i, newWorkspaces)) {
|
|
|
|
if (i == CurrentWorkspace())
|
2005-12-02 18:06:14 +03:00
|
|
|
RootLayer()->RemoveWindow(window);
|
2005-11-30 18:47:01 +03:00
|
|
|
else
|
|
|
|
fWorkspaces[i].RemoveWindow(window);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// window was not on this workspace, is it now?
|
|
|
|
if (workspaces_on_workspace(i, newWorkspaces)) {
|
|
|
|
if (i == CurrentWorkspace())
|
2005-12-02 18:06:14 +03:00
|
|
|
RootLayer()->AddWindow(window);
|
2005-11-30 18:47:01 +03:00
|
|
|
else
|
|
|
|
fWorkspaces[i].AddWindow(window);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
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)
|
|
|
|
{
|
|
|
|
BAutolock _(this);
|
|
|
|
|
|
|
|
if (workspaces == B_CURRENT_WORKSPACE)
|
|
|
|
workspaces = workspace_to_workspaces(CurrentWorkspace());
|
2005-02-28 23:23:51 +03:00
|
|
|
|
2005-11-30 18:47:01 +03:00
|
|
|
_ChangeWindowWorkspaces(window, window->Workspaces(), workspaces);
|
|
|
|
window->SetWorkspaces(workspaces);
|
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-11-30 18:47:01 +03:00
|
|
|
BAutolock _(this);
|
2005-02-28 23:23:51 +03:00
|
|
|
|
2005-11-30 18:47:01 +03:00
|
|
|
if (fWindowLayerList.HasItem(window)) {
|
2005-11-29 02:36:59 +03:00
|
|
|
debugger("AddWindowLayer: WindowLayer already in Desktop list\n");
|
2005-02-28 23:23:51 +03:00
|
|
|
return;
|
|
|
|
}
|
2004-01-13 03:56:36 +03:00
|
|
|
|
2005-11-30 18:47:01 +03:00
|
|
|
fWindowLayerList.AddItem(window);
|
|
|
|
|
|
|
|
if (window->Workspaces() == B_CURRENT_WORKSPACE)
|
|
|
|
window->SetWorkspaces(workspace_to_workspaces(CurrentWorkspace()));
|
2005-11-29 02:36:59 +03:00
|
|
|
|
2005-11-30 18:47:01 +03:00
|
|
|
_ChangeWindowWorkspaces(window, 0, window->Workspaces());
|
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-11-30 18:47:01 +03:00
|
|
|
BAutolock _(this);
|
|
|
|
|
|
|
|
fWindowLayerList.RemoveItem(window);
|
|
|
|
_ChangeWindowWorkspaces(window, window->Workspaces(), 0);
|
|
|
|
|
|
|
|
// make sure this window won't get any events anymore
|
|
|
|
|
|
|
|
if (window->Window() != NULL)
|
|
|
|
EventDispatcher().RemoveTarget(window->Window()->EventTarget());
|
|
|
|
}
|
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-11-30 18:47:01 +03:00
|
|
|
void
|
2005-12-01 16:59:04 +03:00
|
|
|
Desktop::SetWindowLook(WindowLayer *window, window_look look)
|
2005-11-30 18:47:01 +03:00
|
|
|
{
|
2005-12-01 16:59:04 +03:00
|
|
|
fRootLayer->SetWindowLook(window, look);
|
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-01 16:59:04 +03:00
|
|
|
Desktop::SetWindowFeel(WindowLayer *window, window_feel feel)
|
2005-04-21 22:57:34 +04:00
|
|
|
{
|
2005-12-01 16:59:04 +03:00
|
|
|
fRootLayer->SetWindowFeel(window, feel);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
Desktop::SetWindowFlags(WindowLayer *window, uint32 flags)
|
|
|
|
{
|
|
|
|
fRootLayer->SetWindowFlags(window, flags);
|
2005-04-21 22:57:34 +04:00
|
|
|
}
|
|
|
|
|
2005-04-25 18:14:09 +04:00
|
|
|
|
2005-11-24 20:45:26 +03:00
|
|
|
WindowLayer *
|
|
|
|
Desktop::FindWindowLayerByClientToken(int32 token, team_id teamID)
|
2005-02-28 23:23:51 +03:00
|
|
|
{
|
2005-07-05 22:14:24 +04:00
|
|
|
BAutolock locker(this);
|
2005-02-28 23:23:51 +03:00
|
|
|
|
2005-11-24 20:45:26 +03:00
|
|
|
WindowLayer *wb;
|
|
|
|
for (int32 i = 0; (wb = (WindowLayer *)fWindowLayerList.ItemAt(i)); i++) {
|
2005-02-28 23:23:51 +03:00
|
|
|
if (wb->Window()->ClientToken() == token
|
2005-06-23 21:40:35 +04:00
|
|
|
&& wb->Window()->ClientTeam() == teamID)
|
2005-07-05 22:14:24 +04:00
|
|
|
return wb;
|
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-11-24 20:45:26 +03:00
|
|
|
const BObjectList<WindowLayer> &
|
2005-10-31 22:35:46 +03:00
|
|
|
Desktop::WindowList() const
|
|
|
|
{
|
|
|
|
if (!IsLocked())
|
|
|
|
debugger("You must lock before getting registered windows list\n");
|
|
|
|
|
2005-11-24 20:45:26 +03:00
|
|
|
return fWindowLayerList;
|
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)
|
|
|
|
{
|
|
|
|
BAutolock locker(this);
|
|
|
|
|
|
|
|
// compute the number of windows
|
|
|
|
|
|
|
|
int32 count = 0;
|
|
|
|
if (team >= B_OK) {
|
2005-11-24 20:45:26 +03:00
|
|
|
for (int32 i = 0; i < fWindowLayerList.CountItems(); i++) {
|
2005-11-26 19:56:52 +03:00
|
|
|
WindowLayer* layer = fWindowLayerList.ItemAt(i);
|
2005-07-05 22:14:24 +04:00
|
|
|
|
2005-11-26 19:56:52 +03:00
|
|
|
if (layer->Window()->ClientTeam() == team)
|
2005-07-05 22:14:24 +04:00
|
|
|
count++;
|
|
|
|
}
|
|
|
|
} else
|
2005-11-24 20:45:26 +03:00
|
|
|
count = fWindowLayerList.CountItems();
|
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-11-24 20:45:26 +03:00
|
|
|
for (int32 i = 0; i < fWindowLayerList.CountItems(); i++) {
|
2005-11-26 19:56:52 +03:00
|
|
|
WindowLayer* layer = fWindowLayerList.ItemAt(i);
|
2005-07-05 22:14:24 +04:00
|
|
|
|
2005-11-26 19:56:52 +03:00
|
|
|
if (team >= B_OK && layer->Window()->ClientTeam() != team)
|
2005-07-05 22:14:24 +04:00
|
|
|
continue;
|
|
|
|
|
2005-11-26 19:56:52 +03:00
|
|
|
sender.Attach<int32>(layer->Window()->ServerToken());
|
2005-07-05 22:14:24 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
sender.Flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
Desktop::WriteWindowInfo(int32 serverToken, BPrivate::LinkSender& sender)
|
|
|
|
{
|
|
|
|
BAutolock locker(this);
|
|
|
|
BAutolock tokenLocker(BPrivate::gDefaultTokens);
|
|
|
|
|
|
|
|
ServerWindow* window;
|
|
|
|
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
|
|
|
|