Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
1
third-party/vendor/wayland-client/.cargo-checksum.json
vendored
Normal file
1
third-party/vendor/wayland-client/.cargo-checksum.json
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"files":{"Cargo.lock":"a1130c9836e2901b6b2f15f8582c9474d27cc2d04b10788d4fd3b7e96c70b666","Cargo.toml":"4d1f8c78a9fe5e7ef87491557c5d12e73da0bacfeae6b9524e7e86b33da1d3c2","LICENSE.txt":"10e5daea68c3ab7da6468ea51860e9d4ac87ea6a9a2d34127beff17b7193b618","README.md":"c4f1a5c35c0cd0e27a9694e29ef1972e1b14b6c9824b65e873601364deef8dbb","build.rs":"b6b886ce8f337caf6acbe900961e0e7021e448b0ab8e241d95d91526e54807e7","examples/dynamic_globals.rs":"bfc90aa38c6ea97f35b3775a54571566a76f44db9c3625f489832ccf7757de84","examples/list_globals.rs":"84331cc9d40fe6a0cbaa51c10b0ea630d0ab77731d8a54687db1041b88926672","examples/simple_window.rs":"5b6c76b60632e1200e9fc4bacc670836b80ad66b7ffcf48cf4ac374cd6404690","src/display.rs":"494dd4136e440554151b86a4fae64275fddf6f67ae5cc11e319d05ea869ec76f","src/event_queue.rs":"50ed69dd7f16156c5ba85af9740ab6c35d7ffd91fbda8764e317e48370b1dbf6","src/globals.rs":"d135d7e087e7c6018e69e21dafd65b24a3d49bfbbb9565cb287f780a6195a778","src/lib.rs":"4e86757fe8e6d5f1c6a489c480f94b056b2d720902250a74301dcc044a326de9","src/native_lib/display.rs":"ced4cdfac6c97c45d22e65a3df998d8bd7b096d21deaa5ed55f2a0edcbb520a7","src/native_lib/event_queue.rs":"1b76cceb36ea6539fc5f6ea2d2c0829c9d2ac8294a2b624581ce8a8116853cbb","src/native_lib/mod.rs":"f1180b3e6ad9fb3afa55a6e1a71693f79174f3952e3075cfa14f9534f0dd5c09","src/native_lib/proxy.rs":"f0dc9c2b209aad6513b70f345dd7aa50ca7584f27015b693e78ee410965f5445","src/proxy.rs":"56506bb1b1872dba975a2f194f56a795fa25101dc3ac85da953a9c6799666734","src/rust_imp/connection.rs":"e41e7888ad7af769d2ad696bff85a96b0541f374c82a2e029198dcb026a0c57e","src/rust_imp/display.rs":"b7cea1525eb4ff7b3c00a84a223fe2afb30aab7a822a8c8da7fb8de3159b3ad3","src/rust_imp/mod.rs":"0bc0a765490df2219195c2c8ae286999d4bc65d8e26514468eb9b4d8b75ec79f","src/rust_imp/proxy.rs":"91da236137458756fc1dcb882176b887b05a0a4c08412cc649ba1d712c8672c7","src/rust_imp/queues.rs":"87a2a2f02256553dcd35548e300b214d7d7b0c2bf840883f836ab0ba74e7f6c7","wayland.xml":"e20d8e766908e56828b3d39d20968382a3e725cfbca97bbbf0bbfab956cc7455"},"package":"3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715"}
|
||||
254
third-party/vendor/wayland-client/Cargo.lock
generated
vendored
Normal file
254
third-party/vendor/wayland-client/Cargo.lock
generated
vendored
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "dlib"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794"
|
||||
dependencies = [
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "downcast-rs"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
|
||||
dependencies = [
|
||||
"instant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.132"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.24.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"memoffset",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"remove_dir_all",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
|
||||
|
||||
[[package]]
|
||||
name = "wayland-client"
|
||||
version = "0.29.5"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"downcast-rs",
|
||||
"libc",
|
||||
"nix",
|
||||
"scoped-tls",
|
||||
"tempfile",
|
||||
"wayland-commons",
|
||||
"wayland-scanner",
|
||||
"wayland-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-commons"
|
||||
version = "0.29.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902"
|
||||
dependencies = [
|
||||
"nix",
|
||||
"once_cell",
|
||||
"smallvec",
|
||||
"wayland-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-scanner"
|
||||
version = "0.29.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"xml-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-sys"
|
||||
version = "0.29.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be12ce1a3c39ec7dba25594b97b42cb3195d54953ddb9d3d95a7c3902bc6e9d4"
|
||||
dependencies = [
|
||||
"dlib",
|
||||
"lazy_static",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "xml-rs"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3"
|
||||
73
third-party/vendor/wayland-client/Cargo.toml
vendored
Normal file
73
third-party/vendor/wayland-client/Cargo.toml
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
#
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "wayland-client"
|
||||
version = "0.29.5"
|
||||
authors = ["Victor Berger <victor.berger@m4x.org>"]
|
||||
build = "build.rs"
|
||||
description = "Bindings to the standard C implementation of the wayland protocol, client side."
|
||||
documentation = "https://smithay.github.io/wayland-rs/wayland_client/"
|
||||
readme = "README.md"
|
||||
keywords = [
|
||||
"wayland",
|
||||
"client",
|
||||
]
|
||||
categories = [
|
||||
"gui",
|
||||
"api-bindings",
|
||||
]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/smithay/wayland-rs"
|
||||
|
||||
[dependencies.bitflags]
|
||||
version = "1.0"
|
||||
|
||||
[dependencies.downcast-rs]
|
||||
version = "1.0"
|
||||
|
||||
[dependencies.libc]
|
||||
version = "0.2"
|
||||
|
||||
[dependencies.nix]
|
||||
version = "0.24.1"
|
||||
features = [
|
||||
"fs",
|
||||
"poll",
|
||||
]
|
||||
default-features = false
|
||||
|
||||
[dependencies.scoped-tls]
|
||||
version = "1.0"
|
||||
optional = true
|
||||
|
||||
[dependencies.wayland-commons]
|
||||
version = "0.29.5"
|
||||
|
||||
[dependencies.wayland-sys]
|
||||
version = "0.29.5"
|
||||
|
||||
[dev-dependencies.tempfile]
|
||||
version = ">=2.0, <4.0"
|
||||
|
||||
[build-dependencies.wayland-scanner]
|
||||
version = "0.29.5"
|
||||
|
||||
[features]
|
||||
dlopen = [
|
||||
"wayland-sys/dlopen",
|
||||
"use_system_lib",
|
||||
]
|
||||
use_system_lib = [
|
||||
"wayland-sys/client",
|
||||
"scoped-tls",
|
||||
]
|
||||
19
third-party/vendor/wayland-client/LICENSE.txt
vendored
Normal file
19
third-party/vendor/wayland-client/LICENSE.txt
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2015 Victor Berger
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
27
third-party/vendor/wayland-client/README.md
vendored
Normal file
27
third-party/vendor/wayland-client/README.md
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
[](https://crates.io/crates/wayland-client)
|
||||
[](https://docs.rs/wayland-client)
|
||||
[](https://github.com/Smithay/wayland-rs/actions?query=workflow%3A%22Continuous+Integration%22)
|
||||
[](https://codecov.io/gh/Smithay/wayland-rs)
|
||||
|
||||
# wayland-client
|
||||
|
||||
Client side API for the Wayland protocol. This crate provides infrastructure for manipulating
|
||||
Wayland objects, as well as object definitions for the core Wayland protocol. Protocol extensions
|
||||
can be supported as well by combining this crate with `wayland-protocols`, which provides object
|
||||
definitions for a large set of extensions.
|
||||
|
||||
**Note:** This crate is a low-level interface to the Wayland protocol. If you are looking for a more
|
||||
battery-included toolkit for writing a Wayland client app, you may consider
|
||||
[Smithay's Client Toolkit](https://crates.io/crates/smithay-client-toolkit), which is built on top
|
||||
of it.
|
||||
|
||||
The crate has different backends to Wayland protocol serialization:
|
||||
|
||||
- By default, it uses a pure-rust implementation of the protocol, and contains little `unsafe` code.
|
||||
- Activating the `use_system_lib` makes it instead bind to the system `libwayland-client.so`. This
|
||||
allows you to access C pointer versions of the wayland objects, which is necessary for interfacing
|
||||
with other non-Rust Wayland-related libraries (such as for OpenGL support, see the `wayland-egl` crate).
|
||||
- Activating the `dlopen` implies `use_system_lib`, but additionnaly the crate will not explicitly
|
||||
link to `libwayland-client.so` and instead try to open it at runtime, and return an error if it cannot
|
||||
find it. This allows you to build apps that can gracefully run in non-Wayland environment without needing
|
||||
compile-time switches.
|
||||
20
third-party/vendor/wayland-client/build.rs
vendored
Normal file
20
third-party/vendor/wayland-client/build.rs
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
extern crate wayland_scanner;
|
||||
|
||||
use std::env::var;
|
||||
use std::path::Path;
|
||||
use wayland_scanner::*;
|
||||
|
||||
fn main() {
|
||||
let protocol_file = "./wayland.xml";
|
||||
|
||||
let out_dir_str = var("OUT_DIR").unwrap();
|
||||
let out_dir = Path::new(&out_dir_str);
|
||||
|
||||
println!("cargo:rerun-if-changed={}", protocol_file);
|
||||
generate_code_with_destructor_events(
|
||||
protocol_file,
|
||||
out_dir.join("wayland_api.rs"),
|
||||
Side::Client,
|
||||
&[("wl_callback", "done")],
|
||||
);
|
||||
}
|
||||
110
third-party/vendor/wayland-client/examples/dynamic_globals.rs
vendored
Normal file
110
third-party/vendor/wayland-client/examples/dynamic_globals.rs
vendored
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
#[macro_use]
|
||||
extern crate wayland_client;
|
||||
|
||||
use wayland_client::{Display, GlobalManager, Main};
|
||||
|
||||
use wayland_client::protocol::{wl_output, wl_seat};
|
||||
|
||||
// An example showcasing the capability of GlobalManager to handle
|
||||
// dynamically created globals like wl_seat or wl_output, which can
|
||||
// exist with multiplicity and created at any time
|
||||
|
||||
fn main() {
|
||||
let display = Display::connect_to_env().unwrap();
|
||||
|
||||
let mut event_queue = display.create_event_queue();
|
||||
|
||||
let attached_display = (*display).clone().attach(event_queue.token());
|
||||
|
||||
// We create a GlobalManager with a callback, that will be
|
||||
// advertised of any global creation or deletion
|
||||
let _globals = GlobalManager::new_with_cb(
|
||||
&attached_display,
|
||||
// This macro generates a callback for auto-creating the globals
|
||||
// that interest us and calling our provided callbacks
|
||||
global_filter!(
|
||||
// Here we ask that all seats be automatically instantiated
|
||||
// with version 1 when advertised, and provide a callback that
|
||||
// will handle the created wl_seat to implement them
|
||||
//
|
||||
// NOTE: the type annotations are necessary because rustc's
|
||||
// inference is apparently not smart enough
|
||||
[wl_seat::WlSeat, 1, |seat: Main<wl_seat::WlSeat>, _: DispatchData| {
|
||||
let mut seat_name = None;
|
||||
let mut caps = None;
|
||||
seat.quick_assign(move |_, event, _| {
|
||||
use wayland_client::protocol::wl_seat::Event;
|
||||
match event {
|
||||
Event::Name { name } => {
|
||||
seat_name = Some(name);
|
||||
}
|
||||
Event::Capabilities { capabilities } => {
|
||||
// We *should* have received the "name" event first
|
||||
caps = Some(capabilities);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if let (Some(ref name), Some(caps)) = (&seat_name, caps) {
|
||||
println!("Seat '{}' with caps: {:x}", name, caps);
|
||||
}
|
||||
})
|
||||
}],
|
||||
// Same thing with wl_output, but we require version 2
|
||||
[wl_output::WlOutput, 2, |output: Main<wl_output::WlOutput>, _: DispatchData| {
|
||||
let mut name = "<unknown>".to_owned();
|
||||
let mut modes = vec![];
|
||||
let mut scale = 1;
|
||||
output.quick_assign(move |_, event, _| {
|
||||
use wayland_client::protocol::wl_output::Event;
|
||||
match event {
|
||||
Event::Geometry {
|
||||
x,
|
||||
y,
|
||||
physical_width,
|
||||
physical_height,
|
||||
subpixel,
|
||||
make,
|
||||
model,
|
||||
transform,
|
||||
} => {
|
||||
println!("New output: \"{} ({})\"", make, model);
|
||||
println!(
|
||||
" -> physical dimensions {}x{}",
|
||||
physical_width, physical_height
|
||||
);
|
||||
println!(" -> location in the compositor space: ({}, {})", x, y);
|
||||
println!(" -> transform: {:?}", transform);
|
||||
println!(" -> subpixel orientation: {:?}", subpixel);
|
||||
name = format!("{} ({})", make, model);
|
||||
}
|
||||
Event::Mode { flags, width, height, refresh } => {
|
||||
modes.push((flags, width, height, refresh));
|
||||
}
|
||||
Event::Scale { factor } => {
|
||||
scale = factor;
|
||||
}
|
||||
Event::Done => {
|
||||
println!("Modesetting information for output \"{}\"", name);
|
||||
println!(" -> scaling factor: {}", scale);
|
||||
println!(" -> mode list:");
|
||||
for &(f, w, h, r) in &modes {
|
||||
println!(
|
||||
" -> {}x{} @{}Hz (flags: [ {:?} ])",
|
||||
w,
|
||||
h,
|
||||
(r as f32) / 1000.0,
|
||||
f
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
})
|
||||
}]
|
||||
),
|
||||
);
|
||||
|
||||
event_queue.sync_roundtrip(&mut (), |_, _, _| unreachable!()).unwrap();
|
||||
event_queue.sync_roundtrip(&mut (), |_, _, _| unreachable!()).unwrap();
|
||||
event_queue.sync_roundtrip(&mut (), |_, _, _| unreachable!()).unwrap();
|
||||
}
|
||||
29
third-party/vendor/wayland-client/examples/list_globals.rs
vendored
Normal file
29
third-party/vendor/wayland-client/examples/list_globals.rs
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
extern crate wayland_client;
|
||||
|
||||
use wayland_client::{Display, GlobalManager};
|
||||
|
||||
// A minimal example printing the list of globals advertised by the server and
|
||||
// then exiting
|
||||
|
||||
fn main() {
|
||||
// Connect to the server
|
||||
let display = Display::connect_to_env().unwrap();
|
||||
|
||||
let mut event_queue = display.create_event_queue();
|
||||
|
||||
let attached_display = (*display).clone().attach(event_queue.token());
|
||||
|
||||
// We use the GlobalManager convenience provided by the crate, it covers
|
||||
// most classic use cases and avoids us the trouble to manually implement
|
||||
// the registry
|
||||
let globals = GlobalManager::new(&attached_display);
|
||||
|
||||
// A roundtrip synchronization to make sure the server received our registry
|
||||
// creation and sent us the global list
|
||||
event_queue.sync_roundtrip(&mut (), |_, _, _| unreachable!()).unwrap();
|
||||
|
||||
// Print the list
|
||||
for (id, interface, version) in globals.list() {
|
||||
println!("{}: {} (version {})", id, interface, version);
|
||||
}
|
||||
}
|
||||
206
third-party/vendor/wayland-client/examples/simple_window.rs
vendored
Normal file
206
third-party/vendor/wayland-client/examples/simple_window.rs
vendored
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
// Allow single character names so clippy doesn't lint on x, y, r, g, b, which
|
||||
// are reasonable variable names in this domain.
|
||||
#![allow(clippy::many_single_char_names)]
|
||||
|
||||
use std::{
|
||||
cmp::min,
|
||||
io::{BufWriter, Write},
|
||||
os::unix::io::AsRawFd,
|
||||
process::exit,
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
use wayland_client::{
|
||||
event_enum,
|
||||
protocol::{wl_compositor, wl_keyboard, wl_pointer, wl_seat, wl_shm},
|
||||
Display, Filter, GlobalManager,
|
||||
};
|
||||
use wayland_protocols::xdg_shell::client::{xdg_surface, xdg_toplevel, xdg_wm_base};
|
||||
|
||||
// declare an event enum containing the events we want to receive in the iterator
|
||||
event_enum!(
|
||||
Events |
|
||||
Pointer => wl_pointer::WlPointer,
|
||||
Keyboard => wl_keyboard::WlKeyboard
|
||||
);
|
||||
|
||||
fn main() {
|
||||
let now = Instant::now();
|
||||
|
||||
let display = Display::connect_to_env().unwrap();
|
||||
|
||||
let mut event_queue = display.create_event_queue();
|
||||
|
||||
let attached_display = (*display).clone().attach(event_queue.token());
|
||||
|
||||
let globals = GlobalManager::new(&attached_display);
|
||||
|
||||
// Make a synchronized roundtrip to the wayland server.
|
||||
//
|
||||
// When this returns it must be true that the server has already
|
||||
// sent us all available globals.
|
||||
event_queue.sync_roundtrip(&mut (), |_, _, _| unreachable!()).unwrap();
|
||||
|
||||
/*
|
||||
* Create a buffer with window contents
|
||||
*/
|
||||
|
||||
// buffer (and window) width and height
|
||||
let buf_x: u32 = 320;
|
||||
let buf_y: u32 = 240;
|
||||
|
||||
// create a tempfile to write the contents of the window on
|
||||
let mut tmp = tempfile::tempfile().expect("Unable to create a tempfile.");
|
||||
|
||||
// write the contents to it, lets put a nice color gradient
|
||||
{
|
||||
let now = Instant::now();
|
||||
|
||||
let mut buf = BufWriter::new(&mut tmp);
|
||||
for y in 0..buf_y {
|
||||
for x in 0..buf_x {
|
||||
let a = 0xFF;
|
||||
let r = min(((buf_x - x) * 0xFF) / buf_x, ((buf_y - y) * 0xFF) / buf_y);
|
||||
let g = min((x * 0xFF) / buf_x, ((buf_y - y) * 0xFF) / buf_y);
|
||||
let b = min(((buf_x - x) * 0xFF) / buf_x, (y * 0xFF) / buf_y);
|
||||
|
||||
let color = (a << 24) + (r << 16) + (g << 8) + b;
|
||||
buf.write_all(&color.to_ne_bytes()).unwrap();
|
||||
}
|
||||
}
|
||||
buf.flush().unwrap();
|
||||
|
||||
println!(
|
||||
"Time used to create the nice color gradient: {:?}",
|
||||
Instant::now().duration_since(now)
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Init wayland objects
|
||||
*/
|
||||
|
||||
// The compositor allows us to creates surfaces
|
||||
let compositor = globals.instantiate_exact::<wl_compositor::WlCompositor>(1).unwrap();
|
||||
let surface = compositor.create_surface();
|
||||
|
||||
// The SHM allows us to share memory with the server, and create buffers
|
||||
// on this shared memory to paint our surfaces
|
||||
let shm = globals.instantiate_exact::<wl_shm::WlShm>(1).unwrap();
|
||||
let pool = shm.create_pool(
|
||||
tmp.as_raw_fd(), // RawFd to the tempfile serving as shared memory
|
||||
(buf_x * buf_y * 4) as i32, // size in bytes of the shared memory (4 bytes per pixel)
|
||||
);
|
||||
let buffer = pool.create_buffer(
|
||||
0, // Start of the buffer in the pool
|
||||
buf_x as i32, // width of the buffer in pixels
|
||||
buf_y as i32, // height of the buffer in pixels
|
||||
(buf_x * 4) as i32, // number of bytes between the beginning of two consecutive lines
|
||||
wl_shm::Format::Argb8888, // chosen encoding for the data
|
||||
);
|
||||
|
||||
let xdg_wm_base = globals
|
||||
.instantiate_exact::<xdg_wm_base::XdgWmBase>(2)
|
||||
.expect("Compositor does not support xdg_shell");
|
||||
|
||||
xdg_wm_base.quick_assign(|xdg_wm_base, event, _| {
|
||||
if let xdg_wm_base::Event::Ping { serial } = event {
|
||||
xdg_wm_base.pong(serial);
|
||||
};
|
||||
});
|
||||
|
||||
let xdg_surface = xdg_wm_base.get_xdg_surface(&surface);
|
||||
xdg_surface.quick_assign(move |xdg_surface, event, _| match event {
|
||||
xdg_surface::Event::Configure { serial } => {
|
||||
println!("xdg_surface (Configure)");
|
||||
xdg_surface.ack_configure(serial);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
});
|
||||
|
||||
let xdg_toplevel = xdg_surface.get_toplevel();
|
||||
xdg_toplevel.quick_assign(move |_, event, _| match event {
|
||||
xdg_toplevel::Event::Close => {
|
||||
exit(0);
|
||||
}
|
||||
xdg_toplevel::Event::Configure { width, height, states } => {
|
||||
println!(
|
||||
"xdg_toplevel (Configure) width: {}, height: {}, states: {:?}",
|
||||
width, height, states
|
||||
);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
});
|
||||
xdg_toplevel.set_title("Simple Window".to_string());
|
||||
|
||||
// initialize a seat to retrieve pointer & keyboard events
|
||||
//
|
||||
// example of using a common filter to handle both pointer & keyboard events
|
||||
let common_filter = Filter::new(move |event, _, _| match event {
|
||||
Events::Pointer { event, .. } => match event {
|
||||
wl_pointer::Event::Enter { surface_x, surface_y, .. } => {
|
||||
println!("Pointer entered at ({}, {}).", surface_x, surface_y);
|
||||
}
|
||||
wl_pointer::Event::Leave { .. } => {
|
||||
println!("Pointer left.");
|
||||
}
|
||||
wl_pointer::Event::Motion { surface_x, surface_y, .. } => {
|
||||
println!("Pointer moved to ({}, {}).", surface_x, surface_y);
|
||||
}
|
||||
wl_pointer::Event::Button { button, state, .. } => {
|
||||
println!("Button {} was {:?}.", button, state);
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
Events::Keyboard { event, .. } => match event {
|
||||
wl_keyboard::Event::Enter { .. } => {
|
||||
println!("Gained keyboard focus.");
|
||||
}
|
||||
wl_keyboard::Event::Leave { .. } => {
|
||||
println!("Lost keyboard focus.");
|
||||
}
|
||||
wl_keyboard::Event::Key { key, state, .. } => {
|
||||
println!("Key with id {} was {:?}.", key, state);
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
});
|
||||
// to be handled properly this should be more dynamic, as more
|
||||
// than one seat can exist (and they can be created and destroyed
|
||||
// dynamically), however most "traditional" setups have a single
|
||||
// seat, so we'll keep it simple here
|
||||
let mut pointer_created = false;
|
||||
let mut keyboard_created = false;
|
||||
globals.instantiate_exact::<wl_seat::WlSeat>(1).unwrap().quick_assign(move |seat, event, _| {
|
||||
// The capabilities of a seat are known at runtime and we retrieve
|
||||
// them via an events. 3 capabilities exists: pointer, keyboard, and touch
|
||||
// we are only interested in pointer & keyboard here
|
||||
use wayland_client::protocol::wl_seat::{Capability, Event as SeatEvent};
|
||||
|
||||
if let SeatEvent::Capabilities { capabilities } = event {
|
||||
if !pointer_created && capabilities.contains(Capability::Pointer) {
|
||||
// create the pointer only once
|
||||
pointer_created = true;
|
||||
seat.get_pointer().assign(common_filter.clone());
|
||||
}
|
||||
if !keyboard_created && capabilities.contains(Capability::Keyboard) {
|
||||
// create the keyboard only once
|
||||
keyboard_created = true;
|
||||
seat.get_keyboard().assign(common_filter.clone());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
surface.commit();
|
||||
|
||||
event_queue.sync_roundtrip(&mut (), |_, _, _| { /* we ignore unfiltered messages */ }).unwrap();
|
||||
|
||||
surface.attach(Some(&buffer), 0, 0);
|
||||
surface.commit();
|
||||
|
||||
println!("Time used before enter in the main loop: {:?}", Instant::now().duration_since(now));
|
||||
|
||||
loop {
|
||||
event_queue.dispatch(&mut (), |_, _, _| { /* we ignore unfiltered messages */ }).unwrap();
|
||||
}
|
||||
}
|
||||
261
third-party/vendor/wayland-client/src/display.rs
vendored
Normal file
261
third-party/vendor/wayland-client/src/display.rs
vendored
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::io;
|
||||
use std::ops::Deref;
|
||||
use std::os::unix::io::{IntoRawFd, RawFd};
|
||||
use std::os::unix::net::UnixStream;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use nix::fcntl;
|
||||
|
||||
use crate::{EventQueue, Proxy};
|
||||
|
||||
use crate::imp::DisplayInner;
|
||||
|
||||
#[cfg(feature = "use_system_lib")]
|
||||
use wayland_sys::client::wl_display;
|
||||
|
||||
/// Enum representing the possible reasons why connecting to the wayland server failed
|
||||
#[derive(Debug)]
|
||||
pub enum ConnectError {
|
||||
/// The library was compiled with the `dlopen` feature, and the `libwayland-client.so`
|
||||
/// library could not be found at runtime
|
||||
NoWaylandLib,
|
||||
/// The `XDG_RUNTIME_DIR` variable is not set while it should be
|
||||
XdgRuntimeDirNotSet,
|
||||
/// Any needed library was found, but the listening socket of the server was not.
|
||||
///
|
||||
/// Most of the time, this means that the program was not started from a wayland session.
|
||||
NoCompositorListening,
|
||||
/// The provided socket name is invalid
|
||||
InvalidName,
|
||||
/// The FD provided in `WAYLAND_SOCKET` was invalid
|
||||
InvalidFd,
|
||||
}
|
||||
|
||||
impl ::std::error::Error for ConnectError {}
|
||||
|
||||
impl ::std::fmt::Display for ConnectError {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
|
||||
match *self {
|
||||
ConnectError::NoWaylandLib => f.write_str("Could not find libwayland-client.so."),
|
||||
ConnectError::XdgRuntimeDirNotSet => f.write_str("XDG_RUNTIME_DIR is not set."),
|
||||
ConnectError::NoCompositorListening => {
|
||||
f.write_str("Could not find a listening wayland compositor.")
|
||||
}
|
||||
ConnectError::InvalidName => f.write_str("The wayland socket name is invalid."),
|
||||
ConnectError::InvalidFd => f.write_str("The FD provided in WAYLAND_SOCKET is invalid."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A protocol error
|
||||
///
|
||||
/// This kind of error is generated by the server if your client didn't respect
|
||||
/// the protocol, after which the server will kill your connection.
|
||||
///
|
||||
/// If the dispatching methods of `EventQueues` start to fail, you may want to
|
||||
/// check `Display::protocol_error()` to see if a protocol error was generated.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ProtocolError {
|
||||
/// The error code associated with the error
|
||||
///
|
||||
/// It should be interpreted as an instance of the `Error` enum of the
|
||||
/// associated interface.
|
||||
pub code: u32,
|
||||
/// The id of the object that caused the error
|
||||
pub object_id: u32,
|
||||
/// The interface of the object that caused the error
|
||||
pub object_interface: &'static str,
|
||||
/// The message sent by the server describing the error
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
impl ::std::error::Error for ProtocolError {
|
||||
fn description(&self) -> &str {
|
||||
"Wayland protocol error"
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Display for ProtocolError {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
|
||||
write!(
|
||||
f,
|
||||
"Protocol error {} on object {}@{}: {}",
|
||||
self.code, self.object_interface, self.object_id, self.message
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// A connection to a wayland server
|
||||
///
|
||||
/// This object both represent the connection to the server and contains the
|
||||
/// primary `WlDisplay` wayland object. As such, it must be kept alive as long
|
||||
/// as you are connected. You can access the contained `WlDisplay` via `Deref`
|
||||
/// to create all the objects you need.
|
||||
///
|
||||
/// **Safety note:** If you activate the `use_system_lib` cargo feature and provide pointers
|
||||
/// to wayland objects to other libraries, you **must** ensure that these libraries clean up
|
||||
/// their state before the last clone of this `Display` is dropped, otherwise these libraries
|
||||
/// will access freed memory when doing their cleanup.
|
||||
#[derive(Clone)]
|
||||
pub struct Display {
|
||||
pub(crate) inner: Arc<DisplayInner>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Display {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str("Display { ... }")
|
||||
}
|
||||
}
|
||||
|
||||
impl Display {
|
||||
/// Attempt to connect to a wayland server using the contents of the environment variables
|
||||
///
|
||||
/// First of all, if the `WAYLAND_SOCKET` environment variable is set, it'll try to interpret
|
||||
/// it as a FD number to use.
|
||||
///
|
||||
/// Otherwise, it will try to connect to the socket name defined in the `WAYLAND_DISPLAY`
|
||||
/// environment variable, and error if it is not set.
|
||||
///
|
||||
/// This requires the `XDG_RUNTIME_DIR` variable to be properly set.
|
||||
pub fn connect_to_env() -> Result<Display, ConnectError> {
|
||||
if let Ok(txt) = env::var("WAYLAND_SOCKET") {
|
||||
// We should connect to the provided WAYLAND_SOCKET
|
||||
let fd = txt.parse::<i32>().map_err(|_| ConnectError::InvalidFd)?;
|
||||
// remove the variable so any child processes don't see it
|
||||
env::remove_var("WAYLAND_SOCKET");
|
||||
// set the CLOEXEC flag on this FD
|
||||
let flags = fcntl::fcntl(fd, fcntl::FcntlArg::F_GETFD);
|
||||
let result = flags
|
||||
.map(|f| fcntl::FdFlag::from_bits(f).unwrap() | fcntl::FdFlag::FD_CLOEXEC)
|
||||
.and_then(|f| fcntl::fcntl(fd, fcntl::FcntlArg::F_SETFD(f)));
|
||||
match result {
|
||||
Ok(_) => {
|
||||
// setting the O_CLOEXEC worked
|
||||
unsafe { Display::from_fd(fd) }
|
||||
}
|
||||
Err(_) => {
|
||||
// something went wrong in F_GETFD or F_SETFD
|
||||
let _ = ::nix::unistd::close(fd);
|
||||
Err(ConnectError::InvalidFd)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let mut socket_path = env::var_os("XDG_RUNTIME_DIR")
|
||||
.map(Into::<PathBuf>::into)
|
||||
.ok_or(ConnectError::XdgRuntimeDirNotSet)?;
|
||||
socket_path
|
||||
.push(env::var_os("WAYLAND_DISPLAY").ok_or(ConnectError::NoCompositorListening)?);
|
||||
|
||||
let socket = UnixStream::connect(socket_path)
|
||||
.map_err(|_| ConnectError::NoCompositorListening)?;
|
||||
unsafe { Display::from_fd(socket.into_raw_fd()) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempt to connect to a wayland server socket with given name
|
||||
///
|
||||
/// On success, you are given the `Display` object as well as the main `EventQueue` hosting
|
||||
/// the `WlDisplay` wayland object.
|
||||
///
|
||||
/// This requires the `XDG_RUNTIME_DIR` variable to be properly set.
|
||||
pub fn connect_to_name<S: Into<OsString>>(name: S) -> Result<Display, ConnectError> {
|
||||
let mut socket_path = env::var_os("XDG_RUNTIME_DIR")
|
||||
.map(Into::<PathBuf>::into)
|
||||
.ok_or(ConnectError::XdgRuntimeDirNotSet)?;
|
||||
socket_path.push(name.into());
|
||||
|
||||
let socket =
|
||||
UnixStream::connect(socket_path).map_err(|_| ConnectError::NoCompositorListening)?;
|
||||
unsafe { Display::from_fd(socket.into_raw_fd()) }
|
||||
}
|
||||
|
||||
/// Attempt to use an already connected unix socket on given FD to start a wayland connection
|
||||
///
|
||||
/// On success, you are given the `Display` object.
|
||||
///
|
||||
/// Will take ownership of the FD.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The file descriptor must be associated to a connected unix socket.
|
||||
pub unsafe fn from_fd(fd: RawFd) -> Result<Display, ConnectError> {
|
||||
Ok(Display { inner: DisplayInner::from_fd(fd)? })
|
||||
}
|
||||
|
||||
/// Non-blocking write to the server
|
||||
///
|
||||
/// Outgoing messages to the server are buffered by the library for efficiency. This method
|
||||
/// flushes the internal buffer to the server socket.
|
||||
///
|
||||
/// Will write as many pending requests as possible to the server socket. Never blocks: if not all
|
||||
/// requests could be written, will return an io error `WouldBlock`.
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
self.inner.flush()
|
||||
}
|
||||
|
||||
/// Create a new event queue associated with this wayland connection
|
||||
pub fn create_event_queue(&self) -> EventQueue {
|
||||
let evq_inner = DisplayInner::create_event_queue(&self.inner);
|
||||
EventQueue::new(evq_inner, self.clone())
|
||||
}
|
||||
|
||||
/// Retrieve the last protocol error if any occured
|
||||
///
|
||||
/// If your client does not respect some part of a protocol it is using, the server
|
||||
/// will send a special "protocol error" event and kill your connection. This method
|
||||
/// allows you to retrieve the contents of this event if it occured.
|
||||
///
|
||||
/// If the dispatch methods of the `EventQueue` return an error, this is an indication
|
||||
/// that a protocol error may have occured. Such errors are not recoverable, but this
|
||||
/// method allows you to gracefully display them to the user, along with indications for
|
||||
/// submitting a bug-report for example.
|
||||
pub fn protocol_error(&self) -> Option<ProtocolError> {
|
||||
self.inner.protocol_error()
|
||||
}
|
||||
|
||||
/// Retrieve the file descriptor associated with the wayland socket
|
||||
///
|
||||
/// This FD should only be used to integrate into a polling mechanism, and should
|
||||
/// never be directly read from or written to.
|
||||
pub fn get_connection_fd(&self) -> ::std::os::unix::io::RawFd {
|
||||
self.inner.get_connection_fd()
|
||||
}
|
||||
|
||||
#[cfg(feature = "use_system_lib")]
|
||||
/// Create a Display and from an external display
|
||||
///
|
||||
/// This allows you to interface with an already-existing wayland connection,
|
||||
/// for example provided by a GUI toolkit.
|
||||
///
|
||||
/// Note that if you need to retrieve the actual `wl_display` pointer back (rather than
|
||||
/// its wrapper), you must use the `get_display_ptr()` method.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The provided pointer must point to a valid `wl_display` from `libwayland-client`
|
||||
pub unsafe fn from_external_display(display_ptr: *mut wl_display) -> Display {
|
||||
Display { inner: DisplayInner::from_external(display_ptr) }
|
||||
}
|
||||
|
||||
#[cfg(feature = "use_system_lib")]
|
||||
/// Retrieve the `wl_display` pointer
|
||||
///
|
||||
/// If this `Display` was created from an external `wl_display`, its `c_ptr()` method will
|
||||
/// return a wrapper to the actual display. While this is perfectly good as a `wl_proxy`
|
||||
/// pointer, to send requests, this is not the actual `wl_display` and cannot be used as such.
|
||||
///
|
||||
/// This method will give you the `wl_display`.
|
||||
pub fn get_display_ptr(&self) -> *mut wl_display {
|
||||
self.inner.ptr()
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Display {
|
||||
type Target = Proxy<crate::protocol::wl_display::WlDisplay>;
|
||||
fn deref(&self) -> &Proxy<crate::protocol::wl_display::WlDisplay> {
|
||||
self.inner.get_proxy()
|
||||
}
|
||||
}
|
||||
283
third-party/vendor/wayland-client/src/event_queue.rs
vendored
Normal file
283
third-party/vendor/wayland-client/src/event_queue.rs
vendored
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
use std::{io, rc::Rc};
|
||||
|
||||
use crate::imp::EventQueueInner;
|
||||
use crate::{AnonymousObject, DispatchData, Display, Main, RawEvent};
|
||||
|
||||
/// 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:
|
||||
///
|
||||
/// ```no_run
|
||||
/// # extern crate wayland_client;
|
||||
/// # use wayland_client::{Display};
|
||||
/// # let display = Display::connect_to_env().unwrap();
|
||||
/// # let mut event_queue = display.create_event_queue();
|
||||
/// 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()`:
|
||||
///
|
||||
/// ```no_run
|
||||
/// # extern crate wayland_client;
|
||||
/// # use wayland_client::Display;
|
||||
/// # let display = Display::connect_to_env().unwrap();
|
||||
/// # let mut event_queue = display.create_event_queue();
|
||||
/// 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.
|
||||
/// }
|
||||
/// ```
|
||||
pub struct EventQueue {
|
||||
// EventQueue is *not* Send
|
||||
pub(crate) inner: Rc<EventQueueInner>,
|
||||
display: Display,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for EventQueue {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str("EventQueue { ... }")
|
||||
}
|
||||
}
|
||||
|
||||
/// A token representing this event queue
|
||||
///
|
||||
/// This token can be cloned and is meant to allow easier
|
||||
/// interaction with other functions in the library that
|
||||
/// require the specification of an event queue, like
|
||||
/// `Proxy::assign`.
|
||||
#[derive(Clone)]
|
||||
pub struct QueueToken {
|
||||
pub(crate) inner: Rc<EventQueueInner>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for QueueToken {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str("QueueToken { ... }")
|
||||
}
|
||||
}
|
||||
|
||||
impl EventQueue {
|
||||
pub(crate) fn new(inner: EventQueueInner, display: Display) -> EventQueue {
|
||||
EventQueue { inner: Rc::new(inner), display }
|
||||
}
|
||||
/// 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`](struct.DispatchData.html) 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.
|
||||
pub fn dispatch<T: std::any::Any, F>(&mut self, data: &mut T, fallback: F) -> io::Result<u32>
|
||||
where
|
||||
F: FnMut(RawEvent, Main<AnonymousObject>, DispatchData<'_>),
|
||||
{
|
||||
let mut data = DispatchData::wrap(data);
|
||||
self.inner.dispatch(data.reborrow(), fallback)
|
||||
}
|
||||
|
||||
/// 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`](struct.DispatchData.html) 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.
|
||||
pub fn dispatch_pending<T: std::any::Any, F>(
|
||||
&mut self,
|
||||
data: &mut T,
|
||||
fallback: F,
|
||||
) -> io::Result<u32>
|
||||
where
|
||||
F: FnMut(RawEvent, Main<AnonymousObject>, DispatchData<'_>),
|
||||
{
|
||||
let mut data = DispatchData::wrap(data);
|
||||
self.inner.dispatch_pending(data.reborrow(), fallback)
|
||||
}
|
||||
|
||||
/// 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`](struct.DispatchData.html) 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.
|
||||
pub fn sync_roundtrip<T: std::any::Any, F>(
|
||||
&mut self,
|
||||
data: &mut T,
|
||||
fallback: F,
|
||||
) -> io::Result<u32>
|
||||
where
|
||||
F: FnMut(RawEvent, Main<AnonymousObject>, DispatchData<'_>),
|
||||
{
|
||||
let mut data = DispatchData::wrap(data);
|
||||
self.inner.sync_roundtrip(data.reborrow(), fallback)
|
||||
}
|
||||
|
||||
/// Create a new token associated with this event queue
|
||||
///
|
||||
/// See `QueueToken` documentation for its use.
|
||||
pub fn token(&self) -> QueueToken {
|
||||
QueueToken { inner: self.inner.clone() }
|
||||
}
|
||||
|
||||
/// 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 blocked `read_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.
|
||||
pub fn prepare_read(&self) -> Option<ReadEventsGuard> {
|
||||
match self.inner.prepare_read() {
|
||||
Ok(()) => Some(ReadEventsGuard { inner: self.inner.clone(), done: false }),
|
||||
Err(()) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Access the `Display` of the connection
|
||||
pub fn display(&self) -> &Display {
|
||||
&self.display
|
||||
}
|
||||
}
|
||||
|
||||
/// A guard over a read intention.
|
||||
///
|
||||
/// See `EventQueue::prepare_read()` for details about its use.
|
||||
pub struct ReadEventsGuard {
|
||||
inner: Rc<EventQueueInner>,
|
||||
done: bool,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for ReadEventsGuard {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str("ReadEventsGuard { ... }")
|
||||
}
|
||||
}
|
||||
|
||||
impl ReadEventsGuard {
|
||||
/// Read events
|
||||
///
|
||||
/// Reads events from the server socket. If other `ReadEventsGuard` exists, will block
|
||||
/// until they are all consumed or destroyed.
|
||||
pub fn read_events(mut self) -> io::Result<()> {
|
||||
self.done = true;
|
||||
self.inner.read_events()
|
||||
}
|
||||
|
||||
/// Cancel the read
|
||||
///
|
||||
/// Will cancel the read intention associated with this guard. Never blocks.
|
||||
///
|
||||
/// Has the same effect as letting the guard go out of scope.
|
||||
pub fn cancel(self) {
|
||||
// just run the destructor
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ReadEventsGuard {
|
||||
fn drop(&mut self) {
|
||||
if !self.done {
|
||||
self.inner.cancel_read();
|
||||
}
|
||||
}
|
||||
}
|
||||
343
third-party/vendor/wayland-client/src/globals.rs
vendored
Normal file
343
third-party/vendor/wayland-client/src/globals.rs
vendored
Normal file
|
|
@ -0,0 +1,343 @@
|
|||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use crate::protocol::wl_display;
|
||||
use crate::protocol::wl_registry;
|
||||
use crate::{Attached, DispatchData, Interface, Main, Proxy};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Inner {
|
||||
list: Vec<(u32, String, u32)>,
|
||||
}
|
||||
|
||||
/// An utility to manage global objects
|
||||
///
|
||||
/// This utility provides an implemenation for the registry
|
||||
/// that track the list of globals for you, as well as utilities
|
||||
/// to bind them.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct GlobalManager {
|
||||
inner: Arc<Mutex<Inner>>,
|
||||
registry: Main<wl_registry::WlRegistry>,
|
||||
}
|
||||
|
||||
/// An error that occurred trying to bind a global
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum GlobalError {
|
||||
/// The requested global was missing
|
||||
Missing,
|
||||
/// The global advertised by the server has a lower version number
|
||||
/// than the one requested
|
||||
VersionTooLow(u32),
|
||||
}
|
||||
|
||||
impl ::std::error::Error for GlobalError {}
|
||||
|
||||
impl ::std::fmt::Display for GlobalError {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
|
||||
match *self {
|
||||
GlobalError::Missing => f.write_str("The requested global was missing."),
|
||||
GlobalError::VersionTooLow(_) => {
|
||||
f.write_str("The requested global's version is too low.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Event provided to the user callback of GlobalManager
|
||||
#[derive(Debug)]
|
||||
pub enum GlobalEvent {
|
||||
/// A new global was created
|
||||
New {
|
||||
/// Id of the new global
|
||||
id: u32,
|
||||
/// Interface of the new global
|
||||
interface: String,
|
||||
/// Maximum supported version of the new global
|
||||
version: u32,
|
||||
},
|
||||
/// A global was removed
|
||||
Removed {
|
||||
/// Id of the removed global
|
||||
id: u32,
|
||||
/// Interface of the removed global
|
||||
interface: String,
|
||||
},
|
||||
}
|
||||
|
||||
impl GlobalManager {
|
||||
/// Create a global manager handling a registry
|
||||
///
|
||||
/// You need to provide an attached handle of the Waland display, and the
|
||||
/// global manager will be managed by the associated event queue.
|
||||
pub fn new(display: &Attached<wl_display::WlDisplay>) -> GlobalManager {
|
||||
let inner = Arc::new(Mutex::new(Inner { list: Vec::new() }));
|
||||
let inner_clone = inner.clone();
|
||||
|
||||
let registry = display
|
||||
.as_ref()
|
||||
.send::<wl_registry::WlRegistry>(wl_display::Request::GetRegistry {}, None)
|
||||
.unwrap();
|
||||
registry.quick_assign(move |_proxy, msg, _data| {
|
||||
let mut inner = inner.lock().unwrap();
|
||||
match msg {
|
||||
wl_registry::Event::Global { name, interface, version } => {
|
||||
inner.list.push((name, interface, version));
|
||||
}
|
||||
wl_registry::Event::GlobalRemove { name } => {
|
||||
inner.list.retain(|&(n, _, _)| n != name);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
GlobalManager { inner: inner_clone, registry }
|
||||
}
|
||||
|
||||
/// Create a global manager handling a registry with a callback
|
||||
///
|
||||
/// This global manager will track globals as a simple one, but will
|
||||
/// also forward the registry events to your callback.
|
||||
///
|
||||
/// This can be used if you want to handle specially certain globals, but want
|
||||
/// to use the default mechanism for the rest.
|
||||
///
|
||||
/// You need to provide an attached handle of the Waland display, and the
|
||||
/// global manager will be managed by the associated event queue.
|
||||
pub fn new_with_cb<F>(
|
||||
display: &Attached<wl_display::WlDisplay>,
|
||||
mut callback: F,
|
||||
) -> GlobalManager
|
||||
where
|
||||
F: FnMut(GlobalEvent, Attached<wl_registry::WlRegistry>, DispatchData) + 'static,
|
||||
{
|
||||
let inner = Arc::new(Mutex::new(Inner { list: Vec::new() }));
|
||||
let inner_clone = inner.clone();
|
||||
|
||||
let registry = display
|
||||
.as_ref()
|
||||
.send::<wl_registry::WlRegistry>(wl_display::Request::GetRegistry {}, None)
|
||||
.unwrap();
|
||||
registry.quick_assign(move |proxy, msg, data| {
|
||||
let mut inner = inner.lock().unwrap();
|
||||
let inner = &mut *inner;
|
||||
match msg {
|
||||
wl_registry::Event::Global {
|
||||
name,
|
||||
interface,
|
||||
version,
|
||||
} => {
|
||||
inner.list.push((name, interface.clone(), version));
|
||||
callback(
|
||||
GlobalEvent::New {
|
||||
id: name,
|
||||
interface,
|
||||
version,
|
||||
},
|
||||
(*proxy).clone(),
|
||||
data,
|
||||
);
|
||||
}
|
||||
wl_registry::Event::GlobalRemove { name } => {
|
||||
if let Some((i, _)) = inner.list.iter().enumerate().find(|&(_, &(n, _, _))| n == name) {
|
||||
let (id, interface, _) = inner.list.swap_remove(i);
|
||||
callback(GlobalEvent::Removed { id, interface }, (*proxy).clone(), data);
|
||||
} else {
|
||||
panic!(
|
||||
"Wayland protocol error: the server removed non-existing global \"{}\".",
|
||||
name
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
GlobalManager { inner: inner_clone, registry }
|
||||
}
|
||||
|
||||
/// Instantiate a global with a specific version
|
||||
///
|
||||
/// Meaning of requests and events can change depending on the object version you use,
|
||||
/// as such unless you specifically want to support several versions of a protocol, it is
|
||||
/// recommended to use this method with an hardcoded value for the version (the one you'll
|
||||
/// use a as reference for your implementation). Notably you should *not* use `I::VERSION`
|
||||
/// as a version, as this value can change when the protocol files are updated.
|
||||
///
|
||||
/// This method is only appropriate for globals that are expected to
|
||||
/// not exist with multiplicity (such as `wl_compositor` or `wl_shm`),
|
||||
/// as it will always bind the first one that was advertized.
|
||||
pub fn instantiate_exact<I>(&self, version: u32) -> Result<Main<I>, GlobalError>
|
||||
where
|
||||
I: Interface + AsRef<Proxy<I>> + From<Proxy<I>>,
|
||||
{
|
||||
let inner = self.inner.lock().unwrap();
|
||||
for &(id, ref interface, server_version) in &inner.list {
|
||||
if interface == I::NAME {
|
||||
if version > server_version {
|
||||
return Err(GlobalError::VersionTooLow(server_version));
|
||||
} else {
|
||||
return Ok(self.registry.bind::<I>(version, id));
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(GlobalError::Missing)
|
||||
}
|
||||
|
||||
/// Instantiate a global from a version range
|
||||
///
|
||||
/// If you want to support several versions of a particular global, this method allows you to
|
||||
/// specify a range of versions that you accept. It'll bind the highest possible version that
|
||||
/// is between `min_version` and `max_version` inclusive, and return an error if the highest
|
||||
/// version supported by the compositor is lower than `min_version`. As for
|
||||
/// `instantiate_exact`, you should not use `I::VERSION` here: the versions your code support
|
||||
/// do not change when the protocol files are updated.
|
||||
///
|
||||
/// When trying to support several versions of a protocol, you can check which version has
|
||||
/// actually been used on any object using the `Proxy::version()` method.
|
||||
///
|
||||
/// As `instantiate_exact`, it should only be used for singleton globals, for the same reasons.
|
||||
pub fn instantiate_range<I>(
|
||||
&self,
|
||||
min_version: u32,
|
||||
max_version: u32,
|
||||
) -> Result<Main<I>, GlobalError>
|
||||
where
|
||||
I: Interface + AsRef<Proxy<I>> + From<Proxy<I>>,
|
||||
{
|
||||
let inner = self.inner.lock().unwrap();
|
||||
for &(id, ref interface, version) in &inner.list {
|
||||
if interface == I::NAME {
|
||||
if version >= min_version {
|
||||
let version = ::std::cmp::min(version, max_version);
|
||||
return Ok(self.registry.bind::<I>(version, id));
|
||||
} else {
|
||||
return Err(GlobalError::VersionTooLow(version));
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(GlobalError::Missing)
|
||||
}
|
||||
|
||||
/// Retrieve the list of currently known globals
|
||||
pub fn list(&self) -> Vec<(u32, String, u32)> {
|
||||
self.inner.lock().unwrap().list.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for implementation of the global advertisement
|
||||
///
|
||||
/// It is automatically implemented for `FnMut(Main<I>, DispatchData)` closures,
|
||||
/// in which case the `error` messages are ignored.
|
||||
pub trait GlobalImplementor<I: Interface + AsRef<Proxy<I>> + From<Proxy<I>>> {
|
||||
/// A new global of given interface has been instantiated and you can assign
|
||||
/// a filter to it.
|
||||
fn new_global(&mut self, global: Main<I>, data: DispatchData);
|
||||
/// A global was advertised but its version was lower than the minimal version
|
||||
/// you requested.
|
||||
///
|
||||
/// The advertised version is provided as argument.
|
||||
fn error(&mut self, _version: u32, _data: DispatchData) {}
|
||||
}
|
||||
|
||||
impl<F, I: Interface> GlobalImplementor<I> for F
|
||||
where
|
||||
I: Interface + AsRef<Proxy<I>> + From<Proxy<I>>,
|
||||
F: FnMut(Main<I>, DispatchData),
|
||||
{
|
||||
fn new_global(&mut self, global: Main<I>, data: DispatchData) {
|
||||
(*self)(global, data)
|
||||
}
|
||||
}
|
||||
|
||||
/// Convenience macro to create a `GlobalManager` callback
|
||||
///
|
||||
/// This macro aims to simplify the specific but common case of
|
||||
/// providing a callback to the `GlobalManager` that needs to
|
||||
/// auto-bind all advertised instances of some specific globals
|
||||
/// whenever they happen. Typically, your application will likely
|
||||
/// want to keep track of all `wl_seat` and `wl_output` globals
|
||||
/// to be able to correctly react to user input and their different
|
||||
/// monitors.
|
||||
///
|
||||
/// The output of this macro is a closure, that can be given to
|
||||
/// `GlobalManager::new_with_cb` as the callback argument.
|
||||
///
|
||||
/// Example use is typically:
|
||||
///
|
||||
/// ```no_run
|
||||
/// # #[macro_use] extern crate wayland_client;
|
||||
/// use wayland_client::GlobalManager;
|
||||
/// # use wayland_client::{Display, Main, DispatchData};
|
||||
/// use wayland_client::protocol::{wl_output, wl_seat};
|
||||
///
|
||||
/// # fn main() {
|
||||
/// # let display = Display::connect_to_env().unwrap();
|
||||
/// # let mut event_queue = display.create_event_queue();
|
||||
/// # let seat_implementor: fn(Main<_>, DispatchData) = unimplemented!();
|
||||
/// # let output_implementor: fn(Main<_>, DispatchData) = unimplemented!();
|
||||
/// let globals = GlobalManager::new_with_cb(
|
||||
/// &display.attach(event_queue.token()),
|
||||
/// global_filter!(
|
||||
/// // Bind all wl_seat with version 4
|
||||
/// [wl_seat::WlSeat, 4, seat_implementor],
|
||||
/// // Bind all wl_output with version 1
|
||||
/// [wl_output::WlOutput, 1, output_implementor]
|
||||
/// )
|
||||
/// );
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// The supplied callbacks for each global kind must be an instance of a type
|
||||
/// implementing the `GlobalImplementor<I>` trait. The argument provided to your
|
||||
/// callback is a `Main` handle of the newly instantiated global, and you should assign it
|
||||
/// to a filter in this callback if you plan to do so.. The error case happens if the server
|
||||
/// advertised a lower version of the global than the one you requested, in which case you
|
||||
/// are given the version it advertised in the error method, if you want to handle it graciously.
|
||||
///
|
||||
/// You can also provide closures for the various callbacks, in this case the errors will
|
||||
/// be ignored. However, due to a lack of capability of rustc's inference, you'll likely need
|
||||
/// to add some type annotation to your closure, typically something like this:
|
||||
///
|
||||
/// ```ignore
|
||||
/// global_filter!(
|
||||
/// [Interface, version, |proxy: Main<_>, dispatch_data| {
|
||||
/// /* Setup the global as required */
|
||||
/// }]
|
||||
/// );
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! global_filter {
|
||||
($([$interface:ty, $version:expr, $callback:expr]),*) => {
|
||||
{
|
||||
use $crate::protocol::wl_registry;
|
||||
use $crate::{GlobalEvent, Interface, Attached, GlobalImplementor, DispatchData};
|
||||
type Callback = Box<dyn FnMut(u32, u32, Attached<wl_registry::WlRegistry>, DispatchData<'_>)>;
|
||||
let mut callbacks: Vec<(&'static str, Callback)> = Vec::new();
|
||||
// Create the callback list
|
||||
$({
|
||||
let mut cb = { $callback };
|
||||
callbacks.push((
|
||||
<$interface as Interface>::NAME,
|
||||
Box::new(move |id, version, registry: Attached<wl_registry::WlRegistry>, ddata: DispatchData| {
|
||||
if version < $version {
|
||||
GlobalImplementor::<$interface>::error(&mut cb, version, ddata);
|
||||
} else {
|
||||
let proxy = registry.bind::<$interface>(version, id);
|
||||
GlobalImplementor::<$interface>::new_global(&mut cb, proxy, ddata);
|
||||
}
|
||||
}) as Box<_>
|
||||
));
|
||||
})*
|
||||
|
||||
// return the global closure
|
||||
move |event: GlobalEvent, registry: Attached<wl_registry::WlRegistry>, ddata| {
|
||||
if let GlobalEvent::New { id, interface, version } = event {
|
||||
for &mut (iface, ref mut cb) in &mut callbacks {
|
||||
if iface == interface {
|
||||
cb(id, version, registry, ddata);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
321
third-party/vendor/wayland-client/src/lib.rs
vendored
Normal file
321
third-party/vendor/wayland-client/src/lib.rs
vendored
Normal file
|
|
@ -0,0 +1,321 @@
|
|||
//! Client-side Wayland connector
|
||||
//!
|
||||
//! ## Overview
|
||||
//!
|
||||
//! This crate provides the interfaces and machinery to safely create
|
||||
//! client applications for the Wayland protocol. It can be used as a rust
|
||||
//! implementation of the protocol or as a wrapper around the system-wide
|
||||
//! `libwayland-client.so` if you enable the `use_system_lib` cargo feature.
|
||||
//!
|
||||
//! The Wayland protocol revolves around the creation of various objects
|
||||
//! and the exchange of messages associated to these objects. The initial
|
||||
//! object is always the `Display`, that you get at initialization of the
|
||||
//! connection, exposed by this crate as `Display::connect_to_env()`.
|
||||
//!
|
||||
//! ## Protocol and messages handling model
|
||||
//!
|
||||
//! The protocol being bi-directional, you can send and receive messages.
|
||||
//! Sending messages is done via methods of Rust objects corresponding to the wayland protocol
|
||||
//! objects, receiving and handling them is done by providing callbacks.
|
||||
//!
|
||||
//! ### Proxies
|
||||
//!
|
||||
//! Wayland objects are represented by proxies, which are handles to them.
|
||||
//! You can interact with them in 4 states:
|
||||
//!
|
||||
//! - As the interface object directly `I`. This representation is the most immediate
|
||||
//! one. It allows you to send requests though this object and can be send accross threads.
|
||||
//! - As a `Proxy<I>`. This representation is suitable if you want to access the proxy as
|
||||
//! a proxy, rather than a wayland object. You can convert between `I` and `Proxy<I>` via
|
||||
//! the `From` and `Into` traits, and get a `&Proxy<I>` from an `I` via the `AsRef` trait.
|
||||
//! - As a `Main<I>`. This represents a main handle to this proxy, and allows you greater
|
||||
//! control of the object, but cannot be shared accros threads. This handle allows you to
|
||||
//! assign filters to the object, and send requests that create new objects.
|
||||
//! - As an `Attached<I>`. If you use more than one event queue (see below), this allows you
|
||||
//! to control on which event queue the children object are created.
|
||||
//!
|
||||
//! There is not a 1 to 1 mapping between Rust object instances and protocol
|
||||
//! objects. Rather, you can think of the Rust objects as `Rc`-like handles to a
|
||||
//! Wayland object. Multiple instances of a Rust object can exist referring to the same
|
||||
//! protocol object.
|
||||
//!
|
||||
//! Similarly, the lifetimes of the protocol objects and the Rust objects are
|
||||
//! not tightly tied. As protocol objects are created and destroyed by protocol
|
||||
//! messages, it can happen that an object gets destroyed while one or more
|
||||
//! Rust objects still refer to it. In such case, these Rust objects will be disabled
|
||||
//! and the `alive()` method on the underlying `Proxy<I>` will start to return `false`.
|
||||
//!
|
||||
//! Sending requests on dead objects will be silently ignored. And if these requests
|
||||
//! would create new objects, these objects will be created dead.
|
||||
//!
|
||||
//! ### Filters
|
||||
//!
|
||||
//! Your wayland objects can receive events from the server, which need to be processed.
|
||||
//! To do so, you can assign `Filter`s to your object. These are specially wrapped closure
|
||||
//! so that several objects can be assigned to the same `Filter`, to ease state sharing
|
||||
//! between the code handling different objects.
|
||||
//!
|
||||
//! If an object is not assigned to any `Filter`, its events will instead be delivered to the
|
||||
//! fallback closure given to its event queue when dispatching it.
|
||||
//!
|
||||
//! ## Event Queues
|
||||
//!
|
||||
//! The Wayland client machinery provides the possibility to have one or more event queues
|
||||
//! handling the processing of received messages. All Wayland objects are associated to an
|
||||
//! event queue, which controls when its events are dispatched.
|
||||
//!
|
||||
//! Events received from the server are stored in an internal buffer, and processed (by calling
|
||||
//! the appropriate callbacks) when the associated event queue is dispatched.
|
||||
//!
|
||||
//! When you send a request creating a new object, this new object will be assigned to an event
|
||||
//! queue depending on the parent object that created it.
|
||||
//!
|
||||
//! - If the request was sent from a `Main<I>` handle, the child object will be assigned to the
|
||||
//! same event queue as its parent.
|
||||
//! - If the request was sent from an `Attached<I>` handle, the child object will be assigned to
|
||||
//! the event queue its parent has been attached to.
|
||||
//!
|
||||
//! At the beginning you'll need to create an event queue and assign the initial `Proxy<WlDisplay>`
|
||||
//! to it.
|
||||
//!
|
||||
//! ## Dynamic linking with `libwayland-client.so`
|
||||
//!
|
||||
//! If you need to gracefully handle the case of a system on which Wayland is not installed (by
|
||||
//! fallbacking to X11 for example), you can do so by activating the `dlopen` cargo feature.
|
||||
//!
|
||||
//! When this is done, the library will be loaded a runtime rather than directly linked. And trying
|
||||
//! to create a `Display` on a system that does not have this library will return a `NoWaylandLib`
|
||||
//! error.
|
||||
|
||||
#![warn(missing_docs, missing_debug_implementations)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
#[cfg(not(feature = "use_system_lib"))]
|
||||
#[macro_use]
|
||||
extern crate downcast_rs as downcast;
|
||||
|
||||
#[cfg_attr(feature = "use_system_lib", macro_use)]
|
||||
extern crate wayland_sys;
|
||||
|
||||
mod display;
|
||||
mod event_queue;
|
||||
mod globals;
|
||||
mod proxy;
|
||||
|
||||
pub use anonymous_object::AnonymousObject;
|
||||
pub use display::{ConnectError, Display, ProtocolError};
|
||||
pub use event_queue::{EventQueue, QueueToken, ReadEventsGuard};
|
||||
pub use globals::{GlobalError, GlobalEvent, GlobalImplementor, GlobalManager};
|
||||
pub use imp::ProxyMap;
|
||||
pub use proxy::{Attached, Main, Proxy};
|
||||
pub use wayland_commons::{
|
||||
filter::{DispatchData, Filter},
|
||||
user_data::UserData,
|
||||
Interface, MessageGroup, NoMessage,
|
||||
};
|
||||
|
||||
// rust implementation
|
||||
#[cfg(not(feature = "use_system_lib"))]
|
||||
#[path = "rust_imp/mod.rs"]
|
||||
mod imp;
|
||||
// C-lib based implementation
|
||||
#[cfg(feature = "use_system_lib")]
|
||||
#[path = "native_lib/mod.rs"]
|
||||
mod imp;
|
||||
|
||||
/// C-associated types
|
||||
///
|
||||
/// Required for plugging wayland-scanner generated protocols
|
||||
/// or interfacing with C code using wayland objects.
|
||||
pub mod sys {
|
||||
pub use wayland_sys::{client, common};
|
||||
}
|
||||
|
||||
pub mod protocol {
|
||||
#![allow(dead_code, non_camel_case_types, unused_unsafe, unused_variables)]
|
||||
#![allow(non_upper_case_globals, non_snake_case, unused_imports)]
|
||||
#![allow(missing_docs, clippy::all)]
|
||||
|
||||
pub(crate) use crate::{AnonymousObject, Attached, Main, Proxy, ProxyMap};
|
||||
pub(crate) use wayland_commons::map::{Object, ObjectMetadata};
|
||||
pub(crate) use wayland_commons::smallvec;
|
||||
pub(crate) use wayland_commons::wire::{Argument, ArgumentType, Message, MessageDesc};
|
||||
pub(crate) use wayland_commons::{Interface, MessageGroup};
|
||||
pub(crate) use wayland_sys as sys;
|
||||
include!(concat!(env!("OUT_DIR"), "/wayland_api.rs"));
|
||||
}
|
||||
|
||||
mod anonymous_object {
|
||||
use super::{Interface, NoMessage, Proxy};
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
|
||||
/// Anonymous interface
|
||||
///
|
||||
/// A special Interface implementation representing an
|
||||
/// handle to an object for which the interface is not known.
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
pub struct AnonymousObject(pub(crate) Proxy<AnonymousObject>);
|
||||
|
||||
impl Interface for AnonymousObject {
|
||||
type Request = NoMessage;
|
||||
type Event = NoMessage;
|
||||
const NAME: &'static str = "<anonymous>";
|
||||
const VERSION: u32 = 0;
|
||||
fn c_interface() -> *const crate::sys::common::wl_interface {
|
||||
std::ptr::null()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<Proxy<AnonymousObject>> for AnonymousObject {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &Proxy<Self> {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
impl From<Proxy<AnonymousObject>> for AnonymousObject {
|
||||
#[inline]
|
||||
fn from(proxy: Proxy<Self>) -> Self {
|
||||
AnonymousObject(proxy)
|
||||
}
|
||||
}
|
||||
impl From<AnonymousObject> for Proxy<AnonymousObject> {
|
||||
#[inline]
|
||||
fn from(value: AnonymousObject) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
impl Debug for AnonymousObject {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.write_fmt(format_args!("{:?}", self.0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Enum of possible argument in an event
|
||||
#[derive(Debug)]
|
||||
pub enum Argument {
|
||||
/// i32
|
||||
Int(i32),
|
||||
/// u32
|
||||
Uint(u32),
|
||||
/// float
|
||||
Float(f32),
|
||||
/// CString
|
||||
Str(Option<String>),
|
||||
/// id of a wayland object
|
||||
Object(Option<Proxy<AnonymousObject>>),
|
||||
/// id of a newly created wayland object
|
||||
NewId(Option<Main<AnonymousObject>>),
|
||||
/// Vec<u8>
|
||||
Array(Option<Vec<u8>>),
|
||||
/// RawFd
|
||||
Fd(std::os::unix::io::RawFd),
|
||||
}
|
||||
|
||||
/// An generic event
|
||||
#[derive(Debug)]
|
||||
pub struct RawEvent {
|
||||
/// Interface of the associated object
|
||||
pub interface: &'static str,
|
||||
/// Opcode of the event
|
||||
pub opcode: u16,
|
||||
/// Name of the event
|
||||
pub name: &'static str,
|
||||
/// Arguments of the message
|
||||
pub args: Vec<Argument>,
|
||||
}
|
||||
|
||||
/// Generate an enum joining several objects events
|
||||
///
|
||||
/// This macro allows you to easily create a enum type for use with your message Filters. It is
|
||||
/// used like so:
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use wayland_client::protocol::{wl_pointer::WlPointer, wl_keyboard::WlKeyboard, wl_surface::WlSurface};
|
||||
/// # use wayland_client::event_enum;
|
||||
/// event_enum!(
|
||||
/// MyEnum |
|
||||
/// Pointer => WlPointer,
|
||||
/// Keyboard => WlKeyboard,
|
||||
/// Surface => WlSurface
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// This will generate the following enum, unifying the events from each of the provided interface:
|
||||
///
|
||||
/// ```ignore
|
||||
/// pub enum MyEnum {
|
||||
/// Pointer { event: WlPointer::Event, object: Main<WlPointer> },
|
||||
/// Keyboard { event: WlKeyboard::Event, object: Main<WlKeyboard> },
|
||||
/// Surface { event: WlSurface::Event, object: Main<WlSurface> }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// It will also generate the appropriate `From<_>` implementation so that a `Filter<MyEnum>` can be
|
||||
/// used as an implementation for `WlPointer`, `WlKeyboard` and `WlSurface`.
|
||||
///
|
||||
/// If you want to add custom messages to the enum, the macro also supports it:
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use wayland_client::protocol::{wl_pointer::WlPointer, wl_keyboard::WlKeyboard, wl_surface::WlSurface};
|
||||
/// # use wayland_client::event_enum;
|
||||
/// # struct SomeType;
|
||||
/// # struct OtherType;
|
||||
/// event_enum!(
|
||||
/// MyEnum |
|
||||
/// Pointer => WlPointer,
|
||||
/// Keyboard => WlKeyboard,
|
||||
/// Surface => WlSurface |
|
||||
/// MyMessage => SomeType,
|
||||
/// OtherMessage => OtherType
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// will generate the following enum:
|
||||
///
|
||||
/// ```ignore
|
||||
/// pub enum MyEnum {
|
||||
/// Pointer { event: WlPointer::Event, object: Main<WlPointer> },
|
||||
/// Keyboard { event: WlKeyboard::Event, object: Main<WlKeyboard> },
|
||||
/// Surface { event: WlSurface::Event, object: Main<WlSurface> },
|
||||
/// MyMessage(SomeType),
|
||||
/// OtherMessage(OtherType)
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// as well as implementations of `From<SomeType>` and `From<OtherType>`, so that these types can
|
||||
/// directly be provided into a `Filter<MyEnum>`.
|
||||
#[macro_export]
|
||||
macro_rules! event_enum(
|
||||
($(#[$attrs:meta])* $enu:ident | $($evt_name:ident => $iface:ty),*) => {
|
||||
$crate::event_enum!($(#[$attrs])* $enu | $($evt_name => $iface),* | );
|
||||
};
|
||||
($(#[$attrs:meta])* $enu:ident | $($evt_name:ident => $iface:ty),* | $($name:ident => $value:ty),*) => {
|
||||
$(#[$attrs])*
|
||||
pub enum $enu {
|
||||
$(
|
||||
$evt_name { event: <$iface as $crate::Interface>::Event, object: $crate::Main<$iface> },
|
||||
)*
|
||||
$(
|
||||
$name($value),
|
||||
)*
|
||||
}
|
||||
|
||||
$(
|
||||
impl From<($crate::Main<$iface>, <$iface as $crate::Interface>::Event)> for $enu {
|
||||
fn from((object, event): ($crate::Main<$iface>, <$iface as $crate::Interface>::Event)) -> $enu {
|
||||
$enu::$evt_name { event, object }
|
||||
}
|
||||
}
|
||||
)*
|
||||
|
||||
$(
|
||||
impl From<$value> for $enu {
|
||||
fn from(value: $value) -> $enu {
|
||||
$enu::$name(value)
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
);
|
||||
128
third-party/vendor/wayland-client/src/native_lib/display.rs
vendored
Normal file
128
third-party/vendor/wayland-client/src/native_lib/display.rs
vendored
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
use std::io;
|
||||
use std::os::unix::io::RawFd;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::protocol::wl_display::WlDisplay;
|
||||
use wayland_sys::client::*;
|
||||
|
||||
use crate::{ConnectError, Proxy};
|
||||
|
||||
use super::{EventQueueInner, ProxyInner};
|
||||
|
||||
pub(crate) struct DisplayInner {
|
||||
proxy: Proxy<WlDisplay>,
|
||||
display: Arc<DisplayGuard>,
|
||||
}
|
||||
|
||||
pub(crate) struct DisplayGuard {
|
||||
ptr: *mut wl_display,
|
||||
external: bool,
|
||||
}
|
||||
|
||||
unsafe impl Send for DisplayInner {}
|
||||
unsafe impl Sync for DisplayInner {}
|
||||
|
||||
unsafe fn make_display(ptr: *mut wl_display) -> Result<Arc<DisplayInner>, ConnectError> {
|
||||
if ptr.is_null() {
|
||||
return Err(ConnectError::NoCompositorListening);
|
||||
}
|
||||
|
||||
let mut inner = DisplayInner {
|
||||
proxy: Proxy::from_c_ptr(ptr as *mut _),
|
||||
display: Arc::new(DisplayGuard { ptr, external: false }),
|
||||
};
|
||||
|
||||
inner.proxy.inner.display = Some(Arc::downgrade(&inner.display));
|
||||
|
||||
Ok(Arc::new(inner))
|
||||
}
|
||||
|
||||
impl DisplayInner {
|
||||
pub unsafe fn from_fd(fd: RawFd) -> Result<Arc<DisplayInner>, ConnectError> {
|
||||
if !::wayland_sys::client::is_lib_available() {
|
||||
return Err(ConnectError::NoWaylandLib);
|
||||
}
|
||||
|
||||
let display_ptr = ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_connect_to_fd, fd);
|
||||
|
||||
make_display(display_ptr)
|
||||
}
|
||||
|
||||
pub(crate) fn get_connection_fd(&self) -> ::std::os::unix::io::RawFd {
|
||||
unsafe { ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_get_fd, self.ptr()) }
|
||||
}
|
||||
|
||||
pub(crate) fn ptr(&self) -> *mut wl_display {
|
||||
self.display.ptr
|
||||
}
|
||||
|
||||
pub(crate) fn flush(&self) -> io::Result<()> {
|
||||
let ret = unsafe { ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_flush, self.ptr()) };
|
||||
if ret >= 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(io::Error::last_os_error())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn create_event_queue(me: &Arc<DisplayInner>) -> EventQueueInner {
|
||||
unsafe {
|
||||
let ptr = ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_create_queue, me.ptr());
|
||||
EventQueueInner::new(me.clone(), ptr)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_proxy(&self) -> &Proxy<WlDisplay> {
|
||||
&self.proxy
|
||||
}
|
||||
|
||||
pub(crate) fn protocol_error(&self) -> Option<crate::ProtocolError> {
|
||||
let ret = unsafe { ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_get_error, self.ptr()) };
|
||||
if ret == ::nix::errno::Errno::EPROTO as i32 {
|
||||
let mut interface = ::std::ptr::null_mut();
|
||||
let mut id = 0;
|
||||
let code = unsafe {
|
||||
ffi_dispatch!(
|
||||
WAYLAND_CLIENT_HANDLE,
|
||||
wl_display_get_protocol_error,
|
||||
self.ptr(),
|
||||
&mut interface,
|
||||
&mut id
|
||||
)
|
||||
};
|
||||
let interface_name = if !interface.is_null() {
|
||||
unsafe { ::std::ffi::CStr::from_ptr((*interface).name) }
|
||||
.to_str()
|
||||
.unwrap_or("<unknown>")
|
||||
} else {
|
||||
"<unknown>"
|
||||
};
|
||||
Some(crate::ProtocolError {
|
||||
code,
|
||||
object_id: id,
|
||||
object_interface: interface_name,
|
||||
message: String::new(),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn from_external(display_ptr: *mut wl_display) -> Arc<DisplayInner> {
|
||||
Arc::new(DisplayInner {
|
||||
proxy: Proxy::wrap(ProxyInner::from_external_display(display_ptr as *mut _)),
|
||||
display: Arc::new(DisplayGuard { ptr: display_ptr, external: true }),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for DisplayGuard {
|
||||
fn drop(&mut self) {
|
||||
if !self.external {
|
||||
// disconnect only if we are owning this display
|
||||
unsafe {
|
||||
ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_disconnect, self.ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
142
third-party/vendor/wayland-client/src/native_lib/event_queue.rs
vendored
Normal file
142
third-party/vendor/wayland-client/src/native_lib/event_queue.rs
vendored
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
use std::cell::RefCell;
|
||||
use std::io;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{AnonymousObject, DispatchData, Main, RawEvent};
|
||||
use wayland_sys::client::*;
|
||||
|
||||
use super::DisplayInner;
|
||||
|
||||
scoped_tls::scoped_thread_local! {
|
||||
pub(crate) static DISPATCH_METADATA: RefCell<(&mut dyn FnMut(RawEvent, Main<AnonymousObject>, DispatchData), DispatchData)>
|
||||
}
|
||||
|
||||
#[allow(clippy::transmute_ptr_to_ptr)]
|
||||
fn with_dispatch_meta<T, FB, F>(mut fb: FB, data: DispatchData, f: F) -> T
|
||||
where
|
||||
FB: FnMut(RawEvent, Main<AnonymousObject>, DispatchData),
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
// We erase the lifetime of the callback to be able to store it in the tls,
|
||||
// it's safe as it'll only last until the end of this function call anyway
|
||||
let fb = unsafe { std::mem::transmute(&mut fb as &mut dyn FnMut(_, _, _)) };
|
||||
let data = unsafe { std::mem::transmute(data) };
|
||||
DISPATCH_METADATA.set(&RefCell::new((fb, data)), f)
|
||||
}
|
||||
|
||||
pub(crate) struct EventQueueInner {
|
||||
wlevq: *mut wl_event_queue,
|
||||
inner: Arc<super::DisplayInner>,
|
||||
}
|
||||
|
||||
impl EventQueueInner {
|
||||
pub(crate) fn new(inner: Arc<DisplayInner>, wlevq: *mut wl_event_queue) -> EventQueueInner {
|
||||
EventQueueInner { wlevq, inner }
|
||||
}
|
||||
|
||||
pub(crate) fn dispatch<F>(&self, data: DispatchData, fallback: F) -> io::Result<u32>
|
||||
where
|
||||
F: FnMut(RawEvent, Main<AnonymousObject>, DispatchData<'_>),
|
||||
{
|
||||
with_dispatch_meta(fallback, data, || {
|
||||
let ret = unsafe {
|
||||
ffi_dispatch!(
|
||||
WAYLAND_CLIENT_HANDLE,
|
||||
wl_display_dispatch_queue,
|
||||
self.inner.ptr(),
|
||||
self.wlevq
|
||||
)
|
||||
};
|
||||
if ret >= 0 {
|
||||
Ok(ret as u32)
|
||||
} else {
|
||||
Err(io::Error::last_os_error())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn dispatch_pending<F>(&self, data: DispatchData, fallback: F) -> io::Result<u32>
|
||||
where
|
||||
F: FnMut(RawEvent, Main<AnonymousObject>, DispatchData<'_>),
|
||||
{
|
||||
with_dispatch_meta(fallback, data, || {
|
||||
let ret = unsafe {
|
||||
ffi_dispatch!(
|
||||
WAYLAND_CLIENT_HANDLE,
|
||||
wl_display_dispatch_queue_pending,
|
||||
self.inner.ptr(),
|
||||
self.wlevq
|
||||
)
|
||||
};
|
||||
if ret >= 0 {
|
||||
Ok(ret as u32)
|
||||
} else {
|
||||
Err(io::Error::last_os_error())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn sync_roundtrip<F>(&self, data: DispatchData, fallback: F) -> io::Result<u32>
|
||||
where
|
||||
F: FnMut(RawEvent, Main<AnonymousObject>, DispatchData<'_>),
|
||||
{
|
||||
with_dispatch_meta(fallback, data, || {
|
||||
let ret = unsafe {
|
||||
ffi_dispatch!(
|
||||
WAYLAND_CLIENT_HANDLE,
|
||||
wl_display_roundtrip_queue,
|
||||
self.inner.ptr(),
|
||||
self.wlevq
|
||||
)
|
||||
};
|
||||
if ret >= 0 {
|
||||
Ok(ret as u32)
|
||||
} else {
|
||||
Err(io::Error::last_os_error())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn prepare_read(&self) -> Result<(), ()> {
|
||||
let ret = unsafe {
|
||||
ffi_dispatch!(
|
||||
WAYLAND_CLIENT_HANDLE,
|
||||
wl_display_prepare_read_queue,
|
||||
self.inner.ptr(),
|
||||
self.wlevq
|
||||
)
|
||||
};
|
||||
if ret >= 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn read_events(&self) -> io::Result<()> {
|
||||
let ret = unsafe {
|
||||
ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_read_events, self.inner.ptr())
|
||||
};
|
||||
if ret >= 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(io::Error::last_os_error())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn cancel_read(&self) {
|
||||
unsafe { ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_cancel_read, self.inner.ptr()) }
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn assign_proxy(&self, proxy: *mut wl_proxy) {
|
||||
ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_set_queue, proxy, self.wlevq)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for EventQueueInner {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_event_queue_destroy, self.wlevq);
|
||||
}
|
||||
}
|
||||
}
|
||||
36
third-party/vendor/wayland-client/src/native_lib/mod.rs
vendored
Normal file
36
third-party/vendor/wayland-client/src/native_lib/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
mod display;
|
||||
mod event_queue;
|
||||
mod proxy;
|
||||
|
||||
pub(crate) use self::display::DisplayInner;
|
||||
pub(crate) use self::event_queue::EventQueueInner;
|
||||
pub(crate) use self::proxy::ProxyInner;
|
||||
|
||||
use crate::{Interface, Main, Proxy};
|
||||
|
||||
/// This type only exists for type-level compatibility
|
||||
/// with the rust implementation.
|
||||
///
|
||||
/// It is an empty enum that cannot be instantiated
|
||||
#[derive(Debug)]
|
||||
pub enum ProxyMap {}
|
||||
|
||||
impl ProxyMap {
|
||||
/// Unusable method only existing for type-level compatibility
|
||||
pub fn get<I: Interface>(&mut self, _: u32) -> Option<Proxy<I>> {
|
||||
match *self {}
|
||||
}
|
||||
|
||||
/// Unusable method only existing for type-level compatibility
|
||||
pub fn get_or_dead<I: Interface>(&mut self, _: u32) -> Proxy<I> {
|
||||
match *self {}
|
||||
}
|
||||
|
||||
/// Unusable method only existing for type-level compatibility
|
||||
pub fn get_new<I: Interface + AsRef<Proxy<I>> + From<Proxy<I>>>(
|
||||
&mut self,
|
||||
_: u32,
|
||||
) -> Option<Main<I>> {
|
||||
match *self {}
|
||||
}
|
||||
}
|
||||
519
third-party/vendor/wayland-client/src/native_lib/proxy.rs
vendored
Normal file
519
third-party/vendor/wayland-client/src/native_lib/proxy.rs
vendored
Normal file
|
|
@ -0,0 +1,519 @@
|
|||
use std::cell::RefCell;
|
||||
use std::os::raw::{c_int, c_void};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
use crate::{Interface, Main, Proxy, RawEvent};
|
||||
use wayland_commons::filter::Filter;
|
||||
use wayland_commons::user_data::UserData;
|
||||
use wayland_commons::wire::ArgumentType;
|
||||
use wayland_commons::MessageGroup;
|
||||
|
||||
use super::EventQueueInner;
|
||||
|
||||
use wayland_sys::client::*;
|
||||
use wayland_sys::common::*;
|
||||
|
||||
pub struct ProxyInternal {
|
||||
alive: AtomicBool,
|
||||
user_data: UserData,
|
||||
}
|
||||
|
||||
impl ProxyInternal {
|
||||
pub fn new(user_data: UserData) -> ProxyInternal {
|
||||
ProxyInternal { alive: AtomicBool::new(true), user_data }
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ProxyInner {
|
||||
internal: Option<Arc<ProxyInternal>>,
|
||||
ptr: *mut wl_proxy,
|
||||
wrapping: Option<*mut wl_proxy>,
|
||||
pub(crate) display: Option<Weak<super::display::DisplayGuard>>,
|
||||
}
|
||||
|
||||
unsafe impl Send for ProxyInner {}
|
||||
unsafe impl Sync for ProxyInner {}
|
||||
|
||||
impl ProxyInner {
|
||||
pub(crate) fn is_alive(&self) -> bool {
|
||||
if let Some(ref weak) = self.display {
|
||||
if Weak::strong_count(weak) == 0 {
|
||||
// the connection is dead
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
self.internal.as_ref().map(|i| i.alive.load(Ordering::Acquire)).unwrap_or(true)
|
||||
}
|
||||
|
||||
pub(crate) fn is_external(&self) -> bool {
|
||||
self.internal.is_none()
|
||||
}
|
||||
|
||||
pub(crate) fn version(&self) -> u32 {
|
||||
if !self.is_alive() {
|
||||
return 0;
|
||||
}
|
||||
let version =
|
||||
unsafe { ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_version, self.ptr) as u32 };
|
||||
if version == 0 {
|
||||
// For backcompat reasons the C libs return 0 as a version for the wl_display
|
||||
// So override it
|
||||
return 1;
|
||||
}
|
||||
version
|
||||
}
|
||||
|
||||
pub(crate) fn is_interface<I: Interface>(&self) -> bool {
|
||||
if !self.is_alive() {
|
||||
return false;
|
||||
}
|
||||
unsafe {
|
||||
let c_class_ptr = ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_class, self.ptr);
|
||||
let class = std::ffi::CStr::from_ptr(c_class_ptr);
|
||||
let i_class = std::ffi::CStr::from_ptr((*I::c_interface()).name);
|
||||
class == i_class
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn id(&self) -> u32 {
|
||||
if !self.is_alive() {
|
||||
return 0;
|
||||
}
|
||||
unsafe { ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_id, self.ptr) }
|
||||
}
|
||||
|
||||
pub(crate) fn user_data(&self) -> &UserData {
|
||||
static INVALID_USERDATA: UserData = UserData::new();
|
||||
if let Some(ref inner) = self.internal {
|
||||
&inner.user_data
|
||||
} else {
|
||||
INVALID_USERDATA.set_threadsafe(|| ());
|
||||
&INVALID_USERDATA
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn send<I, J>(&self, msg: I::Request, version: Option<u32>) -> Option<ProxyInner>
|
||||
where
|
||||
I: Interface + AsRef<Proxy<I>> + From<Proxy<I>>,
|
||||
J: Interface + AsRef<Proxy<J>> + From<Proxy<J>>,
|
||||
{
|
||||
let destructor = msg.is_destructor();
|
||||
let opcode = msg.opcode();
|
||||
|
||||
// figure out if the call creates an object
|
||||
let nid_idx = I::Request::MESSAGES[opcode as usize]
|
||||
.signature
|
||||
.iter()
|
||||
.position(|&t| t == ArgumentType::NewId);
|
||||
|
||||
let alive = self.is_alive();
|
||||
|
||||
let ret = if let Some(mut nid_idx) = nid_idx {
|
||||
if let Some(o) = I::Request::child(opcode, 1, &()) {
|
||||
if !o.is_interface::<J>() {
|
||||
panic!("Trying to use 'send_constructor' with the wrong return type. Required interface {} but the message creates interface {}", J::NAME, o.interface)
|
||||
}
|
||||
} else {
|
||||
// there is no target interface in the protocol, this is a generic object-creating
|
||||
// function (likely wl_registry.bind), the newid arg will thus expand to (str, u32, obj)
|
||||
nid_idx += 2;
|
||||
}
|
||||
|
||||
let version = version.unwrap_or_else(|| self.version());
|
||||
|
||||
if alive {
|
||||
if self.wrapping.is_none() {
|
||||
panic!("Attemping to create an object from a non-attached proxy.");
|
||||
}
|
||||
unsafe {
|
||||
let ptr = msg.as_raw_c_in(|opcode, args| {
|
||||
assert!(
|
||||
args[nid_idx].o.is_null(),
|
||||
"Trying to use 'send_constructor' with a non-placeholder object."
|
||||
);
|
||||
ffi_dispatch!(
|
||||
WAYLAND_CLIENT_HANDLE,
|
||||
wl_proxy_marshal_array_constructor_versioned,
|
||||
self.wrapping.unwrap_or(self.ptr),
|
||||
opcode,
|
||||
args.as_mut_ptr(),
|
||||
J::c_interface(),
|
||||
version
|
||||
)
|
||||
});
|
||||
let mut new_proxy = ProxyInner::init_from_c_ptr::<J>(ptr);
|
||||
new_proxy.display = self.display.clone();
|
||||
Some(new_proxy)
|
||||
}
|
||||
} else {
|
||||
// Create a dead proxy ex-nihilo
|
||||
Some(ProxyInner::dead())
|
||||
}
|
||||
} else {
|
||||
// not a constructor, nothing much to do
|
||||
if alive {
|
||||
msg.as_raw_c_in(|opcode, args| unsafe {
|
||||
ffi_dispatch!(
|
||||
WAYLAND_CLIENT_HANDLE,
|
||||
wl_proxy_marshal_array,
|
||||
self.wrapping.unwrap_or(self.ptr),
|
||||
opcode,
|
||||
args.as_ptr() as *mut _
|
||||
);
|
||||
});
|
||||
}
|
||||
None
|
||||
};
|
||||
|
||||
if destructor && alive {
|
||||
// we need to destroy the proxy now
|
||||
if let Some(ref internal) = self.internal {
|
||||
internal.alive.store(false, Ordering::Release);
|
||||
unsafe {
|
||||
let user_data =
|
||||
ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_user_data, self.ptr);
|
||||
ffi_dispatch!(
|
||||
WAYLAND_CLIENT_HANDLE,
|
||||
wl_proxy_set_user_data,
|
||||
self.ptr,
|
||||
std::ptr::null_mut()
|
||||
);
|
||||
let _ = Box::from_raw(user_data as *mut ProxyUserData<I>);
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_destroy, self.ptr);
|
||||
}
|
||||
}
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
pub(crate) fn equals(&self, other: &ProxyInner) -> bool {
|
||||
if !self.is_alive() {
|
||||
return false;
|
||||
}
|
||||
match (&self.internal, &other.internal) {
|
||||
(&Some(ref my_inner), &Some(ref other_inner)) => Arc::ptr_eq(my_inner, other_inner),
|
||||
(&None, &None) => self.ptr == other.ptr,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn detach(&mut self) {
|
||||
if !self.is_external() && !self.is_alive() {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(ptr) = self.wrapping.take() {
|
||||
// self.ptr == self.wrapping means we are a Main<_>
|
||||
if ptr != self.ptr {
|
||||
unsafe {
|
||||
ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_wrapper_destroy, ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn attach(&mut self, queue: &EventQueueInner) {
|
||||
if !self.is_external() && !self.is_alive() {
|
||||
return;
|
||||
}
|
||||
|
||||
let wrapper_ptr;
|
||||
unsafe {
|
||||
wrapper_ptr = ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_create_wrapper, self.ptr);
|
||||
queue.assign_proxy(wrapper_ptr);
|
||||
}
|
||||
|
||||
self.wrapping = Some(wrapper_ptr);
|
||||
}
|
||||
|
||||
pub(crate) fn c_ptr(&self) -> *mut wl_proxy {
|
||||
self.wrapping.unwrap_or(self.ptr)
|
||||
}
|
||||
|
||||
pub fn assign<I, E>(&self, filter: Filter<E>)
|
||||
where
|
||||
I: Interface + AsRef<Proxy<I>> + From<Proxy<I>> + Sync,
|
||||
E: From<(Main<I>, I::Event)> + 'static,
|
||||
I::Event: MessageGroup<Map = super::ProxyMap>,
|
||||
{
|
||||
if self.is_external() {
|
||||
panic!("Cannot assign an external proxy to a filter.");
|
||||
}
|
||||
|
||||
if !self.is_alive() {
|
||||
return;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let user_data = ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_user_data, self.ptr)
|
||||
as *mut ProxyUserData<I>;
|
||||
if let Ok(ref mut guard) = (*user_data).implem.try_borrow_mut() {
|
||||
**guard =
|
||||
Some(Box::new(move |evt, obj, data| filter.send((obj, evt).into(), data)));
|
||||
} else {
|
||||
panic!("Re-assigning an object from within its own callback is not supported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn init_from_c_ptr<I: Interface + From<Proxy<I>> + AsRef<Proxy<I>>>(
|
||||
ptr: *mut wl_proxy,
|
||||
) -> Self {
|
||||
let new_user_data = Box::new(ProxyUserData::<I>::new(UserData::new()));
|
||||
let internal = new_user_data.internal.clone();
|
||||
|
||||
ffi_dispatch!(
|
||||
WAYLAND_CLIENT_HANDLE,
|
||||
wl_proxy_add_dispatcher,
|
||||
ptr,
|
||||
proxy_dispatcher::<I>,
|
||||
&::wayland_sys::RUST_MANAGED as *const _ as *const _,
|
||||
Box::into_raw(new_user_data) as *mut _
|
||||
);
|
||||
|
||||
// We are a Main<_>, so ptr == wrapping
|
||||
ProxyInner { internal: Some(internal), ptr, wrapping: Some(ptr), display: None }
|
||||
}
|
||||
|
||||
fn dead() -> Self {
|
||||
ProxyInner {
|
||||
internal: Some(Arc::new(ProxyInternal {
|
||||
alive: AtomicBool::new(false),
|
||||
user_data: UserData::new(),
|
||||
})),
|
||||
ptr: std::ptr::null_mut(),
|
||||
wrapping: None,
|
||||
display: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn from_c_ptr<I: Interface + From<Proxy<I>> + AsRef<Proxy<I>>>(
|
||||
ptr: *mut wl_proxy,
|
||||
) -> Self {
|
||||
if ptr.is_null() {
|
||||
return Self::dead();
|
||||
}
|
||||
|
||||
let is_managed = {
|
||||
ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_listener, ptr)
|
||||
== &::wayland_sys::RUST_MANAGED as *const u8 as *const _
|
||||
};
|
||||
let internal = if is_managed {
|
||||
let user_data = ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_user_data, ptr)
|
||||
as *mut ProxyUserData<I>;
|
||||
Some((*user_data).internal.clone())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
ProxyInner { internal, ptr, wrapping: None, display: None }
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn from_external_display(d: *mut wl_proxy) -> ProxyInner {
|
||||
ProxyInner { internal: None, ptr: d, wrapping: None, display: None }
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for ProxyInner {
|
||||
fn clone(&self) -> ProxyInner {
|
||||
let mut new = ProxyInner {
|
||||
internal: self.internal.clone(),
|
||||
ptr: self.ptr,
|
||||
wrapping: None,
|
||||
display: self.display.clone(),
|
||||
};
|
||||
if !self.is_external() && !self.is_alive() {
|
||||
return new;
|
||||
}
|
||||
if let Some(ptr) = self.wrapping {
|
||||
if ptr != self.ptr {
|
||||
// create a new wrapper to keep correct track of them
|
||||
let wrapper_ptr;
|
||||
unsafe {
|
||||
wrapper_ptr =
|
||||
ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_create_wrapper, ptr);
|
||||
}
|
||||
new.wrapping = Some(wrapper_ptr);
|
||||
} else {
|
||||
// self.wrapping == self.ptr means we are a Main<_>, not a wrapper
|
||||
new.wrapping = Some(self.ptr);
|
||||
}
|
||||
}
|
||||
new
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ProxyInner {
|
||||
fn drop(&mut self) {
|
||||
// always detach on drop to avoid leaking wrappers
|
||||
self.detach();
|
||||
}
|
||||
}
|
||||
|
||||
type BoxedCallback<I> = Box<dyn Fn(<I as Interface>::Event, Main<I>, crate::DispatchData<'_>)>;
|
||||
|
||||
struct ProxyUserData<I: Interface + From<Proxy<I>> + AsRef<Proxy<I>>> {
|
||||
internal: Arc<ProxyInternal>,
|
||||
implem: RefCell<Option<BoxedCallback<I>>>,
|
||||
}
|
||||
|
||||
impl<I: Interface + From<Proxy<I>> + AsRef<Proxy<I>>> ProxyUserData<I> {
|
||||
fn new(user_data: UserData) -> ProxyUserData<I> {
|
||||
ProxyUserData {
|
||||
internal: Arc::new(ProxyInternal::new(user_data)),
|
||||
implem: RefCell::new(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn proxy_dispatcher<I: Interface>(
|
||||
_implem: *const c_void,
|
||||
proxy: *mut c_void,
|
||||
opcode: u32,
|
||||
_msg: *const wl_message,
|
||||
args: *const wl_argument,
|
||||
) -> c_int
|
||||
where
|
||||
I: Interface + From<Proxy<I>> + AsRef<Proxy<I>>,
|
||||
{
|
||||
let proxy = proxy as *mut wl_proxy;
|
||||
|
||||
// We don't need to worry about panic-safeness, because if there is a panic,
|
||||
// we'll abort the process, so no access to corrupted data is possible.
|
||||
let ret = ::std::panic::catch_unwind(move || {
|
||||
let must_destroy = I::Event::MESSAGES[opcode as usize].destructor;
|
||||
// retrieve the impl
|
||||
let user_data = ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_user_data, proxy);
|
||||
{
|
||||
// a scope to ensure the &mut reference to the user data no longer exists when
|
||||
// the callback is invoked
|
||||
let (implem, internal) = {
|
||||
let user_data = &mut *(user_data as *mut ProxyUserData<I>);
|
||||
|
||||
if must_destroy {
|
||||
user_data.internal.alive.store(false, Ordering::Release);
|
||||
ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_destroy, proxy);
|
||||
}
|
||||
// remove the implem from the user data, so that it remains valid even if the
|
||||
// object is destroyed from within the callback
|
||||
(user_data.implem.borrow_mut().take(), user_data.internal.clone())
|
||||
};
|
||||
// if there is an implem, call it, otherwise call the fallback
|
||||
match implem {
|
||||
Some(ref implem) => {
|
||||
// parse the message:
|
||||
let msg = I::Event::from_raw_c(proxy as *mut _, opcode, args)?;
|
||||
// create the proxy object
|
||||
let mut proxy_inner = ProxyInner::from_c_ptr::<I>(proxy);
|
||||
// This proxy must be a Main, so it as attached wrapping itself
|
||||
proxy_inner.wrapping = Some(proxy_inner.ptr);
|
||||
let proxy_obj = crate::Main::wrap(proxy_inner);
|
||||
super::event_queue::DISPATCH_METADATA.with(|meta| {
|
||||
let mut meta = meta.borrow_mut();
|
||||
let (_, ref mut dispatch_data) = *meta;
|
||||
implem(msg, proxy_obj, dispatch_data.reborrow());
|
||||
})
|
||||
}
|
||||
None => {
|
||||
// parse the message:
|
||||
let msg = parse_raw_event::<I>(opcode, args);
|
||||
// create the proxy object
|
||||
let proxy_obj = crate::Main::wrap(ProxyInner::from_c_ptr::<I>(proxy));
|
||||
super::event_queue::DISPATCH_METADATA.with(|meta| {
|
||||
let mut meta = meta.borrow_mut();
|
||||
let (ref mut fallback, ref mut dispatch_data) = *meta;
|
||||
(&mut *fallback)(msg, proxy_obj, dispatch_data.reborrow());
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// if the proxy is still alive, put the implem back in place
|
||||
if internal.alive.load(Ordering::Acquire) {
|
||||
let user_data = &mut *(user_data as *mut ProxyUserData<I>);
|
||||
let mut implem_place = user_data.implem.borrow_mut();
|
||||
// only place the implem back if it has not been replaced with an other
|
||||
if implem_place.is_none() {
|
||||
*implem_place = implem;
|
||||
}
|
||||
}
|
||||
}
|
||||
if must_destroy {
|
||||
// final cleanup
|
||||
let _ = Box::from_raw(user_data as *mut ProxyUserData<I>);
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
// check the return status
|
||||
match ret {
|
||||
Ok(Ok(())) => 0,
|
||||
Ok(Err(())) => {
|
||||
eprintln!(
|
||||
"[wayland-client error] Attempted to dispatch unknown opcode {} for {}, aborting.",
|
||||
opcode,
|
||||
I::NAME
|
||||
);
|
||||
libc::abort();
|
||||
}
|
||||
Err(_) => {
|
||||
eprintln!("[wayland-client error] A handler for {} panicked.", I::NAME);
|
||||
libc::abort()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn parse_raw_event<I: Interface>(opcode: u32, args: *const wl_argument) -> RawEvent {
|
||||
let desc = &I::Event::MESSAGES[opcode as usize];
|
||||
|
||||
let c_args = std::slice::from_raw_parts(args, desc.signature.len());
|
||||
|
||||
let mut args = Vec::with_capacity(c_args.len());
|
||||
// parse the arguments one by one
|
||||
for (t, a) in desc.signature.iter().zip(c_args.iter()) {
|
||||
args.push(match t {
|
||||
ArgumentType::Int => crate::Argument::Int(a.i),
|
||||
ArgumentType::Uint => crate::Argument::Uint(a.u),
|
||||
ArgumentType::Fixed => crate::Argument::Float((a.f as f32) / 256.),
|
||||
ArgumentType::Array => {
|
||||
if a.a.is_null() {
|
||||
crate::Argument::Array(None)
|
||||
} else {
|
||||
let array = &*a.a;
|
||||
crate::Argument::Array(Some(
|
||||
::std::slice::from_raw_parts(array.data as *const u8, array.size)
|
||||
.to_owned(),
|
||||
))
|
||||
}
|
||||
}
|
||||
ArgumentType::Str => {
|
||||
if a.s.is_null() {
|
||||
crate::Argument::Str(None)
|
||||
} else {
|
||||
crate::Argument::Str(Some(
|
||||
::std::ffi::CStr::from_ptr(a.s).to_string_lossy().into_owned(),
|
||||
))
|
||||
}
|
||||
}
|
||||
ArgumentType::Fd => crate::Argument::Fd(a.h),
|
||||
ArgumentType::Object => {
|
||||
if a.o.is_null() {
|
||||
crate::Argument::Object(None)
|
||||
} else {
|
||||
crate::Argument::Object(Some(Proxy::from_c_ptr(a.o as *mut _)))
|
||||
}
|
||||
}
|
||||
ArgumentType::NewId => {
|
||||
if a.o.is_null() {
|
||||
crate::Argument::NewId(None)
|
||||
} else {
|
||||
crate::Argument::NewId(Some(Main::from_c_ptr(a.o as *mut _)))
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
RawEvent { interface: I::NAME, opcode: opcode as u16, name: desc.name, args }
|
||||
}
|
||||
441
third-party/vendor/wayland-client/src/proxy.rs
vendored
Normal file
441
third-party/vendor/wayland-client/src/proxy.rs
vendored
Normal file
|
|
@ -0,0 +1,441 @@
|
|||
use std::fmt::{self, Debug, Formatter};
|
||||
use std::ops::Deref;
|
||||
|
||||
use super::AnonymousObject;
|
||||
use wayland_commons::user_data::UserData;
|
||||
use wayland_commons::Interface;
|
||||
|
||||
use wayland_sys::client::*;
|
||||
|
||||
use crate::event_queue::QueueToken;
|
||||
|
||||
use crate::imp::ProxyInner;
|
||||
|
||||
use wayland_commons::{filter::Filter, MessageGroup};
|
||||
|
||||
/// An handle to a wayland proxy
|
||||
///
|
||||
/// This represents a wayland object instantiated in your client
|
||||
/// session. Several handles to the same object can exist at a given
|
||||
/// time, and cloning them won't create a new protocol object, only
|
||||
/// clone the handle. The lifetime of the protocol object is **not**
|
||||
/// tied to the lifetime of these handles, but rather to sending or
|
||||
/// receiving destroying messages.
|
||||
///
|
||||
/// These handles are notably used to send requests to the server. To do this
|
||||
/// you need to convert them to the corresponding Rust object (using `.into()`)
|
||||
/// and use methods on the Rust object.
|
||||
///
|
||||
/// This handle is the most conservative one: it can be sent between threads,
|
||||
/// but you cannot send any message that would create a new object using it.
|
||||
/// You must attach it to a event queue, that will host the newly created objects.
|
||||
pub struct Proxy<I: Interface> {
|
||||
_i: ::std::marker::PhantomData<&'static I>,
|
||||
pub(crate) inner: ProxyInner,
|
||||
}
|
||||
|
||||
impl<I: Interface> Clone for Proxy<I> {
|
||||
fn clone(&self) -> Proxy<I> {
|
||||
let mut cloned = self.inner.clone();
|
||||
// an owned Proxy must always be detached
|
||||
cloned.detach();
|
||||
Proxy { _i: ::std::marker::PhantomData, inner: cloned }
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interface> PartialEq for Proxy<I>
|
||||
where
|
||||
I: AsRef<Proxy<I>> + From<Proxy<I>>,
|
||||
{
|
||||
fn eq(&self, other: &Proxy<I>) -> bool {
|
||||
self.equals(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interface> Debug for Proxy<I> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}@{}", I::NAME, self.inner.id())
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interface> Eq for Proxy<I> where I: AsRef<Proxy<I>> + From<Proxy<I>> {}
|
||||
|
||||
impl<I: Interface> Proxy<I>
|
||||
where
|
||||
I: AsRef<Proxy<I>> + From<Proxy<I>>,
|
||||
{
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn wrap(inner: ProxyInner) -> Proxy<I> {
|
||||
Proxy { _i: ::std::marker::PhantomData, inner }
|
||||
}
|
||||
|
||||
/// Send a request creating an object through this object
|
||||
///
|
||||
/// **Warning:** This method is mostly intended to be used by code generated
|
||||
/// by `wayland-scanner`, and you should probably never need to use it directly,
|
||||
/// but rather use the appropriate methods on the Rust object.
|
||||
///
|
||||
/// This is the generic method to send requests.
|
||||
pub fn send<J>(&self, msg: I::Request, version: Option<u32>) -> Option<Main<J>>
|
||||
where
|
||||
J: Interface + AsRef<Proxy<J>> + From<Proxy<J>>,
|
||||
{
|
||||
if msg.since() > self.version() && self.version() > 0 {
|
||||
let opcode = msg.opcode() as usize;
|
||||
panic!(
|
||||
"Cannot send request {} which requires version >= {} on proxy {}@{} which is version {}.",
|
||||
I::Request::MESSAGES[opcode].name,
|
||||
msg.since(),
|
||||
I::NAME,
|
||||
self.id(),
|
||||
self.version()
|
||||
);
|
||||
}
|
||||
self.inner.send::<I, J>(msg, version).map(Main::wrap)
|
||||
}
|
||||
|
||||
/// Check if the object associated with this proxy is still alive
|
||||
///
|
||||
/// Will return `false` if the object has been destroyed.
|
||||
///
|
||||
/// If the object is not managed by this library (if it was created from a raw
|
||||
/// pointer from some other library your program interfaces with), this will always
|
||||
/// returns `true`.
|
||||
pub fn is_alive(&self) -> bool {
|
||||
self.inner.is_alive()
|
||||
}
|
||||
|
||||
/// Retrieve the interface version of this wayland object instance
|
||||
///
|
||||
/// Returns 0 on dead objects
|
||||
pub fn version(&self) -> u32 {
|
||||
self.inner.version()
|
||||
}
|
||||
|
||||
/// Retrieve the object id of this wayland object
|
||||
pub fn id(&self) -> u32 {
|
||||
self.inner.id()
|
||||
}
|
||||
|
||||
/// Access the UserData associated to this object
|
||||
///
|
||||
/// Each wayland object has an associated UserData, that can store
|
||||
/// a payload of arbitrary type and is shared by all proxies of this
|
||||
/// object.
|
||||
///
|
||||
/// See [`UserData`](struct.UserData.html) documentation for more details.
|
||||
pub fn user_data(&self) -> &UserData {
|
||||
self.inner.user_data()
|
||||
}
|
||||
|
||||
/// Check if the other proxy refers to the same underlying wayland object
|
||||
///
|
||||
/// You can also use the `PartialEq` implementation.
|
||||
pub fn equals(&self, other: &Proxy<I>) -> bool {
|
||||
self.inner.equals(&other.inner)
|
||||
}
|
||||
|
||||
/// Attach this proxy to the event queue represented by this token
|
||||
///
|
||||
/// Once a proxy is attached, you can use it to send requests that
|
||||
/// create new objects. These new objects will be handled by the
|
||||
/// event queue represented by the provided token.
|
||||
///
|
||||
/// This does not impact the events received by this object, which
|
||||
/// are still handled by their original event queue.
|
||||
pub fn attach(&self, token: QueueToken) -> Attached<I> {
|
||||
let mut other = self.clone();
|
||||
other.inner.attach(&token.inner);
|
||||
Attached { inner: other.into(), _s: std::marker::PhantomData }
|
||||
}
|
||||
|
||||
/// Erase the actual type of this proxy
|
||||
pub fn anonymize(self) -> Proxy<AnonymousObject> {
|
||||
Proxy { _i: ::std::marker::PhantomData, inner: self.inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl Proxy<AnonymousObject> {
|
||||
/// Attempt to recover the typed variant of an anonymous proxy
|
||||
pub fn deanonymize<I: Interface>(self) -> Result<Proxy<I>, Self> {
|
||||
if self.inner.is_interface::<I>() {
|
||||
Ok(Proxy { inner: self.inner, _i: ::std::marker::PhantomData })
|
||||
} else {
|
||||
Err(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interface + Debug> Debug for Attached<I> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}[ATTACHED]", self.inner)
|
||||
}
|
||||
}
|
||||
|
||||
/// A handle to a proxy that has been attached to an event queue
|
||||
///
|
||||
/// As opposed to `Proxy`, you can use it to send requests
|
||||
/// that create new objects. The created objects will be handled
|
||||
/// by the event queue this proxy has been attached to.
|
||||
#[derive(PartialEq)]
|
||||
pub struct Attached<I: Interface> {
|
||||
// AttachedProxy is *not* send/sync
|
||||
_s: ::std::marker::PhantomData<*mut ()>,
|
||||
inner: I,
|
||||
}
|
||||
|
||||
impl<I: Interface> Attached<I>
|
||||
where
|
||||
I: Into<Proxy<I>> + From<Proxy<I>> + AsRef<Proxy<I>>,
|
||||
{
|
||||
/// Create a non-attached handle from this one
|
||||
pub fn detach(&self) -> I {
|
||||
self.inner.as_ref().clone().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interface> Deref for Attached<I> {
|
||||
type Target = I;
|
||||
|
||||
fn deref(&self) -> &I {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interface> Clone for Attached<I>
|
||||
where
|
||||
I: AsRef<Proxy<I>> + From<Proxy<I>>,
|
||||
{
|
||||
fn clone(&self) -> Attached<I> {
|
||||
let cloned = self.inner.as_ref().inner.clone();
|
||||
Attached {
|
||||
inner: Proxy { _i: std::marker::PhantomData, inner: cloned }.into(),
|
||||
_s: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A main handle to a proxy
|
||||
///
|
||||
/// This handle allows the same control as an `Attached` handle,
|
||||
/// but additionnaly can be used to assign the proxy to a `Filter`,
|
||||
/// in order to process its events.
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct Main<I: Interface + AsRef<Proxy<I>> + From<Proxy<I>>> {
|
||||
inner: Attached<I>,
|
||||
}
|
||||
|
||||
impl<I: Interface> Main<I>
|
||||
where
|
||||
I: AsRef<Proxy<I>> + From<Proxy<I>>,
|
||||
{
|
||||
pub(crate) fn wrap(inner: ProxyInner) -> Main<I> {
|
||||
Main {
|
||||
inner: Attached {
|
||||
inner: Proxy { _i: std::marker::PhantomData, inner }.into(),
|
||||
_s: std::marker::PhantomData,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Assign this object to given filter
|
||||
///
|
||||
/// All future event received by this object will be delivered to this
|
||||
/// filter.
|
||||
///
|
||||
/// An object that is not assigned to any filter will see its events
|
||||
/// delivered to the fallback callback of its event queue.
|
||||
///
|
||||
/// Event message type of the filter should verify
|
||||
/// `E: From<(Main<I>, I::Event)>`. See the `event_enum!` macro provided
|
||||
/// in this library to easily generate appropriate types.
|
||||
pub fn assign<E>(&self, filter: Filter<E>)
|
||||
where
|
||||
I: Sync,
|
||||
E: From<(Main<I>, I::Event)> + 'static,
|
||||
I::Event: MessageGroup<Map = crate::ProxyMap>,
|
||||
{
|
||||
self.inner.inner.as_ref().inner.assign(filter);
|
||||
}
|
||||
|
||||
/// Shorthand for assigning a closure to an object
|
||||
///
|
||||
/// Behaves similarly as `assign(..)`, but is a shorthand if
|
||||
/// you want to assign this object to its own filter. In which
|
||||
/// case you just need to provide the appropriate closure, of
|
||||
/// type `FnMut(Main<I>, I::Event)`.
|
||||
pub fn quick_assign<F>(&self, mut f: F)
|
||||
where
|
||||
I: Interface + AsRef<Proxy<I>> + From<Proxy<I>> + Sync,
|
||||
F: FnMut(Main<I>, I::Event, crate::DispatchData) + 'static,
|
||||
I::Event: MessageGroup<Map = crate::ProxyMap>,
|
||||
{
|
||||
self.assign(Filter::new(move |(proxy, event), _, data| f(proxy, event, data)))
|
||||
}
|
||||
}
|
||||
|
||||
impl Main<AnonymousObject> {
|
||||
/// Attempt to recover the typed variant of an anonymous proxy
|
||||
pub fn deanonymize<I: Interface + AsRef<Proxy<I>> + From<Proxy<I>>>(
|
||||
self,
|
||||
) -> Result<Main<I>, Self> {
|
||||
if self.inner.as_ref().inner.is_interface::<I>() {
|
||||
Ok(Main {
|
||||
inner: Attached {
|
||||
inner: Proxy { _i: std::marker::PhantomData, inner: self.inner.inner.0.inner }
|
||||
.into(),
|
||||
_s: std::marker::PhantomData,
|
||||
},
|
||||
})
|
||||
} else {
|
||||
Err(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interface> Deref for Main<I>
|
||||
where
|
||||
I: AsRef<Proxy<I>> + From<Proxy<I>>,
|
||||
{
|
||||
type Target = Attached<I>;
|
||||
|
||||
fn deref(&self) -> &Attached<I> {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interface> From<Main<I>> for Attached<I>
|
||||
where
|
||||
I: AsRef<Proxy<I>> + From<Proxy<I>>,
|
||||
{
|
||||
fn from(main: Main<I>) -> Attached<I> {
|
||||
main.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interface> Debug for Main<I>
|
||||
where
|
||||
I: Debug + AsRef<Proxy<I>> + From<Proxy<I>>,
|
||||
{
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}[MAIN]", self.inner.inner)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* C-interfacing stuff
|
||||
*/
|
||||
|
||||
impl<I: Interface> Main<I>
|
||||
where
|
||||
I: AsRef<Proxy<I>> + From<Proxy<I>>,
|
||||
{
|
||||
/// Create a `Main` instance from a C pointer
|
||||
///
|
||||
/// Create a `Main` from a raw pointer to a wayland object from the
|
||||
/// C library.
|
||||
///
|
||||
/// In order to handle protocol races, invoking it with a NULL pointer will
|
||||
/// create an already-dead object.
|
||||
///
|
||||
/// NOTE: This method will panic if called while the `use_system_lib` feature is
|
||||
/// not activated.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This will take control of the underlying proxy & manage it. To be safe
|
||||
/// you must ensure that:
|
||||
///
|
||||
/// - The provided proxy has not already been used in any way (it was just created)
|
||||
/// - This is called from the same thread as the one hosting the event queue
|
||||
/// handling this proxy
|
||||
pub unsafe fn from_c_ptr(_ptr: *mut wl_proxy) -> Main<I> {
|
||||
#[cfg(feature = "use_system_lib")]
|
||||
{
|
||||
Main::wrap(ProxyInner::init_from_c_ptr::<I>(_ptr))
|
||||
}
|
||||
#[cfg(not(feature = "use_system_lib"))]
|
||||
{
|
||||
panic!("[wayland-client] C interfacing methods can only be used with the `use_system_lib` cargo feature.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interface + AsRef<Proxy<I>> + From<Proxy<I>>> Proxy<I> {
|
||||
/// Check whether this proxy is managed by the library or not
|
||||
///
|
||||
/// See `from_c_ptr` for details.
|
||||
///
|
||||
/// NOTE: This method will panic if called while the `use_system_lib` feature is
|
||||
/// not activated.
|
||||
pub fn is_external(&self) -> bool {
|
||||
#[cfg(feature = "use_system_lib")]
|
||||
{
|
||||
self.inner.is_external()
|
||||
}
|
||||
#[cfg(not(feature = "use_system_lib"))]
|
||||
{
|
||||
panic!("[wayland-client] C interfacing methods can only be used with the `use_system_lib` cargo feature.")
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a raw pointer to the underlying wayland object
|
||||
///
|
||||
/// Retrieve a pointer to the object from the `libwayland-client.so` library.
|
||||
/// You will mostly need it to interface with C libraries needing access
|
||||
/// to wayland objects (to initialize an opengl context for example).
|
||||
///
|
||||
/// NOTE: This method will panic if called while the `use_system_lib` feature is
|
||||
/// not activated.
|
||||
pub fn c_ptr(&self) -> *mut wl_proxy {
|
||||
#[cfg(feature = "use_system_lib")]
|
||||
{
|
||||
self.inner.c_ptr()
|
||||
}
|
||||
#[cfg(not(feature = "use_system_lib"))]
|
||||
{
|
||||
panic!("[wayland-client] C interfacing methods can only be used with the `use_system_lib` cargo feature.")
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a `Proxy` instance from a C pointer
|
||||
///
|
||||
/// Create a `Proxy` from a raw pointer to a wayland object from the
|
||||
/// C library.
|
||||
///
|
||||
/// If the pointer was previously obtained by the `c_ptr()` method, this
|
||||
/// constructs a new proxy for the same object just like the `clone()`
|
||||
/// method would have.
|
||||
///
|
||||
/// If the object was created by some other C library you are interfacing
|
||||
/// with, it will be created in an "unmanaged" state: wayland-client will
|
||||
/// treat it as foreign, and as such most of the safeties will be absent.
|
||||
/// Notably the lifetime of the object can't be tracked, so the `alive()`
|
||||
/// method will always return `true` and you are responsible of not using
|
||||
/// an object past its destruction (as this would cause a protocol error).
|
||||
/// You will also be unable to associate any user data value to this object.
|
||||
///
|
||||
/// In order to handle protocol races, invoking it with a NULL pointer will
|
||||
/// create an already-dead object.
|
||||
///
|
||||
/// NOTE: This method will panic if called while the `use_system_lib` feature is
|
||||
/// not activated.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The provided pointer must point to a valid wayland object from `libwayland-client`
|
||||
/// with the correct interface.
|
||||
pub unsafe fn from_c_ptr(_ptr: *mut wl_proxy) -> Proxy<I>
|
||||
where
|
||||
I: From<Proxy<I>>,
|
||||
{
|
||||
#[cfg(feature = "use_system_lib")]
|
||||
{
|
||||
Proxy { _i: ::std::marker::PhantomData, inner: ProxyInner::from_c_ptr::<I>(_ptr) }
|
||||
}
|
||||
#[cfg(not(feature = "use_system_lib"))]
|
||||
{
|
||||
panic!("[wayland-client] C interfacing methods can only be used with the `use_system_lib` cargo feature.")
|
||||
}
|
||||
}
|
||||
}
|
||||
181
third-party/vendor/wayland-client/src/rust_imp/connection.rs
vendored
Normal file
181
third-party/vendor/wayland-client/src/rust_imp/connection.rs
vendored
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
use std::cell::RefCell;
|
||||
use std::os::unix::io::{FromRawFd, RawFd};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use nix::Result as NixResult;
|
||||
|
||||
use wayland_commons::map::{Object, ObjectMap, SERVER_ID_LIMIT};
|
||||
use wayland_commons::socket::{BufferedSocket, Socket};
|
||||
use wayland_commons::wire::{Argument, ArgumentType, Message, MessageParseError};
|
||||
|
||||
use super::proxy::ObjectMeta;
|
||||
use super::queues::QueueBuffer;
|
||||
|
||||
use crate::ProtocolError;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) enum Error {
|
||||
Protocol(ProtocolError),
|
||||
Parse(MessageParseError),
|
||||
Nix(::nix::Error),
|
||||
}
|
||||
|
||||
pub(crate) struct Connection {
|
||||
pub(crate) socket: BufferedSocket,
|
||||
pub(crate) map: Arc<Mutex<ObjectMap<ObjectMeta>>>,
|
||||
pub(crate) last_error: Arc<Mutex<Option<Error>>>,
|
||||
pub(crate) display_buffer: QueueBuffer,
|
||||
}
|
||||
|
||||
impl Connection {
|
||||
pub(crate) unsafe fn new(fd: RawFd, display_object: Object<ObjectMeta>) -> Connection {
|
||||
let socket = BufferedSocket::new(Socket::from_raw_fd(fd));
|
||||
|
||||
let mut map = ObjectMap::new();
|
||||
// Insert first pre-existing object
|
||||
let display_buffer = display_object.meta.buffer.clone();
|
||||
map.insert_at(1, display_object).unwrap();
|
||||
|
||||
Connection {
|
||||
socket,
|
||||
map: Arc::new(Mutex::new(map)),
|
||||
last_error: Arc::new(Mutex::new(None)),
|
||||
display_buffer,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn write_message(&mut self, msg: &Message) -> NixResult<()> {
|
||||
self.socket.write_message(msg)
|
||||
}
|
||||
|
||||
pub(crate) fn flush(&mut self) -> NixResult<()> {
|
||||
self.socket.flush()
|
||||
}
|
||||
|
||||
pub(crate) fn read_events(&mut self) -> Result<usize, Error> {
|
||||
if let Some(ref err) = *self.last_error.lock().unwrap() {
|
||||
return Err(err.clone());
|
||||
}
|
||||
// acquire the map lock, this means no objects can be created nor destroyed while we
|
||||
// are reading events
|
||||
let mut map = self.map.lock().unwrap();
|
||||
// wrap it in a RefCell for cheap sharing in the two closures below
|
||||
let map = RefCell::new(&mut *map);
|
||||
let mut last_error = self.last_error.lock().unwrap();
|
||||
// read messages
|
||||
let ret = self.socket.read_messages(
|
||||
|id, opcode| {
|
||||
map.borrow()
|
||||
.find(id)
|
||||
.and_then(|o| o.events.get(opcode as usize))
|
||||
.map(|desc| desc.signature)
|
||||
},
|
||||
|msg| {
|
||||
// Early exit on protocol error
|
||||
if msg.sender_id == 1 && msg.opcode == 0 {
|
||||
if let [Argument::Object(faulty_id), Argument::Uint(error_code), Argument::Str(ref error_msg)] = &msg.args[..] {
|
||||
let error_msg = error_msg.to_string_lossy().into_owned();
|
||||
let faulty_interface = map.borrow().find(*faulty_id).map(|obj| obj.interface).unwrap_or("unknown");
|
||||
// abort parsing, this is an unrecoverable error
|
||||
*last_error = Some(Error::Protocol(ProtocolError {
|
||||
code: *error_code,
|
||||
object_id: *faulty_id,
|
||||
object_interface: faulty_interface,
|
||||
message: error_msg
|
||||
}));
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// dispatch the message to the proper object
|
||||
let mut map = map.borrow_mut();
|
||||
let object = map.find(msg.sender_id);
|
||||
|
||||
// create a new object if applicable
|
||||
if let Some((mut child, dead_parent)) = object
|
||||
.as_ref()
|
||||
.and_then(|o| o.event_child(msg.opcode).map(|c| (c, o.meta.client_destroyed)))
|
||||
{
|
||||
let new_id = msg
|
||||
.args
|
||||
.iter()
|
||||
.flat_map(|a| if let Argument::NewId(nid) = *a { Some(nid) } else { None })
|
||||
.next()
|
||||
.unwrap();
|
||||
let child_interface = child.interface;
|
||||
// if this ID belonged to a now destroyed server object, we can replace it
|
||||
if new_id >= SERVER_ID_LIMIT
|
||||
&& map.with(new_id, |obj| obj.meta.client_destroyed).unwrap_or(false)
|
||||
{
|
||||
map.remove(new_id)
|
||||
}
|
||||
// if the parent object is already destroyed, the user will never see this
|
||||
// object, so we set it as client_destroyed to ignore all future messages to it
|
||||
if dead_parent {
|
||||
child.meta.client_destroyed = true;
|
||||
}
|
||||
if let Err(()) = map.insert_at(new_id, child) {
|
||||
// abort parsing, this is an unrecoverable error
|
||||
*last_error = Some(Error::Protocol(ProtocolError {
|
||||
code: 0,
|
||||
object_id: 0,
|
||||
object_interface: "",
|
||||
message: format!(
|
||||
"Protocol error: server tried to create \
|
||||
an object \"{}\" with invalid id \"{}\".",
|
||||
child_interface, new_id
|
||||
),
|
||||
}));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// debug assert: if this opcode does not define a child, then there should be no
|
||||
// NewId argument
|
||||
debug_assert!(!msg.args.iter().any(|a| a.get_type() == ArgumentType::NewId));
|
||||
}
|
||||
|
||||
// send the message to the appropriate pending queue
|
||||
match object {
|
||||
Some(Object { meta: ObjectMeta { client_destroyed: true, .. }, .. }) | None => {
|
||||
// this is a message sent to a destroyed object
|
||||
// to avoid dying because of races, we just consume it into void
|
||||
// closing any associated FDs
|
||||
for a in msg.args {
|
||||
if let Argument::Fd(fd) = a {
|
||||
let _ = ::nix::unistd::close(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(obj) => {
|
||||
obj.meta.buffer.lock().unwrap().push_back(msg);
|
||||
}
|
||||
};
|
||||
|
||||
// continue parsing
|
||||
true
|
||||
},
|
||||
);
|
||||
|
||||
if let Some(ref e) = *last_error {
|
||||
// a protocol error was generated, don't lose it, it is the source of any subsequent error
|
||||
return Err(e.clone());
|
||||
}
|
||||
|
||||
match ret {
|
||||
Ok(Ok(n)) => Ok(n),
|
||||
Ok(Err(e)) => {
|
||||
*last_error = Some(Error::Parse(e.clone()));
|
||||
Err(Error::Parse(e))
|
||||
}
|
||||
// non-fatal error
|
||||
Err(e @ nix::Error::EAGAIN) => Err(Error::Nix(e)),
|
||||
// fatal errors
|
||||
Err(e) => {
|
||||
*last_error = Some(Error::Nix(e));
|
||||
Err(Error::Nix(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
152
third-party/vendor/wayland-client/src/rust_imp/display.rs
vendored
Normal file
152
third-party/vendor/wayland-client/src/rust_imp/display.rs
vendored
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
use std::io;
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use wayland_commons::debug;
|
||||
use wayland_commons::map::{Object, ObjectMap};
|
||||
use wayland_commons::wire::Message;
|
||||
use wayland_commons::MessageGroup;
|
||||
|
||||
use crate::protocol::wl_display::{self, WlDisplay};
|
||||
|
||||
use crate::{ConnectError, ProtocolError, Proxy};
|
||||
|
||||
use super::connection::{Connection, Error as CxError};
|
||||
use super::proxy::{ObjectMeta, ProxyInner};
|
||||
use super::{Dispatched, EventQueueInner, ProxyMap, WAYLAND_DEBUG};
|
||||
|
||||
pub(crate) struct DisplayInner {
|
||||
connection: Arc<Mutex<Connection>>,
|
||||
proxy: Proxy<WlDisplay>,
|
||||
}
|
||||
|
||||
impl DisplayInner {
|
||||
pub unsafe fn from_fd(fd: RawFd) -> Result<Arc<DisplayInner>, ConnectError> {
|
||||
if let Some(value) = std::env::var_os("WAYLAND_DEBUG") {
|
||||
// Follow libwayland-client and enable debug log only on `1` and `client` values.
|
||||
if value == "1" || value == "client" {
|
||||
// Toggle debug log.
|
||||
WAYLAND_DEBUG.store(true, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
// The special buffer for display events
|
||||
let buffer = super::queues::create_queue_buffer();
|
||||
let display_object = Object::from_interface::<WlDisplay>(1, ObjectMeta::new(buffer));
|
||||
let (connection, map) = {
|
||||
let c = Connection::new(fd, display_object);
|
||||
let m = c.map.clone();
|
||||
(Arc::new(Mutex::new(c)), m)
|
||||
};
|
||||
|
||||
// Setup the display dispatcher
|
||||
map.lock()
|
||||
.unwrap()
|
||||
.with(1, |obj| {
|
||||
obj.meta.dispatcher = Arc::new(Mutex::new(DisplayDispatcher {
|
||||
map: map.clone(),
|
||||
last_error: connection.lock().unwrap().last_error.clone(),
|
||||
}));
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let display_proxy = ProxyInner::from_id(1, map, connection.clone()).unwrap();
|
||||
|
||||
let display = DisplayInner { proxy: Proxy::wrap(display_proxy), connection };
|
||||
|
||||
Ok(Arc::new(display))
|
||||
}
|
||||
|
||||
pub(crate) fn flush(&self) -> io::Result<()> {
|
||||
match self.connection.lock().unwrap().flush() {
|
||||
Ok(()) => Ok(()),
|
||||
Err(errno) => Err(errno.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn create_event_queue(me: &Arc<DisplayInner>) -> EventQueueInner {
|
||||
EventQueueInner::new(me.connection.clone(), None)
|
||||
}
|
||||
|
||||
pub(crate) fn get_proxy(&self) -> &Proxy<WlDisplay> {
|
||||
&self.proxy
|
||||
}
|
||||
|
||||
pub(crate) fn protocol_error(&self) -> Option<ProtocolError> {
|
||||
let cx = self.connection.lock().unwrap();
|
||||
let last_error = cx.last_error.lock().unwrap();
|
||||
if let Some(CxError::Protocol(ref e)) = *last_error {
|
||||
Some(e.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_connection_fd(&self) -> ::std::os::unix::io::RawFd {
|
||||
self.connection.lock().unwrap().socket.get_socket().as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
// WlDisplay needs its own dispatcher, as it can be dispatched from multiple threads
|
||||
struct DisplayDispatcher {
|
||||
map: Arc<Mutex<ObjectMap<ObjectMeta>>>,
|
||||
last_error: Arc<Mutex<Option<CxError>>>,
|
||||
}
|
||||
|
||||
impl super::Dispatcher for DisplayDispatcher {
|
||||
fn dispatch(
|
||||
&mut self,
|
||||
msg: Message,
|
||||
proxy: ProxyInner,
|
||||
map: &mut ProxyMap,
|
||||
_data: crate::DispatchData,
|
||||
) -> Dispatched {
|
||||
if WAYLAND_DEBUG.load(Ordering::Relaxed) {
|
||||
debug::print_dispatched_message(
|
||||
proxy.object.interface,
|
||||
proxy.id,
|
||||
proxy.object.events[msg.opcode as usize].name,
|
||||
&msg.args,
|
||||
);
|
||||
}
|
||||
|
||||
let event = match wl_display::Event::from_raw(msg, map) {
|
||||
Ok(v) => v,
|
||||
Err(()) => return Dispatched::BadMsg,
|
||||
};
|
||||
|
||||
match event {
|
||||
wl_display::Event::Error { object_id, code, message } => {
|
||||
eprintln!(
|
||||
"[wayland-client] Protocol error {} on object {}@{}: {}",
|
||||
code,
|
||||
object_id.as_ref().inner.object.interface,
|
||||
object_id.as_ref().id(),
|
||||
message
|
||||
);
|
||||
*self.last_error.lock().unwrap() = Some(CxError::Protocol(ProtocolError {
|
||||
code,
|
||||
object_id: object_id.as_ref().id(),
|
||||
object_interface: object_id.as_ref().inner.object.interface,
|
||||
message,
|
||||
}));
|
||||
}
|
||||
wl_display::Event::DeleteId { id } => {
|
||||
// cleanup the map as appropriate
|
||||
let mut map = self.map.lock().unwrap();
|
||||
let client_destroyed = map
|
||||
.with(id, |obj| {
|
||||
obj.meta.server_destroyed = true;
|
||||
obj.meta.client_destroyed
|
||||
})
|
||||
.unwrap_or(false);
|
||||
if client_destroyed {
|
||||
map.remove(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Dispatched::Yes
|
||||
}
|
||||
}
|
||||
213
third-party/vendor/wayland-client/src/rust_imp/mod.rs
vendored
Normal file
213
third-party/vendor/wayland-client/src/rust_imp/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use downcast::Downcast;
|
||||
|
||||
use wayland_commons::debug;
|
||||
use wayland_commons::filter::Filter;
|
||||
use wayland_commons::map::ObjectMap;
|
||||
use wayland_commons::wire::Message;
|
||||
use wayland_commons::{MessageGroup, ThreadGuard};
|
||||
|
||||
use crate::{Interface, Main, Proxy};
|
||||
|
||||
mod connection;
|
||||
mod display;
|
||||
mod proxy;
|
||||
mod queues;
|
||||
|
||||
pub(crate) use self::display::DisplayInner;
|
||||
pub(crate) use self::proxy::ProxyInner;
|
||||
pub(crate) use self::queues::EventQueueInner;
|
||||
|
||||
/// Flag to toggle debug output.
|
||||
static WAYLAND_DEBUG: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
/// A handle to the object map internal to the library state.
|
||||
///
|
||||
/// This type is only used by code generated by `wayland-scanner`, and can not
|
||||
/// be instantiated directly.
|
||||
pub struct ProxyMap {
|
||||
map: Arc<Mutex<ObjectMap<self::proxy::ObjectMeta>>>,
|
||||
connection: Arc<Mutex<self::connection::Connection>>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for ProxyMap {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str("ProxyMap { ... }")
|
||||
}
|
||||
}
|
||||
|
||||
impl ProxyMap {
|
||||
pub(crate) fn make(
|
||||
map: Arc<Mutex<ObjectMap<self::proxy::ObjectMeta>>>,
|
||||
connection: Arc<Mutex<self::connection::Connection>>,
|
||||
) -> ProxyMap {
|
||||
ProxyMap { map, connection }
|
||||
}
|
||||
|
||||
/// Returns the Proxy corresponding to a given id
|
||||
pub fn get<I: Interface + AsRef<Proxy<I>> + From<Proxy<I>>>(
|
||||
&mut self,
|
||||
id: u32,
|
||||
) -> Option<Proxy<I>> {
|
||||
ProxyInner::from_id(id, self.map.clone(), self.connection.clone()).map(|object| {
|
||||
debug_assert!(I::NAME == "<anonymous>" || object.is_interface::<I>());
|
||||
Proxy::wrap(object)
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the Proxy corresponding to a given id, and create a dead one if none is found
|
||||
pub fn get_or_dead<I: Interface + AsRef<Proxy<I>> + From<Proxy<I>>>(
|
||||
&mut self,
|
||||
id: u32,
|
||||
) -> Proxy<I> {
|
||||
self.get(id).unwrap_or_else(|| {
|
||||
Proxy::wrap(ProxyInner::dead::<I>(id, self.map.clone(), self.connection.clone()))
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a new proxy for given id
|
||||
pub fn get_new<I: Interface + AsRef<Proxy<I>> + From<Proxy<I>>>(
|
||||
&mut self,
|
||||
id: u32,
|
||||
) -> Option<Main<I>> {
|
||||
debug_assert!(self
|
||||
.map
|
||||
.lock()
|
||||
.unwrap()
|
||||
.find(id)
|
||||
.map(|obj| obj.is_interface::<I>())
|
||||
.unwrap_or(true));
|
||||
ProxyInner::from_id(id, self.map.clone(), self.connection.clone()).map(Main::wrap)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispatching logic
|
||||
*/
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
pub(crate) enum Dispatched {
|
||||
Yes,
|
||||
NoDispatch(Message, ProxyInner),
|
||||
BadMsg,
|
||||
}
|
||||
|
||||
pub(crate) trait Dispatcher: Downcast + Send {
|
||||
fn dispatch(
|
||||
&mut self,
|
||||
msg: Message,
|
||||
proxy: ProxyInner,
|
||||
map: &mut ProxyMap,
|
||||
data: crate::DispatchData,
|
||||
) -> Dispatched;
|
||||
}
|
||||
|
||||
mod dispatcher_impl {
|
||||
// this mod has the sole purpose of silencing these `dead_code` warnings...
|
||||
#![allow(dead_code)]
|
||||
use super::Dispatcher;
|
||||
impl_downcast!(Dispatcher);
|
||||
}
|
||||
|
||||
pub(crate) struct ImplDispatcher<
|
||||
I: Interface + AsRef<Proxy<I>> + From<Proxy<I>>,
|
||||
F: FnMut(I::Event, Main<I>, crate::DispatchData<'_>) + 'static,
|
||||
> {
|
||||
_i: ::std::marker::PhantomData<&'static I>,
|
||||
implementation: F,
|
||||
}
|
||||
|
||||
impl<I, F> Dispatcher for ImplDispatcher<I, F>
|
||||
where
|
||||
I: Interface + AsRef<Proxy<I>> + From<Proxy<I>> + Sync,
|
||||
F: FnMut(I::Event, Main<I>, crate::DispatchData<'_>) + 'static + Send,
|
||||
I::Event: MessageGroup<Map = ProxyMap>,
|
||||
{
|
||||
fn dispatch(
|
||||
&mut self,
|
||||
msg: Message,
|
||||
proxy: ProxyInner,
|
||||
map: &mut ProxyMap,
|
||||
data: crate::DispatchData,
|
||||
) -> Dispatched {
|
||||
let opcode = msg.opcode as usize;
|
||||
|
||||
if WAYLAND_DEBUG.load(Ordering::Relaxed) {
|
||||
debug::print_dispatched_message(
|
||||
proxy.object.interface,
|
||||
proxy.id,
|
||||
proxy.object.events[opcode].name,
|
||||
&msg.args,
|
||||
);
|
||||
}
|
||||
|
||||
let message = match I::Event::from_raw(msg, map) {
|
||||
Ok(v) => v,
|
||||
Err(()) => return Dispatched::BadMsg,
|
||||
};
|
||||
|
||||
if message.since() > proxy.version() {
|
||||
eprintln!(
|
||||
"Received an event {} requiring version >= {} while proxy {}@{} is version {}.",
|
||||
proxy.object.events[opcode].name,
|
||||
message.since(),
|
||||
proxy.object.interface,
|
||||
proxy.id,
|
||||
proxy.version()
|
||||
);
|
||||
return Dispatched::BadMsg;
|
||||
}
|
||||
|
||||
if message.is_destructor() {
|
||||
proxy.object.meta.alive.store(false, Ordering::Release);
|
||||
{
|
||||
// cleanup the map as appropriate
|
||||
let mut map = proxy.map.lock().unwrap();
|
||||
let server_destroyed = map
|
||||
.with(proxy.id, |obj| {
|
||||
obj.meta.client_destroyed = true;
|
||||
obj.meta.server_destroyed
|
||||
})
|
||||
.unwrap_or(false);
|
||||
if server_destroyed {
|
||||
map.remove(proxy.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(self.implementation)(message, Main::<I>::wrap(proxy), data);
|
||||
|
||||
Dispatched::Yes
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn make_dispatcher<I, E>(filter: Filter<E>) -> Arc<Mutex<dyn Dispatcher + Send>>
|
||||
where
|
||||
I: Interface + AsRef<Proxy<I>> + From<Proxy<I>> + Sync,
|
||||
E: From<(Main<I>, I::Event)> + 'static,
|
||||
I::Event: MessageGroup<Map = ProxyMap>,
|
||||
{
|
||||
let guard = ThreadGuard::new(filter);
|
||||
Arc::new(Mutex::new(ImplDispatcher {
|
||||
_i: ::std::marker::PhantomData,
|
||||
implementation: move |evt, proxy, data| guard.get().send((proxy, evt).into(), data),
|
||||
}))
|
||||
}
|
||||
|
||||
pub(crate) fn default_dispatcher() -> Arc<Mutex<dyn Dispatcher + Send>> {
|
||||
struct DefaultDisp;
|
||||
impl Dispatcher for DefaultDisp {
|
||||
fn dispatch(
|
||||
&mut self,
|
||||
msg: Message,
|
||||
proxy: ProxyInner,
|
||||
_map: &mut ProxyMap,
|
||||
_data: crate::DispatchData,
|
||||
) -> Dispatched {
|
||||
Dispatched::NoDispatch(msg, proxy)
|
||||
}
|
||||
}
|
||||
|
||||
Arc::new(Mutex::new(DefaultDisp))
|
||||
}
|
||||
248
third-party/vendor/wayland-client/src/rust_imp/proxy.rs
vendored
Normal file
248
third-party/vendor/wayland-client/src/rust_imp/proxy.rs
vendored
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use wayland_commons::debug;
|
||||
use wayland_commons::filter::Filter;
|
||||
use wayland_commons::map::{Object, ObjectMap, ObjectMetadata};
|
||||
use wayland_commons::user_data::UserData;
|
||||
use wayland_commons::wire::{Argument, ArgumentType};
|
||||
use wayland_commons::MessageGroup;
|
||||
|
||||
use super::connection::Connection;
|
||||
use super::queues::QueueBuffer;
|
||||
use super::{Dispatcher, EventQueueInner, WAYLAND_DEBUG};
|
||||
use crate::{Interface, Main, Proxy};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct ObjectMeta {
|
||||
pub(crate) buffer: QueueBuffer,
|
||||
pub(crate) alive: Arc<AtomicBool>,
|
||||
user_data: Arc<UserData>,
|
||||
pub(crate) dispatcher: Arc<Mutex<dyn Dispatcher>>,
|
||||
pub(crate) server_destroyed: bool,
|
||||
pub(crate) client_destroyed: bool,
|
||||
}
|
||||
|
||||
impl ObjectMetadata for ObjectMeta {
|
||||
fn child(&self) -> ObjectMeta {
|
||||
ObjectMeta {
|
||||
buffer: self.buffer.clone(),
|
||||
alive: Arc::new(AtomicBool::new(true)),
|
||||
user_data: Arc::new(UserData::new()),
|
||||
dispatcher: super::default_dispatcher(),
|
||||
server_destroyed: false,
|
||||
client_destroyed: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ObjectMeta {
|
||||
pub(crate) fn new(buffer: QueueBuffer) -> ObjectMeta {
|
||||
ObjectMeta {
|
||||
buffer,
|
||||
alive: Arc::new(AtomicBool::new(true)),
|
||||
user_data: Arc::new(UserData::new()),
|
||||
dispatcher: super::default_dispatcher(),
|
||||
server_destroyed: false,
|
||||
client_destroyed: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn dead() -> ObjectMeta {
|
||||
ObjectMeta {
|
||||
buffer: super::queues::create_queue_buffer(),
|
||||
alive: Arc::new(AtomicBool::new(false)),
|
||||
user_data: Arc::new(UserData::new()),
|
||||
dispatcher: super::default_dispatcher(),
|
||||
server_destroyed: true,
|
||||
client_destroyed: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct ProxyInner {
|
||||
pub(crate) map: Arc<Mutex<ObjectMap<ObjectMeta>>>,
|
||||
pub(crate) connection: Arc<Mutex<Connection>>,
|
||||
pub(crate) object: Object<ObjectMeta>,
|
||||
pub(crate) id: u32,
|
||||
pub(crate) queue: Option<QueueBuffer>,
|
||||
}
|
||||
|
||||
impl ProxyInner {
|
||||
pub(crate) fn from_id(
|
||||
id: u32,
|
||||
map: Arc<Mutex<ObjectMap<ObjectMeta>>>,
|
||||
connection: Arc<Mutex<Connection>>,
|
||||
) -> Option<ProxyInner> {
|
||||
let me = map.lock().unwrap().find(id);
|
||||
me.map(|obj| ProxyInner {
|
||||
map,
|
||||
connection,
|
||||
id,
|
||||
queue: Some(obj.meta.buffer.clone()),
|
||||
object: obj,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn dead<I: Interface>(
|
||||
id: u32,
|
||||
map: Arc<Mutex<ObjectMap<ObjectMeta>>>,
|
||||
connection: Arc<Mutex<Connection>>,
|
||||
) -> ProxyInner {
|
||||
ProxyInner {
|
||||
map,
|
||||
connection,
|
||||
id,
|
||||
queue: None,
|
||||
object: Object::from_interface::<I>(1, ObjectMeta::dead()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn is_interface<I: Interface>(&self) -> bool {
|
||||
self.object.is_interface::<I>()
|
||||
}
|
||||
|
||||
pub(crate) fn is_alive(&self) -> bool {
|
||||
self.object.meta.alive.load(Ordering::Acquire)
|
||||
}
|
||||
|
||||
pub fn version(&self) -> u32 {
|
||||
self.object.version
|
||||
}
|
||||
|
||||
pub(crate) fn id(&self) -> u32 {
|
||||
if self.is_alive() {
|
||||
self.id
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn user_data(&self) -> &UserData {
|
||||
&*self.object.meta.user_data
|
||||
}
|
||||
|
||||
pub(crate) fn detach(&mut self) {
|
||||
self.queue = None;
|
||||
}
|
||||
|
||||
pub(crate) fn attach(&mut self, queue: &EventQueueInner) {
|
||||
self.queue = Some(queue.buffer.clone())
|
||||
}
|
||||
|
||||
pub(crate) fn send<I, J>(&self, msg: I::Request, version: Option<u32>) -> Option<ProxyInner>
|
||||
where
|
||||
I: Interface,
|
||||
J: Interface,
|
||||
{
|
||||
// grab the connection lock before anything else
|
||||
// this avoids the risk or races during object creation
|
||||
let mut conn_lock = self.connection.lock().unwrap();
|
||||
let destructor = msg.is_destructor();
|
||||
let mut msg = msg.into_raw(self.id);
|
||||
|
||||
let opcode = msg.opcode;
|
||||
|
||||
// figure out if the call creates an object
|
||||
let nid_idx = I::Request::MESSAGES[opcode as usize]
|
||||
.signature
|
||||
.iter()
|
||||
.position(|&t| t == ArgumentType::NewId);
|
||||
|
||||
let alive = self.is_alive();
|
||||
|
||||
let ret = if let Some(mut nid_idx) = nid_idx {
|
||||
let target_queue = self
|
||||
.queue
|
||||
.clone()
|
||||
.expect("Attemping to create an object from a non-attached proxy.");
|
||||
if let Some(o) = I::Request::child(opcode, 1, &()) {
|
||||
if !o.is_interface::<J>() {
|
||||
panic!(
|
||||
"Trying to use 'send_constructor' with the wrong return type. \
|
||||
Required interface {} but the message creates interface {}",
|
||||
J::NAME,
|
||||
o.interface
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// There is no target interface in the protocol, this is a generic object-creating
|
||||
// function (likely wl_registry.bind), the newid arg will thus expand to
|
||||
// (str, u32, obj).
|
||||
nid_idx += 2;
|
||||
}
|
||||
// insert the newly created object in the message
|
||||
let new_object = Object::from_interface::<J>(
|
||||
version.unwrap_or(self.object.version),
|
||||
if alive { ObjectMeta::new(target_queue.clone()) } else { ObjectMeta::dead() },
|
||||
);
|
||||
let mut new_id = 0;
|
||||
if alive {
|
||||
new_id = self.map.lock().unwrap().client_insert_new(new_object.clone());
|
||||
msg.args[nid_idx] = Argument::NewId(new_id);
|
||||
}
|
||||
Some(ProxyInner {
|
||||
map: self.map.clone(),
|
||||
connection: self.connection.clone(),
|
||||
id: new_id,
|
||||
object: new_object,
|
||||
queue: Some(target_queue),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if WAYLAND_DEBUG.load(Ordering::Relaxed) {
|
||||
debug::print_send_message(
|
||||
I::NAME,
|
||||
self.id,
|
||||
alive,
|
||||
self.object.requests[msg.opcode as usize].name,
|
||||
&msg.args,
|
||||
);
|
||||
}
|
||||
|
||||
// Only actually send the message (& process destructor) if the object is alive.
|
||||
if !alive {
|
||||
return ret;
|
||||
}
|
||||
|
||||
conn_lock.write_message(&msg).expect("Sending a message failed.");
|
||||
|
||||
if destructor {
|
||||
self.object.meta.alive.store(false, Ordering::Release);
|
||||
|
||||
// Cleanup the map as appropriate.
|
||||
let mut map = conn_lock.map.lock().unwrap();
|
||||
let server_destroyed = map
|
||||
.with(self.id, |obj| {
|
||||
obj.meta.client_destroyed = true;
|
||||
obj.meta.server_destroyed
|
||||
})
|
||||
.unwrap_or(false);
|
||||
|
||||
if server_destroyed {
|
||||
map.remove(self.id);
|
||||
}
|
||||
}
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
pub(crate) fn equals(&self, other: &ProxyInner) -> bool {
|
||||
self.is_alive() && Arc::ptr_eq(&self.object.meta.alive, &other.object.meta.alive)
|
||||
}
|
||||
|
||||
pub fn assign<I, E>(&self, filter: Filter<E>)
|
||||
where
|
||||
I: Interface + AsRef<Proxy<I>> + From<Proxy<I>> + Sync,
|
||||
E: From<(Main<I>, I::Event)> + 'static,
|
||||
I::Event: MessageGroup<Map = super::ProxyMap>,
|
||||
{
|
||||
// ignore failure if target object is dead
|
||||
let _ = self.map.lock().unwrap().with(self.id, |obj| {
|
||||
obj.meta.dispatcher = super::make_dispatcher(filter);
|
||||
});
|
||||
}
|
||||
}
|
||||
300
third-party/vendor/wayland-client/src/rust_imp/queues.rs
vendored
Normal file
300
third-party/vendor/wayland-client/src/rust_imp/queues.rs
vendored
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
use std::cell::Cell;
|
||||
use std::collections::VecDeque;
|
||||
use std::io;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use nix::poll::{poll, PollFd, PollFlags};
|
||||
|
||||
use wayland_commons::map::ObjectMap;
|
||||
use wayland_commons::wire::{Argument, Message};
|
||||
|
||||
use super::connection::{Connection, Error as CError};
|
||||
use super::proxy::{ObjectMeta, ProxyInner};
|
||||
use super::Dispatched;
|
||||
|
||||
use crate::{AnonymousObject, DispatchData, Filter, Main, RawEvent};
|
||||
|
||||
pub(crate) type QueueBuffer = Arc<Mutex<VecDeque<Message>>>;
|
||||
|
||||
pub(crate) fn create_queue_buffer() -> QueueBuffer {
|
||||
Arc::new(Mutex::new(VecDeque::new()))
|
||||
}
|
||||
|
||||
pub(crate) struct EventQueueInner {
|
||||
pub(crate) connection: Arc<Mutex<Connection>>,
|
||||
pub(crate) map: Arc<Mutex<ObjectMap<ObjectMeta>>>,
|
||||
pub(crate) buffer: QueueBuffer,
|
||||
display_buffer: QueueBuffer,
|
||||
}
|
||||
|
||||
impl EventQueueInner {
|
||||
pub(crate) fn new(
|
||||
connection: Arc<Mutex<Connection>>,
|
||||
buffer: Option<QueueBuffer>,
|
||||
) -> EventQueueInner {
|
||||
let (map, display_buffer) = {
|
||||
let cx = connection.lock().unwrap();
|
||||
(cx.map.clone(), cx.display_buffer.clone())
|
||||
};
|
||||
EventQueueInner {
|
||||
connection,
|
||||
map,
|
||||
buffer: buffer.unwrap_or_else(create_queue_buffer),
|
||||
display_buffer,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn dispatch<F>(&self, mut data: DispatchData, mut fallback: F) -> io::Result<u32>
|
||||
where
|
||||
F: FnMut(RawEvent, Main<AnonymousObject>, DispatchData<'_>),
|
||||
{
|
||||
// don't read events if there are some pending
|
||||
if let Err(()) = self.prepare_read() {
|
||||
return self.dispatch_pending(data.reborrow(), &mut fallback);
|
||||
}
|
||||
|
||||
// temporarily retrieve the socket Fd, only using it for POLL-ing!
|
||||
let socket_fd;
|
||||
{
|
||||
// Flush the outgoing socket
|
||||
let mut conn_lock = self.connection.lock().unwrap();
|
||||
socket_fd = conn_lock.socket.get_socket().as_raw_fd();
|
||||
loop {
|
||||
match conn_lock.flush() {
|
||||
Ok(_) => break,
|
||||
Err(nix::Error::EAGAIN) => {
|
||||
// EAGAIN, we need to wait before writing, so we poll the socket
|
||||
let poll_ret = poll(&mut [PollFd::new(socket_fd, PollFlags::POLLOUT)], -1);
|
||||
match poll_ret {
|
||||
Ok(_) => continue,
|
||||
Err(e) => {
|
||||
self.cancel_read();
|
||||
return Err(e.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
if e != nix::Error::EPIPE {
|
||||
// don't abort on EPIPE, so we can continue reading
|
||||
// to get the protocol error
|
||||
self.cancel_read();
|
||||
return Err(e.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// wait for incoming messages to arrive
|
||||
match poll(&mut [PollFd::new(socket_fd, PollFlags::POLLIN)], -1) {
|
||||
Ok(_) => (),
|
||||
Err(e) => {
|
||||
self.cancel_read();
|
||||
return Err(e.into());
|
||||
}
|
||||
}
|
||||
let read_ret = self.read_events();
|
||||
|
||||
// even if read_events returned an error, it may have queued messages the need dispatching
|
||||
// so we dispatch them
|
||||
let dispatch_ret = self.dispatch_pending(data.reborrow(), &mut fallback);
|
||||
|
||||
match read_ret {
|
||||
Ok(()) => (),
|
||||
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
|
||||
// we waited for read readiness be then received a WouldBlock error
|
||||
// this means that an other thread was also reading events and read them
|
||||
// under our nose
|
||||
// this is alright, continue
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
|
||||
dispatch_ret
|
||||
}
|
||||
|
||||
fn dispatch_buffer<F>(
|
||||
&self,
|
||||
buffer: &Mutex<VecDeque<Message>>,
|
||||
mut data: DispatchData,
|
||||
mut fallback: F,
|
||||
) -> io::Result<u32>
|
||||
where
|
||||
F: FnMut(RawEvent, Main<AnonymousObject>, DispatchData<'_>),
|
||||
{
|
||||
let mut count = 0;
|
||||
let mut proxymap = super::ProxyMap::make(self.map.clone(), self.connection.clone());
|
||||
loop {
|
||||
let msg = { buffer.lock().unwrap().pop_front() };
|
||||
let msg = match msg {
|
||||
Some(m) => m,
|
||||
None => break,
|
||||
};
|
||||
let id = msg.sender_id;
|
||||
if let Some(proxy) = ProxyInner::from_id(id, self.map.clone(), self.connection.clone())
|
||||
{
|
||||
let object = proxy.object.clone();
|
||||
if object.meta.client_destroyed {
|
||||
// This is a potential race, if we reach here it means that the proxy was
|
||||
// destroyed by the user between this message was queued and now. To handle it
|
||||
// correctly, we must close any FDs it contains, mark any child object as
|
||||
// destroyed (but the server will never know about it, so the ids will be
|
||||
// leaked) and discard the event.
|
||||
for arg in msg.args {
|
||||
match arg {
|
||||
Argument::Fd(fd) => {
|
||||
let _ = ::nix::unistd::close(fd);
|
||||
}
|
||||
Argument::NewId(id) => {
|
||||
let mut map = self.map.lock().unwrap();
|
||||
map.with(id, |obj| {
|
||||
obj.meta.client_destroyed = true;
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
let mut dispatcher = object.meta.dispatcher.lock().unwrap();
|
||||
match dispatcher.dispatch(msg, proxy, &mut proxymap, data.reborrow()) {
|
||||
Dispatched::Yes => {
|
||||
count += 1;
|
||||
}
|
||||
Dispatched::NoDispatch(msg, proxy) => {
|
||||
let raw_event = message_to_rawevent(msg, &proxy, &mut proxymap);
|
||||
fallback(raw_event, Main::wrap(proxy), data.reborrow());
|
||||
count += 1;
|
||||
}
|
||||
Dispatched::BadMsg => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("Dispatch for object {}@{} errored.", object.interface, id),
|
||||
))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("Received an event for unknown object {}.", id),
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
pub(crate) fn dispatch_pending<F>(&self, mut data: DispatchData, fallback: F) -> io::Result<u32>
|
||||
where
|
||||
F: FnMut(RawEvent, Main<AnonymousObject>, DispatchData<'_>),
|
||||
{
|
||||
// First always dispatch the display buffer
|
||||
let display_dispatched =
|
||||
self.dispatch_buffer(&self.display_buffer, data.reborrow(), |_, _, _| unreachable!())?;
|
||||
|
||||
// Then our actual buffer
|
||||
let self_dispatched = self.dispatch_buffer(&self.buffer, data.reborrow(), fallback)?;
|
||||
|
||||
Ok(display_dispatched + self_dispatched)
|
||||
}
|
||||
|
||||
pub(crate) fn sync_roundtrip<F>(
|
||||
&self,
|
||||
mut data: DispatchData,
|
||||
mut fallback: F,
|
||||
) -> io::Result<u32>
|
||||
where
|
||||
F: FnMut(RawEvent, Main<AnonymousObject>, DispatchData<'_>),
|
||||
{
|
||||
use crate::protocol::wl_callback::{Event as CbEvent, WlCallback};
|
||||
use crate::protocol::wl_display::{Request as DRequest, WlDisplay};
|
||||
// first retrieve the display and make a wrapper for it in this event queue
|
||||
let mut display =
|
||||
ProxyInner::from_id(1, self.map.clone(), self.connection.clone()).unwrap();
|
||||
display.attach(self);
|
||||
|
||||
let done = Rc::new(Cell::new(false));
|
||||
let cb = display.send::<WlDisplay, WlCallback>(DRequest::Sync {}, Some(1)).unwrap();
|
||||
let done2 = done.clone();
|
||||
cb.assign::<WlCallback, _>(Filter::new(move |(_, CbEvent::Done { .. }), _, _| {
|
||||
done2.set(true);
|
||||
}));
|
||||
|
||||
let mut dispatched = 0;
|
||||
|
||||
loop {
|
||||
dispatched += self.dispatch(data.reborrow(), &mut fallback)?;
|
||||
if done.get() {
|
||||
return Ok(dispatched);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn prepare_read(&self) -> Result<(), ()> {
|
||||
if !self.buffer.lock().unwrap().is_empty() {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
// TODO: un-mock
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn read_events(&self) -> io::Result<()> {
|
||||
// TODO: integrate more properly with prepare read with a fence
|
||||
match self.connection.lock().unwrap().read_events() {
|
||||
Ok(_) => Ok(()),
|
||||
Err(CError::Protocol(e)) => {
|
||||
eprintln!("[wayland-client] Protocol error while reading events: {}", e);
|
||||
Err(::nix::errno::Errno::EPROTO.into())
|
||||
}
|
||||
Err(CError::Parse(e)) => {
|
||||
eprintln!("[wayland-client] Parse error while reading events: {}", e);
|
||||
Err(::nix::errno::Errno::EPROTO.into())
|
||||
}
|
||||
Err(CError::Nix(errno)) => Err(errno.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn cancel_read(&self) {
|
||||
// TODO: un-mock
|
||||
}
|
||||
}
|
||||
|
||||
fn message_to_rawevent(msg: Message, proxy: &ProxyInner, map: &mut super::ProxyMap) -> RawEvent {
|
||||
let Message { opcode, args, .. } = msg;
|
||||
|
||||
let args = args
|
||||
.into_iter()
|
||||
.map(|a| match a {
|
||||
Argument::Int(i) => crate::Argument::Int(i),
|
||||
Argument::Uint(u) => crate::Argument::Uint(u),
|
||||
Argument::Array(v) => {
|
||||
crate::Argument::Array(if v.is_empty() { None } else { Some(*v) })
|
||||
}
|
||||
Argument::Fixed(f) => crate::Argument::Float((f as f32) / 256.),
|
||||
Argument::Fd(f) => crate::Argument::Fd(f),
|
||||
Argument::Str(cs) => crate::Argument::Str({
|
||||
let bytes = cs.into_bytes();
|
||||
if bytes.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(
|
||||
String::from_utf8(bytes)
|
||||
.unwrap_or_else(|e| String::from_utf8_lossy(&e.into_bytes()).into()),
|
||||
)
|
||||
}
|
||||
}),
|
||||
Argument::Object(id) => crate::Argument::Object(map.get(id)),
|
||||
Argument::NewId(id) => crate::Argument::NewId(map.get_new(id)),
|
||||
})
|
||||
.collect();
|
||||
|
||||
RawEvent {
|
||||
interface: proxy.object.interface,
|
||||
opcode,
|
||||
name: proxy.object.events[opcode as usize].name,
|
||||
args,
|
||||
}
|
||||
}
|
||||
3019
third-party/vendor/wayland-client/wayland.xml
vendored
Normal file
3019
third-party/vendor/wayland-client/wayland.xml
vendored
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue