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

Class for handling touch input events. More...

+ Inheritance diagram for LTouch:

Public Member Functions

 LTouch (const void *params) noexcept
 Constructor of the LTouch class. More...
 
 ~LTouch () noexcept
 Destructor of the LTouch class. More...
 
LSurfacesurfaceAt (const LPoint &point) const noexcept
 Look for a surface. More...
 
const std::vector< LTouchPoint * > & touchPoints () const noexcept
 Vector of currently active touchpoints. More...
 
LTouchPointcreateOrGetTouchPoint (const LTouchDownEvent &event) noexcept
 Creates a new touch point or returns an existing one with the same id. More...
 
LTouchPointfindTouchPoint (Int32 id) const noexcept
 Gets the touch point that matches the specified id. More...
 
void sendFrameEvent (const LTouchFrameEvent &event) noexcept
 Send a frame event to all clients with surfaces assigned to touch points. More...
 
void sendCancelEvent (const LTouchCancelEvent &event) noexcept
 Send a cancel event to clients with surfaces assigned to touchpoints. More...
 
virtual void touchDownEvent (const LTouchDownEvent &event)
 Triggered by the input backend when a new touch point is created. More...
 
virtual void touchMoveEvent (const LTouchMoveEvent &event)
 Triggered by the input backend when a pressed touchpoint moves. More...
 
virtual void touchUpEvent (const LTouchUpEvent &event)
 Triggered by the input backend when a touchpoint is no longer pressed. More...
 
virtual void touchFrameEvent (const LTouchFrameEvent &event)
 Triggered by the input backend after sending down, move, and up events that logically belong together and should be processed atomically. More...
 
virtual void touchCancelEvent (const LTouchCancelEvent &event)
 Triggered by the input backend when all active touchpoints are cancelled, typically in response to an unavailable touch input device. 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...
 

Static Public Member Functions

static LPointF toGlobal (LOutput *output, const LPointF &touchPointPos) noexcept
 Transforms a touch point position to global coordinates. 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

Class for handling touch input events.

The LTouch class facilitates the management of touch input events, allowing you to redirect them to client surfaces.
Touch events commence with a touch-down event, which can be utilized to create a new touch point using createOrGetTouchPoint(). Each touch point is assigned a unique ID obtained from the touch-down event. Invoking createOrGetTouchPoint() with an already used ID returns the existing touch point associated with that ID. All touch points are initially marked as pressed and can be accessed through the touchPoints() vector.

Once a touch point is created, you can associate it with a surface using LTouchPoint::sendDownEvent(). Only a single surface can be assigned to a touch point at a time, or none at all. Touch-down and move events received from the input backend contain information about the current physical position of the touchpoint on the touch device, represented in a coordinate space ranging from 0 to 1 for both x and y axes, with the top-left corner as the origin.

There is no universal way to associate a touch device with an output. To achieve this, you could use information from the events input device and transform touch point positions to output coordinates with the toGlobal() aux method.

Note
The default implementation transforms touchpoint coordinates to the output coordinates where the LCursor is currently positioned.

After a touch point is created, subsequent touch-down, move, and up events may occur. These events can be forwarded to clients using the methods provided by LTouchPoint. Clients are expected to wait for a frame event to process them atomically, which is triggered by calling sendFrameEvent().

The input backend can also notify of a cancel event, typically when a touch device is unplugged or an error occurs.
You can forward this event to clients using the sendCancelEvent() method. After invoking this method, all touch points are destroyed, even if they haven't been released before with a touch-up event.

Constructor & Destructor Documentation

◆ LTouch()

LTouch ( const void *  params)
noexcept

Constructor of the LTouch class.

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

◆ ~LTouch()

~LTouch ( )
noexcept

Destructor of the LTouch class.

Invoked after LCompositor::onAnticipatedObjectDestruction().

Member Function Documentation

◆ surfaceAt()

LSurface * surfaceAt ( const LPoint point) const
noexcept

Look for a surface.

This method looks for the first mapped surface that contains the point given by the point parameter.
It takes into account the surfaces role position (LSurface::rolePos()), their input region (LSurface::inputRegion()) and the order given by the list of surfaces of the compositor (LCompositor::surfaces()).
Some surface roles do not have an input region such as LCursorRole or LDNDIconRole so these surfaces are always ignored.

Parameters
pointPoint in compositor coordinates.
Returns
Returns the first surface that contains the point or nullptr if no surface is found.

◆ touchPoints()

const std::vector< LTouchPoint * > & touchPoints ( ) const
noexcept

Vector of currently active touchpoints.

