public abstract class Display extends Proxy<Void>
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.| Modifier and Type | Field and Description |
|---|---|
static int |
OBJECT_ID |
| Modifier | Constructor and Description |
|---|---|
protected |
Display(Long pointer) |
| Modifier and Type | Method and Description |
|---|---|
void |
cancelRead()
Release exclusive access to display file descriptor
This releases the exclusive access.
|
EventQueue |
createQueue()
Create a new event queue for this display
|
void |
disconnect()
Close a connection to a Wayland display
Close the connection to the display and free all resources associated
with it.
|
int |
dispatch()
Process incoming events
Dispatch the display's main event queue.
|
int |
dispatchPending()
Dispatch main queue events without reading from the display fd
This function dispatches events on the main event queue.
|
int |
dispatchQueue(EventQueue queue)
Dispatch events in an event queue
Dispatch all incoming events for objects assigned to the given
event queue.
|
int |
dispatchQueuePending(EventQueue queue)
Dispatch pending events in an event queue
Dispatch all incoming events for objects assigned to the given
event queue.
|
int |
flush()
Send all buffered requests on the display to the server
Send all buffered data on the client side to the server.
|
int |
getError()
Retrieve the last error that occurred on a display
Return the last error that occurred on the display.
|
int |
getFD()
Get a display context's file descriptor
Return the file descriptor associated with a display so it can be
integrated into the client's main loop.
|
int |
prepareRead()
Prepare to read events after polling file descriptor
This function must be called before reading from the file
descriptor using
readEvents(). |
int |
prepareReadQueue(EventQueue queue) |
int |
readEvents()
Read events from display file descriptor
This will read events from the file descriptor for the display.
|
int |
roundtrip()
Block until all pending request are processed by the server
Blocks until the server process all currently issued requests and
sends out pending events on all event queues.
|
destroy, equals, getId, getImplementation, getPointer, getVersion, hashCode, marshal, marshal, marshalConstructor, setQueuepublic static final int OBJECT_ID
protected Display(Long pointer)
public void disconnect()
public int getFD()
public int dispatch()
dispatchPending().
Calling this will release the display file descriptor if this
thread acquired it using wl_display_acquire_fd().dispatchPending(),
dispatchQueue(EventQueue)public int dispatchPending()
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 to poll(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 then
flush() 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.dispatch(),
dispatchQueue(EventQueue),
flush()public int dispatchQueue(EventQueue queue)
queue - The event queue to dispatchpublic int dispatchQueuePending(EventQueue queue)
queue - The event queue to dispatchpublic int flush()
public int roundtrip()
public EventQueue createQueue()
public int getError()
public int prepareReadQueue(EventQueue queue)
public int prepareRead()
readEvents(). Calling
prepareRead() announces the calling threads intention
to read and ensures that until the thread is ready to read and
calls readEvents(), 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 call readEvents() when it's ready or cancel the
read intention by calling cancelRead().
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 calling dispatch(). 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 calling
readEvents(), no other thread will read from the fd and
queue events in our queue. If the call to
prepareRead() fails, we dispatch the pending events and
try again until we're successful.public void cancelRead()
public int readEvents()
readEvents() returns
immediately. To dispatch events that may have been queued, call
dispatchPending() or
dispatchQueuePending(EventQueue).
Before calling this function, prepareRead() must be
called first.Copyright © 2016. All rights reserved.