In anticipation of Stippi's new clipping code, I refactored the EventDispatcher
a bit: * listeners are now managed per target (ie. per messenger) (by the Target class) * therefore, the fFocusTokens/fLastFocusTokens lists are no longer needed; every Target knows its listeners already. * this also fixes the obvious bug that the focus window's views would get both keyboard and pointer events, no matter which of them they originally wanted. * renamed event_target to event_listener (there was actually a mix up in naming before - to the outside it was "listener", and internally, "target" was used) * WinBorder::MouseMoved()/MouseUp() now also add the view token to the message; the messages weren't received by the target before (unless the view used tracking via BView::SetMouseEventMask()...) - maybe the client should only update fLastMouseMoved on B_MOUSE_MOVED events, and direct B_MOUSE_UP/DOWN (plus wheel changes) always to fLastMouseMoved... * some cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15123 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+320
-145
@@ -28,19 +28,60 @@
|
|||||||
#endif
|
#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
|
The differentiation between messenger and token looks odd, but it
|
||||||
really has a reason as well:
|
really has a reason as well:
|
||||||
All events are sent to the window only - it may then use the token or
|
All events are sent to the preferred window handler only - the window
|
||||||
token list to identify the specific target view(s).
|
may then use the token or token list to identify the specific target
|
||||||
|
view(s).
|
||||||
*/
|
*/
|
||||||
struct EventDispatcher::event_target {
|
|
||||||
BMessenger messenger;
|
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 {
|
||||||
int32 token;
|
int32 token;
|
||||||
uint32 event_mask;
|
uint32 event_mask;
|
||||||
uint32 options;
|
uint32 options;
|
||||||
uint32 temporary_event_mask;
|
uint32 temporary_event_mask;
|
||||||
uint32 temporary_options;
|
uint32 temporary_options;
|
||||||
|
|
||||||
|
uint32 EffectiveEventMask() const { return event_mask | temporary_event_mask; }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char* kTokenName = "_token";
|
static const char* kTokenName = "_token";
|
||||||
@@ -51,18 +92,151 @@ static const float kStandardImportance = 0.9f;
|
|||||||
static const float kListenerImportance = 0.8f;
|
static const float kListenerImportance = 0.8f;
|
||||||
|
|
||||||
|
|
||||||
|
EventDispatcher::Target::Target(const BMessenger& messenger)
|
||||||
|
:
|
||||||
|
fListeners(2, true),
|
||||||
|
fMessenger(messenger),
|
||||||
|
fFocusOrLastFocus(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EventDispatcher::Target::~Target()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EventDispatcher::event_listener*
|
||||||
|
EventDispatcher::Target::FindListener(int32 token, int32* _index)
|
||||||
|
{
|
||||||
|
for (int32 i = fListeners.CountItems(); i-- > 0;) {
|
||||||
|
event_listener* listener = fListeners.ItemAt(i);
|
||||||
|
|
||||||
|
if (listener->token == token) {
|
||||||
|
if (_index)
|
||||||
|
*_index = i;
|
||||||
|
return listener;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
EventDispatcher::Target::_RemoveTemporaryListener(event_listener* listener, int32 index)
|
||||||
|
{
|
||||||
|
if (listener->event_mask == 0) {
|
||||||
|
// this is only a temporary target
|
||||||
|
ETRACE(("events: remove temp. listener: token %ld, eventMask = %ld, options = %ld\n",
|
||||||
|
listener->token, listener->temporary_event_mask, listener->temporary_options));
|
||||||
|
|
||||||
|
fListeners.RemoveItemAt(index);
|
||||||
|
delete listener;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listener->temporary_event_mask != 0) {
|
||||||
|
ETRACE(("events: clear temp. listener: token %ld, eventMask = %ld, options = %ld\n",
|
||||||
|
listener->token, listener->temporary_event_mask, listener->temporary_options));
|
||||||
|
|
||||||
|
listener->temporary_event_mask = 0;
|
||||||
|
listener->temporary_options = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
EventDispatcher::Target::RemoveTemporaryListeners()
|
||||||
|
{
|
||||||
|
for (int32 index = CountListeners(); index-- > 0;) {
|
||||||
|
event_listener* listener = ListenerAt(index);
|
||||||
|
|
||||||
|
_RemoveTemporaryListener(listener, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
EventDispatcher::Target::RemoveTemporaryListener(int32 token)
|
||||||
|
{
|
||||||
|
int32 index;
|
||||||
|
event_listener* listener = FindListener(token, &index);
|
||||||
|
if (listener == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return _RemoveTemporaryListener(listener, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
EventDispatcher::Target::RemoveListener(int32 token)
|
||||||
|
{
|
||||||
|
int32 index;
|
||||||
|
event_listener* listener = FindListener(token, &index);
|
||||||
|
if (listener == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (listener->temporary_event_mask != 0) {
|
||||||
|
// we still need this event
|
||||||
|
listener->event_mask = 0;
|
||||||
|
listener->options = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fListeners.RemoveItemAt(index);
|
||||||
|
delete listener;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
EventDispatcher::Target::AddListener(int32 token, uint32 eventMask,
|
||||||
|
uint32 options, bool temporary)
|
||||||
|
{
|
||||||
|
event_listener* listener = new (std::nothrow) event_listener;
|
||||||
|
if (listener == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
listener->token = token;
|
||||||
|
|
||||||
|
if (temporary) {
|
||||||
|
listener->event_mask = 0;
|
||||||
|
listener->options = 0;
|
||||||
|
listener->temporary_event_mask = eventMask;
|
||||||
|
listener->temporary_options = options;
|
||||||
|
} else {
|
||||||
|
listener->event_mask = eventMask;
|
||||||
|
listener->options = options;
|
||||||
|
listener->temporary_event_mask = 0;
|
||||||
|
listener->temporary_options = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success = fListeners.AddItem(listener);
|
||||||
|
if (!success)
|
||||||
|
delete listener;
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
EventDispatcher::EventDispatcher()
|
EventDispatcher::EventDispatcher()
|
||||||
: BLocker("event dispatcher"),
|
: BLocker("event dispatcher"),
|
||||||
fStream(NULL),
|
fStream(NULL),
|
||||||
fThread(-1),
|
fThread(-1),
|
||||||
fCursorThread(-1),
|
fCursorThread(-1),
|
||||||
fHasFocus(false),
|
fFocus(NULL),
|
||||||
fHasLastFocus(false),
|
fLastFocus(NULL),
|
||||||
fTransit(false),
|
fTransit(false),
|
||||||
fSuspendFocus(false),
|
fSuspendFocus(false),
|
||||||
fMouseFilter(NULL),
|
fMouseFilter(NULL),
|
||||||
fKeyboardFilter(NULL),
|
fKeyboardFilter(NULL),
|
||||||
fListeners(10, true),
|
fTargets(10, true),
|
||||||
// the list owns its items
|
// the list owns its items
|
||||||
fCursorLock("cursor loop lock"),
|
fCursorLock("cursor loop lock"),
|
||||||
fHWInterface(NULL)
|
fHWInterface(NULL)
|
||||||
@@ -145,50 +319,63 @@ EventDispatcher::_Run()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
EventDispatcher::_UnsetLastFocus()
|
||||||
|
{
|
||||||
|
if (fLastFocus == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fLastFocus->SetFocusOrLastFocus(false);
|
||||||
|
if (!fLastFocus->IsNeeded())
|
||||||
|
_RemoveTarget(fLastFocus);
|
||||||
|
|
||||||
|
fLastFocus = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
EventDispatcher::SetFocus(const BMessenger* messenger)
|
EventDispatcher::SetFocus(const BMessenger* messenger)
|
||||||
{
|
{
|
||||||
BAutolock _(this);
|
BAutolock _(this);
|
||||||
|
ETRACE(("EventDispatcher::SetFocus(messenger = %p)\n", messenger));
|
||||||
|
|
||||||
if ((messenger == NULL && !fHasFocus)
|
if ((messenger == NULL && fFocus == NULL)
|
||||||
|| (messenger != NULL && fFocus == *messenger))
|
|| (messenger != NULL && fFocus != NULL && fFocus->Messenger() == *messenger))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fHasLastFocus = fHasFocus;
|
// update last focus
|
||||||
fLastFocusTokens.MakeEmpty();
|
|
||||||
|
|
||||||
if (fHasFocus) {
|
if (fLastFocus != NULL)
|
||||||
fLastFocus = fFocus;
|
_UnsetLastFocus();
|
||||||
fLastFocusTokens.AddList(&fFocusTokens);
|
|
||||||
}
|
|
||||||
|
|
||||||
fHasFocus = messenger != NULL;
|
fLastFocus = fFocus;
|
||||||
fFocusTokens.MakeEmpty();
|
|
||||||
|
|
||||||
if (fHasFocus) {
|
// update focus
|
||||||
fFocus = *messenger;
|
|
||||||
|
|
||||||
// add all tokens that target this messenger
|
if (messenger != NULL) {
|
||||||
for (int32 i = fListeners.CountItems(); i-- > 0;) {
|
fFocus = _FindTarget(*messenger);
|
||||||
event_target* target = fListeners.ItemAt(i);
|
if (fFocus == NULL) {
|
||||||
|
// we need a new target for this focus
|
||||||
if (target->messenger == fFocus)
|
fFocus = _AddTarget(*messenger);
|
||||||
fFocusTokens.AddItem((void *)target->token);
|
if (fFocus == NULL)
|
||||||
|
printf("EventDispatcher: could not set focus!\n");
|
||||||
}
|
}
|
||||||
}
|
if (fFocus != NULL)
|
||||||
|
fFocus->SetFocusOrLastFocus(true);
|
||||||
|
} else
|
||||||
|
fFocus = NULL;
|
||||||
|
|
||||||
fTransit = true;
|
fTransit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EventDispatcher::event_target*
|
EventDispatcher::Target*
|
||||||
EventDispatcher::_FindListener(const BMessenger& messenger, int32 token,
|
EventDispatcher::_FindTarget(const BMessenger& messenger, int32* _index)
|
||||||
int32* _index)
|
|
||||||
{
|
{
|
||||||
for (int32 i = fListeners.CountItems(); i-- > 0;) {
|
for (int32 i = fTargets.CountItems(); i-- > 0;) {
|
||||||
event_target* target = fListeners.ItemAt(i);
|
Target* target = fTargets.ItemAt(i);
|
||||||
|
|
||||||
if (target->token == token && target->messenger == messenger) {
|
if (target->Messenger() == messenger) {
|
||||||
if (_index)
|
if (_index)
|
||||||
*_index = i;
|
*_index = i;
|
||||||
return target;
|
return target;
|
||||||
@@ -199,6 +386,34 @@ EventDispatcher::_FindListener(const BMessenger& messenger, int32 token,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Adds the specified listener or updates its event mask and options
|
\brief Adds the specified listener or updates its event mask and options
|
||||||
if already added.
|
if already added.
|
||||||
@@ -211,17 +426,25 @@ EventDispatcher::_AddListener(const BMessenger& messenger, int32 token,
|
|||||||
uint32 eventMask, uint32 options, bool temporary)
|
uint32 eventMask, uint32 options, bool temporary)
|
||||||
{
|
{
|
||||||
BAutolock _(this);
|
BAutolock _(this);
|
||||||
event_target* target = _FindListener(messenger, token);
|
Target* target = _FindTarget(messenger);
|
||||||
if (target != NULL) {
|
if (target == NULL) {
|
||||||
|
// we need a new target for this messenger
|
||||||
|
target = _AddTarget(messenger);
|
||||||
|
if (target == NULL)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
event_listener* listener = target->FindListener(token);
|
||||||
|
if (listener != NULL) {
|
||||||
// we already have this target, update its event mask
|
// we already have this target, update its event mask
|
||||||
if (temporary) {
|
if (temporary) {
|
||||||
if (eventMask != 0)
|
if (eventMask != 0)
|
||||||
target->temporary_event_mask = eventMask;
|
listener->temporary_event_mask = eventMask;
|
||||||
target->temporary_options = options;
|
listener->temporary_options = options;
|
||||||
} else {
|
} else {
|
||||||
if (eventMask != 0)
|
if (eventMask != 0)
|
||||||
target->event_mask = eventMask;
|
listener->event_mask = eventMask;
|
||||||
target->options = options;
|
listener->options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -235,76 +458,26 @@ EventDispatcher::_AddListener(const BMessenger& messenger, int32 token,
|
|||||||
|
|
||||||
// we need a new target
|
// we need a new target
|
||||||
|
|
||||||
target = new (std::nothrow) event_target;
|
bool success = target->AddListener(token, eventMask, options, temporary);
|
||||||
if (target == NULL)
|
if (!success) {
|
||||||
return false;
|
if (!target->IsNeeded())
|
||||||
|
_RemoveTarget(target);
|
||||||
target->messenger = messenger;
|
} else {
|
||||||
target->token = token;
|
|
||||||
|
|
||||||
if (temporary) {
|
|
||||||
target->event_mask = 0;
|
|
||||||
target->options = 0;
|
|
||||||
target->temporary_event_mask = eventMask;
|
|
||||||
target->temporary_options = options;
|
|
||||||
if (options & B_SUSPEND_VIEW_FOCUS)
|
if (options & B_SUSPEND_VIEW_FOCUS)
|
||||||
fSuspendFocus = true;
|
fSuspendFocus = true;
|
||||||
} else {
|
|
||||||
target->event_mask = eventMask;
|
|
||||||
target->options = options;
|
|
||||||
target->temporary_event_mask = 0;
|
|
||||||
target->temporary_options = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool success = fListeners.AddItem(target);
|
|
||||||
if (success) {
|
|
||||||
if (fHasFocus && fFocus == messenger) {
|
|
||||||
// add this token to the current token list
|
|
||||||
ETRACE((" add token %ld to focus list\n", token));
|
|
||||||
fFocusTokens.AddItem((void *)token);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
delete target;
|
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
EventDispatcher::_RemoveTemporaryListener(event_target* target, int32 index)
|
|
||||||
{
|
|
||||||
if (target->event_mask == 0) {
|
|
||||||
// this is only a temporary target
|
|
||||||
fListeners.RemoveItemAt(index);
|
|
||||||
|
|
||||||
ETRACE(("events: remove temp. listener: token %ld, eventMask = %ld, options = %ld\n",
|
|
||||||
target->token, target->temporary_event_mask, target->temporary_options));
|
|
||||||
|
|
||||||
if (fHasFocus && fFocus == target->messenger) {
|
|
||||||
// remove this token from the current token list
|
|
||||||
ETRACE((" remove token %ld from focus list\n",
|
|
||||||
target->token));
|
|
||||||
fFocusTokens.RemoveItem((void *)target->token);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete target;
|
|
||||||
} else if (target->temporary_event_mask != 0) {
|
|
||||||
ETRACE(("events: clear temp. listener: token %ld, eventMask = %ld, options = %ld\n",
|
|
||||||
target->token, target->temporary_event_mask, target->temporary_options));
|
|
||||||
|
|
||||||
target->temporary_event_mask = 0;
|
|
||||||
target->temporary_options = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
EventDispatcher::_RemoveTemporaryListeners()
|
EventDispatcher::_RemoveTemporaryListeners()
|
||||||
{
|
{
|
||||||
for (int32 i = fListeners.CountItems(); i-- > 0;) {
|
for (int32 i = fTargets.CountItems(); i-- > 0;) {
|
||||||
event_target* target = fListeners.ItemAt(i);
|
Target* target = fTargets.ItemAt(i);
|
||||||
|
|
||||||
_RemoveTemporaryListener(target, i);
|
target->RemoveTemporaryListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,26 +508,14 @@ EventDispatcher::RemoveListener(const BMessenger& messenger, int32 token)
|
|||||||
ETRACE(("events: remove listener token %ld\n", token));
|
ETRACE(("events: remove listener token %ld\n", token));
|
||||||
|
|
||||||
int32 index;
|
int32 index;
|
||||||
event_target* target = _FindListener(messenger, token, &index);
|
Target* target = _FindTarget(messenger, &index);
|
||||||
if (target == NULL)
|
if (target == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (target->temporary_event_mask != 0) {
|
if (target->RemoveListener(token) && !target->IsNeeded()) {
|
||||||
// we still need this event
|
fTargets.RemoveItemAt(index);
|
||||||
target->event_mask = 0;
|
delete target;
|
||||||
target->options = 0;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fHasFocus && fFocus == target->messenger) {
|
|
||||||
// remove this token from the current token list
|
|
||||||
ETRACE((" remove token %ld from focus list\n",
|
|
||||||
target->token));
|
|
||||||
fFocusTokens.RemoveItem((void *)target->token);
|
|
||||||
}
|
|
||||||
|
|
||||||
fListeners.RemoveItemAt(index);
|
|
||||||
delete target;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -364,11 +525,14 @@ EventDispatcher::RemoveTemporaryListener(const BMessenger& messenger, int32 toke
|
|||||||
BAutolock _(this);
|
BAutolock _(this);
|
||||||
|
|
||||||
int32 index;
|
int32 index;
|
||||||
event_target* target = _FindListener(messenger, token, &index);
|
Target* target = _FindTarget(messenger, &index);
|
||||||
if (target == NULL)
|
if (target == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_RemoveTemporaryListener(target, index);
|
if (target->RemoveTemporaryListener(token) && !target->IsNeeded()) {
|
||||||
|
fTargets.RemoveItemAt(index);
|
||||||
|
delete target;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -428,6 +592,9 @@ EventDispatcher::SetHWInterface(HWInterface* interface)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Message methods
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Sends \a message to the provided \a messenger.
|
\brief Sends \a message to the provided \a messenger.
|
||||||
|
|
||||||
@@ -459,16 +626,21 @@ EventDispatcher::_SendMessage(BMessenger& messenger, BMessage* message,
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
EventDispatcher::_AddTokens(BMessage* message, BList& tokens)
|
EventDispatcher::_AddTokens(BMessage* message, Target* target, uint32 eventMask)
|
||||||
{
|
{
|
||||||
_RemoveTokens(message);
|
_RemoveTokens(message);
|
||||||
|
|
||||||
int32 count = tokens.CountItems();
|
int32 count = target->CountListeners();
|
||||||
for (int32 i = count; i-- > 0;) {
|
for (int32 i = count; i-- > 0;) {
|
||||||
int32 token = (int32)tokens.ItemAt(i);
|
event_listener* listener = target->ListenerAt(i);
|
||||||
ETRACE((" add token %ld\n", token));
|
if ((listener->EffectiveEventMask() & eventMask) == 0) {
|
||||||
|
count--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (message->AddInt32(kTokenName, token) != B_OK)
|
ETRACE((" add token %ld\n", listener->token));
|
||||||
|
|
||||||
|
if (message->AddInt32(kTokenName, listener->token) != B_OK)
|
||||||
count--;
|
count--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -506,6 +678,9 @@ EventDispatcher::_UnsetFeedFocus(BMessage* message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Event loops
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
EventDispatcher::_EventLoop()
|
EventDispatcher::_EventLoop()
|
||||||
{
|
{
|
||||||
@@ -522,7 +697,6 @@ EventDispatcher::_EventLoop()
|
|||||||
bool sendToLastFocus = false;
|
bool sendToLastFocus = false;
|
||||||
bool pointerEvent = false;
|
bool pointerEvent = false;
|
||||||
bool keyboardEvent = false;
|
bool keyboardEvent = false;
|
||||||
bool addedTransit = false;
|
|
||||||
bool addedTokens = false;
|
bool addedTokens = false;
|
||||||
|
|
||||||
switch (event->what) {
|
switch (event->what) {
|
||||||
@@ -540,18 +714,17 @@ EventDispatcher::_EventLoop()
|
|||||||
if (fTransit) {
|
if (fTransit) {
|
||||||
// target has changed, we need to add the be:transit field
|
// target has changed, we need to add the be:transit field
|
||||||
// to the message
|
// to the message
|
||||||
if (fHasLastFocus) {
|
if (fLastFocus != NULL) {
|
||||||
addedTokens = _AddTokens(event, fLastFocusTokens);
|
addedTokens = _AddTokens(event, fLastFocus, B_POINTER_EVENTS);
|
||||||
_SendMessage(fLastFocus, event, kMouseTransitImportance);
|
_SendMessage(fLastFocus->Messenger(), event,
|
||||||
|
kMouseTransitImportance);
|
||||||
sendToLastFocus = true;
|
sendToLastFocus = true;
|
||||||
|
|
||||||
// we no longer need the last focus messenger
|
// we no longer need the last focus messenger
|
||||||
fHasLastFocus = false;
|
_UnsetLastFocus();
|
||||||
fLastFocusTokens.MakeEmpty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fTransit = false;
|
fTransit = false;
|
||||||
addedTransit = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BPoint where;
|
BPoint where;
|
||||||
@@ -562,6 +735,10 @@ EventDispatcher::_EventLoop()
|
|||||||
}
|
}
|
||||||
case B_MOUSE_DOWN:
|
case B_MOUSE_DOWN:
|
||||||
case B_MOUSE_UP:
|
case B_MOUSE_UP:
|
||||||
|
#ifdef TRACE_EVENTS
|
||||||
|
if (event->what != B_MOUSE_MOVED)
|
||||||
|
printf("mouse up/down event, focus = %p\n", fFocus);
|
||||||
|
#endif
|
||||||
if (fMouseFilter != NULL
|
if (fMouseFilter != NULL
|
||||||
&& fMouseFilter->Filter(event, NULL) == B_SKIP_MESSAGE) {
|
&& fMouseFilter->Filter(event, NULL) == B_SKIP_MESSAGE) {
|
||||||
// this is a work-around if the wrong B_MOUSE_UP
|
// this is a work-around if the wrong B_MOUSE_UP
|
||||||
@@ -586,11 +763,11 @@ EventDispatcher::_EventLoop()
|
|||||||
|
|
||||||
pointerEvent = true;
|
pointerEvent = true;
|
||||||
|
|
||||||
if (fHasFocus) {
|
if (fFocus != NULL) {
|
||||||
addedTokens |= _AddTokens(event, fFocusTokens);
|
addedTokens |= _AddTokens(event, fFocus, B_POINTER_EVENTS);
|
||||||
if (addedTokens)
|
if (addedTokens)
|
||||||
_SetFeedFocus(event);
|
_SetFeedFocus(event);
|
||||||
_SendMessage(fFocus, event, event->what == B_MOUSE_MOVED
|
_SendMessage(fFocus->Messenger(), event, event->what == B_MOUSE_MOVED
|
||||||
? kMouseMovedImportance : kStandardImportance);
|
? kMouseMovedImportance : kStandardImportance);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -600,13 +777,15 @@ EventDispatcher::_EventLoop()
|
|||||||
case B_UNMAPPED_KEY_DOWN:
|
case B_UNMAPPED_KEY_DOWN:
|
||||||
case B_UNMAPPED_KEY_UP:
|
case B_UNMAPPED_KEY_UP:
|
||||||
case B_MODIFIERS_CHANGED:
|
case B_MODIFIERS_CHANGED:
|
||||||
|
ETRACE(("key event, focus = %p\n", fFocus));
|
||||||
|
|
||||||
if (fKeyboardFilter != NULL
|
if (fKeyboardFilter != NULL
|
||||||
&& fKeyboardFilter->Filter(event, NULL) == B_SKIP_MESSAGE)
|
&& fKeyboardFilter->Filter(event, NULL) == B_SKIP_MESSAGE)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
keyboardEvent = true;
|
keyboardEvent = true;
|
||||||
|
|
||||||
if (fHasFocus && _AddTokens(event, fFocusTokens)) {
|
if (fFocus != NULL && _AddTokens(event, fFocus, B_KEYBOARD_EVENTS)) {
|
||||||
// if tokens were added, we need to explicetly suspend
|
// if tokens were added, we need to explicetly suspend
|
||||||
// focus in the event - if not, the event is simply not
|
// focus in the event - if not, the event is simply not
|
||||||
// forwarded to the target
|
// forwarded to the target
|
||||||
@@ -619,8 +798,8 @@ EventDispatcher::_EventLoop()
|
|||||||
// supposed to fall through
|
// supposed to fall through
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (fHasFocus && (!fSuspendFocus || addedTokens))
|
if (fFocus != NULL && (!fSuspendFocus || addedTokens))
|
||||||
_SendMessage(fFocus, event, kStandardImportance);
|
_SendMessage(fFocus->Messenger(), event, kStandardImportance);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,26 +816,22 @@ EventDispatcher::_EventLoop()
|
|||||||
event->RemoveName("_view_token");
|
event->RemoveName("_view_token");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int32 i = fListeners.CountItems(); i-- > 0;) {
|
for (int32 i = fTargets.CountItems(); i-- > 0;) {
|
||||||
event_target* target = fListeners.ItemAt(i);
|
Target* target = fTargets.ItemAt(i);
|
||||||
|
|
||||||
// we already sent the event to the all focus and last focus tokens
|
// we already sent the event to the all focus and last focus tokens
|
||||||
if ((fHasFocus && target->messenger == fFocus)
|
if (fFocus == target || (sendToLastFocus && fLastFocus == target))
|
||||||
|| (sendToLastFocus && target->messenger == fLastFocus))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
uint32 effectiveEvents = target->event_mask | target->temporary_event_mask;
|
// don't send the message if there are no tokens for this event
|
||||||
|
if (!_AddTokens(event, target,
|
||||||
// make sure only those interested listeners get the message
|
keyboardEvent ? B_KEYBOARD_EVENTS : B_POINTER_EVENTS))
|
||||||
if ((keyboardEvent && (effectiveEvents & B_KEYBOARD_EVENTS) == 0)
|
|
||||||
|| (pointerEvent && (effectiveEvents & B_POINTER_EVENTS) == 0))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
_SetToken(event, target->token);
|
if (!_SendMessage(target->Messenger(), event, event->what == B_MOUSE_MOVED
|
||||||
if (!_SendMessage(target->messenger, event, event->what == B_MOUSE_MOVED
|
|
||||||
? kMouseMovedImportance : kListenerImportance)) {
|
? kMouseMovedImportance : kListenerImportance)) {
|
||||||
// the target doesn't seem to exist anymore, let's remove this target
|
// the target doesn't seem to exist anymore, let's remove it
|
||||||
fListeners.RemoveItemAt(i);
|
fTargets.RemoveItemAt(i);
|
||||||
delete target;
|
delete target;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,24 +45,31 @@ class EventDispatcher : public BLocker {
|
|||||||
void SetHWInterface(HWInterface* interface);
|
void SetHWInterface(HWInterface* interface);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct event_target;
|
struct event_listener;
|
||||||
|
class Target;
|
||||||
|
|
||||||
status_t _Run();
|
status_t _Run();
|
||||||
void _Unset();
|
void _Unset();
|
||||||
|
|
||||||
bool _SendMessage(BMessenger& messenger, BMessage* message, float importance);
|
bool _SendMessage(BMessenger& messenger, BMessage* message, float importance);
|
||||||
|
|
||||||
bool _AddTokens(BMessage* message, BList& tokens);
|
bool _AddTokens(BMessage* message, Target* target, uint32 eventMask);
|
||||||
void _RemoveTokens(BMessage* message);
|
void _RemoveTokens(BMessage* message);
|
||||||
void _SetToken(BMessage* message, int32 token);
|
void _SetToken(BMessage* message, int32 token);
|
||||||
void _SetFeedFocus(BMessage* message);
|
void _SetFeedFocus(BMessage* message);
|
||||||
void _UnsetFeedFocus(BMessage* message);
|
void _UnsetFeedFocus(BMessage* message);
|
||||||
|
|
||||||
event_target* _FindListener(const BMessenger& messenger, int32 token,
|
void _UnsetLastFocus();
|
||||||
|
|
||||||
|
Target* _FindTarget(const BMessenger& messenger, int32* _index = NULL);
|
||||||
|
Target* _AddTarget(const BMessenger& messenger);
|
||||||
|
void _RemoveTarget(Target* target);
|
||||||
|
|
||||||
|
event_listener* _FindListener(const BMessenger& messenger, int32 token,
|
||||||
int32* _index = NULL);
|
int32* _index = NULL);
|
||||||
bool _AddListener(const BMessenger& messenger, int32 token,
|
bool _AddListener(const BMessenger& messenger, int32 token,
|
||||||
uint32 eventMask, uint32 options, bool temporary);
|
uint32 eventMask, uint32 options, bool temporary);
|
||||||
void _RemoveTemporaryListener(event_target* target, int32 index);
|
// void _RemoveTemporaryListener(event_target* target, int32 index);
|
||||||
void _RemoveTemporaryListeners();
|
void _RemoveTemporaryListeners();
|
||||||
|
|
||||||
void _EventLoop();
|
void _EventLoop();
|
||||||
@@ -76,19 +83,15 @@ class EventDispatcher : public BLocker {
|
|||||||
thread_id fThread;
|
thread_id fThread;
|
||||||
thread_id fCursorThread;
|
thread_id fCursorThread;
|
||||||
|
|
||||||
BMessenger fFocus;
|
Target* fFocus;
|
||||||
BMessenger fLastFocus;
|
Target* fLastFocus;
|
||||||
bool fHasFocus;
|
|
||||||
bool fHasLastFocus;
|
|
||||||
bool fTransit;
|
bool fTransit;
|
||||||
BList fLastFocusTokens;
|
|
||||||
BList fFocusTokens;
|
|
||||||
bool fSuspendFocus;
|
bool fSuspendFocus;
|
||||||
|
|
||||||
BMessageFilter* fMouseFilter;
|
BMessageFilter* fMouseFilter;
|
||||||
BMessageFilter* fKeyboardFilter;
|
BMessageFilter* fKeyboardFilter;
|
||||||
|
|
||||||
BObjectList<event_target> fListeners;
|
BObjectList<Target> fTargets;
|
||||||
|
|
||||||
BPoint fLastCursorPosition;
|
BPoint fLastCursorPosition;
|
||||||
int32 fLastButtons;
|
int32 fLastButtons;
|
||||||
|
|||||||
@@ -527,6 +527,12 @@ WinBorder::MouseUp(BMessage *msg, BPoint where)
|
|||||||
fIsDragging = false;
|
fIsDragging = false;
|
||||||
fIsResizing = false;
|
fIsResizing = false;
|
||||||
fIsSlidingTab = false;
|
fIsSlidingTab = false;
|
||||||
|
|
||||||
|
Layer* target = LayerAt(where);
|
||||||
|
if (target != NULL && target != this) {
|
||||||
|
msg->AddInt32("_view_token", target->ViewToken());
|
||||||
|
target->MouseUp(msg, where);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -574,6 +580,12 @@ WinBorder::MouseMoved(BMessage *msg, BPoint where)
|
|||||||
// What message? Is there a message on Focus change?
|
// What message? Is there a message on Focus change?
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Layer* target = LayerAt(where);
|
||||||
|
if (target != NULL && target != this) {
|
||||||
|
msg->AddInt32("_view_token", target->ViewToken());
|
||||||
|
target->MouseMoved(msg, where);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user