Each touchpoint has a unique identifier and can be associated with a single surface at a time or none at all.

Returns
A constant reference to the vector of currently active touchpoints.

◆ createOrGetTouchPoint()

LTouchPoint * createOrGetTouchPoint ( const LTouchDownEvent event)
noexcept

Creates a new touch point or returns an existing one with the same id.

This method generates a new touch point based on the provided touch down event id.
If a touch point with the same id already exists, that existing touchpoint is returned instead.
Newly created touchpoints are initially marked as pressed.

Parameters
eventThe touch down event used to create the touch point.
Returns
A pointer to the newly created or existing touch point.

◆ findTouchPoint()

LTouchPoint * findTouchPoint ( Int32  id) const
noexcept

Gets the touch point that matches the specified id.

This method searches for a touch point with the given id. If found, a pointer to the matching touch point is returned; otherwise, nullptr is returned.

Parameters
idThe unique identifier of the touch point to be found.
Returns
A pointer to the matching touch point or nullptr if no touch point with the id is found.

◆ toGlobal()

LPointF toGlobal ( LOutput output,
const LPointF touchPointPos 
)
staticnoexcept

Transforms a touch point position to global coordinates.

This method enables the conversion of a touch point position, defined within the range of 0 to 1 for both x and y axes, to a global position. The transformation takes into account the specified output's position, size, and any applied transform.

Returns
The transformed global position of the touch point, or the same position if output is nullptr.

◆ sendFrameEvent()

void sendFrameEvent ( const LTouchFrameEvent event)
noexcept

Send a frame event to all clients with surfaces assigned to touch points.

Clients are expected to wait for this event before processing previously sent touch events.
After this frame event, touch points that are no longer pressed are destroyed.

Parameters
eventThe frame event to be sent to clients.

◆ sendCancelEvent()

void sendCancelEvent ( const LTouchCancelEvent event)
noexcept

Send a cancel event to clients with surfaces assigned to touchpoints.

This method notifies clients of a cancel event, and subsequently, all current touchpoints are destroyed.

Parameters
eventThe touch cancel event to be sent to clients.

◆ touchDownEvent()

virtual void touchDownEvent ( const LTouchDownEvent event)
virtual

Triggered by the input backend when a new touch point is created.

This virtual method is called when a touch-down event occurs, signaling the creation of a new touch point.

Parameters
eventThe touch-down event providing details about the new touch point.

Default Implementation

void LTouch::touchDownEvent(const LTouchDownEvent &event)
{
if (!cursor()->output()) return;
const bool sessionLocked { sessionLockManager()->state() != LSessionLockManager::Unlocked };
LTouchPoint *tp { createOrGetTouchPoint(event) };
const LPointF globalPos { toGlobal(cursor()->output(), event.pos()) };
LSurface *surface { surfaceAt(globalPos) };
if (surface)
{
if (sessionLocked && surface->client() != sessionLockManager()->client())
return;
event.localPos = globalPos - surface->rolePos();
if (!seat()->keyboard()->focus() || !surface->isSubchildOf(seat()->keyboard()->focus()))
seat()->keyboard()->setFocus(surface);
tp->sendDownEvent(event, surface);
surface->raise();
}
else
{
tp->sendDownEvent(event);
}
}
const LPointF & pos() const noexcept
Gets the current cursor position in compositor-global coordinates.
Definition: LCursor.h:56
void setFocus(LSurface *surface)
Set keyboard focus.
Definition: LKeyboard.cpp:276
void dismissPopups() noexcept
Close all popups.
Definition: LSeat.cpp:121
LKeyboard * keyboard() const noexcept
Access to keyboard events.
Definition: LSeat.h:179
State state() const noexcept
Gets the current state of the session.
Definition: LSessionLockManager.h:65
@ Unlocked
Definition: LSessionLockManager.h:27
const LPoint & rolePos() const
Role position.
Definition: LSurface.cpp:326
LSurface * surfaceAt(const LPoint &point) const noexcept
Look for a surface.
Definition: LTouch.cpp:29
LTouchPoint * createOrGetTouchPoint(const LTouchDownEvent &event) noexcept
Creates a new touch point or returns an existing one with the same id.
Definition: LTouch.cpp:39
static LPointF toGlobal(LOutput *output, const LPointF &touchPointPos) noexcept
Transforms a touch point position to global coordinates.
Definition: LTouch.cpp:57
virtual void touchDownEvent(const LTouchDownEvent &event)
Triggered by the input backend when a new touch point is created.
LCursor * cursor() noexcept
Gets the compositor's cursor.
Definition: LCompositor.cpp:47
LPointTemplate< Float32 > LPointF
2D vector of 32 bits floats
Definition: LNamespaces.h:256
LSessionLockManager * sessionLockManager() noexcept
Gets the compositor's session lock manager.
Definition: LCompositor.cpp:52
LSeat * seat() noexcept
Gets the compositor's seat.
Definition: LCompositor.cpp:42

