use human::{Btn, Input, Key, Mod};
use dl_api::linker;
use std::{
convert::TryInto,
ffi::{CStr, CString},
os::raw::{c_char, c_int, c_uint, c_void},
ptr::{null, null_mut, NonNull},
str,
time::Duration,
};
static ZXDG_TOPLEVEL_V6_INTERFACE_NAME: &[u8] = b"zxdg_toplevel_v6\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_DESTROY: &[u8] = b"destroy\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_DESTROY_SIG: &[u8] = b"\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_SET_PARENT: &[u8] = b"set_parent\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_SET_PARENT_SIG: &[u8] = b"?o\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_SET_TITLE: &[u8] = b"set_title\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_SET_TITLE_SIG: &[u8] = b"s\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_SET_APP_ID: &[u8] = b"set_app_id\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_SET_APP_ID_SIG: &[u8] = b"s\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_SHOW_WINDOW_MENU: &[u8] =
b"show_window_menu\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_SHOW_WINDOW_MENU_SIG: &[u8] = b"ouii\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_MOVE: &[u8] = b"move\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_MOVE_SIG: &[u8] = b"ou\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_RESIZE: &[u8] = b"resize\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_RESIZE_SIG: &[u8] = b"ouu\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_SET_MAX_SIZE: &[u8] = b"set_max_size\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_SET_MAX_SIZE_SIG: &[u8] = b"ii\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_SET_MIN_SIZE: &[u8] = b"set_min_size\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_SET_MIN_SIZE_SIG: &[u8] = b"ii\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_SET_MAXIMIZED: &[u8] = b"set_maximized\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_SET_MAXIMIZED_SIG: &[u8] = b"\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_UNSET_MAXIMIZED: &[u8] = b"unset_maximized\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_UNSET_MAXIMIZED_SIG: &[u8] = b"\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_SET_FULLSCREEN: &[u8] = b"set_fullscreen\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_SET_FULLSCREEN_SIG: &[u8] = b"?o\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_UNSET_FULLSCREEN: &[u8] =
b"unset_fullscreen\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_UNSET_FULLSCREEN_SIG: &[u8] = b"\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_SET_MINIMIZED: &[u8] = b"set_minimized\0";
static ZXDG_TOPLEVEL_V6_INTERFACE_SET_MINIMIZED_SIG: &[u8] = b"\0";
static mut ZXDG_TOPLEVEL_V6_INTERFACE_METHODS: [WlMessage; 14] = [
WlMessage {
name: ZXDG_TOPLEVEL_V6_INTERFACE_DESTROY.as_ptr().cast(),
signature: ZXDG_TOPLEVEL_V6_INTERFACE_DESTROY_SIG.as_ptr().cast(),
wl_interface: std::ptr::null(),
},
WlMessage {
name: ZXDG_TOPLEVEL_V6_INTERFACE_SET_PARENT.as_ptr().cast(),
signature: ZXDG_TOPLEVEL_V6_INTERFACE_SET_PARENT_SIG.as_ptr().cast(),
wl_interface: std::ptr::null(),
},
WlMessage {
name: ZXDG_TOPLEVEL_V6_INTERFACE_SET_TITLE.as_ptr().cast(),
signature: ZXDG_TOPLEVEL_V6_INTERFACE_SET_TITLE_SIG.as_ptr().cast(),
wl_interface: std::ptr::null(),
},
WlMessage {
name: ZXDG_TOPLEVEL_V6_INTERFACE_SET_APP_ID.as_ptr().cast(),
signature: ZXDG_TOPLEVEL_V6_INTERFACE_SET_APP_ID_SIG.as_ptr().cast(),
wl_interface: std::ptr::null(),
},
WlMessage {
name: ZXDG_TOPLEVEL_V6_INTERFACE_SHOW_WINDOW_MENU.as_ptr().cast(),
signature: ZXDG_TOPLEVEL_V6_INTERFACE_SHOW_WINDOW_MENU_SIG
.as_ptr()
.cast(),
wl_interface: std::ptr::null(),
},
WlMessage {
name: ZXDG_TOPLEVEL_V6_INTERFACE_MOVE.as_ptr().cast(),
signature: ZXDG_TOPLEVEL_V6_INTERFACE_MOVE_SIG.as_ptr().cast(),
wl_interface: std::ptr::null(),
},
WlMessage {
name: ZXDG_TOPLEVEL_V6_INTERFACE_RESIZE.as_ptr().cast(),
signature: ZXDG_TOPLEVEL_V6_INTERFACE_RESIZE_SIG.as_ptr().cast(),
wl_interface: std::ptr::null(),
},
WlMessage {
name: ZXDG_TOPLEVEL_V6_INTERFACE_SET_MAX_SIZE.as_ptr().cast(),
signature: ZXDG_TOPLEVEL_V6_INTERFACE_SET_MAX_SIZE_SIG.as_ptr().cast(),
wl_interface: std::ptr::null(),
},
WlMessage {
name: ZXDG_TOPLEVEL_V6_INTERFACE_SET_MIN_SIZE.as_ptr().cast(),
signature: ZXDG_TOPLEVEL_V6_INTERFACE_SET_MIN_SIZE_SIG.as_ptr().cast(),
wl_interface: std::ptr::null(),
},
WlMessage {
name: ZXDG_TOPLEVEL_V6_INTERFACE_SET_MAXIMIZED.as_ptr().cast(),
signature: ZXDG_TOPLEVEL_V6_INTERFACE_SET_MAXIMIZED_SIG.as_ptr().cast(),
wl_interface: std::ptr::null(),
},
WlMessage {
name: ZXDG_TOPLEVEL_V6_INTERFACE_UNSET_MAXIMIZED.as_ptr().cast(),
signature: ZXDG_TOPLEVEL_V6_INTERFACE_UNSET_MAXIMIZED_SIG
.as_ptr()
.cast(),
wl_interface: std::ptr::null(),
},
WlMessage {
name: ZXDG_TOPLEVEL_V6_INTERFACE_SET_FULLSCREEN.as_ptr().cast(),
signature: ZXDG_TOPLEVEL_V6_INTERFACE_SET_FULLSCREEN_SIG
.as_ptr()
.cast(),
wl_interface: std::ptr::null(),
},
WlMessage {
name: ZXDG_TOPLEVEL_V6_INTERFACE_UNSET_FULLSCREEN.as_ptr().cast(),
signature: ZXDG_TOPLEVEL_V6_INTERFACE_UNSET_FULLSCREEN_SIG
.as_ptr()
.cast(),
wl_interface: std::ptr::null(),
},
WlMessage {
name: ZXDG_TOPLEVEL_V6_INTERFACE_SET_MINIMIZED.as_ptr().cast(),
signature: ZXDG_TOPLEVEL_V6_INTERFACE_SET_MINIMIZED_SIG.as_ptr().cast(),
wl_interface: std::ptr::null(),
},
];
static mut ZXDG_TOPLEVEL_V6_INTERFACE_EVENTS: [WlMessage; 2] = [
WlMessage {
name: b"configure\0".as_ptr().cast(),
signature: b"iia\0".as_ptr().cast(),
wl_interface: std::ptr::null(),
},
WlMessage {
name: b"close\0".as_ptr().cast(),
signature: b"\0".as_ptr().cast(),
wl_interface: std::ptr::null(),
},
];
static mut ZXDG_TOPLEVEL_V6_INTERFACE: WlInterface = WlInterface {
name: ZXDG_TOPLEVEL_V6_INTERFACE_NAME.as_ptr().cast(),
version: 1,
method_count: 14,
methods: unsafe { ZXDG_TOPLEVEL_V6_INTERFACE_METHODS.as_ptr() },
event_count: 2,
events: unsafe { ZXDG_TOPLEVEL_V6_INTERFACE_EVENTS.as_ptr() },
};
static mut ZXDG_TOPLEVEL_V6_INTERFACE1: [*const WlInterface; 1] =
[unsafe { &ZXDG_TOPLEVEL_V6_INTERFACE }];
static mut ZXDG_SURFACE_V6_INTERFACE_METHODS: [WlMessage; 5] = [
WlMessage {
name: b"destroy\0".as_ptr().cast(),
signature: b"\0".as_ptr().cast(),
wl_interface: std::ptr::null(),
},
WlMessage {
name: b"get_toplevel\0".as_ptr().cast(),
signature: b"n\0".as_ptr().cast(),
wl_interface: unsafe { WL_SURFACE_INTERFACE.as_ptr() },
},
WlMessage {
name: b"get_popup\0".as_ptr().cast(),
signature: b"noo\0".as_ptr().cast(),
wl_interface: unsafe { ZXDG_TOPLEVEL_V6_INTERFACE1.as_ptr() },
},
WlMessage {
name: b"set_window_geometry\0".as_ptr().cast(),
signature: b"iiii\0".as_ptr().cast(),
wl_interface: std::ptr::null(),
},
WlMessage {
name: b"ack_configure\0".as_ptr().cast(),
signature: b"u\0".as_ptr().cast(),
wl_interface: std::ptr::null(),
},
];
static mut ZXDG_SURFACE_V6_INTERFACE: WlInterface = WlInterface {
name: b"zxdg_surface_v6\0".as_ptr().cast(),
version: 1,
method_count: 5,
methods: unsafe { ZXDG_SURFACE_V6_INTERFACE_METHODS.as_ptr() },
event_count: 1,
events: [WlMessage {
name: b"configure\0".as_ptr().cast(),
signature: b"u\0".as_ptr().cast(),
wl_interface: std::ptr::null(),
}]
.as_ptr(), };
static mut SHELL_INTERFACE_DESTROY_SIG: &[u8] = b"\0";
static mut SHELL_INTERFACE_CREATE_POSITIONER_SIG: &[u8] = b"n\0";
static mut SHELL_INTERFACE_GET_SURFACE_SIG: &[u8] = b"no\0";
static mut ZXDG_SHELL_INTERFACE_GET_SURFACE: &[u8] = b"get_xdg_surface\0";
static mut WL_SURFACE_INTERFACE: [*const WlInterface; 1] = [null()];
static mut ZXDG_SHELL_V6_INTERFACE_METHODS: [WlMessage; 4] = [
WlMessage {
name: ZXDG_SHELL_INTERFACE_DESTROY.as_ptr().cast(),
signature: unsafe { SHELL_INTERFACE_DESTROY_SIG.as_ptr().cast() },
wl_interface: std::ptr::null(),
},
WlMessage {
name: ZXDG_SHELL_INTERFACE_CREATE_POSITIONER.as_ptr().cast(),
signature: unsafe {
SHELL_INTERFACE_CREATE_POSITIONER_SIG.as_ptr().cast()
},
wl_interface: unsafe { WL_SURFACE_INTERFACE.as_ptr() },
},
WlMessage {
name: unsafe { ZXDG_SHELL_INTERFACE_GET_SURFACE.as_ptr().cast() },
signature: unsafe { SHELL_INTERFACE_GET_SURFACE_SIG.as_ptr().cast() },
wl_interface: unsafe { ZXDG_TOPLEVEL_V6_INTERFACE1.as_ptr() },
},
WlMessage {
name: b"pong\0".as_ptr().cast(),
signature: b"u\0".as_ptr().cast(),
wl_interface: std::ptr::null(),
},
];
static ZXDG_SHELL_INTERFACE_NAME: &[u8] = b"zxdg_shell_v6\0";
static ZXDG_SHELL_INTERFACE_DESTROY: &[u8] = b"destroy\0";
static ZXDG_SHELL_INTERFACE_CREATE_POSITIONER: &[u8] = b"create_positioner\0";
static mut ZXDG_SHELL_V6_INTERFACE: WlInterface = WlInterface {
name: ZXDG_SHELL_INTERFACE_NAME.as_ptr().cast(),
version: 1,
method_count: 4,
methods: unsafe { ZXDG_SHELL_V6_INTERFACE_METHODS.as_ptr() },
event_count: 1,
events: [WlMessage {
name: b"ping\0".as_ptr().cast(),
signature: b"u\0".as_ptr().cast(),
wl_interface: std::ptr::null(),
}]
.as_ptr(), };
#[repr(transparent)]
struct WlProxy(c_void);
#[repr(transparent)]
struct WlDisplay(c_void);
#[repr(C)]
struct WlArray {
size: usize,
alloc: usize,
data: *mut c_void,
}
#[repr(C)]
struct WlMessage {
name: *const c_char,
signature: *const c_char,
wl_interface: *const *const WlInterface,
}
#[repr(C)]
struct WlInterface {
name: *const c_char,
version: c_int,
method_count: c_int,
methods: *const WlMessage,
event_count: c_int,
events: *const WlMessage,
}
#[repr(transparent)]
struct WlSurface(c_void);
#[repr(transparent)]
struct WlRegistry(c_void);
#[repr(transparent)]
struct WlCompositor(c_void);
#[repr(transparent)]
struct WlSeat(c_void);
#[repr(transparent)]
struct WlCallback(c_void);
#[repr(transparent)]
struct WlOutput(c_void);
#[repr(transparent)]
struct WlKeyboard(c_void);
#[repr(transparent)]
struct WlPointer(c_void);
#[repr(transparent)]
struct WlTouch(c_void);
#[repr(C)]
#[derive(Copy, Clone)]
enum WlSeatCapability {
Pointer = 1,
Keyboard = 2,
Touch = 4,
}
#[repr(C)]
struct WlRegistryListener {
global: Option<
extern "C" fn(
data: *mut c_void,
wl_registry: *mut WlRegistry,
name: u32,
interface: *const c_char,
version: u32,
) -> (),
>,
global_remove: Option<
extern "C" fn(
data: *mut c_void,
wl_registry: *mut WlRegistry,
name: u32,
),
>,
}
#[repr(C)]
struct WlCallbackListener {
done: Option<
extern "C" fn(
data: *mut c_void,
callback: *mut WlCallback,
callback_data: u32,
) -> (),
>,
}
#[repr(C)]
struct WlOutputListener {
geometry: Option<
extern "C" fn(
data: *mut c_void,
output: *mut WlOutput,
x: i32,
y: i32,
physical_width: i32,
physical_height: i32,
subpixel: i32,
make: *const c_char,
model: *const c_char,
transform: i32,
) -> (),
>,
mode: Option<
extern "C" fn(
data: *mut c_void,
output: *mut WlOutput,
flags: u32,
width: i32,
height: i32,
refresh: i32,
) -> (),
>,
done: Option<extern "C" fn(data: *mut c_void, output: *mut WlOutput) -> ()>,
scale: Option<
extern "C" fn(
data: *mut c_void,
output: *mut WlOutput,
factor: i32,
) -> (),
>,
}
#[repr(C)]
struct WlSeatListener {
capabilities: Option<
extern "C" fn(
data: *mut c_void,
seat: *mut WlSeat,
capabilites: u32,
) -> (),
>,
name: Option<
extern "C" fn(
data: *mut c_void,
seat: *mut WlSeat,
name: *const c_char,
) -> (),
>,
}
#[repr(C)]
struct WlKeyboardListener {
keymap: Option<
extern "C" fn(
data: *mut c_void,
keyboard: *mut WlKeyboard,
format: u32,
fd: i32,
size: u32,
) -> (),
>,
enter: Option<
extern "C" fn(
data: *mut c_void,
keyboard: *mut WlKeyboard,
serial: u32,
surface: *mut WlSurface,
keys: *mut WlArray,
) -> (),
>,
leave: Option<
extern "C" fn(
data: *mut c_void,
keyboard: *mut WlKeyboard,
serial: u32,
surface: *mut WlSurface,
) -> (),
>,
key: Option<
extern "C" fn(
data: *mut c_void,
keyboard: *mut WlKeyboard,
serial: u32,
time: u32,
key: u32,
state: u32,
) -> (),
>,
modifiers: Option<
extern "C" fn(
data: *mut c_void,
keyboard: *mut WlKeyboard,
serial: u32,
mods_depressed: u32,
mods_latched: u32,
mods_locked: u32,
group: u32,
) -> (),
>,
repeat_info: Option<
extern "C" fn(
data: *mut c_void,
keyboard: *mut WlKeyboard,
rate: i32,
delay: i32,
) -> (),
>,
}
#[repr(C)]
struct WlPointerListener {
enter: Option<
extern "C" fn(
data: *mut c_void,
pointer: *mut WlPointer,
serial: u32,
surface: *mut WlSurface,
surface_x: i32,
surface_y: i32,
) -> (),
>,
leave: Option<
extern "C" fn(
data: *mut c_void,
pointer: *mut WlPointer,
serial: u32,
surface: *mut WlSurface,
) -> (),
>,
motion: Option<
extern "C" fn(
data: *mut c_void,
pointer: *mut WlPointer,
time: u32,
surface_x: i32,
surface_y: i32,
) -> (),
>,
button: Option<
extern "C" fn(
data: *mut c_void,
pointer: *mut WlPointer,
serial: u32,
time: u32,
button: u32,
state: u32,
) -> (),
>,
axis: Option<
extern "C" fn(
data: *mut c_void,
pointer: *mut WlPointer,
time: u32,
axis: u32,
value: i32,
) -> (),
>,
frame:
Option<extern "C" fn(data: *mut c_void, pointer: *mut WlPointer) -> ()>,
axis_source: Option<
extern "C" fn(
data: *mut c_void,
pointer: *mut WlPointer,
axis_source: u32,
) -> (),
>,
axis_stop: Option<
extern "C" fn(
data: *mut c_void,
pointer: *mut WlPointer,
time: u32,
axis: u32,
) -> (),
>,
axis_discrete: Option<
extern "C" fn(
data: *mut c_void,
pointer: *mut WlPointer,
axis: u32,
discrete: i32,
) -> (),
>,
}
#[repr(C)]
struct WlTouchListener {
down: Option<
extern "C" fn(
data: *mut c_void,
touch: *mut WlTouch,
serial: u32,
time: u32,
surface: *mut WlSurface,
id: i32,
x: i32,
y: i32,
) -> (),
>,
up: Option<
extern "C" fn(
data: *mut c_void,
touch: *mut WlTouch,
serial: u32,
time: u32,
id: i32,
) -> (),
>,
motion: Option<
extern "C" fn(
data: *mut c_void,
touch: *mut WlTouch,
time: u32,
id: i32,
x: i32,
y: i32,
) -> (),
>,
frame: Option<extern "C" fn(data: *mut c_void, touch: *mut WlTouch) -> ()>,
cancel: Option<extern "C" fn(data: *mut c_void, touch: *mut WlTouch) -> ()>,
shape: Option<
extern "C" fn(
data: *mut c_void,
touch: *mut WlTouch,
id: i32,
major: i32,
minor: i32,
) -> (),
>,
orientation: Option<
extern "C" fn(
data: *mut c_void,
touch: *mut WlTouch,
id: i32,
orientation: i32,
) -> (),
>,
}
#[repr(C)]
pub(crate) struct WlCursorImage {
width: u32,
height: u32,
hotspot_x: u32,
hotspot_y: u32,
delay: u32,
}
#[repr(C)]
struct WlCursor {
image_count: c_uint,
images: *mut *mut WlCursorImage,
name: *mut c_char,
}
#[repr(transparent)]
struct ZxdgSurface(c_void);
#[repr(transparent)]
struct ZxdgToplevel(c_void);
#[repr(transparent)]
struct ZxdgShell(c_void);
#[repr(C)]
struct ZxdgSurfaceListener {
configure: Option<
extern "C" fn(
data: *mut c_void,
surface: *mut ZxdgSurface,
serial: u32,
) -> (),
>,
}
#[repr(C)]
struct ZxdgToplevelListener {
configure: Option<
extern "C" fn(
data: *mut c_void,
toplevel: *mut ZxdgToplevel,
width: i32,
height: i32,
states: *mut WlArray,
) -> (),
>,
close: Option<
extern "C" fn(data: *mut c_void, toplevel: *mut ZxdgToplevel) -> (),
>,
}
#[repr(C)]
struct ZxdgShellListener {
ping: Option<
extern "C" fn(
data: *mut c_void,
xdg_shell: *mut ZxdgShell,
serial: u32,
) -> (),
>,
}
#[repr(transparent)]
struct WlEglWindow(c_void);
#[repr(transparent)]
struct WlCursorTheme(c_void);
#[repr(transparent)]
struct WlBuffer(c_void);
#[repr(transparent)]
struct WlShm(c_void);
const NIL: *mut c_void = null_mut();
static FRAME_LISTENER: WlCallbackListener = WlCallbackListener {
done: Some(redraw_wl),
};
static TOUCH_LISTENER: WlTouchListener = WlTouchListener {
down: Some(touch_handle_down),
up: Some(touch_handle_up),
motion: Some(touch_handle_motion),
frame: Some(touch_handle_frame),
cancel: Some(touch_handle_cancel),
shape: None,
orientation: None,
};
static KEYBOARD_LISTENER: WlKeyboardListener = WlKeyboardListener {
keymap: Some(keyboard_handle_keymap),
enter: Some(keyboard_handle_enter),
leave: Some(keyboard_handle_leave),
key: Some(keyboard_handle_key),
modifiers: Some(keyboard_handle_modifiers),
repeat_info: None,
};
static POINTER_LISTENER: WlPointerListener = WlPointerListener {
enter: Some(pointer_handle_enter),
leave: Some(pointer_handle_leave),
motion: Some(pointer_handle_motion),
button: Some(pointer_handle_button),
axis: Some(pointer_handle_axis),
frame: None,
axis_source: None,
axis_stop: None,
axis_discrete: None,
};
static OUTPUT_LISTENER: WlOutputListener = WlOutputListener {
geometry: Some(output_geometry),
mode: Some(output_mode),
done: Some(output_done),
scale: Some(output_scale),
};
static SEAT_LISTENER: WlSeatListener = WlSeatListener {
capabilities: Some(seat_handle_capabilities),
name: None,
};
static REGISTRY_LISTENER: WlRegistryListener = WlRegistryListener {
global: Some(registry_global),
global_remove: Some(registry_global_remove),
};
static XDG_SHELL_LISTENER: ZxdgShellListener = ZxdgShellListener {
ping: Some(handle_xdg_shell_ping),
};
static XDG_TOPLEVEL_LISTENER: ZxdgToplevelListener = ZxdgToplevelListener {
configure: Some(toplevel_configure),
close: Some(toplevel_close),
};
static XDG_SURFACE_LISTENER: ZxdgSurfaceListener = ZxdgSurfaceListener {
configure: Some(surface_configure),
};
linker!(extern "C" WaylandClient "libwayland-client.so.0" {
static wl_registry_interface: *const WlInterface;
static wl_compositor_interface: *const WlInterface;
static wl_seat_interface: *const WlInterface;
static wl_shm_interface: *const WlInterface;
static wl_pointer_interface: *const WlInterface;
static wl_output_interface: *const WlInterface;
static wl_keyboard_interface: *const WlInterface;
static wl_touch_interface: *const WlInterface;
static wl_callback_interface: *const WlInterface;
static wl_surface_interface: *const WlInterface;
valist fn wl_proxy_marshal(p: *mut WlProxy, opcode: u32, ...) -> ();
valist fn wl_proxy_marshal_constructor(
proxy: *mut WlProxy,
opcode: u32,
interface: *const WlInterface,
...
) -> *mut WlProxy;
valist fn wl_proxy_marshal_constructor_versioned(
proxy: *mut WlProxy,
opcode: u32,
interface: *const WlInterface,
version: u32,
...
) -> *mut WlProxy;
fn wl_proxy_destroy(proxy: *mut WlProxy) -> ();
fn wl_display_connect(name: *const c_char) -> *mut WlDisplay;
fn wl_proxy_add_listener(
proxy: *mut WlProxy,
listener: *const extern "C" fn() -> (),
data: *mut c_void,
) -> c_int;
fn wl_display_dispatch(display: *mut WlDisplay) -> c_int;
});
impl WaylandClient {
fn init(&self) {
unsafe {
WL_SURFACE_INTERFACE[0] = self.wl_surface_interface;
}
}
#[inline(always)]
unsafe fn pointer_set_cursor(
&self,
pointer: *mut WlPointer,
cursor_surface: *mut WlSurface,
image: *mut WlCursorImage,
serial: u32,
) {
(self.wl_proxy_marshal)(
pointer.cast(),
0,
serial,
cursor_surface,
(*image).hotspot_x,
(*image).hotspot_y,
);
}
#[inline(always)]
unsafe fn surface_attach(
&self,
cursor_surface: *mut WlSurface,
buffer: *mut WlBuffer,
) {
(self.wl_proxy_marshal)(
cursor_surface.cast(),
1,
buffer,
0,
0,
);
}
#[inline(always)]
unsafe fn surface_damage(
&self,
cursor_surface: *mut WlSurface,
image: *mut WlCursorImage,
) {
(self.wl_proxy_marshal)(
cursor_surface.cast(),
2,
0,
0,
(*image).width,
(*image).height,
);
}
#[inline(always)]
unsafe fn surface_commit(&self, cursor_surface: *mut WlSurface) {
(self.wl_proxy_marshal)(
cursor_surface.cast(),
6,
);
}
#[inline(always)]
unsafe fn display_get_registry(
&self,
display: *mut WlDisplay,
) -> *mut WlRegistry {
(self.wl_proxy_marshal_constructor)(
display.cast(),
1,
self.wl_registry_interface,
NIL,
)
.cast()
}
#[inline(always)]
unsafe fn registry_add_listener(
&self,
registry: *mut WlRegistry,
listener: *const WlRegistryListener,
data: *mut c_void,
) -> c_int {
(self.wl_proxy_add_listener)(registry.cast(), listener.cast(), data)
}
#[inline(always)]
unsafe fn compositor_create_surface(
&self,
compositor: *mut WlCompositor,
) -> *mut WlSurface {
(self.wl_proxy_marshal_constructor)(
compositor.cast(),
0,
self.wl_surface_interface,
NIL,
)
.cast()
}
#[inline(always)]
unsafe fn display_sync(&self, display: *mut WlDisplay) -> *mut WlCallback {
(self.wl_proxy_marshal_constructor)(
display.cast(),
0,
self.wl_callback_interface,
NIL,
)
.cast()
}
#[inline(always)]
unsafe fn callback_add_listener(
&self,
callback: *mut WlCallback,
listener: *const WlCallbackListener,
data: *mut c_void,
) -> c_int {
(self.wl_proxy_add_listener)(callback.cast(), listener.cast(), data)
}
#[inline(always)]
unsafe fn output_add_listener(
&self,
output: *mut WlOutput,
listener: *const WlOutputListener,
data: *mut c_void,
) -> c_int {
(self.wl_proxy_add_listener)(output.cast(), listener.cast(), data)
}
#[inline(always)]
unsafe fn seat_add_listener(
&self,
seat: *mut WlSeat,
listener: *const WlSeatListener,
data: *mut c_void,
) -> c_int {
(self.wl_proxy_add_listener)(seat.cast(), listener.cast(), data)
}
#[inline(always)]
unsafe fn pointer_add_listener(
&self,
pointer: *mut WlPointer,
listener: *const WlPointerListener,
data: *mut c_void,
) -> c_int {
(self.wl_proxy_add_listener)(pointer.cast(), listener.cast(), data)
}
#[inline(always)]
unsafe fn keyboard_add_listener(
&self,
keyboard: *mut WlKeyboard,
listener: *const WlKeyboardListener,
data: *mut c_void,
) -> c_int {
(self.wl_proxy_add_listener)(keyboard.cast(), listener.cast(), data)
}
#[inline(always)]
unsafe fn touch_add_listener(
&self,
touch: *mut WlTouch,
listener: *const WlTouchListener,
data: *mut c_void,
) -> c_int {
(self.wl_proxy_add_listener)(touch.cast(), listener.cast(), data)
}
#[inline(always)]
unsafe fn registry_bind(
&self,
registry: *mut WlRegistry,
name: u32,
interface: *const WlInterface,
version: u32,
) -> *mut c_void {
(self.wl_proxy_marshal_constructor_versioned)(
registry.cast(),
0,
interface,
version,
name,
(*interface).name,
version,
NIL,
)
.cast()
}
#[inline(always)]
unsafe fn callback_destroy(&self, callback: *mut WlCallback) {
(self.wl_proxy_destroy)(callback.cast());
}
#[inline(always)]
unsafe fn seat_get_pointer(&self, seat: *mut WlSeat) -> *mut WlPointer {
(self.wl_proxy_marshal_constructor)(
seat.cast(),
0,
self.wl_pointer_interface,
NIL,
)
.cast()
}
#[inline(always)]
unsafe fn seat_get_keyboard(&self, seat: *mut WlSeat) -> *mut WlKeyboard {
(self.wl_proxy_marshal_constructor)(
seat.cast(),
1,
self.wl_keyboard_interface,
NIL,
)
.cast()
}
#[inline(always)]
unsafe fn seat_get_touch(&self, seat: *mut WlSeat) -> *mut WlTouch {
(self.wl_proxy_marshal_constructor)(
seat.cast(),
2,
self.wl_touch_interface,
NIL,
)
.cast()
}
#[inline(always)]
unsafe fn surface_frame(&self, surface: *mut WlSurface) -> *mut WlCallback {
(self.wl_proxy_marshal_constructor)(
surface.cast(),
3,
self.wl_callback_interface,
NIL,
)
.cast()
}
#[inline(always)]
unsafe fn zxdg_shell_v6_get_xdg_surface(
&self,
shell: *mut ZxdgShell,
surface: *mut WlSurface,
) -> *mut ZxdgSurface {
(self.wl_proxy_marshal_constructor)(
shell.cast(),
2,
&ZXDG_SURFACE_V6_INTERFACE,
NIL,
surface,
)
.cast()
}
#[inline(always)]
unsafe fn zxdg_surface_v6_get_toplevel(
&self,
surface: *mut ZxdgSurface,
) -> *mut ZxdgToplevel {
(self.wl_proxy_marshal_constructor)(
surface.cast(),
1,
&ZXDG_TOPLEVEL_V6_INTERFACE,
NIL,
)
.cast()
}
#[inline(always)]
unsafe fn zxdg_surface_v6_add_listener(
&self,
surface: *mut ZxdgSurface,
listener: *const ZxdgSurfaceListener,
data: *mut c_void,
) -> c_int {
(self.wl_proxy_add_listener)(surface.cast(), listener.cast(), data)
}
#[inline(always)]
unsafe fn zxdg_toplevel_v6_add_listener(
&self,
toplevel: *mut ZxdgToplevel,
listener: *const ZxdgToplevelListener,
data: *mut c_void,
) -> c_int {
(self.wl_proxy_add_listener)(toplevel.cast(), listener.cast(), data)
}
#[inline(always)]
unsafe fn zxdg_shell_v6_add_listener(
&self,
shell: *mut ZxdgShell,
listener: *const ZxdgShellListener,
data: *mut c_void,
) -> c_int {
(self.wl_proxy_add_listener)(shell.cast(), listener.cast(), data)
}
#[inline(always)]
unsafe fn zxdg_toplevel_v6_set_title(
&self,
toplevel: *mut ZxdgToplevel,
title: *const c_char,
) {
(self.wl_proxy_marshal)(
toplevel.cast(),
2,
title,
);
}
#[inline(always)]
unsafe fn zxdg_toplevel_v6_set_app_id(
&self,
toplevel: *mut ZxdgToplevel,
title: *const c_char,
) {
(self.wl_proxy_marshal)(
toplevel.cast(),
3,
title,
);
}
#[inline(always)]
unsafe fn zxdg_toplevel_v6_set_maximized(
&self,
toplevel: *mut ZxdgToplevel,
) {
(self.wl_proxy_marshal)(
toplevel.cast(),
9,
);
}
#[inline(always)]
unsafe fn zxdg_toplevel_v6_set_fullscreen(
&self,
toplevel: *mut ZxdgToplevel,
) {
(self.wl_proxy_marshal)(
toplevel.cast(),
11,
NIL,
);
}
#[inline(always)]
unsafe fn zxdg_toplevel_v6_unset_fullscreen(
&self,
toplevel: *mut ZxdgToplevel,
) {
(self.wl_proxy_marshal)(
toplevel.cast(),
12,
);
}
#[inline(always)]
unsafe fn zxdg_surface_v6_ack_configure(
&self,
zxdg_surface_v6: *mut ZxdgSurface,
serial: u32,
) {
(self.wl_proxy_marshal)(
zxdg_surface_v6.cast(),
4,
serial,
);
}
#[inline(always)]
unsafe fn zxdg_shell_v6_pong(&self, shell: *mut ZxdgShell, serial: u32) {
(self.wl_proxy_marshal)(
shell.cast(),
3,
serial,
);
}
#[inline(always)]
unsafe fn connect(&self) -> Option<NonNull<WlDisplay>> {
NonNull::new((self.wl_display_connect)(null()))
}
}
linker!(extern "C" WaylandEGL "libwayland-egl.so.1" {
fn wl_egl_window_create(
surface: *mut WlSurface,
width: c_int,
height: c_int,
) -> *mut WlEglWindow;
fn wl_egl_window_resize(
egl_window: *mut WlEglWindow,
width: c_int,
height: c_int,
dx: c_int,
dy: c_int,
) -> ();
fn wl_egl_window_destroy(egl_window: *mut WlEglWindow) -> ();
});
linker!(extern "C" WaylandCursor "libwayland-cursor.so.0" {
fn wl_cursor_image_get_buffer(image: *mut WlCursorImage) -> *mut WlBuffer;
fn wl_cursor_theme_destroy(theme: *mut WlCursorTheme) -> ();
fn wl_cursor_theme_load(
name: *const c_char,
size: c_int,
shm: *mut WlShm,
) -> *mut WlCursorTheme;
fn wl_cursor_theme_get_cursor(
theme: *mut WlCursorTheme,
name: *const c_char,
) -> *mut WlCursor;
});
pub(super) struct Wayland {
window: *mut crate::Window,
draw: Option<NonNull<dyn crate::Draw>>,
client: WaylandClient,
egl: WaylandEGL,
cursor: WaylandCursor,
display: NonNull<WlDisplay>,
callback: *mut WlCallback,
compositor: *mut WlCompositor,
surface: *mut WlSurface,
cursor_surface: *mut WlSurface,
seat: *mut WlSeat,
pointer: *mut WlPointer,
keyboard: *mut WlKeyboard,
touch: *mut WlTouch,
shell: *mut ZxdgShell,
shell_surface: *mut ZxdgSurface,
toplevel: *mut ZxdgToplevel,
restore_width: c_int,
restore_height: c_int,
window_width: c_int,
window_height: c_int,
refresh_rate: Duration,
is_restored: bool,
fullscreen: bool,
configured: bool,
egl_window: *mut WlEglWindow,
default_cursor: *mut WlCursor,
cursor_theme: *mut WlCursorTheme,
shm: *mut WlShm,
redraw: fn(window: &mut crate::Window, nanos: Duration) -> (),
input_queue: Vec<Input>,
move_: fn(x: f32, y: f32) -> bool,
move_state: bool,
}
fn move_dummy(_x: f32, _y: f32) -> bool {
false
}
impl Wayland {
pub(super) fn new(
name: &str,
redraw: fn(window: &mut crate::Window, nanos: Duration) -> (),
) -> Result<Box<Self>, String> {
let client = WaylandClient::new()
.map_err(|e| format!("Wayland Client {}", e))?;
let egl =
WaylandEGL::new().map_err(|e| format!("Wayland EGL {}", e))?;
let cursor = WaylandCursor::new()
.map_err(|e| format!("Wayland Cursor {}", e))?;
client.init();
unsafe {
let display = client.connect().ok_or("Failed to find client")?;
let registry = client.display_get_registry(display.as_ptr());
let mut wayland = Box::new(Wayland {
window: std::ptr::null_mut(),
draw: None,
client,
egl,
cursor,
display,
callback: null_mut(),
compositor: null_mut(),
surface: null_mut(),
cursor_surface: null_mut(),
seat: null_mut(),
pointer: null_mut(),
keyboard: null_mut(),
touch: null_mut(),
shell: null_mut(),
shell_surface: null_mut(),
toplevel: null_mut(),
restore_width: 640,
restore_height: 360,
window_width: 640,
window_height: 360,
refresh_rate: Duration::new(0, 0),
is_restored: false,
fullscreen: false,
configured: false,
egl_window: null_mut(),
default_cursor: null_mut(),
cursor_theme: null_mut(),
shm: null_mut(),
redraw,
input_queue: Vec::new(),
move_state: false,
move_: move_dummy,
});
let window: *mut Wayland = &mut *wayland;
wayland.client.registry_add_listener(
registry,
®ISTRY_LISTENER,
window.cast(),
);
(wayland.client.wl_display_dispatch)(display.as_ptr());
wayland.surface =
wayland.client.compositor_create_surface(wayland.compositor);
wayland.cursor_surface =
wayland.client.compositor_create_surface(wayland.compositor);
wayland.shell_surface = wayland
.client
.zxdg_shell_v6_get_xdg_surface(wayland.shell, wayland.surface);
wayland.client.zxdg_surface_v6_add_listener(
wayland.shell_surface,
&XDG_SURFACE_LISTENER,
window.cast(),
);
wayland.toplevel = wayland
.client
.zxdg_surface_v6_get_toplevel(wayland.shell_surface);
wayland.client.zxdg_toplevel_v6_add_listener(
wayland.toplevel,
&XDG_TOPLEVEL_LISTENER,
window.cast(),
);
let window_title = CString::new(name).unwrap();
wayland.client.zxdg_toplevel_v6_set_title(
wayland.toplevel,
window_title.as_ptr(),
);
wayland.client.zxdg_toplevel_v6_set_app_id(
wayland.toplevel,
window_title.as_ptr(),
);
wayland
.client
.zxdg_toplevel_v6_set_maximized(wayland.toplevel);
let callback =
wayland.client.display_sync(wayland.display.as_ptr());
wayland.client.callback_add_listener(
callback,
&FRAME_LISTENER,
window.cast(),
);
Ok(wayland)
}
}
}
impl crate::Nwin for Wayland {
fn handle(&self) -> crate::NwinHandle {
crate::NwinHandle::Wayland(self.display.as_ptr().cast())
}
fn connect(&mut self, draw: &mut Box<dyn crate::Draw>) {
self.draw = NonNull::new(&mut **draw);
match draw.handle() {
crate::DrawHandle::Gl(_c) => {
self.egl_window = unsafe {
(self.egl.wl_egl_window_create)(
self.surface,
self.window_width,
self.window_height,
)
};
}
crate::DrawHandle::Vulkan(_c) => unimplemented!(),
}
draw.connect(self.egl_window.cast());
}
fn run(&mut self, window: *mut crate::Window) -> bool {
self.window = window;
let ret =
unsafe { (self.client.wl_display_dispatch)(self.display.as_ptr()) };
if !self.input_queue.is_empty() {
let mut input_queue = Vec::new();
std::mem::swap(&mut input_queue, &mut self.input_queue);
unsafe { crate::ffi::push_inputs(input_queue) };
}
ret != -1
}
fn dimensions(&self) -> (u16, u16) {
(self.window_width as u16, self.window_height as u16)
}
}
extern "C" fn registry_global(
window: *mut c_void,
registry: *mut WlRegistry,
name: u32,
interface: *const c_char,
_version: u32,
) {
let window: *mut Wayland = window.cast();
unsafe {
let interface =
str::from_utf8(CStr::from_ptr(interface).to_bytes()).unwrap();
match interface {
"wl_compositor" => {
(*window).compositor = (*window)
.client
.registry_bind(
registry,
name,
(*window).client.wl_compositor_interface,
1,
)
.cast();
}
"zxdg_shell_v6" => {
(*window).shell = (*window)
.client
.registry_bind(registry, name, &ZXDG_SHELL_V6_INTERFACE, 1)
.cast();
(*window).client.zxdg_shell_v6_add_listener(
(*window).shell,
&XDG_SHELL_LISTENER,
window.cast(),
);
}
"wl_seat" => {
(*window).seat = (*window)
.client
.registry_bind(
registry,
name,
(*window).client.wl_seat_interface,
1,
)
.cast();
(*window).client.seat_add_listener(
(*window).seat,
&SEAT_LISTENER,
window.cast(),
);
}
"wl_shm" => {
(*window).shm = (*window)
.client
.registry_bind(
registry,
name,
(*window).client.wl_shm_interface,
1,
)
.cast();
(*window).cursor_theme = ((*window)
.cursor
.wl_cursor_theme_load)(
null_mut(), 16, (*window).shm
);
if (*window).cursor_theme.is_null() {
eprintln!("unable to load default theme");
}
static LEFT_PTR: &[u8] = b"left_ptr\0";
(*window).default_cursor =
((*window).cursor.wl_cursor_theme_get_cursor)(
(*window).cursor_theme,
CStr::from_bytes_with_nul(LEFT_PTR).unwrap().as_ptr(),
);
if (*window).default_cursor.is_null() {
panic!("unable to load default left pointer");
}
}
"wl_output" => {
let output = (*window)
.client
.registry_bind(
registry,
name,
(*window).client.wl_output_interface,
1,
)
.cast();
(*window).client.output_add_listener(
output,
&OUTPUT_LISTENER,
window.cast(),
);
}
_ => {}
}
}
}
extern "C" fn registry_global_remove(
_data: *mut c_void,
_registry: *mut WlRegistry,
_name: u32,
) {
}
extern "C" fn surface_configure(
window: *mut c_void,
zxdg_surface_v6: *mut ZxdgSurface,
serial: u32,
) {
let window: *mut Wayland = window.cast();
unsafe {
(*window)
.client
.zxdg_surface_v6_ack_configure(zxdg_surface_v6, serial);
}
}
extern "C" fn toplevel_configure(
window: *mut c_void,
_zxdg_toplevel_v6: *mut ZxdgToplevel,
width: i32,
height: i32,
_states: *mut WlArray,
) {
let window: *mut Wayland = window.cast();
unsafe {
if !(*window).egl_window.is_null() && (*window).configured {
((*window).egl.wl_egl_window_resize)(
(*window).egl_window,
width,
height,
0,
0,
);
(*window).configured = false;
(*window).window_width = width;
(*window).window_height = height;
} else if (*window).fullscreen {
} else if width != 0 && height != 0 {
if (*window).is_restored {
(*window).restore_width = (*window).window_width;
(*window).restore_height = (*window).window_height;
}
(*window).is_restored = false;
if !(*window).egl_window.is_null() {
((*window).egl.wl_egl_window_resize)(
(*window).egl_window,
width,
height,
0,
0,
);
}
(*window).window_width = width;
(*window).window_height = height;
} else {
(*window).window_width = (*window).restore_width;
(*window).window_height = (*window).restore_height;
(*window).is_restored = true;
if !(*window).egl_window.is_null() {
((*window).egl.wl_egl_window_resize)(
(*window).egl_window,
(*window).restore_width,
(*window).restore_height,
0,
0,
);
}
}
if let Some(draw) = (*window).draw {
(*draw.as_ptr()).resize(
(*window).window_width.try_into().unwrap(),
(*window).window_height.try_into().unwrap(),
);
}
}
}
extern "C" fn toplevel_close(
window: *mut c_void,
_zxdg_toplevel_v6: *mut ZxdgToplevel,
) {
let _window: &mut Wayland = unsafe { &mut *window.cast() };
todo!();
}
extern "C" fn output_geometry(
_data: *mut c_void,
_wl_output: *mut WlOutput,
_x: i32, _y: i32, _physical_width: i32, _physical_height: i32, _subpixel: i32, _make: *const c_char, _model: *const c_char, _transform: i32,
) {
}
extern "C" fn output_mode(
data: *mut c_void,
_wl_output: *mut WlOutput,
_flags: u32,
_width: i32, _height: i32, refresh: i32,
) {
let window: *mut Wayland = data.cast();
unsafe {
(*window).refresh_rate =
Duration::from_secs(1000).div_f64(refresh as f64);
}
}
extern "C" fn output_done(_data: *mut c_void, _wl_output: *mut WlOutput) {}
extern "C" fn output_scale(
_data: *mut c_void,
_wl_output: *mut WlOutput,
_factor: i32, ) {
}
extern "C" fn seat_handle_capabilities(
window: *mut c_void,
seat: *mut WlSeat,
caps: u32,
) {
unsafe {
let window: *mut Wayland = window.cast();
let has_pointer = (caps & WlSeatCapability::Pointer as u32) != 0;
if has_pointer && (*window).pointer.is_null() {
(*window).pointer = (*window).client.seat_get_pointer(seat);
(*window).client.pointer_add_listener(
(*window).pointer,
&POINTER_LISTENER,
window.cast(),
);
} else if !has_pointer && !(*window).pointer.is_null() {
((*window).client.wl_proxy_destroy)((*window).pointer.cast());
(*window).pointer = std::ptr::null_mut();
}
let has_keyboard = (caps & WlSeatCapability::Keyboard as u32) != 0;
if has_keyboard && (*window).keyboard.is_null() {
(*window).keyboard = (*window).client.seat_get_keyboard(seat);
(*window).client.keyboard_add_listener(
(*window).keyboard,
&KEYBOARD_LISTENER,
window.cast(),
);
} else if !has_keyboard && !(*window).keyboard.is_null() {
((*window).client.wl_proxy_destroy)((*window).keyboard.cast());
(*window).keyboard = std::ptr::null_mut();
}
let has_touch = (caps & WlSeatCapability::Touch as u32) != 0;
if has_touch && (*window).touch.is_null() {
(*window).touch = (*window).client.seat_get_touch(seat);
(*window).client.touch_add_listener(
(*window).touch,
&TOUCH_LISTENER,
window.cast(),
);
} else if !has_touch && !(*window).touch.is_null() {
((*window).client.wl_proxy_destroy)((*window).touch.cast());
(*window).touch = std::ptr::null_mut();
}
}
}
extern "C" fn handle_xdg_shell_ping(
window: *mut c_void,
shell: *mut ZxdgShell,
serial: u32,
) {
let window: *mut Wayland = window.cast();
unsafe {
(*window).client.zxdg_shell_v6_pong(shell, serial);
}
}
extern "C" fn touch_handle_down(
_window: *mut c_void,
_touch: *mut WlTouch,
_serial: u32,
_time: u32,
_surface: *mut WlSurface,
id: i32,
x: i32,
y: i32,
) {
println!("Touch::Down {} {} {}", id, x, y);
}
extern "C" fn touch_handle_up(
_window: *mut c_void,
_touch: *mut WlTouch,
_serial: u32,
_time: u32,
id: i32,
) {
println!("Touch::Up {}", id);
}
extern "C" fn touch_handle_motion(
_window: *mut c_void,
_touch: *mut WlTouch,
_time: u32,
id: i32,
x: i32,
y: i32,
) {
println!("Touch::Motion {} {} {}", id, x, y);
}
extern "C" fn touch_handle_frame(_data: *mut c_void, _touch: *mut WlTouch) {
println!("Touch::Frame");
}
extern "C" fn touch_handle_cancel(_data: *mut c_void, _touch: *mut WlTouch) {
println!("Touch::Cancel");
}
extern "C" fn keyboard_handle_keymap(
_window: *mut c_void,
_keyboard: *mut WlKeyboard,
_format: u32,
_fd: i32,
_size: u32,
) {
}
extern "C" fn keyboard_handle_enter(
_window: *mut c_void,
_keyboard: *mut WlKeyboard,
_serial: u32,
_surface: *mut WlSurface,
_keys: *mut WlArray,
) {
}
extern "C" fn keyboard_handle_leave(
_window: *mut c_void,
_keyboard: *mut WlKeyboard,
_serial: u32,
_surface: *mut WlSurface,
) {
}
extern "C" fn keyboard_handle_key(
wayland: *mut c_void,
_keyboard: *mut WlKeyboard,
_serial: u32,
_time: u32,
key: u32,
state: u32,
) {
let window: &mut Wayland = unsafe { &mut *wayland.cast() };
if key == 87 && state != 0 {
(*window).configured = true;
if (*window).fullscreen {
unsafe {
(*window)
.client
.zxdg_toplevel_v6_unset_fullscreen((*window).toplevel);
}
(*window).fullscreen = false;
} else {
unsafe {
(*window)
.client
.zxdg_toplevel_v6_set_fullscreen((*window).toplevel);
}
(*window).fullscreen = true;
}
let callback = unsafe {
(*window).client.display_sync((*window).display.as_ptr())
};
unsafe {
(*window).client.callback_add_listener(
callback,
&FRAME_LISTENER,
wayland,
);
}
} else {
let held = state != 0;
let mods = Mod::new();
window.input_queue.push(match key {
1 => Input::Key(mods, Key::Back, held),
2 => Input::Key(mods, Key::One, held),
3 => Input::Key(mods, Key::Two, held),
4 => Input::Key(mods, Key::Three, held),
5 => Input::Key(mods, Key::Four, held),
6 => Input::Key(mods, Key::Five, held),
7 => Input::Key(mods, Key::Six, held),
8 => Input::Key(mods, Key::Seven, held),
9 => Input::Key(mods, Key::Eight, held),
10 => Input::Key(mods, Key::Nine, held),
11 => Input::Key(mods, Key::Zero, held),
12 => Input::Key(mods, Key::Minus, held),
13 => Input::Key(mods, Key::Equal, held),
14 => Input::Key(mods, Key::Backspace, held),
15 => Input::Key(mods, Key::Tab, held),
16 => Input::Key(mods, Key::Q, held),
17 => Input::Key(mods, Key::W, held),
18 => Input::Key(mods, Key::E, held),
19 => Input::Key(mods, Key::R, held),
20 => Input::Key(mods, Key::T, held),
21 => Input::Key(mods, Key::Y, held),
22 => Input::Key(mods, Key::U, held),
23 => Input::Key(mods, Key::I, held),
24 => Input::Key(mods, Key::O, held),
25 => Input::Key(mods, Key::P, held),
26 => Input::Key(mods, Key::BracketOpen, held),
27 => Input::Key(mods, Key::BracketClose, held),
28 => Input::Key(mods, Key::Enter, held),
29 => Input::Key(mods, Key::LCtrl, held),
30 => Input::Key(mods, Key::A, held),
31 => Input::Key(mods, Key::S, held),
32 => Input::Key(mods, Key::D, held),
33 => Input::Key(mods, Key::F, held),
34 => Input::Key(mods, Key::G, held),
35 => Input::Key(mods, Key::H, held),
36 => Input::Key(mods, Key::J, held),
37 => Input::Key(mods, Key::K, held),
38 => Input::Key(mods, Key::L, held),
39 => Input::Key(mods, Key::Semicolon, held),
40 => Input::Key(mods, Key::Apostrophe, held),
41 => Input::Key(mods, Key::Backtick, held),
42 => Input::Key(mods, Key::LShift, held),
43 => Input::Key(mods, Key::Backslash, held),
44 => Input::Key(mods, Key::Z, held),
45 => Input::Key(mods, Key::X, held),
46 => Input::Key(mods, Key::C, held),
47 => Input::Key(mods, Key::V, held),
48 => Input::Key(mods, Key::B, held),
49 => Input::Key(mods, Key::N, held),
50 => Input::Key(mods, Key::M, held),
51 => Input::Key(mods, Key::Comma, held),
52 => Input::Key(mods, Key::Period, held),
53 => Input::Key(mods, Key::Slash, held),
54 => Input::Key(mods, Key::RShift, held),
55 => Input::Key(mods.add_shift(), Key::Eight, held), 56 => Input::Key(mods, Key::LAlt, held),
57 => Input::Key(mods, Key::Space, held),
58 => Input::Key(mods, Key::CapsLock, held),
59 => Input::Key(mods, Key::F1, held),
60 => Input::Key(mods, Key::F2, held),
61 => Input::Key(mods, Key::F3, held),
62 => Input::Key(mods, Key::F4, held),
63 => Input::Key(mods, Key::F5, held),
64 => Input::Key(mods, Key::F6, held),
65 => Input::Key(mods, Key::F7, held),
66 => Input::Key(mods, Key::F8, held),
67 => Input::Key(mods, Key::F9, held),
68 => Input::Key(mods, Key::F10, held),
69 => Input::Key(mods, Key::Compose, held), 70 => Input::Key(mods, Key::Compose, held), 71 => Input::Key(mods, Key::Seven, held), 72 => Input::Key(mods, Key::Eight, held), 73 => Input::Key(mods, Key::Nine, held), 74 => Input::Key(mods, Key::Minus, held), 75 => Input::Key(mods, Key::Four, held), 76 => Input::Key(mods, Key::Five, held), 77 => Input::Key(mods, Key::Six, held), 78 => Input::Key(mods.add_shift(), Key::Equal, held), 79 => Input::Key(mods, Key::One, held), 80 => Input::Key(mods, Key::Two, held), 81 => Input::Key(mods, Key::Three, held), 82 => Input::Key(mods, Key::Zero, held), 83 => Input::Key(mods, Key::Period, held), 84 => Input::Key(mods, Key::Compose, held), 85 => Input::Key(mods, Key::Compose, held), 86 => Input::Key(mods, Key::Compose, held), 87 => Input::Key(mods, Key::F11, held),
88 => Input::Key(mods, Key::F12, held),
89 => Input::Key(mods, Key::Compose, held), 90 => Input::Key(mods, Key::Compose, held), 91 => Input::Key(mods, Key::Compose, held), 92 => Input::Key(mods, Key::Compose, held), 93 => Input::Key(mods, Key::Compose, held), 94 => Input::Key(mods, Key::Compose, held), 95 => Input::Key(mods, Key::Compose, held), 96 => Input::Key(mods, Key::Enter, held), 97 => Input::Key(mods, Key::RCtrl, held), 98 => Input::Key(mods, Key::Slash, held), 99 => return, 100 => Input::Key(mods, Key::RAlt, held),
101 => Input::Key(mods, Key::Enter, held), 102 => Input::Key(mods, Key::Home, held),
103 => Input::Key(mods, Key::Up, held),
104 => Input::Key(mods, Key::PageUp, held),
105 => Input::Key(mods, Key::Left, held),
106 => Input::Key(mods, Key::Right, held),
107 => Input::Key(mods, Key::End, held),
108 => Input::Key(mods, Key::Down, held),
109 => Input::Key(mods, Key::PageDown, held),
110 => Input::Key(mods, Key::Insert, held),
111 => Input::Key(mods, Key::Delete, held),
112 => Input::Key(mods, Key::Compose, held), 113 => return, 114 => return, 115 => return, 116 => return, 117 => return, 118 => return, 119 => return, 120 => return, 121 => return, 122 => return, 123 => return, 124 => return, 125 => Input::Key(mods, Key::LCtrl, held), 126 => Input::Key(mods, Key::RCtrl, held), 127 => Input::Key(mods, Key::Compose, held),
e => {
eprintln!("Error: Unknown key: {}", e);
return;
}
});
}
}
extern "C" fn keyboard_handle_modifiers(
_window: *mut c_void,
_keyboard: *mut WlKeyboard,
_serial: u32,
_mods_depressed: u32,
_mods_latched: u32,
_mods_locked: u32,
_group: u32,
) {
}
extern "C" fn pointer_handle_enter(
window: *mut c_void,
pointer: *mut WlPointer,
serial: u32,
_surface: *mut WlSurface,
_sx: i32,
_sy: i32,
) {
unsafe {
let window: *mut Wayland = window.cast();
let cursor = (*window).default_cursor;
let image = *(*cursor).images;
let buffer = ((*window).cursor.wl_cursor_image_get_buffer)(image);
if buffer.is_null() {
return;
}
(*window).client.pointer_set_cursor(
pointer,
(*window).cursor_surface,
image,
serial,
);
(*window)
.client
.surface_attach((*window).cursor_surface, buffer);
(*window)
.client
.surface_damage((*window).cursor_surface, image);
(*window).client.surface_commit((*window).cursor_surface);
}
}
extern "C" fn pointer_handle_leave(
_window: *mut c_void,
_pointer: *mut WlPointer,
_serial: u32,
_surface: *mut WlSurface,
) {
}
extern "C" fn pointer_handle_motion(
window: *mut c_void,
_pointer: *mut WlPointer,
_time: u32,
x: i32,
y: i32,
) {
let wayland: &mut Wayland = unsafe { &mut *window.cast() };
let w = (wayland.window_width as f32 * 256.0).recip();
let x = x as f32 * w;
let y = y as f32 * w;
wayland.move_state = (wayland.move_)(x, y);
wayland.input_queue.push(Input::PointerX(x));
wayland.input_queue.push(Input::PointerY(y));
}
extern "C" fn pointer_handle_button(
window: *mut c_void,
_pointer: *mut WlPointer,
serial: u32,
_time: u32,
button: u32,
state: u32,
) {
let window: &mut Wayland = unsafe { &mut *window.cast() };
let pressed = state != 0;
let mods = Mod::new();
let mut input = match button {
0x110 => Some(Input::Click(mods, Btn::Left, pressed)),
0x111 => Some(Input::Click(mods, Btn::Right, pressed)),
0x112 => Some(Input::Click(mods, Btn::Middle, pressed)),
0x113 => Some(Input::Click(mods, Btn::Dpi, pressed)),
0x114 => Some(Input::Click(mods, Btn::Extra, pressed)),
0x115 => Some(Input::Click(mods, Btn::Next, pressed)),
0x116 => Some(Input::Click(mods, Btn::Back, pressed)),
0x117 => Some(Input::Click(mods, Btn::Extra, pressed)),
_ => None,
};
if let Some(input) = input.take() {
if matches!(input, Input::Click(_mods, Btn::Left, true)) {
unsafe {
(window.client.wl_proxy_marshal)(
window.toplevel.cast(),
5,
window.seat,
serial,
);
}
}
window.input_queue.push(input);
}
}
extern "C" fn pointer_handle_axis(
window: *mut c_void,
_pointer: *mut WlPointer,
_time: u32,
axis: u32,
value: i32,
) {
let window: &mut Wayland = unsafe { &mut *window.cast() };
window.input_queue.push(match axis {
0 => Input::ScrollY(Mod::new(), value as f32 / 2560.0),
1 => Input::ScrollX(Mod::new(), value as f32 / 2560.0),
x => {
eprintln!("Unknown Wayland Axis {}", x);
return;
}
});
}
extern "C" fn redraw_wl(
data: *mut c_void,
callback: *mut WlCallback,
_millis: u32, ) {
let wayland: &mut Wayland = unsafe { &mut *data.cast() };
unsafe {
if !callback.is_null() {
wayland.client.callback_destroy(callback);
}
wayland.callback = std::ptr::null_mut();
(*wayland.draw.unwrap().as_ptr()).begin_draw();
(wayland.redraw)(&mut *wayland.window, wayland.refresh_rate);
wayland.callback = wayland.client.surface_frame((*wayland).surface);
wayland.client.callback_add_listener(
wayland.callback,
&FRAME_LISTENER,
data,
);
(*wayland.draw.unwrap().as_ptr()).finish_draw();
}
}