Louvre  v2.9.0-1
C++ library for Wayland compositors
Public Member Functions | List of all members
LActivationTokenManager Class Reference

Activation Token Manager. More...

+ Inheritance diagram for LActivationTokenManager:

Public Member Functions

 LActivationTokenManager (const void *params) noexcept
 LActivationTokenManager class constructor. More...
 
 ~LActivationTokenManager () noexcept
 Destructor of the LActivationTokenManager class. More...
 
const std::unordered_map< std::string, LActivationToken * > & tokens () const noexcept
 Retrieve available tokens. More...
 
LActivationTokentoken () const noexcept
 Retrieve the current token. More...
 
void destroyTokensOlderThanMs (UInt32 ms)
 Destroy tokens older than the specified number of milliseconds. More...
 
- Public Member Functions inherited from LFactoryObject
Type factoryObjectType () const noexcept
 Gets the base factory object type. More...
 
- Public Member Functions inherited from LObject
 LObject (const LObject &) noexcept
 Copy constructor. More...
 
LObjectoperator= (const LObject &) noexcept
 Assignment operator (each object has its own individual LWeak reference count). More...
 
void setUserData (UIntPtr data) const noexcept
 Store an unsigned integer value/pointer. More...
 
UIntPtr userData () const noexcept
 Retrieves the stored unsigned integer value/pointer. More...
 

Virtual Methods

virtual void createTokenRequest ()
 Request to create an activation token. More...
 
virtual void activateSurfaceRequest (LSurface *surface)
 Request to activate a surface. More...
 

Additional Inherited Members

- Public Types inherited from LFactoryObject
enum class  Type : Int32
 Base factory object types. More...
 
- Protected Member Functions inherited from LObject
 LObject () noexcept=default
 Constructor of the LObject class. More...
 
virtual ~LObject () noexcept
 Destructor of the LObject class. More...
 
void notifyDestruction () noexcept
 Notifies the object destruction. More...
 

Detailed Description

Activation Token Manager.

The XDG Activation protocol allows clients to pass focus to another client's surface.

The protocol functions as follows:

  1. The "activator" client requests a new token from the compositor via the createTokenRequest() method. During the request, the client can provide additional (optional) information, such as the application ID of the "target" client (LActivationToken::toActivateAppId()), the event that triggered the request (LActivationToken::triggeringEvent()), and the surface that received the triggering event (LActivationToken::origin()).
  2. If the request is accepted, the compositor generates an activation token (a unique and random string) and sends it to the client. The token is stored in the tokens() map.
  3. The "activator" client then passes the token to the "target" client via its own communication channel (e.g., D-Bus, the XDG_ACTIVATION_TOKEN environment variable).
  4. The "target" client can use the token to activate one of its surfaces by invoking the activateSurfaceRequest() method.

The default implementations of createTokenRequest() and activateSurfaceRequest() only accept requests that provide a valid triggering event and destroy the token after it is used, as well as those that haven't been used in the last 10 seconds. This is for security reasons, tokens can remain valid indefinitely if desired.

There is a unique instance of this class, created within LCompositor::createObjectRequest(), which can be accessed globally via Louvre::activationTokenManager().

To disable this protocol, remove its global from LCompositor::createGlobalsRequest()

See also
LActivationToken

Constructor & Destructor Documentation

◆ LActivationTokenManager()

LActivationTokenManager ( const void *  params)
noexcept

LActivationTokenManager class constructor.

There is only one instance of this class, which can be accessed globally via activationTokenManager().

Parameters
paramsInternal parameters provided in LCompositor::createObjectRequest().

◆ ~LActivationTokenManager()

~LActivationTokenManager ( )
noexcept

Member Function Documentation

◆ tokens()

const std::unordered_map<std::string, LActivationToken*>& tokens ( ) const
inlinenoexcept

Retrieve available tokens.

Provides all currently available tokens, which clients can use to activate surfaces.

To expire tokens, use LActivationToken::destroy() or the destroyTokensOlderThanMs() method.

◆ token()

LActivationToken* token ( ) const
inlinenoexcept

Retrieve the current token.

This method provides access to the token used during createTokenRequest() or activateSurfaceRequest() requests. If neither request is in progress, this method returns nullptr.

The token is not provided as an argument to those requests because the default implementation of activateSurfaceRequest() triggers LToplevelRole::activateRequest() if the surface has a toplevel role. This way, the token can be accessed from LToplevelRole::activateRequest() if needed.

◆ destroyTokensOlderThanMs()

void destroyTokensOlderThanMs ( UInt32  ms)

Destroy tokens older than the specified number of milliseconds.

