inital commit
This commit is contained in:
commit
35c8f12c96
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
1500
Cargo.lock
generated
Normal file
1500
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
27
Cargo.toml
Normal file
27
Cargo.toml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
[package]
|
||||||
|
name = "mybar"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
wayland-backend = { version = "0.3.6", features = ["client_system"] }
|
||||||
|
wayland-client = "0.31.5"
|
||||||
|
wayland-scanner = "0.31.4"
|
||||||
|
wayland-protocols-wlr = { version = "0.3.3", features = ["client"] }
|
||||||
|
wayland-protocols = { version = "0.32.3", features = ["client"]}
|
||||||
|
|
||||||
|
tempfile = "3.2"
|
||||||
|
bitflags = "2"
|
||||||
|
rustix = { version = "0.38.0", features = ["event"] }
|
||||||
|
log = { version = "0.4", optional = true }
|
||||||
|
wgpu = "22.1.0"
|
||||||
|
raw-window-handle = { version = "0.6.2", features = ["alloc"] }
|
||||||
|
smithay-client-toolkit = "0.19.2"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
futures-channel = "0.3.16"
|
||||||
|
futures-util = "0.3"
|
||||||
|
|
||||||
|
[package.metadata.docs.rs]
|
||||||
|
all-features = true
|
||||||
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
391
src/main.rs
Normal file
391
src/main.rs
Normal file
@ -0,0 +1,391 @@
|
|||||||
|
use std::{borrow::{Borrow, BorrowMut}, ffi::c_void, fs::File, os::unix::io::AsFd, ptr::NonNull};
|
||||||
|
|
||||||
|
use wayland_client::{
|
||||||
|
delegate_noop, protocol::{
|
||||||
|
wl_buffer, wl_compositor, wl_keyboard, wl_pointer, wl_registry, wl_seat, wl_shm, wl_shm_pool, wl_surface
|
||||||
|
}, Connection, Dispatch, Proxy, QueueHandle, WEnum
|
||||||
|
};
|
||||||
|
|
||||||
|
use wayland_protocols::xdg::shell::client::{xdg_surface, xdg_toplevel, xdg_wm_base};
|
||||||
|
|
||||||
|
use wayland_protocols_wlr::layer_shell::v1::client::zwlr_layer_shell_v1::ZwlrLayerShellV1;
|
||||||
|
use wayland_protocols_wlr::layer_shell::v1::client::{zwlr_layer_shell_v1, zwlr_layer_surface_v1, __interfaces as layer_shell_interfaces};
|
||||||
|
|
||||||
|
use wgpu;
|
||||||
|
use raw_window_handle::{self, DisplayHandle, HasDisplayHandle, HasWindowHandle, RawWindowHandle, WindowHandle};
|
||||||
|
|
||||||
|
|
||||||
|
use raw_window_handle::{
|
||||||
|
RawDisplayHandle, WaylandDisplayHandle, WaylandWindowHandle,
|
||||||
|
};
|
||||||
|
use smithay_client_toolkit::{
|
||||||
|
compositor::{CompositorHandler, CompositorState},
|
||||||
|
delegate_compositor, delegate_output, delegate_registry, delegate_seat, delegate_xdg_shell,
|
||||||
|
delegate_xdg_window,
|
||||||
|
output::{OutputHandler, OutputState},
|
||||||
|
registry::{ProvidesRegistryState, RegistryState},
|
||||||
|
registry_handlers,
|
||||||
|
seat::{Capability, SeatHandler, SeatState},
|
||||||
|
shell::{
|
||||||
|
xdg::{
|
||||||
|
window::{Window, WindowConfigure, WindowDecorations, WindowHandler},
|
||||||
|
XdgShell,
|
||||||
|
},
|
||||||
|
WaylandSurface,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use wayland_client::{
|
||||||
|
globals::registry_queue_init,
|
||||||
|
protocol::{wl_output},
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let conn = Connection::connect_to_env().unwrap();
|
||||||
|
|
||||||
|
let mut event_queue = conn.new_event_queue();
|
||||||
|
let qhandle = event_queue.handle();
|
||||||
|
|
||||||
|
let display = conn.display();
|
||||||
|
display.get_registry(&qhandle, ());
|
||||||
|
|
||||||
|
let mut state = State {
|
||||||
|
running: true,
|
||||||
|
base_surface: None,
|
||||||
|
buffer: None,
|
||||||
|
wm_base: None,
|
||||||
|
xdg_surface: None,
|
||||||
|
configured: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("Starting the example window app, press <ESC> to quit.");
|
||||||
|
|
||||||
|
while state.running {
|
||||||
|
event_queue.blocking_dispatch(&mut state).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct State {
|
||||||
|
running: bool,
|
||||||
|
base_surface: Option<wl_surface::WlSurface>,
|
||||||
|
buffer: Option<wl_buffer::WlBuffer>,
|
||||||
|
wm_base: Option<xdg_wm_base::XdgWmBase>,
|
||||||
|
xdg_surface: Option<(xdg_surface::XdgSurface, xdg_toplevel::XdgToplevel)>,
|
||||||
|
configured: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dispatch<wl_registry::WlRegistry, ()> for State {
|
||||||
|
fn event(
|
||||||
|
state: &mut Self,
|
||||||
|
registry: &wl_registry::WlRegistry,
|
||||||
|
event: wl_registry::Event,
|
||||||
|
_: &(),
|
||||||
|
_: &Connection,
|
||||||
|
qh: &QueueHandle<Self>,
|
||||||
|
) {
|
||||||
|
if let wl_registry::Event::Global { name, interface, .. } = event {
|
||||||
|
println!("Event Global: {interface}");
|
||||||
|
match &interface[..] {
|
||||||
|
"wl_compositor" => {
|
||||||
|
let compositor =
|
||||||
|
registry.bind::<wl_compositor::WlCompositor, _, _>(name, 1, qh, ());
|
||||||
|
let surface = compositor.create_surface(qh, ());
|
||||||
|
state.base_surface = Some(surface);
|
||||||
|
|
||||||
|
if state.wm_base.is_some() && state.xdg_surface.is_none() {
|
||||||
|
state.init_xdg_surface(qh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"wl_shm" => {
|
||||||
|
let shm = registry.bind::<wl_shm::WlShm, _, _>(name, 1, qh, ());
|
||||||
|
|
||||||
|
let (init_w, init_h) = (320, 240);
|
||||||
|
|
||||||
|
let mut file = tempfile::tempfile().unwrap();
|
||||||
|
draw(&mut file, (init_w, init_h));
|
||||||
|
let pool = shm.create_pool(file.as_fd(), (init_w * init_h * 4) as i32, qh, ());
|
||||||
|
let buffer = pool.create_buffer(
|
||||||
|
0,
|
||||||
|
init_w as i32,
|
||||||
|
init_h as i32,
|
||||||
|
(init_w * 4) as i32,
|
||||||
|
wl_shm::Format::Argb8888,
|
||||||
|
qh,
|
||||||
|
(),
|
||||||
|
);
|
||||||
|
state.buffer = Some(buffer.clone());
|
||||||
|
|
||||||
|
if state.configured {
|
||||||
|
let surface = state.base_surface.as_ref().unwrap();
|
||||||
|
surface.attach(Some(&buffer), 0, 0);
|
||||||
|
surface.commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"wl_seat" => {
|
||||||
|
registry.bind::<wl_seat::WlSeat, _, _>(name, 1, qh, ());
|
||||||
|
}
|
||||||
|
"xdg_wm_base" => {
|
||||||
|
let wm_base = registry.bind::<xdg_wm_base::XdgWmBase, _, _>(name, 1, qh, ());
|
||||||
|
state.wm_base = Some(wm_base);
|
||||||
|
|
||||||
|
if state.base_surface.is_some() && state.xdg_surface.is_none() {
|
||||||
|
// state.init_xdg_surface(qh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"zwlr_layer_shell_v1" => {
|
||||||
|
let ls = registry.bind::<ZwlrLayerShellV1, _, _>(name, 1, qh, ());
|
||||||
|
let wl_s = state.base_surface.as_ref().unwrap();
|
||||||
|
let ss = ls.get_layer_surface(wl_s, None,
|
||||||
|
zwlr_layer_shell_v1::Layer::Overlay, "".to_string(), qh, ());
|
||||||
|
use zwlr_layer_surface_v1::Anchor;
|
||||||
|
// ss.set_anchor(Anchor::Left);
|
||||||
|
let width: u32 = 40;
|
||||||
|
ss.set_exclusive_zone(width as i32);
|
||||||
|
// ss.set_size(200, 200);
|
||||||
|
ss.set_anchor(Anchor::Left | Anchor::Top | Anchor::Bottom);
|
||||||
|
// ss.set_anchor(Anchor::Bottom);
|
||||||
|
ss.set_size(width, 0);
|
||||||
|
|
||||||
|
ss.set_keyboard_interactivity(zwlr_layer_surface_v1::KeyboardInteractivity::OnDemand);
|
||||||
|
wl_s.commit();
|
||||||
|
|
||||||
|
println!("Well done");
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore events from these object types in this example.
|
||||||
|
delegate_noop!(State: ignore wl_compositor::WlCompositor);
|
||||||
|
delegate_noop!(State: ignore wl_surface::WlSurface);
|
||||||
|
delegate_noop!(State: ignore wl_shm::WlShm);
|
||||||
|
delegate_noop!(State: ignore wl_shm_pool::WlShmPool);
|
||||||
|
delegate_noop!(State: ignore wl_buffer::WlBuffer);
|
||||||
|
|
||||||
|
fn draw(tmp: &mut File, (buf_x, buf_y): (u32, u32)) {
|
||||||
|
println!("Buf: (x: {buf_x}, y: {buf_y})");
|
||||||
|
use std::{cmp::min, io::Write};
|
||||||
|
let mut buf = std::io::BufWriter::new(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);
|
||||||
|
buf.write_all(&[b as u8, g as u8, r as u8, a as u8]).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf.flush().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl State {
|
||||||
|
fn init_xdg_surface(&mut self, qh: &QueueHandle<State>) {
|
||||||
|
let wm_base = self.wm_base.as_ref().unwrap();
|
||||||
|
let base_surface = self.base_surface.as_ref().unwrap();
|
||||||
|
|
||||||
|
let xdg_surface = wm_base.get_xdg_surface(base_surface, qh, ());
|
||||||
|
let toplevel = xdg_surface.get_toplevel(qh, ());
|
||||||
|
// toplevel.set_title("A fantastic window!".into());
|
||||||
|
|
||||||
|
base_surface.commit();
|
||||||
|
|
||||||
|
self.xdg_surface = Some((xdg_surface, toplevel));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dispatch<xdg_wm_base::XdgWmBase, ()> for State {
|
||||||
|
fn event(
|
||||||
|
_: &mut Self,
|
||||||
|
wm_base: &xdg_wm_base::XdgWmBase,
|
||||||
|
event: xdg_wm_base::Event,
|
||||||
|
_: &(),
|
||||||
|
_: &Connection,
|
||||||
|
_: &QueueHandle<Self>,
|
||||||
|
) {
|
||||||
|
if let xdg_wm_base::Event::Ping { serial } = event {
|
||||||
|
wm_base.pong(serial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dispatch<xdg_surface::XdgSurface, ()> for State {
|
||||||
|
fn event(
|
||||||
|
state: &mut Self,
|
||||||
|
xdg_surface: &xdg_surface::XdgSurface,
|
||||||
|
event: xdg_surface::Event,
|
||||||
|
_: &(),
|
||||||
|
_: &Connection,
|
||||||
|
_: &QueueHandle<Self>,
|
||||||
|
) {
|
||||||
|
if let xdg_surface::Event::Configure { serial, .. } = event {
|
||||||
|
xdg_surface.ack_configure(serial);
|
||||||
|
state.configured = true;
|
||||||
|
let surface = state.base_surface.as_ref().unwrap();
|
||||||
|
if let Some(ref buffer) = state.buffer {
|
||||||
|
surface.attach(Some(buffer), 0, 0);
|
||||||
|
surface.commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dispatch<xdg_toplevel::XdgToplevel, ()> for State {
|
||||||
|
fn event(
|
||||||
|
state: &mut Self,
|
||||||
|
_: &xdg_toplevel::XdgToplevel,
|
||||||
|
event: xdg_toplevel::Event,
|
||||||
|
_: &(),
|
||||||
|
_: &Connection,
|
||||||
|
_: &QueueHandle<Self>,
|
||||||
|
) {
|
||||||
|
if let xdg_toplevel::Event::Close {} = event {
|
||||||
|
state.running = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dispatch<wl_seat::WlSeat, ()> for State {
|
||||||
|
fn event(
|
||||||
|
_: &mut Self,
|
||||||
|
seat: &wl_seat::WlSeat,
|
||||||
|
event: wl_seat::Event,
|
||||||
|
_: &(),
|
||||||
|
_: &Connection,
|
||||||
|
qh: &QueueHandle<Self>,
|
||||||
|
) {
|
||||||
|
if let wl_seat::Event::Capabilities { capabilities: WEnum::Value(capabilities) } = event {
|
||||||
|
if capabilities.contains(wl_seat::Capability::Keyboard) {
|
||||||
|
seat.get_keyboard(qh, ());
|
||||||
|
}
|
||||||
|
if capabilities.contains(wl_seat::Capability::Pointer) {
|
||||||
|
seat.get_pointer(qh, ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MyWindow<'a> {
|
||||||
|
conn: &'a Connection,
|
||||||
|
state: &'a State,
|
||||||
|
}
|
||||||
|
impl<'a> HasWindowHandle for MyWindow<'a> {
|
||||||
|
fn window_handle(&self) -> Result<WindowHandle<'_>, raw_window_handle::HandleError> {
|
||||||
|
// let wls = self.state.base_surface.as_ref().unwrap();
|
||||||
|
// // let sptr = std::ptr::from_ref(wls.id().borrow()) as *const _ as *const c_void;
|
||||||
|
// let sptr = std::ptr::from_ref(wls) as *const _ as *const c_void;
|
||||||
|
let sptr = self.state.base_surface.as_ref().unwrap().id().as_ptr();
|
||||||
|
let raww = raw_window_handle::RawWindowHandle::Wayland(
|
||||||
|
raw_window_handle::WaylandWindowHandle::new(NonNull::new(sptr as *mut _).unwrap())
|
||||||
|
);
|
||||||
|
let h = unsafe { raw_window_handle::WindowHandle::borrow_raw(raww) };
|
||||||
|
|
||||||
|
Ok(h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a> HasDisplayHandle for MyWindow<'a> {
|
||||||
|
fn display_handle(&self) -> Result<DisplayHandle<'_>, raw_window_handle::HandleError> {
|
||||||
|
let d = unsafe {
|
||||||
|
// let display = self.conn.display();
|
||||||
|
// // let dptr = std::ptr::from_ref(display.id().borrow()) as *const _ as *const c_void;
|
||||||
|
// let dptr = std::ptr::from_ref(&display) as *const _ as *const c_void;
|
||||||
|
let dptr = self.conn.backend().display_ptr();
|
||||||
|
let rawd = raw_window_handle::RawDisplayHandle::Wayland(
|
||||||
|
raw_window_handle::WaylandDisplayHandle::new(NonNull::new(dptr as *mut _).unwrap())
|
||||||
|
);
|
||||||
|
raw_window_handle::DisplayHandle::borrow_raw(rawd)
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn anchor_surface<Q>(conn: &Connection, qh: &QueueHandle<Q>, state: &mut State) {
|
||||||
|
let mw = MyWindow {
|
||||||
|
conn,
|
||||||
|
state
|
||||||
|
};
|
||||||
|
|
||||||
|
// wls.id().interface().c_ptr.as
|
||||||
|
let st = wgpu::SurfaceTarget::Window(Box::new(mw));
|
||||||
|
|
||||||
|
let instance = wgpu::Instance::default();
|
||||||
|
let s = instance.create_surface(st).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dispatch<zwlr_layer_surface_v1::ZwlrLayerSurfaceV1, ()> for State {
|
||||||
|
fn event(
|
||||||
|
state: &mut Self,
|
||||||
|
layer_surface: &zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
|
||||||
|
event: zwlr_layer_surface_v1::Event,
|
||||||
|
_: &(),
|
||||||
|
conn: &Connection,
|
||||||
|
qh: &QueueHandle<Self>,
|
||||||
|
) {
|
||||||
|
println!("Surface Layer!");
|
||||||
|
println!("Event: {event:?}");
|
||||||
|
if let zwlr_layer_surface_v1::Event::Closed {} = event {
|
||||||
|
state.running = false;
|
||||||
|
}
|
||||||
|
if let zwlr_layer_surface_v1::Event::Configure { serial, .. } = event {
|
||||||
|
layer_surface.ack_configure(serial);
|
||||||
|
state.configured = true;
|
||||||
|
let surface = state.base_surface.as_ref().unwrap();
|
||||||
|
if let Some(ref buffer) = state.buffer {
|
||||||
|
surface.attach(Some(buffer), 0, 0);
|
||||||
|
surface.commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dispatch<ZwlrLayerShellV1, ()> for State {
|
||||||
|
fn event(
|
||||||
|
state: &mut Self,
|
||||||
|
_: &ZwlrLayerShellV1,
|
||||||
|
event: zwlr_layer_shell_v1::Event,
|
||||||
|
_: &(),
|
||||||
|
conn: &Connection,
|
||||||
|
qh: &QueueHandle<Self>,
|
||||||
|
) {
|
||||||
|
println!("Layer Shell!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dispatch<wl_keyboard::WlKeyboard, ()> for State {
|
||||||
|
fn event(
|
||||||
|
state: &mut Self,
|
||||||
|
_: &wl_keyboard::WlKeyboard,
|
||||||
|
event: wl_keyboard::Event,
|
||||||
|
_: &(),
|
||||||
|
conn: &Connection,
|
||||||
|
qh: &QueueHandle<Self>,
|
||||||
|
) {
|
||||||
|
if let wl_keyboard::Event::Key { key, .. } = event {
|
||||||
|
if key == 1 || key == 16 {
|
||||||
|
// ESC key
|
||||||
|
state.running = false;
|
||||||
|
} else if key == 17 {
|
||||||
|
anchor_surface(conn, qh, state);
|
||||||
|
} else {
|
||||||
|
println!("Key: {key}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dispatch<wl_pointer::WlPointer, ()> for State {
|
||||||
|
fn event(
|
||||||
|
state: &mut Self,
|
||||||
|
_: &wl_pointer::WlPointer,
|
||||||
|
event: wl_pointer::Event,
|
||||||
|
_: &(),
|
||||||
|
conn: &Connection,
|
||||||
|
qh: &QueueHandle<Self>,
|
||||||
|
) {
|
||||||
|
if let wl_pointer::Event::Button { button, .. } = event {
|
||||||
|
// state.base_surface.as_ref().unwrap().commit();
|
||||||
|
println!("Mouse click: {button}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user