xref: /haiku/src/kits/app/Handler.cpp (revision 3be79a33b059ba22f25c7db93743b758717d8b68)
1  /*
2   * Copyright 2001-2014 Haiku, Inc. All rights reserved.
3   * Distributed under the terms of the MIT License.
4   *
5   * Authors:
6   *		Axel Dörfler, axeld@pinc-software.de
7   *		Erik Jaesler, erik@cgsoftware.com
8   */
9  
10  
11  #include <TokenSpace.h>
12  
13  #include <AppDefs.h>
14  #include <Handler.h>
15  #include <Looper.h>
16  #include <Message.h>
17  #include <MessageFilter.h>
18  #include <Messenger.h>
19  #include <PropertyInfo.h>
20  
21  #include <algorithm>
22  #include <new>
23  #include <stdlib.h>
24  #include <stdio.h>
25  #include <string.h>
26  #include <vector>
27  
28  using std::map;
29  using std::vector;
30  using BPrivate::gDefaultTokens;
31  
32  
33  static const char* kArchiveNameField = "_name";
34  
35  static const uint32 kMsgStartObserving = '_OBS';
36  static const uint32 kMsgStopObserving = '_OBP';
37  static const char* kObserveTarget = "be:observe_target";
38  
39  
40  static property_info sHandlerPropInfo[] = {
41  	{
42  		"Suites",					// name
43  		{ B_GET_PROPERTY },			// commands
44  		{ B_DIRECT_SPECIFIER },		// specifiers
45  		NULL,						// usage
46  		0,							// extra data
47  		{ 0 },						// types
48  		{							// ctypes (compound_type)
49  			{						// ctypes[0]
50  				{					// pairs[0]
51  					{
52  						"suites",		// name
53  						B_STRING_TYPE	// type
54  					}
55  				}
56  			},
57  			{						// ctypes[1]
58  				{					// pairs[0]
59  					{
60  						"messages",
61  						B_PROPERTY_INFO_TYPE
62  					}
63  				}
64  			}
65  		},
66  		{}		// reserved
67  	},
68  	{
69  		"Messenger",
70  			{ B_GET_PROPERTY },
71  			{ B_DIRECT_SPECIFIER },
72  			NULL, 0,
73  			{ B_MESSENGER_TYPE },
74  			{},
75  			{}
76  	},
77  	{
78  		"InternalName",
79  			{ B_GET_PROPERTY },
80  			{ B_DIRECT_SPECIFIER },
81  			NULL, 0,
82  			{ B_STRING_TYPE },
83  			{},
84  			{}
85  	},
86  
87  	{ 0 }
88  };
89  
90  bool FilterDeleter(void* filter);
91  
92  namespace BPrivate {
93  
94  class ObserverList {
95  	public:
96  		ObserverList();
97  		~ObserverList();
98  
99  		status_t SendNotices(uint32 what, const BMessage* notice);
100  		status_t Add(const BHandler* handler, uint32 what);
101  		status_t Add(const BMessenger& messenger, uint32 what);
102  		status_t Remove(const BHandler* handler, uint32 what);
103  		status_t Remove(const BMessenger& messenger, uint32 what);
104  		bool IsEmpty();
105  
106  	private:
107  		typedef map<uint32, vector<const BHandler*> > HandlerObserverMap;
108  		typedef map<uint32, vector<BMessenger> > MessengerObserverMap;
109  
110  		void _ValidateHandlers(uint32 what);
111  		void _SendNotices(uint32 what, BMessage* notice);
112  
113  		HandlerObserverMap		fHandlerMap;
114  		MessengerObserverMap	fMessengerMap;
115  };
116  
117  }	// namespace BPrivate
118  
119  using namespace BPrivate;
120  
121  
122  //	#pragma mark -
123  
124  
125  BHandler::BHandler(const char* name)
126  	: BArchivable(),
127  	fName(NULL)
128  {
129  	_InitData(name);
130  }
131  
132  
133  BHandler::~BHandler()
134  {
135  	if (LockLooper()) {
136  		BLooper* looper = Looper();
137  		looper->RemoveHandler(this);
138  		looper->Unlock();
139  	}
140  
141  	// remove all filters
142  	if (fFilters) {
143  		int32 count = fFilters->CountItems();
144  		for (int32 i = 0; i < count; i++)
145  			delete (BMessageFilter*)fFilters->ItemAtFast(i);
146  		delete fFilters;
147  	}
148  
149  	// remove all observers (the observer list manages itself)
150  	delete fObserverList;
151  
152  	// free rest
153  	free(fName);
154  	gDefaultTokens.RemoveToken(fToken);
155  }
156  
157  
158  BHandler::BHandler(BMessage* data)
159  	: BArchivable(data),
160  	fName(NULL)
161  {
162  	const char* name = NULL;
163  
164  	if (data)
165  		data->FindString(kArchiveNameField, &name);
166  
167  	_InitData(name);
168  }
169  
170  
171  BArchivable*
172  BHandler::Instantiate(BMessage* data)
173  {
174  	if (!validate_instantiation(data, "BHandler"))
175  		return NULL;
176  
177  	return new BHandler(data);
178  }
179  
180  
181  status_t
182  BHandler::Archive(BMessage* data, bool deep) const
183  {
184  	status_t status = BArchivable::Archive(data, deep);
185  	if (status < B_OK)
186  		return status;
187  
188  	if (fName == NULL)
189  		return B_OK;
190  
191  	return data->AddString(kArchiveNameField, fName);
192  }
193  
194  
195  void
196  BHandler::MessageReceived(BMessage* message)
197  {
198  	BMessage reply(B_REPLY);
199  
200  	switch (message->what) {
201  		case kMsgStartObserving:
202  		case kMsgStopObserving:
203  		{
204  			BMessenger target;
205  			uint32 what;
206  			if (message->FindMessenger(kObserveTarget, &target) != B_OK
207  				|| message->FindInt32(B_OBSERVE_WHAT_CHANGE, (int32*)&what)
208  					!= B_OK) {
209  				break;
210  			}
211  
212  			ObserverList* list = _ObserverList();
213  			if (list != NULL) {
214  				if (message->what == kMsgStartObserving)
215  					list->Add(target, what);
216  				else
217  					list->Remove(target, what);
218  			}
219  			break;
220  		}
221  
222  		case B_GET_PROPERTY:
223  		{
224  			int32 cur;
225  			BMessage specifier;
226  			int32 form;
227  			const char* prop;
228  
229  			status_t err = message->GetCurrentSpecifier(&cur, &specifier,
230  				&form, &prop);
231  			if (err != B_OK && err != B_BAD_SCRIPT_SYNTAX)
232  				break;
233  			bool known = false;
234  			// B_BAD_SCRIPT_SYNTAX defaults to the Messenger property
235  			if (err == B_BAD_SCRIPT_SYNTAX || cur < 0
236  				|| (strcmp(prop, "Messenger") == 0)) {
237  				err = reply.AddMessenger("result", this);
238  				known = true;
239  			} else if (strcmp(prop, "Suites") == 0) {
240  				err = GetSupportedSuites(&reply);
241  				known = true;
242  			} else if (strcmp(prop, "InternalName") == 0) {
243  				err = reply.AddString("result", Name());
244  				known = true;
245  			}
246  
247  			if (known) {
248  				reply.AddInt32("error", B_OK);
249  				message->SendReply(&reply);
250  				return;
251  			}
252  			// let's try next handler
253  			break;
254  		}
255  
256  		case B_GET_SUPPORTED_SUITES:
257  		{
258  			reply.AddInt32("error", GetSupportedSuites(&reply));
259  			message->SendReply(&reply);
260  			return;
261  		}
262  	}
263  
264  	// ToDo: there is some more work needed here
265  	// (someone in the know should fill in)!
266  
267  	if (fNextHandler) {
268  		// we need to apply the next handler's filters here, too
269  		BHandler* target = Looper()->_HandlerFilter(message, fNextHandler);
270  		if (target != NULL && target != this) {
271  			// TODO: we also need to make sure that "target" is not before
272  			//	us in the handler chain - at least in case it wasn't before
273  			//	the handler actually targeted with this message - this could
274  			//	get ugly, though.
275  			target->MessageReceived(message);
276  		}
277  	} else if (message->what != B_MESSAGE_NOT_UNDERSTOOD
278  		&& (message->WasDropped() || message->HasSpecifiers())) {
279  		printf("BHandler %s: MessageReceived() couldn't understand the message:\n", Name());
280  		message->PrintToStream();
281  		message->SendReply(B_MESSAGE_NOT_UNDERSTOOD);
282  	}
283  }
284  
285  
286  BLooper*
287  BHandler::Looper() const
288  {
289  	return fLooper;
290  }
291  
292  
293  void
294  BHandler::SetName(const char* name)
295  {
296  	if (fName != NULL) {
297  		free(fName);
298  		fName = NULL;
299  	}
300  
301  	if (name != NULL)
302  		fName = strdup(name);
303  }
304  
305  
306  const char*
307  BHandler::Name() const
308  {
309  	return fName;
310  }
311  
312  
313  void
314  BHandler::SetNextHandler(BHandler* handler)
315  {
316  	if (fLooper == NULL) {
317  		debugger("handler must belong to looper before setting NextHandler");
318  		return;
319  	}
320  
321  	if (!fLooper->IsLocked()) {
322  		debugger("The handler's looper must be locked before setting NextHandler");
323  		return;
324  	}
325  
326  	if (handler != NULL && fLooper != handler->Looper()) {
327  		debugger("The handler and its NextHandler must have the same looper");
328  		return;
329  	}
330  
331  	fNextHandler = handler;
332  }
333  
334  
335  BHandler*
336  BHandler::NextHandler() const
337  {
338  	return fNextHandler;
339  }
340  
341  
342  void
343  BHandler::AddFilter(BMessageFilter* filter)
344  {
345  	BLooper* looper = fLooper;
346  	if (looper != NULL && !looper->IsLocked()) {
347  		debugger("Owning Looper must be locked before calling SetFilterList");
348  		return;
349  	}
350  
351  	if (looper != NULL)
352  		filter->SetLooper(looper);
353  
354  	if (fFilters == NULL)
355  		fFilters = new BList;
356  
357  	fFilters->AddItem(filter);
358  }
359  
360  
361  bool
362  BHandler::RemoveFilter(BMessageFilter* filter)
363  {
364  	BLooper* looper = fLooper;
365  	if (looper != NULL && !looper->IsLocked()) {
366  		debugger("Owning Looper must be locked before calling SetFilterList");
367  		return false;
368  	}
369  
370  	if (fFilters != NULL && fFilters->RemoveItem((void*)filter)) {
371  		filter->SetLooper(NULL);
372  		return true;
373  	}
374  
375  	return false;
376  }
377  
378  
379  void
380  BHandler::SetFilterList(BList* filters)
381  {
382  	BLooper* looper = fLooper;
383  	if (looper != NULL && !looper->IsLocked()) {
384  		debugger("Owning Looper must be locked before calling SetFilterList");
385  		return;
386  	}
387  
388  	/**
389  		@note	I would like to use BObjectList internally, but this function is
390  				spec'd such that fFilters would get deleted and then assigned
391  				'filters', which would obviously mess this up.  Wondering if
392  				anyone ever assigns a list of filters and then checks against
393  				FilterList() to see if they are the same.
394  	 */
395  
396  	// TODO: Explore issues with using BObjectList
397  	if (fFilters != NULL) {
398  		fFilters->DoForEach(FilterDeleter);
399  		delete fFilters;
400  	}
401  
402  	fFilters = filters;
403  	if (fFilters) {
404  		for (int32 i = 0; i < fFilters->CountItems(); ++i) {
405  			BMessageFilter* filter =
406  				static_cast<BMessageFilter*>(fFilters->ItemAt(i));
407  			if (filter != NULL)
408  				filter->SetLooper(looper);
409  		}
410  	}
411  }
412  
413  
414  BList*
415  BHandler::FilterList()
416  {
417  	return fFilters;
418  }
419  
420  
421  bool
422  BHandler::LockLooper()
423  {
424  	BLooper* looper = fLooper;
425  	// Locking the looper also makes sure that the looper is valid
426  	if (looper != NULL && looper->Lock()) {
427  		// Have we locked the right looper? That's as far as the
428  		// "pseudo-atomic" operation mentioned in the BeBook.
429  		if (fLooper == looper)
430  			return true;
431  
432  		// we locked the wrong looper, bail out
433  		looper->Unlock();
434  	}
435  
436  	return false;
437  }
438  
439  
440  status_t
441  BHandler::LockLooperWithTimeout(bigtime_t timeout)
442  {
443  	BLooper* looper = fLooper;
444  	if (looper == NULL)
445  		return B_BAD_VALUE;
446  
447  	status_t status = looper->LockWithTimeout(timeout);
448  	if (status != B_OK)
449  		return status;
450  
451  	if (fLooper != looper) {
452  		// we locked the wrong looper, bail out
453  		looper->Unlock();
454  		return B_MISMATCHED_VALUES;
455  	}
456  
457  	return B_OK;
458  }
459  
460  
461  void
462  BHandler::UnlockLooper()
463  {
464  	fLooper->Unlock();
465  }
466  
467  
468  BHandler*
469  BHandler::ResolveSpecifier(BMessage* message, int32 index,
470  	BMessage* specifier, int32 what, const char* property)
471  {
472  	// Straight from the BeBook
473  	BPropertyInfo propertyInfo(sHandlerPropInfo);
474  	if (propertyInfo.FindMatch(message, index, specifier, what, property) >= 0)
475  		return this;
476  
477  	BMessage reply(B_MESSAGE_NOT_UNDERSTOOD);
478  	reply.AddInt32("error", B_BAD_SCRIPT_SYNTAX);
479  	reply.AddString("message", "Didn't understand the specifier(s)");
480  	message->SendReply(&reply);
481  
482  	return NULL;
483  }
484  
485  
486  status_t
487  BHandler::GetSupportedSuites(BMessage* data)
488  {
489  /**
490  	@note	This is the output from the original implementation (calling
491  			PrintToStream() on both data and the contained BPropertyInfo):
492  
493  BMessage: what =  (0x0, or 0)
494  	entry         suites, type='CSTR', c=1, size=21, data[0]: "suite/vnd.Be-handler"
495  	entry       messages, type='SCTD', c=1, size= 0,
496  	  property   commands                       types                specifiers
497  --------------------------------------------------------------------------------
498  		Suites   PGET                                               1
499  				 (RTSC,suites)
500  				 (DTCS,messages)
501  
502  	 Messenger   PGET                          GNSM                 1
503    InternalName   PGET                          RTSC                 1
504  
505  			With a good deal of trial and error, I determined that the
506  			parenthetical clauses are entries in the 'ctypes' field of
507  			property_info.  'ctypes' is an array of 'compound_type', which
508  			contains an array of 'field_pair's.  I haven't the foggiest what
509  			either 'compound_type' or 'field_pair' is for, being as the
510  			scripting docs are so bloody horrible.  The corresponding
511  			property_info array is declared in the globals section.
512   */
513  
514  	if (data == NULL)
515  		return B_BAD_VALUE;
516  
517  	status_t result = data->AddString("suites", "suite/vnd.Be-handler");
518  	if (result == B_OK) {
519  		BPropertyInfo propertyInfo(sHandlerPropInfo);
520  		result = data->AddFlat("messages", &propertyInfo);
521  	}
522  
523  	return result;
524  }
525  
526  
527  status_t
528  BHandler::StartWatching(BMessenger target, uint32 what)
529  {
530  	BMessage message(kMsgStartObserving);
531  	message.AddMessenger(kObserveTarget, this);
532  	message.AddInt32(B_OBSERVE_WHAT_CHANGE, what);
533  
534  	return target.SendMessage(&message);
535  }
536  
537  
538  status_t
539  BHandler::StartWatchingAll(BMessenger target)
540  {
541  	return StartWatching(target, B_OBSERVER_OBSERVE_ALL);
542  }
543  
544  
545  status_t
546  BHandler::StopWatching(BMessenger target, uint32 what)
547  {
548  	BMessage message(kMsgStopObserving);
549  	message.AddMessenger(kObserveTarget, this);
550  	message.AddInt32(B_OBSERVE_WHAT_CHANGE, what);
551  
552  	return target.SendMessage(&message);
553  }
554  
555  
556  status_t
557  BHandler::StopWatchingAll(BMessenger target)
558  {
559  	return StopWatching(target, B_OBSERVER_OBSERVE_ALL);
560  }
561  
562  
563  status_t
564  BHandler::StartWatching(BHandler* handler, uint32 what)
565  {
566  	ObserverList* list = _ObserverList();
567  	if (list == NULL)
568  		return B_NO_MEMORY;
569  
570  	return list->Add(handler, what);
571  }
572  
573  
574  status_t
575  BHandler::StartWatchingAll(BHandler* handler)
576  {
577  	return StartWatching(handler, B_OBSERVER_OBSERVE_ALL);
578  }
579  
580  
581  status_t
582  BHandler::StopWatching(BHandler* handler, uint32 what)
583  {
584  	ObserverList* list = _ObserverList();
585  	if (list == NULL)
586  		return B_NO_MEMORY;
587  
588  	return list->Remove(handler, what);
589  }
590  
591  
592  status_t
593  BHandler::StopWatchingAll(BHandler* handler)
594  {
595  	return StopWatching(handler, B_OBSERVER_OBSERVE_ALL);
596  }
597  
598  
599  status_t
600  BHandler::Perform(perform_code d, void* arg)
601  {
602  	return BArchivable::Perform(d, arg);
603  }
604  
605  
606  void
607  BHandler::SendNotices(uint32 what, const BMessage* notice)
608  {
609  	if (fObserverList != NULL)
610  		fObserverList->SendNotices(what, notice);
611  }
612  
613  
614  bool
615  BHandler::IsWatched() const
616  {
617  	return fObserverList && !fObserverList->IsEmpty();
618  }
619  
620  
621  void
622  BHandler::_InitData(const char* name)
623  {
624  	SetName(name);
625  
626  	fLooper = NULL;
627  	fNextHandler = NULL;
628  	fFilters = NULL;
629  	fObserverList = NULL;
630  
631  	fToken = gDefaultTokens.NewToken(B_HANDLER_TOKEN, this);
632  }
633  
634  
635  ObserverList*
636  BHandler::_ObserverList()
637  {
638  	if (fObserverList == NULL)
639  		fObserverList = new (std::nothrow) BPrivate::ObserverList();
640  
641  	return fObserverList;
642  }
643  
644  
645  void
646  BHandler::SetLooper(BLooper* looper)
647  {
648  	fLooper = looper;
649  	gDefaultTokens.SetHandlerTarget(fToken,
650  		looper ? looper->fDirectTarget : NULL);
651  
652  	if (fFilters != NULL) {
653  		for (int32 i = 0; i < fFilters->CountItems(); i++) {
654  			static_cast<BMessageFilter*>(
655  				fFilters->ItemAtFast(i))->SetLooper(looper);
656  		}
657  	}
658  }
659  
660  
661  #if __GNUC__ < 3
662  // binary compatibility with R4.5
663  
664  extern "C" void
665  _ReservedHandler1__8BHandler(BHandler* handler, uint32 what,
666  	const BMessage* notice)
667  {
668  	handler->BHandler::SendNotices(what, notice);
669  }
670  
671  
672  BHandler::BHandler(const BHandler &)
673  {
674  	// No copy construction allowed.
675  }
676  
677  
678  BHandler &
679  BHandler::operator=(const BHandler &)
680  {
681  	// No assignments allowed.
682  	return *this;
683  }
684  #endif
685  
686  void BHandler::_ReservedHandler2() {}
687  void BHandler::_ReservedHandler3() {}
688  void BHandler::_ReservedHandler4() {}
689  
690  
691  //	#pragma mark -
692  
693  
694  ObserverList::ObserverList()
695  {
696  }
697  
698  
699  ObserverList::~ObserverList()
700  {
701  }
702  
703  
704  void
705  ObserverList::_ValidateHandlers(uint32 what)
706  {
707  	vector<const BHandler*>& handlers = fHandlerMap[what];
708  	vector<const BHandler*>::iterator iterator = handlers.begin();
709  
710  	while (iterator != handlers.end()) {
711  		BMessenger target(*iterator);
712  		if (!target.IsValid()) {
713  			iterator++;
714  			continue;
715  		}
716  
717  		Add(target, what);
718  		iterator = handlers.erase(iterator);
719  	}
720  	if (handlers.empty())
721  		fHandlerMap.erase(what);
722  }
723  
724  
725  void
726  ObserverList::_SendNotices(uint32 what, BMessage* notice)
727  {
728  	// first iterate over the list of handlers and try to make valid
729  	// messengers out of them
730  	_ValidateHandlers(what);
731  
732  	// now send it to all messengers we know
733  	vector<BMessenger>& messengers = fMessengerMap[what];
734  	vector<BMessenger>::iterator iterator = messengers.begin();
735  
736  	while (iterator != messengers.end()) {
737  		if (!(*iterator).IsValid()) {
738  			iterator = messengers.erase(iterator);
739  			continue;
740  		}
741  
742  		(*iterator).SendMessage(notice);
743  		iterator++;
744  	}
745  	if (messengers.empty())
746  		fMessengerMap.erase(what);
747  }
748  
749  
750  status_t
751  ObserverList::SendNotices(uint32 what, const BMessage* notice)
752  {
753  	BMessage* copy = NULL;
754  	if (notice != NULL) {
755  		copy = new BMessage(*notice);
756  		copy->what = B_OBSERVER_NOTICE_CHANGE;
757  		copy->AddInt32(B_OBSERVE_ORIGINAL_WHAT, notice->what);
758  	} else
759  		copy = new BMessage(B_OBSERVER_NOTICE_CHANGE);
760  
761  	copy->AddInt32(B_OBSERVE_WHAT_CHANGE, what);
762  
763  	_SendNotices(what, copy);
764  	_SendNotices(B_OBSERVER_OBSERVE_ALL, copy);
765  
766  	delete copy;
767  
768  	return B_OK;
769  }
770  
771  
772  status_t
773  ObserverList::Add(const BHandler* handler, uint32 what)
774  {
775  	if (handler == NULL)
776  		return B_BAD_HANDLER;
777  
778  	// if this handler already represents a valid target, add its messenger
779  	BMessenger target(handler);
780  	if (target.IsValid())
781  		return Add(target, what);
782  
783  	vector<const BHandler*> &handlers = fHandlerMap[what];
784  
785  	vector<const BHandler*>::iterator iter;
786  	iter = find(handlers.begin(), handlers.end(), handler);
787  	if (iter != handlers.end()) {
788  		// TODO: do we want to have a reference count for this?
789  		return B_OK;
790  	}
791  
792  	handlers.push_back(handler);
793  	return B_OK;
794  }
795  
796  
797  status_t
798  ObserverList::Add(const BMessenger &messenger, uint32 what)
799  {
800  	vector<BMessenger> &messengers = fMessengerMap[what];
801  
802  	vector<BMessenger>::iterator iter;
803  	iter = find(messengers.begin(), messengers.end(), messenger);
804  	if (iter != messengers.end()) {
805  		// TODO: do we want to have a reference count for this?
806  		return B_OK;
807  	}
808  
809  	messengers.push_back(messenger);
810  	return B_OK;
811  }
812  
813  
814  status_t
815  ObserverList::Remove(const BHandler* handler, uint32 what)
816  {
817  	if (handler == NULL)
818  		return B_BAD_HANDLER;
819  
820  	// look into the list of messengers
821  	BMessenger target(handler);
822  	if (target.IsValid() && Remove(target, what) == B_OK)
823  		return B_OK;
824  
825  	status_t status = B_BAD_HANDLER;
826  
827  	vector<const BHandler*> &handlers = fHandlerMap[what];
828  
829  	vector<const BHandler*>::iterator iterator = find(handlers.begin(),
830  		handlers.end(), handler);
831  	if (iterator != handlers.end()) {
832  		handlers.erase(iterator);
833  		status = B_OK;
834  	}
835  	if (handlers.empty())
836  		fHandlerMap.erase(what);
837  
838  	return status;
839  }
840  
841  
842  status_t
843  ObserverList::Remove(const BMessenger &messenger, uint32 what)
844  {
845  	status_t status = B_BAD_HANDLER;
846  
847  	vector<BMessenger> &messengers = fMessengerMap[what];
848  
849  	vector<BMessenger>::iterator iterator = find(messengers.begin(),
850  		messengers.end(), messenger);
851  	if (iterator != messengers.end()) {
852  		messengers.erase(iterator);
853  		status = B_OK;
854  	}
855  	if (messengers.empty())
856  		fMessengerMap.erase(what);
857  
858  	return status;
859  }
860  
861  
862  bool
863  ObserverList::IsEmpty()
864  {
865  	return fHandlerMap.empty() && fMessengerMap.empty();
866  }
867  
868  
869  //	#pragma mark -
870  
871  
872  bool
873  FilterDeleter(void* _filter)
874  {
875  	delete static_cast<BMessageFilter*>(_filter);
876  	return false;
877  }
878