◆ touchMoveEvent()

virtual void touchMoveEvent ( const LTouchMoveEvent event)
virtual

Triggered by the input backend when a pressed touchpoint moves.

This virtual method is called when a touch-move event occurs, indicating the movement of a pressed touchpoint.

Parameters
eventThe touch-move event providing details about the moving touchpoint.

Default Implementation

void LTouch::touchMoveEvent(const LTouchMoveEvent &event)
{
if (!cursor()->output()) return;
LTouchPoint *tp { findTouchPoint(event.id()) };
if (!tp)
return;
const LPointF globalPos { toGlobal(cursor()->output(), event.pos()) };
// Handle DND session
LDND &dnd { *seat()->dnd() };
if (dnd.dragging() && dnd.triggeringEvent().type() == LEvent::Type::Touch)
{
const auto &touchEvent { static_cast<const LTouchEvent&>(dnd.triggeringEvent()) };
if (touchEvent.id() == tp->id())
{
if (dnd.icon())
{
dnd.icon()->surface()->setPos(globalPos);
dnd.icon()->surface()->repaintOutputs();
}
LSurface *surface { surfaceAt(globalPos) };
if (surface)
{
if (dnd.focus() == surface)
dnd.sendMoveEvent(globalPos - surface->rolePos(), event.ms());
else
dnd.setFocus(surface, globalPos - surface->rolePos());
}
else
dnd.setFocus(nullptr, LPoint());
}
}
bool activeResizing { false };
for (LToplevelResizeSession *session : seat()->toplevelResizeSessions())
{
if (session->triggeringEvent().type() == LEvent::Type::Touch)
{
const auto &touchEvent { static_cast<const LTouchEvent&>(session->triggeringEvent()) };
if (touchEvent.id() == tp->id())
{
activeResizing = true;
session->updateDragPoint(globalPos);
session->toplevel()->surface()->repaintOutputs();
if (session->toplevel()->maximized())
session->toplevel()->configureState(session->toplevel()->pendingConfiguration().state &~ LToplevelRole::Maximized);
}
}
}
if (activeResizing)
return;
bool activeMoving { false };
for (LToplevelMoveSession *session : seat()->toplevelMoveSessions())
{
if (session->triggeringEvent().type() == LEvent::Type::Touch)
{
const auto &touchEvent { static_cast<const LTouchEvent&>(session->triggeringEvent()) };
if (touchEvent.id() == tp->id())
{
activeMoving = true;
session->updateDragPoint(globalPos);
session->toplevel()->surface()->repaintOutputs();
if (session->toplevel()->maximized())
session->toplevel()->configureState(session->toplevel()->pendingConfiguration().state &~ LToplevelRole::Maximized);
}
}
}
if (activeMoving)
return;
if (tp->surface())
{
event.localPos = globalPos - tp->surface()->rolePos();
tp->sendMoveEvent(event);
}
else
tp->sendMoveEvent(event);
}
LSurface * surface() const noexcept
Returns the surface that has acquired the role provided in the constructor.
Definition: LBaseSurfaceRole.h:117
LDNDIconRole * icon() const noexcept
Drag & drop session icon.
Definition: LDND.cpp:118
@ Touch
Touch event type.
LDND * dnd() const noexcept
Access to the drag & drop session manager.
Definition: LSeat.h:197
const std::vector< LToplevelMoveSession * > & toplevelMoveSessions() const noexcept
Active LToplevelRole move sessions.
Definition: LSeat.cpp:116
void repaintOutputs() noexcept
Repaints the intersected outputs.
Definition: LSurface.cpp:196
LToplevelRole * toplevel() const noexcept
Toplevel role.
Definition: LSurface.cpp:60
void setPos(const LPoint &newPos) noexcept
Assigns the position.
virtual void touchMoveEvent(const LTouchMoveEvent &event)
Triggered by the input backend when a pressed touchpoint moves.
LTouchPoint * findTouchPoint(Int32 id) const noexcept
Gets the touch point that matches the specified id.
Definition: LTouch.cpp:48
LPointTemplate< Int32 > LPoint
2D vector of 32 bits integers
Definition: LNamespaces.h:250

◆ touchUpEvent()