The default implementation of activateSurfaceRequest() uses this method to destroy all tokens older than 10 seconds to prevent unnecessary tokens from remaining active.

See also
LActivationToken::destroy() and LActivationToken::created().

◆ createTokenRequest()

virtual void createTokenRequest ( )
virtual

Request to create an activation token.

This request is triggered each time a client wants to create a new activation token. The activation token data can be accessed via token(). If the token is denied, token()->destroy() must be called, otherwise, the token will be retained in the tokens() map, and clients will be allowed to use it for activateSurfaceRequest().

The default implementation only accepts tokens generated by the currently focused client.

Default implementation

{
// Deny requests not originated from a recent user event
bool allowed { false };
if (token()->triggeringEvent())
{
switch (token()->triggeringEvent()->type())
{
allowed = seat()->pointer()->focus() && seat()->pointer()->focus()->client() == token()->creator();
break;
allowed = seat()->keyboard()->focus() && seat()->keyboard()->focus()->client() == token()->creator();
break;
const auto &touchPoints { seat()->touch()->touchPoints() };
allowed = std::any_of(touchPoints.begin(), touchPoints.end(), [this](LTouchPoint *tp) { return tp->surface() && tp->surface()->client() == token()->creator();});
break;
}
}
if (!allowed)
token()->destroy();
}
LClient * creator() const noexcept
The client that requested the token creation.
Definition: LActivationToken.h:31
const std::unordered_map< std::string, LActivationToken * >::iterator destroy() const noexcept
Invalidates and destroys the token.
Definition: LActivationToken.cpp:8
void destroyTokensOlderThanMs(UInt32 ms)
Destroy tokens older than the specified number of milliseconds.
Definition: LActivationTokenManager.cpp:20
virtual void createTokenRequest()
Request to create an activation token.
LActivationToken * token() const noexcept
Retrieve the current token.
Definition: LActivationTokenManager.h:84
@ Pointer
Pointer event type.
@ Keyboard
Keyboard event type.
@ Touch
Touch event type.
LSurface * focus() const noexcept
Focused surface.
Definition: LKeyboard.cpp:269
LSurface * focus() const noexcept
Gets the focused surface.
Definition: LPointer.cpp:400
LKeyboard * keyboard() const noexcept
Access to keyboard events.
Definition: LSeat.h:146
LPointer * pointer() const noexcept
Access to pointer events.
Definition: LSeat.h:136
LTouch * touch() const noexcept
Access to touch events.
Definition: LSeat.h:156
LClient * client() const noexcept
Client owner of the surface.
Definition: LSurface.cpp:474
const std::vector< LTouchPoint * > & touchPoints() const noexcept
Vector of currently active touchpoints.
Definition: LTouch.cpp:32
LSeat * seat() noexcept
Gets the compositor's seat.
Definition: LCompositor.cpp:40

◆ activateSurfaceRequest()

virtual void activateSurfaceRequest ( LSurface surface)
virtual

Request to activate a surface.

This request indicates that a client wants to activate one of its surfaces and is only triggered if the client provides one of the tokens(), which can be accessed during the request with token().

The default implementation verifies if the token is recent and destroys it immediately after use, along with any tokens older than 10 seconds.

If the token is not destroyed, LActivationToken::timesUsed() is incremented by 1.

Parameters
surfaceThe surface to activate.

Default implementation

{
bool allowed { false };
if (token()->creator() && token()->triggeringEvent() && sessionLockManager()->state() == LSessionLockManager::Unlocked)
{
switch (token()->triggeringEvent()->type())
{
allowed = seat()->pointer()->focus() && seat()->pointer()->focus()->client() == token()->creator();
break;
allowed = seat()->keyboard()->focus() && seat()->keyboard()->focus()->client() == token()->creator();
break;
const auto &touchPoints { seat()->touch()->touchPoints() };
allowed = std::any_of(touchPoints.begin(), touchPoints.end(), [this](LTouchPoint *tp) { return tp->surface() && tp->surface()->client() == token()->creator();});
break;
}
}
if (allowed)
{
if (surface->toplevel())
surface->toplevel()->activateRequest();
else
{
seat()->keyboard()->setFocus(surface);
surface->raise();
}
}
token()->destroy();
}
virtual void activateSurfaceRequest(LSurface *surface)
Request to activate a surface.
void setFocus(LSurface *surface)
Set keyboard focus.
Definition: LKeyboard.cpp:274
@ Unlocked
Definition: LSessionLockManager.h:27
LSessionLockManager * sessionLockManager() noexcept
Gets the compositor's session lock manager.
Definition: LCompositor.cpp:50