Class Display
- All Implemented Interfaces:
WaylandObject
- Direct Known Subclasses:
WlDisplayProxy
Display
singleton object.
A Display
object represents a client connection to a Wayland
compositor. It is created with either WlDisplayProxy.connect()
or
WlDisplayProxy.connectToFd()
. A connection is terminated using
disconnect()
.
A Display
is also used as the Proxy
for the Display
singleton object on the compositor side.
A Display
object handles all the data sent from and to the
compositor. When a Proxy
marshals a request, it will write its wire
representation to the display's write buffer. The data is sent to the
compositor when the client calls flush()
.
Incoming data is handled in two steps: queueing and dispatching. In the
queue step, the data coming from the display fd is interpreted and
added to a queue. On the dispatch step, the handler for the incoming
event set by the client on the corresponding Proxy
is called.
A Display
has at least one event queue, called the main
queue. Clients can create additional event queues with \ref
createQueue()
and assign Proxy
's to it. Events
occurring in a particular proxy are always queued in its assigned queue.
A client can ensure that a certain assumption, such as holding a lock
or running from a given thread, is true when a proxy event handler is
called by assigning that proxy to an event queue and making sure that
this queue is only dispatched when the assumption holds.
The main queue is dispatched by calling dispatch()
.
This will dispatch any events queued on the main queue and attempt
to read from the display fd if its empty. Events read are then queued
on the appropriate queues according to the proxy assignment. Calling
that function makes the calling thread the main thread.
A user created queue is dispatched with dispatchQueue(EventQueue)
.
If there are no events to dispatch this function will block. If this
is called by the main thread, this will attempt to read data from the
display fd and queue any events on the appropriate queues. If calling
from any other thread, the function will block until the main thread
queues an event on the queue being dispatched.
A real world example of event queue usage is Mesa's implementation of
eglSwapBuffers()
for the Wayland platform. This function might need
to block until a frame callback is received, but dispatching the main
queue could cause an event handler on the client to start drawing
again. This problem is solved using another event queue, so that only
the events handled by the EGL code are dispatched during the block.
This creates a problem where the main thread dispatches a non-main
queue, reading all the data from the display fd. If the application
would call poll(2) after that it would block, even though there
might be events queued on the main queue. Those events should be
dispatched with dispatchPending()
before
flushing and blocking.
-
Field Summary
Fields -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionstatic MemorySegment
_connect()
protected static MemorySegment
_connect
(int fd) protected static MemorySegment
void
Release exclusive access to display file descriptorCreate a new event queue for this displayvoid
Close a connection to a Wayland displayint
dispatch()
Process incoming eventsint
Dispatch main queue events without reading from the display fdint
dispatchQueue
(EventQueue queue) Dispatch events in an event queueint
dispatchQueuePending
(EventQueue queue) Dispatch pending events in an event queueint
flush()
Send all buffered requests on the display to the serverint
getError()
Retrieve the last error that occurred on a displayint
getFD()
Get a display context's file descriptorint
Prepare to read events after polling file descriptorint
prepareReadQueue
(EventQueue queue) int
Read events from display file descriptorint
Block until all pending request are processed by the serverMethods inherited from class org.freedesktop.wayland.client.Proxy
destroy, equals, getId, getImplementation, getPointer, getVersion, hashCode, marshal, marshal, marshalConstructor, setQueue
-
Field Details
-
OBJECT_ID
public static final int OBJECT_ID- See Also:
-
-
Constructor Details
-
Display
-
-
Method Details
-
_connect
-
_connect
-
_connect
-
disconnect
public void disconnect()Close a connection to a Wayland displayClose the connection to the display and free all resources associated with it.
-
getFD
public int getFD()Get a display context's file descriptorReturn the file descriptor associated with a display so it can be integrated into the client's main loop.
- Returns:
- Display object file descriptor
-
dispatch
public int dispatch()Process incoming eventsDispatch the display's main event queue.
If the main event queue is empty, this function blocks until there are events to be read from the display fd. Events are read and queued on the appropriate event queues. Finally, events on the main event queue are dispatched.
It is not possible to check if there are events on the main queue or not. For dispatching main queue events without blocking, see
dispatchPending()
.Calling this will release the display file descriptor if this thread acquired it using wl_display_acquire_fd().
- Returns:
- The number of dispatched events on success or -1 on failure
- See Also:
-
dispatchPending
public int dispatchPending()Dispatch main queue events without reading from the display fdThis function dispatches events on the main event queue. It does not attempt to read the display fd and simply returns zero if the main queue is empty, i.e., it doesn't block.
This is necessary when a client's main loop wakes up on some fd other than the display fd (network socket, timer fd, etc) and calls
dispatchQueue(EventQueue)
from that callback. This may queue up events in the main queue while reading all data from the display fd. When the main thread returns to the main loop to block, the display fd no longer has data, causing a call topoll(2)
(or similar functions) to block indefinitely, even though there are events ready to dispatch.To proper integrate the wayland display fd into a main loop, the client should always call
dispatchPending()
and thenflush()
prior to going back to sleep. At that point, the fd typically doesn't have data so attempting I/O could block, but events queued up on the main queue should be dispatched.A real-world example is a main loop that wakes up on a timerfd (or a sound card fd becoming writable, for example in a video player), which then triggers GL rendering and eventually eglSwapBuffers(). eglSwapBuffers() may call
dispatchQueue(EventQueue)
if it didn't receive the frame event for the previous frame, and as such queue events in the main queue.Calling this makes the current thread the main one.
- Returns:
- The number of dispatched events or -1 on failure
- See Also:
-
dispatchQueue
Dispatch events in an event queueDispatch all incoming events for objects assigned to the given event queue. On failure -1 is returned and errno set appropriately.
This function blocks if there are no events to dispatch. If calling from the main thread, it will block reading data from the display fd. For other threads this will block until the main thread queues events on the queue passed as argument.
- Parameters:
queue
- The event queue to dispatch- Returns:
- The number of dispatched events on success or -1 on failure
-
dispatchQueuePending
Dispatch pending events in an event queueDispatch all incoming events for objects assigned to the given event queue. On failure -1 is returned and errno set appropriately. If there are no events queued, this function returns immediately.
- Parameters:
queue
- The event queue to dispatch- Returns:
- The number of dispatched events on success or -1 on failure
- Since:
- 1.0.2
-
flush
public int flush()Send all buffered requests on the display to the serverSend all buffered data on the client side to the server. Clients should call this function before blocking. On success, the number of bytes sent to the server is returned. On failure, this function returns -1 and errno is set appropriately.
flush() never blocks. It will write as much data as possible, but if all data could not be written, errno will be set to EAGAIN and -1 returned. In that case, use poll on the display file descriptor to wait for it to become writable again.
- Returns:
- The number of bytes sent on success or -1 on failure
-
roundtrip
public int roundtrip()Block until all pending request are processed by the serverBlocks until the server process all currently issued requests and sends out pending events on all event queues.
- Returns:
- The number of dispatched events on success or -1 on failure
-
createQueue
Create a new event queue for this display- Returns:
- A new event queue associated with this display or NULL on failure.
-
getError
public int getError()Retrieve the last error that occurred on a displayReturn the last error that occurred on the display. This may be an error sent by the server or caused by the local client.
Errors are fatal. If this function returns non-zero the display can no longer be used.
- Returns:
- The last error that occurred on display or 0 if no error occurred
-
prepareReadQueue
-
prepareRead
public int prepareRead()Prepare to read events after polling file descriptorThis function must be called before reading from the file descriptor using
readEvents()
. CallingprepareRead()
announces the calling threads intention to read and ensures that until the thread is ready to read and callsreadEvents()
, no other thread will read from the file descriptor. This only succeeds if the event queue is empty though, and if there are undispatched events in the queue, -1 is returned and errno set to EAGAIN.If a thread successfully calls
prepareRead()
, it must either callreadEvents()
when it's ready or cancel the read intention by callingcancelRead()
.Use this function before polling on the display fd or to integrate the fd into a toolkit event loop in a race-free way. Typically, a toolkit will call
dispatchPending()
before sleeping, to make sure it doesn't block with unhandled events. Upon waking up, it will assume the file descriptor is readable and read events from the fd by callingdispatch()
. Simplified, we have:display.dispatchPending(); display.flush(); poll(fds, nfds, -1); display.dispatch();
There are two races here: first, before blocking in poll(), the fd could become readable and another thread reads the events. Some of these events may be for the main queue and the other thread will queue them there and then the main thread will go to sleep in poll(). This will stall the application, which could be waiting for a event to kick of the next animation frame, for example.
The other race is immediately after poll(), where another thread could preempt and read events before the main thread calls
dispatch()
. This call now blocks and starves the other fds in the event loop.A correct sequence would be:
while (display.prepareRead() != 0) display.dispatch_Pending(); display.flush(); poll(fds, nfds, -1); display.readEvents(); display.dispatchPending();
Here we call
prepareRead()
, which ensures that between returning from that call and eventually callingreadEvents()
, no other thread will read from the fd and queue events in our queue. If the call toprepareRead()
fails, we dispatch the pending events and try again until we're successful.- Returns:
- 0 on success or -1 if event queue was not empty
-
cancelRead
public void cancelRead()Release exclusive access to display file descriptorThis releases the exclusive access. Useful for canceling the lock when a timed out poll returns fd not readable and we're not going to read from the fd anytime soon.
-
readEvents
public int readEvents()Read events from display file descriptorThis will read events from the file descriptor for the display. This function does not dispatch events, it only reads and queues events into their corresponding event queues. If no data is avilable on the file descriptor,
readEvents()
returns immediately. To dispatch events that may have been queued, calldispatchPending()
ordispatchQueuePending(EventQueue)
.Before calling this function,
prepareRead()
must be called first.- Returns:
- 0 on success or -1 on error. In case of error errno will be set accordingly
-