virtual void touchUpEvent ( const LTouchUpEvent event)
virtual

Triggered by the input backend when a touchpoint is no longer pressed.

This virtual method is called when a touch-up event occurs, indicating that a touchpoint is no longer pressed.

Parameters
eventThe touch-up event providing details about the released touchpoint.

Default Implementation

void LTouch::touchUpEvent(const LTouchUpEvent &event)
{
LTouchPoint *tp { findTouchPoint(event.id()) };
if (!tp)
return;
LDND &dnd { *seat()->dnd() };
if (dnd.dragging() && dnd.triggeringEvent().type() == LEvent::Type::Touch)
{
const auto &touchEvent { static_cast<const LTouchEvent&>(dnd.triggeringEvent()) };
if (touchEvent.id() == tp->id())
dnd.drop();
}
// Stop touch toplevel resizing sessions
for (auto it = seat()->toplevelResizeSessions().begin(); it != seat()->toplevelResizeSessions().end();)
{
if ((*it)->triggeringEvent().type() == LEvent::Type::Touch)
{
const auto &touchEvent { static_cast<const LTouchEvent&>((*it)->triggeringEvent()) };
if (touchEvent.id() == tp->id())
{
it = (*it)->stop();
continue;
}
}
it++;
}
for (auto it = seat()->toplevelMoveSessions().begin(); it != seat()->toplevelMoveSessions().end();)
{
if ((*it)->triggeringEvent().type() == LEvent::Type::Touch)
{
const auto &touchEvent { static_cast<const LTouchEvent&>((*it)->triggeringEvent()) };
if (touchEvent.id() == tp->id())
{
it = (*it)->stop();
continue;
}
}
it++;
}
// Send the event
tp->sendUpEvent(event);
}
void drop() noexcept
Drop the data offer.
Definition: LDND.cpp:160
const std::vector< LToplevelResizeSession * > & toplevelResizeSessions() const noexcept
Active LToplevelRole resize sessions.
Definition: LSeat.cpp:111
virtual void touchUpEvent(const LTouchUpEvent &event)
Triggered by the input backend when a touchpoint is no longer pressed.

◆ touchFrameEvent()

virtual void touchFrameEvent ( const LTouchFrameEvent event)
virtual

Triggered by the input backend after sending down, move, and up events that logically belong together and should be processed atomically.

This virtual method is called when a touch frame event occurs, signifying the completion of a set of related touch events (down, move, up) that should be processed as a single atomic unit.

Parameters
eventThe touch frame event providing details about the synchronized touch events.

Default Implementation

void LTouch::touchFrameEvent(const LTouchFrameEvent &event)
{
// Released touch points are destroyed after sending this event
}
void sendFrameEvent(const LTouchFrameEvent &event) noexcept
Send a frame event to all clients with surfaces assigned to touch points.
Definition: LTouch.cpp:102
virtual void touchFrameEvent(const LTouchFrameEvent &event)
Triggered by the input backend after sending down, move, and up events that logically belong together...

◆ touchCancelEvent()

virtual void touchCancelEvent ( const LTouchCancelEvent event)
virtual

Triggered by the input backend when all active touchpoints are cancelled, typically in response to an unavailable touch input device.

This virtual method is called when a touch cancel event occurs, indicating the cancellation of all active touchpoints, often triggered by the unavailability of a touch input device.

Parameters
eventThe touch cancel event providing details about the cancellation.

Default Implementation

void LTouch::touchCancelEvent(const LTouchCancelEvent &event)
{
LDND &dnd { *seat()->dnd() };
if (dnd.dragging() && dnd.triggeringEvent().type() == LEvent::Type::Touch)
dnd.drop();
// Stop touch toplevel resizing sessions
for (auto it = seat()->toplevelResizeSessions().begin(); it != seat()->toplevelResizeSessions().end();)
{
if ((*it)->triggeringEvent().type() == LEvent::Type::Touch)
it = (*it)->stop();
else
it++;
}
// Stop touch toplevel moving sessions
for (auto it = seat()->toplevelMoveSessions().begin(); it != seat()->toplevelMoveSessions().end();)
{
if ((*it)->triggeringEvent().type() == LEvent::Type::Touch)
it = (*it)->stop();
else
it++;
}
// All touch points are destroyed
}
virtual void touchCancelEvent(const LTouchCancelEvent &event)
Triggered by the input backend when all active touchpoints are cancelled, typically in response to an...
void sendCancelEvent(const LTouchCancelEvent &event) noexcept
Send a cancel event to clients with surfaces assigned to touchpoints.
Definition: LTouch.cpp:123