Struct wayland_client::EventQueue
source · [−]pub struct EventQueue { /* private fields */ }
Expand description
An event queue for protocol messages
Event dispatching in wayland is made on a queue basis, allowing you to organize your objects into different queues that can be dispatched independently, for example from different threads.
An EventQueue
is not Send
, and thus must stay on the thread on which
it was created. However the Display
object is Send + Sync
, allowing
you to create the queues directly on the threads that host them.
When a queue is dispatched (via the dispatch(..)
or dispatch_pending(..)
methods)
all the incoming messages from the server designated to objects associated with
the queue are processed sequentially, and the appropriate implementation for each
is invoked. When all messages have been processed these methods return.
There are two main ways to driving an event queue forward. The first way is the
simplest and generally sufficient for single-threaded apps that only process events
from wayland. It consists of using the EventQueue::dispatch(..)
method, which will
take care of sending pending requests to the server, block until some events are
available, read them, and call the associated handlers:
loop {
// The dispatch() method returns once it has received some events to dispatch
// and have emptied the wayland socket from its pending messages, so it needs
// to be called in a loop. If this method returns an error, your connection to
// the wayland server is very likely dead. See its documentation for more details.
event_queue.dispatch(&mut (), |_,_,_| {
/* This closure will be called for every event received by an object not
assigned to any Filter. If you plan to assign all your objects to Filter,
the simplest thing to do is to assert this is never called. */
unreachable!();
}).expect("An error occurred during event dispatching!");
}
The second way is more appropriate for apps that are either multithreaded (and need to process
wayland events from different threads conccurently) or need to react to events from different
sources and can’t affort to just block on the wayland socket. It centers around three methods:
Display::flush()
, EventQueue::read_events()
and EventQueue::dispatch_pending()
:
loop {
// The first method, called on the Display, is flush(). It writes all pending
// requests to the socket. Calling it ensures that the server will indeed
// receive your requests (so it can react to them).
if let Err(e) = display.flush() {
if e.kind() != ::std::io::ErrorKind::WouldBlock {
// if you are sending a realy large number of request, it might fill
// the internal buffers of the socket, in which case you should just
// retry flushing later. Other errors are a problem though.
eprintln!("Error while trying to flush the wayland socket: {:?}", e);
}
}
// The second method will try to read events from the socket. It is done in two
// steps, first the read is prepared, and then it is actually executed. This allows
// lower contention when different threads are trying to trigger a read of events
// concurently
if let Some(guard) = event_queue.prepare_read() {
// prepare_read() returns None if there are already events pending in this
// event queue, in which case there is no need to try to read from the socket
if let Err(e) = guard.read_events() {
if e.kind() != ::std::io::ErrorKind::WouldBlock {
// if read_events() returns Err(WouldBlock), this just means that no new
// messages are available to be read
eprintln!("Error while trying to read from the wayland socket: {:?}", e);
}
}
}
// Then, once events have been read from the socket and stored in the internal
// queues, they need to be dispatched to their handler. Note that while flush()
// and read_events() are global and will affect the whole connection, this last
// method will only affect the event queue it is being called on. This method
// cannot error unless there is a bug in the server or a previous read of events
// already errored.
event_queue.dispatch_pending(&mut (), |_,_,_| {}).expect("Failed to dispatch all messages.");
// Note that none of these methods are blocking, as such they should not be used
// as a loop as-is if there are no other sources of events your program is waiting on.
// The wayland socket can also be integrated in a poll-like mechanism by using
// the file descriptor provided by the `get_connection_fd()` method.
}
Implementations
sourceimpl EventQueue
impl EventQueue
sourcepub fn dispatch<T: Any, F>(&mut self, data: &mut T, fallback: F) -> Result<u32> where
F: FnMut(RawEvent, Main<AnonymousObject>, DispatchData<'_>),
pub fn dispatch<T: Any, F>(&mut self, data: &mut T, fallback: F) -> Result<u32> where
F: FnMut(RawEvent, Main<AnonymousObject>, DispatchData<'_>),
Dispatches events from the internal buffer.
Dispatches all events to their appropriate filters. If no events were in the internal buffer, will block until some events are read and dispatch them. This process can insert events in the internal buffers of other event queues.
The provided data
will be mutably accessible from all the callbacks, via the
DispatchData
mechanism. If you don’t need global data, you
can just provide a &mut ()
there.
If an error is returned, your connection with the wayland compositor is probably lost.
You may want to check Display::protocol_error()
to see if it was caused by a protocol error.
sourcepub fn dispatch_pending<T: Any, F>(
&mut self,
data: &mut T,
fallback: F
) -> Result<u32> where
F: FnMut(RawEvent, Main<AnonymousObject>, DispatchData<'_>),
pub fn dispatch_pending<T: Any, F>(
&mut self,
data: &mut T,
fallback: F
) -> Result<u32> where
F: FnMut(RawEvent, Main<AnonymousObject>, DispatchData<'_>),
Dispatches pending events from the internal buffer.
Dispatches all events to their appropriate callbacks.
Never blocks, if no events were pending, simply returns
Ok(0)
.
The provided data
will be mutably accessible from all the callbacks, via the
DispatchData
mechanism. If you don’t need global data, you
can just provide a &mut ()
there.
If an error is returned, your connection with the wayland compositor is probably lost.
You may want to check Display::protocol_error()
to see if it was caused by a protocol error.
sourcepub fn sync_roundtrip<T: Any, F>(
&mut self,
data: &mut T,
fallback: F
) -> Result<u32> where
F: FnMut(RawEvent, Main<AnonymousObject>, DispatchData<'_>),
pub fn sync_roundtrip<T: Any, F>(
&mut self,
data: &mut T,
fallback: F
) -> Result<u32> where
F: FnMut(RawEvent, Main<AnonymousObject>, DispatchData<'_>),
Synchronous roundtrip
This call will cause a synchronous roundtrip with the wayland server. It will block until all pending requests of this queue are sent to the server and it has processed all of them and send the appropriate events.
Handlers are called as a consequence.
The provided data
will be mutably accessible from all the callbacks, via the
DispatchData
mechanism. If you don’t need global data, you
can just provide a &mut ()
there.
On success returns the number of dispatched events.
If an error is returned, your connection with the wayland compositor is probably lost.
You may want to check Display::protocol_error()
to see if it was caused by a protocol error.
sourcepub fn token(&self) -> QueueToken
pub fn token(&self) -> QueueToken
Create a new token associated with this event queue
See QueueToken
documentation for its use.
sourcepub fn prepare_read(&self) -> Option<ReadEventsGuard>
pub fn prepare_read(&self) -> Option<ReadEventsGuard>
Prepare an concurrent read
Will declare your intention to read events from the server socket.
Will return None
if there are still some events awaiting dispatch on this EventIterator.
In this case, you need to call dispatch_pending()
before calling this method again.
The guard can then be used by two means:
- Calling its
cancel()
method (or letting it go out of scope): the read intention will be cancelled - Calling its
read_events()
method: will block until all existing guards are destroyed by one of these methods, then events will be read and all blockedread_events()
calls will return.
This call will otherwise not block on the server socket if it is empty, and return
an io error WouldBlock
in such cases.
Trait Implementations
Auto Trait Implementations
impl !RefUnwindSafe for EventQueue
impl !Send for EventQueue
impl !Sync for EventQueue
impl Unpin for EventQueue
impl !UnwindSafe for EventQueue
Blanket Implementations
sourceimpl<T> BorrowMut<T> for T where
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
const: unstable · sourcefn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
sourceimpl<T> Downcast for T where
T: Any,
impl<T> Downcast for T where
T: Any,
sourcefn into_any(self: Box<T, Global>) -> Box<dyn Any + 'static, Global>
fn into_any(self: Box<T, Global>) -> Box<dyn Any + 'static, Global>
Convert Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
. Read more
sourcefn into_any_rc(self: Rc<T>) -> Rc<dyn Any + 'static>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any + 'static>
Convert Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
. Read more
sourcefn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
Convert &Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s. Read more
sourcefn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
Convert &mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s. Read more