diff --git a/docs/user/app/LaunchRoster.dox b/docs/user/app/LaunchRoster.dox index 0eaf43864f..28dc7a3c2d 100644 --- a/docs/user/app/LaunchRoster.dox +++ b/docs/user/app/LaunchRoster.dox @@ -257,4 +257,23 @@ on { */ +/*! + \fn status_t BLaunchRoster::ResetStickyEvent(const BMessenger& source, + const char* name); + \brief Resets a previously triggered sticky event. + + When an event triggered that is marked as \c B_STICKY_EVENT, its status + will be reset when you call this method for it. + + You must have previously registered the event, in order to make the + launch_daemon do anything. Unknown event notifications will be ignored. + + \param source The messenger the event is coming from. + \param name The name of the event. + \return B_OK if the event could be reset, otherwise an error code. + + \since Haiku R1 +*/ + + //! @} diff --git a/headers/private/app/LaunchDaemonDefs.h b/headers/private/app/LaunchDaemonDefs.h index 9842f850f8..f0452847c5 100644 --- a/headers/private/app/LaunchDaemonDefs.h +++ b/headers/private/app/LaunchDaemonDefs.h @@ -31,6 +31,7 @@ enum { B_REGISTER_LAUNCH_EVENT = 'lnre', B_UNREGISTER_LAUNCH_EVENT = 'lnue', B_NOTIFY_LAUNCH_EVENT = 'lnne', + B_RESET_STICKY_LAUNCH_EVENT = 'lnRe', }; diff --git a/headers/private/app/LaunchRoster.h b/headers/private/app/LaunchRoster.h index 32e05e89e3..970b3120aa 100644 --- a/headers/private/app/LaunchRoster.h +++ b/headers/private/app/LaunchRoster.h @@ -42,6 +42,8 @@ public: const char* name); status_t NotifyEvent(const BMessenger& source, const char* name); + status_t ResetStickyEvent(const BMessenger& source, + const char* name); class Private; diff --git a/src/kits/app/LaunchRoster.cpp b/src/kits/app/LaunchRoster.cpp index dee7401322..eec0128555 100644 --- a/src/kits/app/LaunchRoster.cpp +++ b/src/kits/app/LaunchRoster.cpp @@ -227,6 +227,13 @@ BLaunchRoster::NotifyEvent(const BMessenger& source, const char* name) } +status_t +BLaunchRoster::ResetStickyEvent(const BMessenger& source, const char* name) +{ + return _UpdateEvent(B_RESET_STICKY_LAUNCH_EVENT, source, name); +} + + void BLaunchRoster::_InitMessenger() { diff --git a/src/servers/launch/Events.cpp b/src/servers/launch/Events.cpp index b25fc4bef2..e623aa4fc6 100644 --- a/src/servers/launch/Events.cpp +++ b/src/servers/launch/Events.cpp @@ -86,6 +86,7 @@ public: const BString& Name() const; bool Resolve(uint32 flags); + void ResetSticky(); virtual void ResetTrigger(); virtual status_t Register(EventRegistrator& registrator); @@ -457,12 +458,18 @@ ExternalEvent::Resolve(uint32 flags) void -ExternalEvent::ResetTrigger() +ExternalEvent::ResetSticky() { if ((fFlags & B_STICKY_EVENT) != 0) - return; + Event::ResetTrigger(); +} - Event::ResetTrigger(); + +void +ExternalEvent::ResetTrigger() +{ + if ((fFlags & B_STICKY_EVENT) == 0) + Event::ResetTrigger(); } @@ -642,6 +649,30 @@ Events::TriggerExternalEvent(Event* event, const char* name) } +/*static*/ void +Events::ResetStickyExternalEvent(Event* event, const char* name) +{ + if (event == NULL) + return; + + if (EventContainer* container = dynamic_cast(event)) { + for (int32 index = 0; index < container->Events().CountItems(); + index++) { + Event* event = container->Events().ItemAt(index); + if (ExternalEvent* external = dynamic_cast(event)) { + if (external->Name() == name) { + external->ResetSticky(); + return; + } + } else if (dynamic_cast(event) != NULL) { + ResetStickyExternalEvent(event, name); + } + } + } + return; +} + + /*! This will trigger a demand event, if it exists. \return \c true, if there is a demand event, and it has been diff --git a/src/servers/launch/Events.h b/src/servers/launch/Events.h index d827182a00..46059754b8 100644 --- a/src/servers/launch/Events.h +++ b/src/servers/launch/Events.h @@ -60,6 +60,8 @@ public: const char* name, uint32 flags); static void TriggerExternalEvent(Event* event, const char* name); + static void ResetStickyExternalEvent(Event* event, + const char* name); static bool TriggerDemand(Event* event); }; diff --git a/src/servers/launch/LaunchDaemon.cpp b/src/servers/launch/LaunchDaemon.cpp index 69e925838b..71f46189d7 100644 --- a/src/servers/launch/LaunchDaemon.cpp +++ b/src/servers/launch/LaunchDaemon.cpp @@ -144,7 +144,8 @@ private: void _HandleRegisterLaunchEvent(BMessage* message); void _HandleUnregisterLaunchEvent(BMessage* message); void _HandleNotifyLaunchEvent(BMessage* message); - + void _HandleResetStickyLaunchEvent( + BMessage* message); uid_t _GetUserID(BMessage* message); void _ReadPaths(const BStringList& paths); @@ -463,6 +464,10 @@ LaunchDaemon::MessageReceived(BMessage* message) _HandleNotifyLaunchEvent(message); break; + case B_RESET_STICKY_LAUNCH_EVENT: + _HandleResetStickyLaunchEvent(message); + break; + case kMsgEventTriggered: { // An internal event has been triggered. @@ -762,6 +767,34 @@ LaunchDaemon::_HandleNotifyLaunchEvent(BMessage* message) } +void +LaunchDaemon::_HandleResetStickyLaunchEvent(BMessage* message) +{ + uid_t user = _GetUserID(message); + if (user < 0) + return; + + if (user == 0 || fUserMode) { + // Reset sticky events + const char* name = message->GetString("name"); + const char* ownerName = message->GetString("owner"); + // TODO: support arguments (as selectors) + + ExternalEventSource* event = _FindEvent(ownerName, name); + if (event != NULL) { + // Evaluate all of its jobs + int32 count = event->CountListeners(); + for (int32 index = 0; index < count; index++) { + BaseJob* listener = event->ListenerAt(index); + Events::ResetStickyExternalEvent(listener->Event(), name); + } + } + } + + _ForwardEventMessage(user, message); +} + + uid_t LaunchDaemon::_GetUserID(BMessage* message) {