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
This commit is contained in:
parent
c7bba5ca04
commit
f89b4c9a23
@ -49,26 +49,46 @@
|
||||
#endif
|
||||
|
||||
|
||||
class KeyboardFilter : public BMessageFilter {
|
||||
class KeyboardFilter : public EventFilter {
|
||||
public:
|
||||
KeyboardFilter(Desktop* desktop);
|
||||
|
||||
virtual filter_result Filter(BMessage* message, BHandler** _target);
|
||||
virtual filter_result Filter(BMessage* message, EventTarget** _target,
|
||||
int32* _viewToken);
|
||||
|
||||
private:
|
||||
Desktop* fDesktop;
|
||||
Desktop* fDesktop;
|
||||
EventTarget* fLastFocus;
|
||||
bigtime_t fTimestamp;
|
||||
};
|
||||
|
||||
class MouseFilter : public EventFilter {
|
||||
public:
|
||||
MouseFilter(Desktop* desktop);
|
||||
|
||||
virtual filter_result Filter(BMessage* message, EventTarget** _target,
|
||||
int32* _viewToken);
|
||||
|
||||
private:
|
||||
Desktop* fDesktop;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
KeyboardFilter::KeyboardFilter(Desktop* desktop)
|
||||
: BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),
|
||||
fDesktop(desktop)
|
||||
:
|
||||
fDesktop(desktop),
|
||||
fLastFocus(NULL),
|
||||
fTimestamp(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
filter_result
|
||||
KeyboardFilter::Filter(BMessage* message, BHandler** /*_target*/)
|
||||
KeyboardFilter::Filter(BMessage* message, EventTarget** _target,
|
||||
int32* /*_viewToken*/)
|
||||
{
|
||||
int32 key;
|
||||
int32 modifiers;
|
||||
@ -123,6 +143,93 @@ KeyboardFilter::Filter(BMessage* message, BHandler** /*_target*/)
|
||||
return B_SKIP_MESSAGE;
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
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();
|
||||
|
||||
return B_DISPATCH_MESSAGE;
|
||||
}
|
||||
|
||||
@ -185,28 +292,7 @@ Desktop::Init()
|
||||
fEventDispatcher.SetTo(gInputManager->GetStream());
|
||||
fEventDispatcher.SetHWInterface(fVirtualScreen.HWInterface());
|
||||
|
||||
// temporary hack to get things started
|
||||
class MouseFilter : public BMessageFilter {
|
||||
public:
|
||||
MouseFilter(::RootLayer* layer)
|
||||
: BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),
|
||||
fRootLayer(layer)
|
||||
{
|
||||
}
|
||||
|
||||
virtual filter_result
|
||||
Filter(BMessage* message, BHandler** /*_target*/)
|
||||
{
|
||||
fRootLayer->Lock();
|
||||
fRootLayer->MouseEventHandler(message);
|
||||
fRootLayer->Unlock();
|
||||
return B_DISPATCH_MESSAGE;
|
||||
}
|
||||
|
||||
private:
|
||||
::RootLayer* fRootLayer;
|
||||
};
|
||||
fEventDispatcher.SetMouseFilter(new MouseFilter(fRootLayer));
|
||||
fEventDispatcher.SetMouseFilter(new MouseFilter(this));
|
||||
fEventDispatcher.SetKeyboardFilter(new KeyboardFilter(this));
|
||||
|
||||
// take care of setting the default cursor
|
||||
@ -560,6 +646,9 @@ Desktop::RemoveWindowLayer(WindowLayer *windowLayer)
|
||||
Unlock();
|
||||
|
||||
RootLayer()->RemoveWindowLayer(windowLayer);
|
||||
|
||||
if (windowLayer->Window() != NULL)
|
||||
EventDispatcher().RemoveTarget(windowLayer->Window()->EventTarget());
|
||||
}
|
||||
|
||||
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include "HWInterface.h"
|
||||
#include "InputManager.h"
|
||||
|
||||
#include <TokenSpace.h>
|
||||
|
||||
#include <Autolock.h>
|
||||
#include <MessageFilter.h>
|
||||
#include <View.h>
|
||||
@ -29,11 +31,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
// TODO: the Target class could be made public, and ServerWindow could inherit
|
||||
// from it - this would especially be nice if we didn't have to lock the root
|
||||
// layer when messing with ServerWindow children (because then, RootLayer's
|
||||
// mouse filter could almost be moved completely to the window).
|
||||
|
||||
/*!
|
||||
The differentiation between messenger and token looks odd, but it
|
||||
really has a reason as well:
|
||||
@ -42,40 +39,7 @@
|
||||
view(s).
|
||||
*/
|
||||
|
||||
class EventDispatcher::Target {
|
||||
public:
|
||||
Target(const BMessenger& messenger);
|
||||
~Target();
|
||||
|
||||
BMessenger& Messenger() { return fMessenger; }
|
||||
|
||||
event_listener* FindListener(int32 token, int32* _index = NULL);
|
||||
bool AddListener(int32 token, uint32 eventMask, uint32 options,
|
||||
bool temporary);
|
||||
void RemoveListener(event_listener* listener, bool temporary);
|
||||
|
||||
bool RemoveListener(int32 token);
|
||||
bool RemoveTemporaryListener(int32 token);
|
||||
void RemoveTemporaryListeners();
|
||||
|
||||
bool IsNeeded() const { return fFocusOrLastFocus || !fListeners.IsEmpty(); }
|
||||
|
||||
void SetFocusOrLastFocus(bool focus) { fFocusOrLastFocus = focus; }
|
||||
bool FocusOrLastFocus() const { return fFocusOrLastFocus; }
|
||||
|
||||
int32 CountListeners() const { return fListeners.CountItems(); }
|
||||
event_listener* ListenerAt(int32 index) const { return fListeners.ItemAt(index); }
|
||||
|
||||
private:
|
||||
bool _RemoveTemporaryListener(event_listener* listener, int32 index);
|
||||
|
||||
BObjectList<event_listener> fListeners;
|
||||
BMessenger fMessenger;
|
||||
bool fFocusOrLastFocus;
|
||||
|
||||
};
|
||||
|
||||
struct EventDispatcher::event_listener {
|
||||
struct event_listener {
|
||||
int32 token;
|
||||
uint32 event_mask;
|
||||
uint32 options;
|
||||
@ -93,22 +57,27 @@ static const float kStandardImportance = 0.9f;
|
||||
static const float kListenerImportance = 0.8f;
|
||||
|
||||
|
||||
EventDispatcher::Target::Target(const BMessenger& messenger)
|
||||
EventTarget::EventTarget()
|
||||
:
|
||||
fListeners(2, true),
|
||||
fMessenger(messenger),
|
||||
fFocusOrLastFocus(false)
|
||||
fListeners(2, true)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
EventDispatcher::Target::~Target()
|
||||
EventTarget::~EventTarget()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
EventDispatcher::event_listener*
|
||||
EventDispatcher::Target::FindListener(int32 token, int32* _index)
|
||||
void
|
||||
EventTarget::SetTo(const BMessenger& messenger)
|
||||
{
|
||||
fMessenger = messenger;
|
||||
}
|
||||
|
||||
|
||||
event_listener*
|
||||
EventTarget::FindListener(int32 token, int32* _index)
|
||||
{
|
||||
for (int32 i = fListeners.CountItems(); i-- > 0;) {
|
||||
event_listener* listener = fListeners.ItemAt(i);
|
||||
@ -125,7 +94,7 @@ EventDispatcher::Target::FindListener(int32 token, int32* _index)
|
||||
|
||||
|
||||
bool
|
||||
EventDispatcher::Target::_RemoveTemporaryListener(event_listener* listener, int32 index)
|
||||
EventTarget::_RemoveTemporaryListener(event_listener* listener, int32 index)
|
||||
{
|
||||
if (listener->event_mask == 0) {
|
||||
// this is only a temporary target
|
||||
@ -150,7 +119,7 @@ EventDispatcher::Target::_RemoveTemporaryListener(event_listener* listener, int3
|
||||
|
||||
|
||||
void
|
||||
EventDispatcher::Target::RemoveTemporaryListeners()
|
||||
EventTarget::RemoveTemporaryListeners()
|
||||
{
|
||||
for (int32 index = CountListeners(); index-- > 0;) {
|
||||
event_listener* listener = ListenerAt(index);
|
||||
@ -161,7 +130,7 @@ EventDispatcher::Target::RemoveTemporaryListeners()
|
||||
|
||||
|
||||
bool
|
||||
EventDispatcher::Target::RemoveTemporaryListener(int32 token)
|
||||
EventTarget::RemoveTemporaryListener(int32 token)
|
||||
{
|
||||
int32 index;
|
||||
event_listener* listener = FindListener(token, &index);
|
||||
@ -173,7 +142,7 @@ EventDispatcher::Target::RemoveTemporaryListener(int32 token)
|
||||
|
||||
|
||||
bool
|
||||
EventDispatcher::Target::RemoveListener(int32 token)
|
||||
EventTarget::RemoveListener(int32 token)
|
||||
{
|
||||
int32 index;
|
||||
event_listener* listener = FindListener(token, &index);
|
||||
@ -194,7 +163,7 @@ EventDispatcher::Target::RemoveListener(int32 token)
|
||||
|
||||
|
||||
bool
|
||||
EventDispatcher::Target::AddListener(int32 token, uint32 eventMask,
|
||||
EventTarget::AddListener(int32 token, uint32 eventMask,
|
||||
uint32 options, bool temporary)
|
||||
{
|
||||
event_listener* listener = new (std::nothrow) event_listener;
|
||||
@ -231,15 +200,12 @@ EventDispatcher::EventDispatcher()
|
||||
fStream(NULL),
|
||||
fThread(-1),
|
||||
fCursorThread(-1),
|
||||
fPreviousMouseTarget(NULL),
|
||||
fFocus(NULL),
|
||||
fLastFocus(NULL),
|
||||
fTransit(false),
|
||||
fSuspendFocus(false),
|
||||
fMouseFilter(NULL),
|
||||
fKeyboardFilter(NULL),
|
||||
fTargets(10, true),
|
||||
// the list owns its items
|
||||
fListenerLock("listener lock"),
|
||||
fTargets(10),
|
||||
fCursorLock("cursor loop lock"),
|
||||
fHWInterface(NULL)
|
||||
{
|
||||
@ -321,101 +287,20 @@ EventDispatcher::_Run()
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Removes any reference to the target, but doesn't delete it.
|
||||
*/
|
||||
void
|
||||
EventDispatcher::_UnsetLastFocus()
|
||||
{
|
||||
if (fLastFocus == NULL)
|
||||
return;
|
||||
|
||||
fLastFocus->SetFocusOrLastFocus(false);
|
||||
if (!fLastFocus->IsNeeded())
|
||||
_RemoveTarget(fLastFocus);
|
||||
|
||||
fLastFocus = NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EventDispatcher::SetFocus(const BMessenger* messenger)
|
||||
EventDispatcher::RemoveTarget(EventTarget& target)
|
||||
{
|
||||
BAutolock _(this);
|
||||
BAutolock _temp(fListenerLock);
|
||||
|
||||
ETRACE(("EventDispatcher::SetFocus(messenger = %p)\n", messenger));
|
||||
|
||||
if ((messenger == NULL && fFocus == NULL)
|
||||
|| (messenger != NULL && fFocus != NULL && fFocus->Messenger() == *messenger))
|
||||
return;
|
||||
|
||||
// update last focus
|
||||
|
||||
if (fLastFocus != NULL)
|
||||
_UnsetLastFocus();
|
||||
|
||||
fLastFocus = fFocus;
|
||||
|
||||
// update focus
|
||||
|
||||
if (messenger != NULL) {
|
||||
fFocus = _FindTarget(*messenger);
|
||||
if (fFocus == NULL) {
|
||||
// we need a new target for this focus
|
||||
fFocus = _AddTarget(*messenger);
|
||||
if (fFocus == NULL)
|
||||
printf("EventDispatcher: could not set focus!\n");
|
||||
}
|
||||
if (fFocus != NULL)
|
||||
fFocus->SetFocusOrLastFocus(true);
|
||||
} else
|
||||
if (fFocus == &target)
|
||||
fFocus = NULL;
|
||||
if (fPreviousMouseTarget == &target)
|
||||
fPreviousMouseTarget = NULL;
|
||||
|
||||
fFocusGotExitTransit = true;
|
||||
fTransit = true;
|
||||
}
|
||||
|
||||
|
||||
EventDispatcher::Target*
|
||||
EventDispatcher::_FindTarget(const BMessenger& messenger, int32* _index)
|
||||
{
|
||||
for (int32 i = fTargets.CountItems(); i-- > 0;) {
|
||||
Target* target = fTargets.ItemAt(i);
|
||||
|
||||
if (target->Messenger() == messenger) {
|
||||
if (_index)
|
||||
*_index = i;
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
EventDispatcher::Target*
|
||||
EventDispatcher::_AddTarget(const BMessenger& messenger)
|
||||
{
|
||||
Target* target = new (std::nothrow) Target(messenger);
|
||||
if (target == NULL) {
|
||||
printf("EventDispatcher: could not create new target!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool success = fTargets.AddItem(target);
|
||||
if (!success) {
|
||||
printf("EventDispatcher: could not add new target!\n");
|
||||
delete target;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EventDispatcher::_RemoveTarget(Target* target)
|
||||
{
|
||||
// the list owns its items and will delete the target itself
|
||||
fTargets.RemoveItem(target);
|
||||
fTargets.RemoveItem(&target);
|
||||
}
|
||||
|
||||
|
||||
@ -427,19 +312,15 @@ EventDispatcher::_RemoveTarget(Target* target)
|
||||
leaves the event mask untouched and just updates the options.
|
||||
*/
|
||||
bool
|
||||
EventDispatcher::_AddListener(const BMessenger& messenger, int32 token,
|
||||
EventDispatcher::_AddListener(EventTarget& target, int32 token,
|
||||
uint32 eventMask, uint32 options, bool temporary)
|
||||
{
|
||||
BAutolock _(fListenerLock);
|
||||
Target* target = _FindTarget(messenger);
|
||||
if (target == NULL) {
|
||||
// we need a new target for this messenger
|
||||
target = _AddTarget(messenger);
|
||||
if (target == NULL)
|
||||
return false;
|
||||
}
|
||||
BAutolock _(this);
|
||||
|
||||
event_listener* listener = target->FindListener(token);
|
||||
if (!fTargets.HasItem(&target))
|
||||
fTargets.AddItem(&target);
|
||||
|
||||
event_listener* listener = target.FindListener(token);
|
||||
if (listener != NULL) {
|
||||
// we already have this target, update its event mask
|
||||
if (temporary) {
|
||||
@ -463,10 +344,10 @@ EventDispatcher::_AddListener(const BMessenger& messenger, int32 token,
|
||||
|
||||
// we need a new target
|
||||
|
||||
bool success = target->AddListener(token, eventMask, options, temporary);
|
||||
bool success = target.AddListener(token, eventMask, options, temporary);
|
||||
if (!success) {
|
||||
if (!target->IsNeeded())
|
||||
_RemoveTarget(target);
|
||||
if (target.IsEmpty())
|
||||
fTargets.RemoveItem(&target);
|
||||
} else {
|
||||
if (options & B_SUSPEND_VIEW_FOCUS)
|
||||
fSuspendFocus = true;
|
||||
@ -480,7 +361,7 @@ void
|
||||
EventDispatcher::_RemoveTemporaryListeners()
|
||||
{
|
||||
for (int32 i = fTargets.CountItems(); i-- > 0;) {
|
||||
Target* target = fTargets.ItemAt(i);
|
||||
EventTarget* target = fTargets.ItemAt(i);
|
||||
|
||||
target->RemoveTemporaryListeners();
|
||||
}
|
||||
@ -488,61 +369,48 @@ EventDispatcher::_RemoveTemporaryListeners()
|
||||
|
||||
|
||||
bool
|
||||
EventDispatcher::AddListener(const BMessenger& messenger, int32 token,
|
||||
EventDispatcher::AddListener(EventTarget& target, int32 token,
|
||||
uint32 eventMask, uint32 options)
|
||||
{
|
||||
options &= B_NO_POINTER_HISTORY;
|
||||
// that's currently the only allowed option
|
||||
|
||||
return _AddListener(messenger, token, eventMask, options, false);
|
||||
return _AddListener(target, token, eventMask, options, false);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
EventDispatcher::AddTemporaryListener(const BMessenger& messenger,
|
||||
EventDispatcher::AddTemporaryListener(EventTarget& target,
|
||||
int32 token, uint32 eventMask, uint32 options)
|
||||
{
|
||||
return _AddListener(messenger, token, eventMask, options, true);
|
||||
return _AddListener(target, token, eventMask, options, true);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EventDispatcher::RemoveListener(const BMessenger& messenger, int32 token)
|
||||
EventDispatcher::RemoveListener(EventTarget& target, int32 token)
|
||||
{
|
||||
BAutolock _(fListenerLock);
|
||||
BAutolock _(this);
|
||||
ETRACE(("events: remove listener token %ld\n", token));
|
||||
|
||||
int32 index;
|
||||
Target* target = _FindTarget(messenger, &index);
|
||||
if (target == NULL)
|
||||
return;
|
||||
|
||||
if (target->RemoveListener(token) && !target->IsNeeded()) {
|
||||
fTargets.RemoveItemAt(index);
|
||||
delete target;
|
||||
}
|
||||
if (target.RemoveListener(token) && target.IsEmpty())
|
||||
fTargets.RemoveItem(&target);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EventDispatcher::RemoveTemporaryListener(const BMessenger& messenger, int32 token)
|
||||
EventDispatcher::RemoveTemporaryListener(EventTarget& target, int32 token)
|
||||
{
|
||||
BAutolock _(fListenerLock);
|
||||
BAutolock _(this);
|
||||
ETRACE(("events: remove temporary listener token %ld\n", token));
|
||||
|
||||
int32 index;
|
||||
Target* target = _FindTarget(messenger, &index);
|
||||
if (target == NULL)
|
||||
return;
|
||||
|
||||
if (target->RemoveTemporaryListener(token) && !target->IsNeeded()) {
|
||||
fTargets.RemoveItemAt(index);
|
||||
delete target;
|
||||
}
|
||||
if (target.RemoveTemporaryListener(token) && target.IsEmpty())
|
||||
fTargets.RemoveItem(&target);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EventDispatcher::SetMouseFilter(BMessageFilter* filter)
|
||||
EventDispatcher::SetMouseFilter(EventFilter* filter)
|
||||
{
|
||||
BAutolock _(this);
|
||||
|
||||
@ -555,7 +423,7 @@ EventDispatcher::SetMouseFilter(BMessageFilter* filter)
|
||||
|
||||
|
||||
void
|
||||
EventDispatcher::SetKeyboardFilter(BMessageFilter* filter)
|
||||
EventDispatcher::SetKeyboardFilter(EventFilter* filter)
|
||||
{
|
||||
BAutolock _(this);
|
||||
|
||||
@ -633,13 +501,10 @@ EventDispatcher::_SendMessage(BMessenger& messenger, BMessage* message,
|
||||
|
||||
|
||||
bool
|
||||
EventDispatcher::_AddTokens(BMessage* message, Target* target, uint32 eventMask)
|
||||
EventDispatcher::_AddTokens(BMessage* message, EventTarget* target, uint32 eventMask)
|
||||
{
|
||||
_RemoveTokens(message);
|
||||
|
||||
BAutolock _(fListenerLock);
|
||||
// temporary lock
|
||||
|
||||
int32 count = target->CountListeners();
|
||||
for (int32 i = count; i-- > 0;) {
|
||||
event_listener* listener = target->ListenerAt(i);
|
||||
@ -696,7 +561,8 @@ EventDispatcher::_EventLoop()
|
||||
|
||||
BAutolock _(this);
|
||||
|
||||
bool sendToLastFocus = false;
|
||||
EventTarget* current = NULL;
|
||||
EventTarget* previous = NULL;
|
||||
bool pointerEvent = false;
|
||||
bool keyboardEvent = false;
|
||||
bool addedTokens = false;
|
||||
@ -704,45 +570,37 @@ EventDispatcher::_EventLoop()
|
||||
switch (event->what) {
|
||||
case B_MOUSE_MOVED:
|
||||
{
|
||||
BPoint where;
|
||||
if (event->FindPoint("where", &where) == B_OK)
|
||||
fLastCursorPosition = where;
|
||||
|
||||
if (!HasCursorThread()) {
|
||||
// there is no cursor thread, we need to move the cursor ourselves
|
||||
BAutolock _(fCursorLock);
|
||||
|
||||
BPoint where;
|
||||
if (fHWInterface != NULL && event->FindPoint("where", &where) == B_OK)
|
||||
fHWInterface->MoveCursorTo(where.x, where.y);
|
||||
}
|
||||
|
||||
if (fTransit) {
|
||||
// target has changed, we need to add the be:transit field
|
||||
// to the message
|
||||
if (fLastFocus != NULL) {
|
||||
addedTokens = _AddTokens(event, fLastFocus, B_POINTER_EVENTS);
|
||||
_SendMessage(fLastFocus->Messenger(), event,
|
||||
kMouseTransitImportance);
|
||||
sendToLastFocus = true;
|
||||
|
||||
// we no longer need the last focus messenger
|
||||
_UnsetLastFocus();
|
||||
if (fHWInterface != NULL) {
|
||||
fHWInterface->MoveCursorTo(fLastCursorPosition.x,
|
||||
fLastCursorPosition.y);
|
||||
}
|
||||
|
||||
fTransit = false;
|
||||
}
|
||||
|
||||
BPoint where;
|
||||
if (event->FindPoint("where", &where) == B_OK)
|
||||
fLastCursorPosition = where;
|
||||
|
||||
// supposed to fall through
|
||||
}
|
||||
case B_MOUSE_DOWN:
|
||||
case B_MOUSE_UP:
|
||||
{
|
||||
#ifdef TRACE_EVENTS
|
||||
if (event->what != B_MOUSE_MOVED)
|
||||
printf("mouse up/down event, focus = %p\n", fFocus);
|
||||
printf("mouse up/down event, previous target = %p\n", fPreviousMouseTarget);
|
||||
#endif
|
||||
if (fMouseFilter != NULL
|
||||
&& fMouseFilter->Filter(event, NULL) == B_SKIP_MESSAGE) {
|
||||
pointerEvent = true;
|
||||
|
||||
if (fMouseFilter == NULL)
|
||||
break;
|
||||
|
||||
EventTarget* mouseTarget = fPreviousMouseTarget;
|
||||
int32 viewToken = B_NULL_TOKEN;
|
||||
if (fMouseFilter->Filter(event, &mouseTarget, &viewToken) == B_SKIP_MESSAGE) {
|
||||
// this is a work-around if the wrong B_MOUSE_UP
|
||||
// event is filtered out
|
||||
if (event->what == B_MOUSE_UP) {
|
||||
@ -763,31 +621,30 @@ EventDispatcher::_EventLoop()
|
||||
event->RemoveName("where");
|
||||
event->AddPoint("screen_where", fLastCursorPosition);
|
||||
|
||||
pointerEvent = true;
|
||||
if (event->what == B_MOUSE_MOVED
|
||||
&& fPreviousMouseTarget != NULL
|
||||
&& mouseTarget != fPreviousMouseTarget) {
|
||||
// target has changed, we need to notify the previous target
|
||||
// that the mouse has exited its views
|
||||
addedTokens = _AddTokens(event, fPreviousMouseTarget,
|
||||
B_POINTER_EVENTS);
|
||||
_SendMessage(fPreviousMouseTarget->Messenger(), event,
|
||||
kMouseTransitImportance);
|
||||
previous = fPreviousMouseTarget;
|
||||
}
|
||||
|
||||
if (fFocus != NULL) {
|
||||
int32 viewToken;
|
||||
current = fPreviousMouseTarget = mouseTarget;
|
||||
|
||||
addedTokens |= _AddTokens(event, fFocus, B_POINTER_EVENTS);
|
||||
if (addedTokens)
|
||||
_SetFeedFocus(event);
|
||||
else if (fFocusGotExitTransit) {
|
||||
// TODO: this is a temporary hack to not continue to
|
||||
// send mouse messages to the client when the mouse
|
||||
// pointer is not over it
|
||||
if (event->FindInt32("_view_token", &viewToken) != B_OK)
|
||||
break;
|
||||
if (current != NULL) {
|
||||
addedTokens |= _AddTokens(event, current, B_POINTER_EVENTS);
|
||||
if (viewToken != B_NULL_TOKEN)
|
||||
event->AddInt32("_view_token", viewToken);
|
||||
|
||||
fFocusGotExitTransit = false;
|
||||
} else if (event->what == B_MOUSE_MOVED) {
|
||||
if (event->FindInt32("_view_token", &viewToken) != B_OK)
|
||||
fFocusGotExitTransit = true;
|
||||
}
|
||||
|
||||
_SendMessage(fFocus->Messenger(), event, event->what == B_MOUSE_MOVED
|
||||
_SendMessage(current->Messenger(), event, event->what == B_MOUSE_MOVED
|
||||
? kMouseMovedImportance : kStandardImportance);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case B_KEY_DOWN:
|
||||
case B_KEY_UP:
|
||||
@ -797,12 +654,12 @@ EventDispatcher::_EventLoop()
|
||||
ETRACE(("key event, focus = %p\n", fFocus));
|
||||
|
||||
if (fKeyboardFilter != NULL
|
||||
&& fKeyboardFilter->Filter(event, NULL) == B_SKIP_MESSAGE)
|
||||
&& fKeyboardFilter->Filter(event, &fFocus) == B_SKIP_MESSAGE)
|
||||
break;
|
||||
|
||||
keyboardEvent = true;
|
||||
|
||||
if (fFocus != NULL && _AddTokens(event, fFocus, B_KEYBOARD_EVENTS)) {
|
||||
if (current != NULL && _AddTokens(event, fFocus, B_KEYBOARD_EVENTS)) {
|
||||
// if tokens were added, we need to explicetly suspend
|
||||
// focus in the event - if not, the event is simply not
|
||||
// forwarded to the target
|
||||
@ -815,8 +672,10 @@ EventDispatcher::_EventLoop()
|
||||
// supposed to fall through
|
||||
|
||||
default:
|
||||
if (fFocus != NULL && (!fSuspendFocus || addedTokens))
|
||||
_SendMessage(fFocus->Messenger(), event, kStandardImportance);
|
||||
current = fFocus;
|
||||
|
||||
if (current != NULL && (!fSuspendFocus || addedTokens))
|
||||
_SendMessage(current->Messenger(), event, kStandardImportance);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -833,13 +692,11 @@ EventDispatcher::_EventLoop()
|
||||
event->RemoveName("_view_token");
|
||||
}
|
||||
|
||||
BAutolock _temp(fListenerLock);
|
||||
|
||||
for (int32 i = fTargets.CountItems(); i-- > 0;) {
|
||||
Target* target = fTargets.ItemAt(i);
|
||||
EventTarget* target = fTargets.ItemAt(i);
|
||||
|
||||
// we already sent the event to the all focus and last focus tokens
|
||||
if (fFocus == target || (sendToLastFocus && fLastFocus == target))
|
||||
if (current == target || previous == target)
|
||||
continue;
|
||||
|
||||
// don't send the message if there are no tokens for this event
|
||||
@ -851,7 +708,6 @@ EventDispatcher::_EventLoop()
|
||||
? kMouseMovedImportance : kListenerImportance)) {
|
||||
// the target doesn't seem to exist anymore, let's remove it
|
||||
fTargets.RemoveItemAt(i);
|
||||
delete target;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,14 +10,52 @@
|
||||
|
||||
|
||||
#include <Locker.h>
|
||||
#include <MessageFilter.h>
|
||||
#include <Messenger.h>
|
||||
#include <ObjectList.h>
|
||||
|
||||
class BMessageFilter;
|
||||
|
||||
class EventStream;
|
||||
class HWInterface;
|
||||
|
||||
struct event_listener;
|
||||
|
||||
|
||||
class EventTarget {
|
||||
public:
|
||||
EventTarget();
|
||||
~EventTarget();
|
||||
|
||||
void SetTo(const BMessenger& messenger);
|
||||
BMessenger& Messenger() { return fMessenger; }
|
||||
|
||||
event_listener* FindListener(int32 token, int32* _index = NULL);
|
||||
bool AddListener(int32 token, uint32 eventMask, uint32 options,
|
||||
bool temporary);
|
||||
void RemoveListener(event_listener* listener, bool temporary);
|
||||
|
||||
bool RemoveListener(int32 token);
|
||||
bool RemoveTemporaryListener(int32 token);
|
||||
void RemoveTemporaryListeners();
|
||||
|
||||
bool IsEmpty() const { return fListeners.IsEmpty(); }
|
||||
|
||||
int32 CountListeners() const { return fListeners.CountItems(); }
|
||||
event_listener* ListenerAt(int32 index) const
|
||||
{ return fListeners.ItemAt(index); }
|
||||
|
||||
private:
|
||||
bool _RemoveTemporaryListener(event_listener* listener, int32 index);
|
||||
|
||||
BObjectList<event_listener> fListeners;
|
||||
BMessenger fMessenger;
|
||||
};
|
||||
|
||||
class EventFilter {
|
||||
public:
|
||||
virtual filter_result Filter(BMessage* event, EventTarget** _target,
|
||||
int32* _viewToken = NULL) = 0;
|
||||
};
|
||||
|
||||
class EventDispatcher : public BLocker {
|
||||
public:
|
||||
@ -27,17 +65,17 @@ class EventDispatcher : public BLocker {
|
||||
status_t SetTo(EventStream* stream);
|
||||
status_t InitCheck();
|
||||
|
||||
void SetFocus(const BMessenger* messenger);
|
||||
void RemoveTarget(EventTarget& target);
|
||||
|
||||
bool AddListener(const BMessenger& messenger, int32 token,
|
||||
bool AddListener(EventTarget& target, int32 token,
|
||||
uint32 eventMask, uint32 options);
|
||||
bool AddTemporaryListener(const BMessenger& messenger,
|
||||
bool AddTemporaryListener(EventTarget& target,
|
||||
int32 token, uint32 eventMask, uint32 options);
|
||||
void RemoveListener(const BMessenger& messenger, int32 token);
|
||||
void RemoveTemporaryListener(const BMessenger& messenger, int32 token);
|
||||
void RemoveListener(EventTarget& target, int32 token);
|
||||
void RemoveTemporaryListener(EventTarget& target, int32 token);
|
||||
|
||||
void SetMouseFilter(BMessageFilter* filter);
|
||||
void SetKeyboardFilter(BMessageFilter* filter);
|
||||
void SetMouseFilter(EventFilter* filter);
|
||||
void SetKeyboardFilter(EventFilter* filter);
|
||||
|
||||
void GetMouse(BPoint& where, int32& buttons);
|
||||
|
||||
@ -45,26 +83,20 @@ class EventDispatcher : public BLocker {
|
||||
void SetHWInterface(HWInterface* interface);
|
||||
|
||||
private:
|
||||
struct event_listener;
|
||||
class Target;
|
||||
|
||||
status_t _Run();
|
||||
void _Unset();
|
||||
|
||||
bool _SendMessage(BMessenger& messenger, BMessage* message, float importance);
|
||||
|
||||
bool _AddTokens(BMessage* message, Target* target, uint32 eventMask);
|
||||
bool _AddTokens(BMessage* message, EventTarget* target, uint32 eventMask);
|
||||
void _RemoveTokens(BMessage* message);
|
||||
void _SetFeedFocus(BMessage* message);
|
||||
void _UnsetFeedFocus(BMessage* message);
|
||||
|
||||
void _UnsetLastFocus();
|
||||
void _SetMouseTarget(const BMessenger* messenger);
|
||||
void _UnsetLastMouseTarget();
|
||||
|
||||
Target* _FindTarget(const BMessenger& messenger, int32* _index = NULL);
|
||||
Target* _AddTarget(const BMessenger& messenger);
|
||||
void _RemoveTarget(Target* target);
|
||||
|
||||
bool _AddListener(const BMessenger& messenger, int32 token,
|
||||
bool _AddListener(EventTarget& target, int32 token,
|
||||
uint32 eventMask, uint32 options, bool temporary);
|
||||
void _RemoveTemporaryListeners();
|
||||
|
||||
@ -79,22 +111,18 @@ class EventDispatcher : public BLocker {
|
||||
thread_id fThread;
|
||||
thread_id fCursorThread;
|
||||
|
||||
Target* fFocus;
|
||||
Target* fLastFocus;
|
||||
bool fTransit;
|
||||
bool fFocusGotExitTransit;
|
||||
EventTarget* fPreviousMouseTarget;
|
||||
EventTarget* fFocus;
|
||||
bool fSuspendFocus;
|
||||
|
||||
BMessageFilter* fMouseFilter;
|
||||
BMessageFilter* fKeyboardFilter;
|
||||
EventFilter* fMouseFilter;
|
||||
EventFilter* fKeyboardFilter;
|
||||
|
||||
BObjectList<Target> fTargets;
|
||||
BObjectList<EventTarget> fTargets;
|
||||
|
||||
BPoint fLastCursorPosition;
|
||||
int32 fLastButtons;
|
||||
|
||||
BLocker fListenerLock;
|
||||
// temporary locker until we have an actual locking model
|
||||
BLocker fCursorLock;
|
||||
HWInterface* fHWInterface;
|
||||
};
|
||||
|
@ -834,26 +834,23 @@ Layer::CopyBits(BRect& src, BRect& dst, int32 xOffset, int32 yOffset)
|
||||
|
||||
|
||||
void
|
||||
Layer::MouseDown(BMessage *msg, BPoint where)
|
||||
Layer::MouseDown(BMessage *msg, BPoint where, int32* _viewToken)
|
||||
{
|
||||
*_viewToken = ViewToken();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Layer::MouseUp(BMessage *msg, BPoint where)
|
||||
Layer::MouseUp(BMessage *msg, BPoint where, int32* _viewToken)
|
||||
{
|
||||
*_viewToken = ViewToken();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Layer::MouseMoved(BMessage *msg, BPoint where)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Layer::MouseWheelChanged(BMessage *msg, BPoint where)
|
||||
Layer::MouseMoved(BMessage *msg, BPoint where, int32* _viewToken)
|
||||
{
|
||||
*_viewToken = ViewToken();
|
||||
}
|
||||
|
||||
|
||||
|
@ -151,10 +151,9 @@ class Layer {
|
||||
int32 xOffset, int32 yOffset);
|
||||
|
||||
// input handling
|
||||
virtual void MouseDown(BMessage *msg, BPoint where);
|
||||
virtual void MouseUp(BMessage *msg, BPoint where);
|
||||
virtual void MouseMoved(BMessage *msg, BPoint where);
|
||||
virtual void MouseWheelChanged(BMessage *msg, BPoint where);
|
||||
virtual void MouseDown(BMessage *msg, BPoint where, int32* _viewToken);
|
||||
virtual void MouseUp(BMessage *msg, BPoint where, int32* _viewToken);
|
||||
virtual void MouseMoved(BMessage *msg, BPoint where, int32* _viewToken);
|
||||
|
||||
virtual void WorkspaceActivated(int32 index, bool active);
|
||||
virtual void WorkspacesChanged(uint32 oldWorkspaces, uint32 newWorkspaces);
|
||||
|
@ -55,7 +55,7 @@ RootLayer::RootLayer(const char *name, Desktop *desktop, DrawingEngine *driver)
|
||||
: Layer(BRect(0, 0, 0, 0), name, 0, B_FOLLOW_ALL, B_WILL_DRAW, driver),
|
||||
fDesktop(desktop),
|
||||
fDragMessage(NULL),
|
||||
fMouseEventLayer(NULL),
|
||||
fMouseEventWindow(NULL),
|
||||
fAllRegionsLock("root layer region lock"),
|
||||
|
||||
fDirtyForRedraw(),
|
||||
@ -172,20 +172,15 @@ RootLayer::_SetFocus(WindowLayer* focus, BRegion& update)
|
||||
|
||||
if (fFocus != NULL) {
|
||||
update.Include(&fFocus->VisibleRegion());
|
||||
//fFocus->SetFocus(false);
|
||||
fFocus->SetFocus(false);
|
||||
}
|
||||
|
||||
fFocus = focus;
|
||||
|
||||
if (focus != NULL) {
|
||||
// TODO: the unlocking is evil, but there is currently no cleaner way to do this, ugh...
|
||||
// (this is also responsible for an occasional crash on quit)
|
||||
Unlock();
|
||||
fDesktop->EventDispatcher().SetFocus(&focus->Window()->FocusMessenger());
|
||||
Lock();
|
||||
update.Include(&focus->VisibleRegion());
|
||||
} else
|
||||
fDesktop->EventDispatcher().SetFocus(NULL);
|
||||
focus->SetFocus(true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -194,6 +189,8 @@ RootLayer::_SetFocus(WindowLayer* focus, BRegion& update)
|
||||
bool
|
||||
RootLayer::SetFocus(WindowLayer* focus)
|
||||
{
|
||||
BAutolock _(fAllRegionsLock);
|
||||
|
||||
BRegion update;
|
||||
bool success = _SetFocus(focus, update);
|
||||
if (!success)
|
||||
@ -524,15 +521,15 @@ RootLayer::_WindowsChanged(BRegion& region)
|
||||
}
|
||||
|
||||
|
||||
Layer*
|
||||
RootLayer::_ChildAt(BPoint where)
|
||||
WindowLayer*
|
||||
RootLayer::WindowAt(BPoint where)
|
||||
{
|
||||
if (VisibleRegion().Contains(where))
|
||||
return NULL;
|
||||
|
||||
for (Layer* child = LastChild(); child; child = child->PreviousLayer()) {
|
||||
if (child->FullVisible().Contains(where))
|
||||
return child;
|
||||
return dynamic_cast<WindowLayer*>(child);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@ -543,48 +540,17 @@ RootLayer::_ChildAt(BPoint where)
|
||||
|
||||
|
||||
void
|
||||
RootLayer::MouseEventHandler(BMessage *event)
|
||||
RootLayer::SetMouseEventWindow(WindowLayer* window)
|
||||
{
|
||||
BPoint where;
|
||||
if (event->FindPoint("where", &where) != B_OK)
|
||||
return;
|
||||
|
||||
Layer* layer = fMouseEventLayer;
|
||||
if (layer == NULL) {
|
||||
layer = _ChildAt(where);
|
||||
if (layer == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event->what) {
|
||||
case B_MOUSE_DOWN:
|
||||
layer->MouseDown(event, where);
|
||||
break;
|
||||
|
||||
case B_MOUSE_UP:
|
||||
layer->MouseUp(event, where);
|
||||
SetMouseEventLayer(NULL);
|
||||
break;
|
||||
|
||||
case B_MOUSE_MOVED:
|
||||
layer->MouseMoved(event, where);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RootLayer::SetMouseEventLayer(Layer* layer)
|
||||
{
|
||||
fMouseEventLayer = layer;
|
||||
fMouseEventWindow = window;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RootLayer::LayerRemoved(Layer* layer)
|
||||
{
|
||||
if (fMouseEventLayer == layer)
|
||||
fMouseEventLayer = NULL;
|
||||
if (fMouseEventWindow == layer)
|
||||
fMouseEventWindow = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -57,7 +57,6 @@ class RootLayer : public Layer {
|
||||
void HideWindowLayer(WindowLayer* windowLayer);
|
||||
void ShowWindowLayer(WindowLayer* windowLayer, bool toFront = true);
|
||||
|
||||
// void RevealNewWMState(Workspace::State &oldWMState);
|
||||
bool SetFocus(WindowLayer* focus);
|
||||
WindowLayer* Focus() const { return fFocus; }
|
||||
WindowLayer* Front() const { return fFront; }
|
||||
@ -67,15 +66,13 @@ class RootLayer : public Layer {
|
||||
void SetWorkspacesLayer(Layer* layer) { fWorkspacesLayer = layer; }
|
||||
Layer* WorkspacesLayer() const { return fWorkspacesLayer; }
|
||||
|
||||
#if 0
|
||||
void SetBGColor(const RGBColor &col);
|
||||
RGBColor BGColor(void) const;
|
||||
#endif
|
||||
|
||||
void SetDragMessage(BMessage *msg);
|
||||
BMessage* DragMessage() const;
|
||||
|
||||
void SetMouseEventLayer(Layer* layer);
|
||||
WindowLayer* WindowAt(BPoint where);
|
||||
|
||||
WindowLayer* MouseEventWindow() const { return fMouseEventWindow; }
|
||||
void SetMouseEventWindow(WindowLayer* layer);
|
||||
|
||||
void LayerRemoved(Layer* layer);
|
||||
|
||||
@ -100,8 +97,6 @@ class RootLayer : public Layer {
|
||||
void AddWindowLayer(WindowLayer* windowLayer);
|
||||
void RemoveWindowLayer(WindowLayer* windowLayer);
|
||||
|
||||
void MouseEventHandler(BMessage *msg);
|
||||
|
||||
private:
|
||||
bool _SetFocus(WindowLayer* focus, BRegion& update);
|
||||
void _SetFront(WindowLayer* front, BRegion& update);
|
||||
@ -112,11 +107,9 @@ class RootLayer : public Layer {
|
||||
void _WindowsChanged(BRegion& region);
|
||||
void _UpdateWorkspace(Workspace& workspace);
|
||||
|
||||
Layer* _ChildAt(BPoint where);
|
||||
|
||||
Desktop* fDesktop;
|
||||
BMessage* fDragMessage;
|
||||
Layer* fMouseEventLayer;
|
||||
WindowLayer* fMouseEventWindow;
|
||||
|
||||
BLocker fAllRegionsLock;
|
||||
|
||||
|
@ -159,6 +159,8 @@ ServerWindow::ServerWindow(const char *title, ServerApp *app,
|
||||
BMessenger::Private(fHandlerMessenger).SetTo(fClientTeam,
|
||||
looperPort, clientToken);
|
||||
|
||||
fEventTarget.SetTo(fFocusMessenger);
|
||||
|
||||
fDeathSemaphore = create_sem(0, "window death");
|
||||
}
|
||||
|
||||
@ -680,7 +682,7 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
||||
}
|
||||
|
||||
if (fCurrentLayer->EventMask() != 0) {
|
||||
fDesktop->EventDispatcher().RemoveListener(FocusMessenger(),
|
||||
fDesktop->EventDispatcher().RemoveListener(EventTarget(),
|
||||
fCurrentLayer->ViewToken());
|
||||
}
|
||||
|
||||
@ -721,6 +723,8 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
||||
case AS_LAYER_SET_EVENT_MASK:
|
||||
{
|
||||
STRACE(("ServerWindow %s: Message AS_LAYER_SET_MOUSE_EVENT_MASK: Layer name: %s\n", fTitle, fCurrentLayer->Name()));
|
||||
rootLayer->Unlock();
|
||||
// we don't want RootLayer to be locked while we play with the events
|
||||
|
||||
uint32 eventMask, options;
|
||||
|
||||
@ -729,33 +733,38 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
||||
fCurrentLayer->SetEventMask(eventMask, options);
|
||||
|
||||
if (eventMask != 0 || options != 0) {
|
||||
fDesktop->EventDispatcher().AddListener(FocusMessenger(),
|
||||
fDesktop->EventDispatcher().AddListener(EventTarget(),
|
||||
fCurrentLayer->ViewToken(), eventMask, options);
|
||||
} else {
|
||||
fDesktop->EventDispatcher().RemoveListener(FocusMessenger(),
|
||||
fDesktop->EventDispatcher().RemoveListener(EventTarget(),
|
||||
fCurrentLayer->ViewToken());
|
||||
}
|
||||
}
|
||||
|
||||
rootLayer->Lock();
|
||||
break;
|
||||
}
|
||||
case AS_LAYER_SET_MOUSE_EVENT_MASK:
|
||||
{
|
||||
STRACE(("ServerWindow %s: Message AS_LAYER_SET_MOUSE_EVENT_MASK: Layer name: %s\n", fTitle, fCurrentLayer->Name()));
|
||||
rootLayer->Unlock();
|
||||
// we don't want RootLayer to be locked while we play with the events
|
||||
|
||||
uint32 eventMask, options;
|
||||
|
||||
link.Read<uint32>(&eventMask);
|
||||
if (link.Read<uint32>(&options) == B_OK) {
|
||||
if (eventMask != 0 || options != 0) {
|
||||
fDesktop->EventDispatcher().AddTemporaryListener(FocusMessenger(),
|
||||
fDesktop->EventDispatcher().AddTemporaryListener(EventTarget(),
|
||||
fCurrentLayer->ViewToken(), eventMask, options);
|
||||
} else {
|
||||
fDesktop->EventDispatcher().RemoveTemporaryListener(FocusMessenger(),
|
||||
fDesktop->EventDispatcher().RemoveTemporaryListener(EventTarget(),
|
||||
fCurrentLayer->ViewToken());
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: support B_LOCK_WINDOW_FOCUS option in RootLayer
|
||||
rootLayer->Lock();
|
||||
break;
|
||||
}
|
||||
case AS_LAYER_MOVE_TO:
|
||||
|
@ -13,6 +13,7 @@
|
||||
#define SERVER_WINDOW_H
|
||||
|
||||
|
||||
#include "EventDispatcher.h"
|
||||
#include "MessageLooper.h"
|
||||
|
||||
#include <PortLink.h>
|
||||
@ -59,6 +60,8 @@ public:
|
||||
virtual bool Run();
|
||||
virtual port_id MessagePort() const { return fMessagePort; }
|
||||
|
||||
::EventTarget& EventTarget() { return fEventTarget; }
|
||||
|
||||
void ReplaceDecorator();
|
||||
void Show();
|
||||
void Hide();
|
||||
@ -135,6 +138,7 @@ private:
|
||||
port_id fClientLooperPort;
|
||||
BMessenger fFocusMessenger;
|
||||
BMessenger fHandlerMessenger;
|
||||
::EventTarget fEventTarget;
|
||||
|
||||
BMessage fClientViewsWithInvalidCoords;
|
||||
|
||||
|
@ -70,6 +70,8 @@ WindowLayer::WindowLayer(const BRect &frame,
|
||||
fMouseButtons(0),
|
||||
fLastMousePosition(-1.0, -1.0),
|
||||
|
||||
fIsFocus(false),
|
||||
|
||||
fIsClosing(false),
|
||||
fIsMinimizing(false),
|
||||
fIsZooming(false),
|
||||
@ -148,7 +150,7 @@ WindowLayer::Draw(const BRect& updateRect)
|
||||
|
||||
// if we have a visible region, it is decorator's one.
|
||||
if (fDecorator) {
|
||||
fDecorator->SetFocus(GetRootLayer()->Focus() == this);
|
||||
fDecorator->SetFocus(IsFocus());
|
||||
fDecorator->Draw(updateRect);
|
||||
}
|
||||
}
|
||||
@ -389,7 +391,7 @@ WindowLayer::GetSizeLimits(float* minWidth, float* maxWidth,
|
||||
|
||||
|
||||
void
|
||||
WindowLayer::MouseDown(BMessage *msg, BPoint where)
|
||||
WindowLayer::MouseDown(BMessage *msg, BPoint where, int32* _viewToken)
|
||||
{
|
||||
Desktop* desktop = Window()->App()->GetDesktop();
|
||||
|
||||
@ -403,8 +405,8 @@ WindowLayer::MouseDown(BMessage *msg, BPoint where)
|
||||
if (fDecorator)
|
||||
action = _ActionFor(msg);
|
||||
|
||||
// deactivate border buttons on first click(select)
|
||||
if (GetRootLayer()->Focus() != this && action != DEC_MOVETOBACK
|
||||
// deactivate border buttons on first click (select)
|
||||
if (!IsFocus() && action != DEC_MOVETOBACK
|
||||
&& action != DEC_RESIZE && action != DEC_SLIDETAB)
|
||||
action = DEC_DRAG;
|
||||
|
||||
@ -454,12 +456,12 @@ WindowLayer::MouseDown(BMessage *msg, BPoint where)
|
||||
if (action == DEC_MOVETOBACK) {
|
||||
desktop->SendBehindWindow(this, NULL);
|
||||
} else {
|
||||
GetRootLayer()->SetMouseEventLayer(this);
|
||||
GetRootLayer()->SetMouseEventWindow(this);
|
||||
desktop->ActivateWindow(this);
|
||||
}
|
||||
} else if (target != NULL) {
|
||||
// clicking a simple Layer.
|
||||
if (GetRootLayer()->Focus() != this) {
|
||||
if (!IsFocus()) {
|
||||
DesktopSettings desktopSettings(desktop);
|
||||
|
||||
// not in FFM mode?
|
||||
@ -470,14 +472,13 @@ WindowLayer::MouseDown(BMessage *msg, BPoint where)
|
||||
return;
|
||||
}
|
||||
|
||||
msg->AddInt32("_view_token", target->ViewToken());
|
||||
target->MouseDown(msg, where);
|
||||
target->MouseDown(msg, where, _viewToken);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WindowLayer::MouseUp(BMessage *msg, BPoint where)
|
||||
WindowLayer::MouseUp(BMessage *msg, BPoint where, int32* _viewToken)
|
||||
{
|
||||
bool invalidate = false;
|
||||
if (fDecorator) {
|
||||
@ -517,15 +518,13 @@ WindowLayer::MouseUp(BMessage *msg, BPoint where)
|
||||
fIsSlidingTab = false;
|
||||
|
||||
Layer* target = LayerAt(where);
|
||||
if (target != NULL && target != this) {
|
||||
msg->AddInt32("_view_token", target->ViewToken());
|
||||
target->MouseUp(msg, where);
|
||||
}
|
||||
if (target != NULL && target != this)
|
||||
target->MouseUp(msg, where, _viewToken);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WindowLayer::MouseMoved(BMessage *msg, BPoint where)
|
||||
WindowLayer::MouseMoved(BMessage *msg, BPoint where, int32* _viewToken)
|
||||
{
|
||||
if (fDecorator) {
|
||||
// TODO: present behavior is not fine!
|
||||
@ -560,14 +559,12 @@ WindowLayer::MouseMoved(BMessage *msg, BPoint where)
|
||||
Desktop* desktop = Window()->App()->GetDesktop();
|
||||
DesktopSettings desktopSettings(desktop);
|
||||
|
||||
if (desktopSettings.MouseMode() != B_NORMAL_MOUSE && GetRootLayer()->Focus() != this)
|
||||
if (desktopSettings.MouseMode() != B_NORMAL_MOUSE && !IsFocus())
|
||||
GetRootLayer()->SetFocus(this);
|
||||
|
||||
Layer* target = LayerAt(where);
|
||||
if (target != NULL && target != this) {
|
||||
msg->AddInt32("_view_token", target->ViewToken());
|
||||
target->MouseMoved(msg, where);
|
||||
}
|
||||
if (target != NULL && target != this)
|
||||
target->MouseMoved(msg, where, _viewToken);
|
||||
}
|
||||
|
||||
|
||||
|
@ -84,9 +84,9 @@ class WindowLayer : public Layer {
|
||||
float* minHeight,
|
||||
float* maxHeight) const;
|
||||
|
||||
virtual void MouseDown(BMessage *msg, BPoint where);
|
||||
virtual void MouseUp(BMessage *msg, BPoint where);
|
||||
virtual void MouseMoved(BMessage *msg, BPoint where);
|
||||
virtual void MouseDown(BMessage *msg, BPoint where, int32* _viewToken);
|
||||
virtual void MouseUp(BMessage *msg, BPoint where, int32* _viewToken);
|
||||
virtual void MouseMoved(BMessage *msg, BPoint where, int32* _viewToken);
|
||||
|
||||
// click_type ActionFor(const BMessage *msg)
|
||||
// { return _ActionFor(evt); }
|
||||
@ -100,6 +100,9 @@ class WindowLayer : public Layer {
|
||||
void UpdateFont();
|
||||
void UpdateScreen();
|
||||
|
||||
bool IsFocus() const { return fIsFocus; }
|
||||
void SetFocus(bool focus) { fIsFocus = focus; }
|
||||
|
||||
inline Decorator* GetDecorator() const { return fDecorator; }
|
||||
|
||||
inline int32 Look() const { return fLook; }
|
||||
@ -151,6 +154,8 @@ class WindowLayer : public Layer {
|
||||
BPoint fLastMousePosition;
|
||||
BPoint fResizingClickOffset;
|
||||
|
||||
bool fIsFocus;
|
||||
|
||||
bool fIsClosing;
|
||||
bool fIsMinimizing;
|
||||
bool fIsZooming;
|
||||
|
Loading…
Reference in New Issue
Block a user