From d991f59c9048088922a94dcca97270bbe32d8c54 Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Thu, 16 Jun 2022 10:48:15 -0400 Subject: [PATCH] 0.30 --- Cargo.lock | 76 ++++- applets/cosmic-applet-workspaces/Cargo.toml | 6 +- applets/cosmic-applet-workspaces/build.rs | 21 +- .../src/ext-workspace-unstable-v1.xml | 306 ++++++++++++++++++ .../cosmic-applet-workspaces/src/wayland.rs | 134 +++++--- 5 files changed, 470 insertions(+), 73 deletions(-) create mode 100644 applets/cosmic-applet-workspaces/src/ext-workspace-unstable-v1.xml diff --git a/Cargo.lock b/Cargo.lock index 44b0a032..8ff3ab2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -368,11 +368,11 @@ dependencies = [ "once_cell", "pretty_env_logger", "rust-embed", - "smithay-client-toolkit", "tokio", - "wayland-client", + "wayland-backend", + "wayland-client 0.30.0-beta.4", "wayland-commons", - "wayland-scanner", + "wayland-scanner 0.30.0-beta.4", ] [[package]] @@ -1829,6 +1829,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scoped-tls" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" + [[package]] name = "scopeguard" version = "1.1.0" @@ -1978,7 +1984,7 @@ dependencies = [ "memmap2", "nix 0.22.3", "pkg-config", - "wayland-client", + "wayland-client 0.29.4", "wayland-cursor", "wayland-protocols", ] @@ -2231,6 +2237,20 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wayland-backend" +version = "0.1.0-beta.4" +source = "git+https://github.com/smithay/wayland-rs.git#797f697a66f8541327cbaac319692ec8d2395a38" +dependencies = [ + "cc", + "downcast-rs", + "log", + "nix 0.24.1", + "scoped-tls", + "smallvec", + "wayland-sys 0.30.0-beta.4", +] + [[package]] name = "wayland-client" version = "0.29.4" @@ -2242,8 +2262,23 @@ dependencies = [ "libc", "nix 0.22.3", "wayland-commons", - "wayland-scanner", - "wayland-sys", + "wayland-scanner 0.29.4", + "wayland-sys 0.29.4", +] + +[[package]] +name = "wayland-client" +version = "0.30.0-beta.4" +source = "git+https://github.com/smithay/wayland-rs.git#797f697a66f8541327cbaac319692ec8d2395a38" +dependencies = [ + "bitflags", + "futures-channel", + "futures-core", + "log", + "nix 0.24.1", + "thiserror", + "wayland-backend", + "wayland-scanner 0.30.0-beta.4", ] [[package]] @@ -2255,7 +2290,7 @@ dependencies = [ "nix 0.22.3", "once_cell", "smallvec", - "wayland-sys", + "wayland-sys 0.29.4", ] [[package]] @@ -2265,7 +2300,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c52758f13d5e7861fc83d942d3d99bf270c83269575e52ac29e5b73cb956a6bd" dependencies = [ "nix 0.22.3", - "wayland-client", + "wayland-client 0.29.4", "xcursor", ] @@ -2276,9 +2311,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60147ae23303402e41fe034f74fb2c35ad0780ee88a1c40ac09a3be1e7465741" dependencies = [ "bitflags", - "wayland-client", + "wayland-client 0.29.4", "wayland-commons", - "wayland-scanner", + "wayland-scanner 0.29.4", ] [[package]] @@ -2292,6 +2327,17 @@ dependencies = [ "xml-rs", ] +[[package]] +name = "wayland-scanner" +version = "0.30.0-beta.4" +source = "git+https://github.com/smithay/wayland-rs.git#797f697a66f8541327cbaac319692ec8d2395a38" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "xml-rs", +] + [[package]] name = "wayland-sys" version = "0.29.4" @@ -2301,6 +2347,16 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "wayland-sys" +version = "0.30.0-beta.4" +source = "git+https://github.com/smithay/wayland-rs.git#797f697a66f8541327cbaac319692ec8d2395a38" +dependencies = [ + "dlib", + "log", + "pkg-config", +] + [[package]] name = "wepoll-ffi" version = "0.1.2" diff --git a/applets/cosmic-applet-workspaces/Cargo.toml b/applets/cosmic-applet-workspaces/Cargo.toml index acbaf4bd..9a22dbcb 100644 --- a/applets/cosmic-applet-workspaces/Cargo.toml +++ b/applets/cosmic-applet-workspaces/Cargo.toml @@ -17,10 +17,10 @@ i18n-embed = { version = "0.13.4", features = ["fluent-system", "desktop-request i18n-embed-fl = "0.6.4" rust-embed = "6.3.0" tokio = { version = "1.16.1", features = ["sync"] } -wayland-client = "0.29.4" wayland-commons = "0.29.4" -sctk = { package = "smithay-client-toolkit", git = "https://github.com/wash2/client-toolkit.git", default-features = false, features = ["calloop"] } +wayland-scanner = { git = "https://github.com/smithay/wayland-rs.git", version = "0.30.0-beta.4"} +wayland-backend = { version = "0.1.0-beta.4", git = "https://github.com/smithay/wayland-rs.git" } +wayland-client = { version = "0.30.0-beta.4", git = "https://github.com/smithay/wayland-rs.git" } [build-dependencies] gio = "0.15.10" -wayland-scanner = "0.29" diff --git a/applets/cosmic-applet-workspaces/build.rs b/applets/cosmic-applet-workspaces/build.rs index d99ec86a..49c3dbed 100644 --- a/applets/cosmic-applet-workspaces/build.rs +++ b/applets/cosmic-applet-workspaces/build.rs @@ -1,7 +1,5 @@ -extern crate wayland_scanner; - use std::{env, path::PathBuf, process::Command}; -use wayland_scanner::{generate_code, Side}; +// use wayland_scanner::{generate_client_code}; fn main() { if let Some(output) = Command::new("git") @@ -17,13 +15,12 @@ fn main() { "data/resources/resources.gresource.xml", "compiled.gresource", ); - let dest = PathBuf::from(&env::var("OUT_DIR").unwrap()); - // Location of the xml file, relative to the `Cargo.toml` - let ext_workspace_protocol_file = "data/resources/ext-workspace-unstable-v1.xml"; - // Target directory for the generate files - generate_code( - ext_workspace_protocol_file, - &dest.join("ext_workspace.rs"), - Side::Client, - ); + // let dest = PathBuf::from(&env::var("OUT_DIR").unwrap()); + // // Location of the xml file, relative to the `Cargo.toml` + // let ext_workspace_protocol_file = "data/resources/ext-workspace-unstable-v1.xml"; + // // Target directory for the generate files + // generate_client_code!( + // ext_workspace_protocol_file, + // &dest.join("ext_workspace.rs"), + // ); } diff --git a/applets/cosmic-applet-workspaces/src/ext-workspace-unstable-v1.xml b/applets/cosmic-applet-workspaces/src/ext-workspace-unstable-v1.xml new file mode 100644 index 00000000..24410b62 --- /dev/null +++ b/applets/cosmic-applet-workspaces/src/ext-workspace-unstable-v1.xml @@ -0,0 +1,306 @@ + + + + Copyright © 2019 Christopher Billington + Copyright © 2020 Ilia Bozhinov + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that copyright notice and this permission + notice appear in supporting documentation, and that the name of + the copyright holders not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. The copyright holders make no + representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied + warranty. + + THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF + THIS SOFTWARE. + + + + + Workspaces, also called virtual desktops, are groups of surfaces. A + compositor with a concept of workspaces may only show some such groups of + surfaces (those of 'active' workspaces) at a time. 'Activating' a + workspace is a request for the compositor to display that workspace's + surfaces as normal, whereas the compositor may hide or otherwise + de-emphasise surfaces that are associated only with 'inactive' workspaces. + Workspaces are grouped by which sets of outputs they correspond to, and + may contain surfaces only from those outputs. In this way, it is possible + for each output to have its own set of workspaces, or for all outputs (or + any other arbitrary grouping) to share workspaces. Compositors may + optionally conceptually arrange each group of workspaces in an + N-dimensional grid. + + The purpose of this protocol is to enable the creation of taskbars and + docks by providing them with a list of workspaces and their properties, + and allowing them to activate and deactivate workspaces. + + After a client binds the zext_workspace_manager_v1, each workspace will be + sent via the workspace event. + + + + + This event is emitted whenever a new workspace group has been created. + + All initial details of the workspace group (workspaces, outputs) will be + sent immediately after this event via the corresponding events in + zext_workspace_group_handle_v1. + + + + + + + The client must send this request after it has finished sending other + requests. The compositor must process a series of requests preceding a + commit request atomically. + + This allows changes to the workspace properties to be seen as atomic, + even if they happen via multiple events, and even if they involve + multiple zext_workspace_handle_v1 objects, for example, deactivating one + workspace and activating another. + + + + + + This event is sent after all changes in all workspace groups have been + sent. + + This allows changes to one or more zext_workspace_group_handle_v1 + properties to be seen as atomic, even if they happen via multiple + events. In particular, an output moving from one workspace group to + another sends an output_enter event and an output_leave event to the two + zext_workspace_group_handle_v1 objects in question. The compositor sends + the done event only after updating the output information in both + workspace groups. + + + + + + This event indicates that the compositor is done sending events to the + zext_workspace_manager_v1. The server will destroy the object + immediately after sending this request, so it will become invalid and + the client should free any resources associated with it. + + + + + + Indicates the client no longer wishes to receive events for new + workspace groups. However the compositor may emit further workspace + events, until the finished event is emitted. + + The client must not send any more requests after this one. + + + + + + + A zext_workspace_group_handle_v1 object represents a a workspace group + that is assigned a set of outputs and contains a number of workspaces. + + The set of outputs assigned to the workspace group is conveyed to the client via + output_enter and output_leave events, and its workspaces are conveyed with + workspace events. + + For example, a compositor which has a set of workspaces for each output may + advertise a workspace group (and its workspaces) per output, whereas a compositor + where a workspace spans all outputs may advertise a single workspace group for all + outputs. + + + + + This event is emitted whenever an output is assigned to the workspace + group. + + + + + + + This event is emitted whenever an output is removed from the workspace + group. + + + + + + + This event is emitted whenever a new workspace has been created. + + All initial details of the workspace (name, coordinates, state) will + be sent immediately after this event via the corresponding events in + zext_workspace_handle_v1. + + + + + + + This event means the zext_workspace_group_handle_v1 has been destroyed. + It is guaranteed there won't be any more events for this + zext_workspace_group_handle_v1. The zext_workspace_group_handle_v1 becomes + inert so any requests will be ignored except the destroy request. + + The compositor must remove all workspaces belonging to a workspace group + before removing the workspace group. + + + + + + Request that the compositor create a new workspace with the given name. + + There is no guarantee that the compositor will create a new workspace, + or that the created workspace will have the provided name. + + + + + + + Destroys the zext_workspace_handle_v1 object. + + This request should be called either when the client does not want to + use the workspace object any more or after the remove event to finalize + the destruction of the object. + + + + + + + A zext_workspace_handle_v1 object represents a a workspace that handles a + group of surfaces. + + Each workspace has a name, conveyed to the client with the name event; a + list of states, conveyed to the client with the state event; and + optionally a set of coordinates, conveyed to the client with the + coordinates event. The client may request that the compositor activate or + deactivate the workspace. + + Each workspace can belong to only a single workspace group. + Depepending on the compositor policy, there might be workspaces with + the same name in different workspace groups, but these workspaces are still + separate (e.g. one of them might be active while the other is not). + + + + + This event is emitted immediately after the zext_workspace_handle_v1 is + created and whenever the name of the workspace changes. + + + + + + + This event is used to organize workspaces into an N-dimensional grid + within a workspace group, and if supported, is emitted immediately after + the zext_workspace_handle_v1 is created and whenever the coordinates of + the workspace change. Compositors may not send this event if they do not + conceptually arrange workspaces in this way. If compositors simply + number workspaces, without any geometric interpretation, they may send + 1D coordinates, which clients should not interpret as implying any + geometry. Sending an empty array means that the compositor no longer + orders the workspace geometrically. + + Coordinates have an arbitrary number of dimensions N with an uint32 + position along each dimension. By convention if N > 1, the first + dimension is X, the second Y, the third Z, and so on. The compositor may + chose to utilize these events for a more novel workspace layout + convention, however. No guarantee is made about the grid being filled or + bounded; there may be a workspace at coordinate 1 and another at + coordinate 1000 and none in between. Within a workspace group, however, + workspaces must have unique coordinates of equal dimensionality. + + + + + + + This event is emitted immediately after the zext_workspace_handle_v1 is + created and each time the workspace state changes, either because of a + compositor action or because of a request in this protocol. + + + + + + + The different states that a workspace can have. + + + + + + + The workspace is not visible in its workspace group, and clients + attempting to visualize the compositor workspace state should not + display such workspaces. + + + + + + + This event means the zext_workspace_handle_v1 has been destroyed. It is + guaranteed there won't be any more events for this + zext_workspace_handle_v1. The zext_workspace_handle_v1 becomes inert so + any requests will be ignored except the destroy request. + + + + + + Destroys the zext_workspace_handle_v1 object. + + This request should be called either when the client does not want to + use the workspace object any more or after the remove event to finalize + the destruction of the object. + + + + + + Request that this workspace be activated. + + There is no guarantee the workspace will be actually activated, and + behaviour may be compositor-dependent. For example, activating a + workspace may or may not deactivate all other workspaces in the same + group. + + + + + + Request that this workspace be deactivated. + + There is no guarantee the workspace will be actually deactivated. + + + + + + Request that this workspace be removed. + + There is no guarantee the workspace will be actually removed. + + + + diff --git a/applets/cosmic-applet-workspaces/src/wayland.rs b/applets/cosmic-applet-workspaces/src/wayland.rs index 5af6e35e..94720e84 100644 --- a/applets/cosmic-applet-workspaces/src/wayland.rs +++ b/applets/cosmic-applet-workspaces/src/wayland.rs @@ -1,68 +1,67 @@ use crate::utils::{Activate, Workspace}; use std::{ - num::ParseIntError, - os::unix::prelude::RawFd, - sync::{Arc, Mutex}, + os::unix::{net::UnixStream}, env, path::PathBuf, }; +use wayland_client::{ConnectError, DelegateDispatch, protocol::wl_registry}; use tokio::sync::mpsc; -use wayland_client::{protocol::wl_registry, Display, GlobalManager}; -use generated::client::{zext_workspace_manager_v1, zext_workspace_group_handle_v1, zext_workspace_handle_v1}; -use sctk::environment::{SimpleGlobal, Environment}; -use sctk::environment; + +use wayland_client::{ + Connection, Dispatch, QueueHandle, +}; + +/// Generated protocol definitions mod generated { - // The generated code tends to trigger a lot of warnings - // so we isolate it into a very permissive module - #![allow(dead_code, non_camel_case_types, unused_unsafe, unused_variables)] - #![allow(non_upper_case_globals, non_snake_case, unused_imports)] + #![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 mod client { - // These imports are used by the generated code - 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_client::protocol::wl_output; - pub(crate) use wayland_client::sys; - pub(crate) use wayland_client::{AnonymousObject, Main, Proxy, ProxyMap}; - include!(concat!(env!("OUT_DIR"), "/ext_workspace.rs")); + //! Client-side API of this protocol + use wayland_client; + use wayland_client::protocol::*; + + pub mod __interfaces { + use wayland_client::protocol::__interfaces::*; + wayland_scanner::generate_interfaces!("src/ext-workspace-unstable-v1.xml"); + } + use self::__interfaces::*; + + wayland_scanner::generate_client_code!("src/ext-workspace-unstable-v1.xml"); } } -#[derive(Debug)] -struct State { - workspace_manager: SimpleGlobal, -} - -environment!(State, - singles = [ - zext_workspace_manager_v1::ZextWorkspaceManagerV1 => workspace_manager, - ], - multis = [] -); +use generated::client::zext_workspace_manager_v1; pub fn spawn_workspaces(tx: mpsc::Sender>) -> mpsc::Sender { let (workspaces_tx, mut workspaces_rx) = mpsc::channel(100); - if let Ok(display) = std::env::var("HOST_WAYLAND_DISPLAY") + if let Ok(Ok(conn)) = std::env::var("HOST_WAYLAND_DISPLAY") .map_err(anyhow::Error::msg) - .and_then(|fd| Display::connect_to_name(fd).map_err(anyhow::Error::msg)) + .map(|fd| { + let mut socket_path = env::var_os("XDG_RUNTIME_DIR") + .map(Into::::into) + .ok_or(ConnectError::NoCompositor)?; + socket_path.push(env::var_os("WAYLAND_DISPLAY").ok_or(ConnectError::NoCompositor)?); + + Ok(UnixStream::connect(socket_path).map_err(|_| ConnectError::NoCompositor)?) + }) + .and_then(|s| s.map(|s| Connection::from_socket(s).map_err(anyhow::Error::msg))) { std::thread::spawn(move || { - let mut event_queue = display.create_event_queue(); - let attached_display = display.attach(event_queue.token()); - let env = State { - workspace_manager: SimpleGlobal::new(), + let mut event_queue= conn.new_event_queue::(); + let qhandle = event_queue.handle(); + + let display = conn.display(); + display.get_registry(&qhandle, ()).unwrap(); + + let mut state = State { + workspace_manager: None, + tx, + running: true, }; - let env = Environment::new(&attached_display, &mut event_queue, env).expect("Failed to create environment"); - - let workspace_manager = env.require_global::(); - dbg!(workspace_manager); - // let globals = GlobalManager::new(&attached_display); - // let _ = event_queue.sync_roundtrip(&mut (), |_, _, _| unreachable!()); - - // println!("Globals: "); - // for (name, interface, version) in globals.list() { - // println!("{}: {} (version {})", name, interface, version); - // } + + while state.running { + event_queue.blocking_dispatch(&mut state).unwrap(); + } }); } else { eprintln!("ENV variable HOST_WAYLAND_DISPLAY is missing. Exiting..."); @@ -74,5 +73,44 @@ pub fn spawn_workspaces(tx: mpsc::Sender>) -> mpsc::Sender>, + workspace_manager: Option, +} +impl Dispatch for State { + fn event( + &mut self, + registry: &wl_registry::WlRegistry, + event: wl_registry::Event, + _: &(), + _: &Connection, + qh: &QueueHandle, + ) { + if let wl_registry::Event::Global { name, interface, version } = event { + println!("[{}] {} (v{})", name, interface, version); + match &interface[..] { + "zext_workspace_manager_v1" => { + println!("binding to workspace manager"); + registry.bind::(name, 1, qh, ()).unwrap(); + }, + _ => {} + } + } + } +} +impl Dispatch for State { + fn event( + &mut self, + _: &zext_workspace_manager_v1::ZextWorkspaceManagerV1, + _: zext_workspace_manager_v1::Event, + _: &(), + _: &Connection, + _: &QueueHandle, + ) { + todo!() + // wl_compositor has no event + } +}