mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-24 22:31:30 +11:00
commit
1f170264ed
|
@ -39,7 +39,7 @@ kernel32-sys = "0.2"
|
|||
dwmapi-sys = "0.1"
|
||||
|
||||
[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))'.dependencies]
|
||||
wayland-client = { version = "0.5.4", features = ["dlopen"] }
|
||||
wayland-kbd = "0.3.3"
|
||||
wayland-window = "0.2.2"
|
||||
wayland-client = { version = "0.7.4", features = ["dlopen"] }
|
||||
wayland-kbd = "0.6.2"
|
||||
wayland-window = "0.4.2"
|
||||
x11-dl = "2.8"
|
||||
|
|
|
@ -1,211 +1,662 @@
|
|||
use Event as GlutinEvent;
|
||||
use {Event, ElementState, MouseButton, MouseScrollDelta, TouchPhase};
|
||||
|
||||
use std::collections::{HashMap, VecDeque, HashSet};
|
||||
use std::collections::VecDeque;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use libc::c_void;
|
||||
|
||||
use wayland_client::{EventIterator, Proxy, ProxyId};
|
||||
use wayland_client::wayland::get_display;
|
||||
use wayland_client::wayland::compositor::{WlCompositor, WlSurface};
|
||||
use wayland_client::wayland::output::WlOutput;
|
||||
use wayland_client::wayland::seat::{WlSeat, WlPointer};
|
||||
use wayland_client::wayland::shell::{WlShell, WlShellSurface};
|
||||
use wayland_client::wayland::shm::WlShm;
|
||||
use wayland_client::wayland::subcompositor::WlSubcompositor;
|
||||
use wayland_client::{EnvHandler, default_connect, EventQueue, EventQueueHandle, Init, Proxy};
|
||||
use wayland_client::protocol::{wl_compositor, wl_seat, wl_shell, wl_shm, wl_subcompositor,
|
||||
wl_display, wl_registry, wl_output, wl_surface, wl_pointer,
|
||||
wl_keyboard};
|
||||
|
||||
use super::wayland_window;
|
||||
use super::wayland_kbd::MappedKeyboard;
|
||||
use super::wayland_window::DecoratedSurface;
|
||||
use super::keyboard::KbdHandler;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref WAYLAND_CONTEXT: Option<WaylandContext> = {
|
||||
WaylandContext::init()
|
||||
};
|
||||
}
|
||||
/*
|
||||
* Registry and globals handling
|
||||
*/
|
||||
|
||||
wayland_env!(InnerEnv,
|
||||
compositor: WlCompositor,
|
||||
seat: WlSeat,
|
||||
shell: WlShell,
|
||||
shm: WlShm,
|
||||
subcompositor: WlSubcompositor
|
||||
compositor: wl_compositor::WlCompositor,
|
||||
shell: wl_shell::WlShell,
|
||||
shm: wl_shm::WlShm,
|
||||
subcompositor: wl_subcompositor::WlSubcompositor
|
||||
);
|
||||
|
||||
pub struct WaylandFocuses {
|
||||
pub pointer: Option<WlPointer>,
|
||||
pub pointer_on: Option<ProxyId>,
|
||||
pub pointer_at: Option<(f64, f64)>,
|
||||
pub keyboard: Option<MappedKeyboard>,
|
||||
pub keyboard_on: Option<ProxyId>
|
||||
enum KbdType {
|
||||
Mapped(MappedKeyboard<KbdHandler>),
|
||||
Plain(Option<Arc<Mutex<VecDeque<Event>>>>)
|
||||
}
|
||||
|
||||
struct WaylandEnv {
|
||||
registry: wl_registry::WlRegistry,
|
||||
inner: EnvHandler<InnerEnv>,
|
||||
monitors: Vec<OutputInfo>,
|
||||
my_id: usize,
|
||||
windows: Vec<(Arc<wl_surface::WlSurface>,Arc<Mutex<VecDeque<Event>>>)>,
|
||||
seat: Option<wl_seat::WlSeat>,
|
||||
mouse: Option<wl_pointer::WlPointer>,
|
||||
mouse_focus: Option<Arc<Mutex<VecDeque<Event>>>>,
|
||||
mouse_location: (i32, i32),
|
||||
axis_buffer: Option<(f32, f32)>,
|
||||
axis_discrete_buffer: Option<(i32, i32)>,
|
||||
axis_state: TouchPhase,
|
||||
kbd: Option<wl_keyboard::WlKeyboard>,
|
||||
kbd_handler: KbdType
|
||||
}
|
||||
|
||||
struct OutputInfo {
|
||||
output: wl_output::WlOutput,
|
||||
id: u32,
|
||||
scale: f32,
|
||||
pix_size: (u32, u32),
|
||||
name: String
|
||||
}
|
||||
|
||||
impl OutputInfo {
|
||||
fn new(output: wl_output::WlOutput, id: u32) -> OutputInfo {
|
||||
OutputInfo {
|
||||
output: output,
|
||||
id: id,
|
||||
scale: 1.0,
|
||||
pix_size: (0, 0),
|
||||
name: "".into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WaylandEnv {
|
||||
fn new(registry: wl_registry::WlRegistry) -> WaylandEnv {
|
||||
let kbd_handler = match MappedKeyboard::new(KbdHandler::new()) {
|
||||
Ok(h) => KbdType::Mapped(h),
|
||||
Err(_) => KbdType::Plain(None)
|
||||
};
|
||||
WaylandEnv {
|
||||
registry: registry,
|
||||
inner: EnvHandler::new(),
|
||||
monitors: Vec::new(),
|
||||
my_id: 0,
|
||||
windows: Vec::new(),
|
||||
seat: None,
|
||||
mouse: None,
|
||||
mouse_focus: None,
|
||||
mouse_location: (0,0),
|
||||
axis_buffer: None,
|
||||
axis_discrete_buffer: None,
|
||||
axis_state: TouchPhase::Started,
|
||||
kbd: None,
|
||||
kbd_handler: kbd_handler
|
||||
}
|
||||
}
|
||||
|
||||
fn get_seat(&self) -> Option<wl_seat::WlSeat> {
|
||||
for &(name, ref interface, version) in self.inner.globals() {
|
||||
if interface == "wl_seat" {
|
||||
// this "expect" cannot trigger (see https://github.com/vberger/wayland-client-rs/issues/69)
|
||||
let seat = self.registry.bind::<wl_seat::WlSeat>(5, name).expect("Seat cannot be destroyed");
|
||||
return Some(seat)
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Init for WaylandEnv {
|
||||
fn init(&mut self, evqh: &mut EventQueueHandle, index: usize) {
|
||||
evqh.register::<_, WaylandEnv>(&self.registry, index);
|
||||
self.my_id = index
|
||||
}
|
||||
}
|
||||
|
||||
impl wl_registry::Handler for WaylandEnv {
|
||||
fn global(&mut self,
|
||||
evqh: &mut EventQueueHandle,
|
||||
registry: &wl_registry::WlRegistry,
|
||||
name: u32,
|
||||
interface: String,
|
||||
version: u32)
|
||||
{
|
||||
if interface == "wl_output" {
|
||||
// intercept outputs
|
||||
// this "expect" cannot trigger (see https://github.com/vberger/wayland-client-rs/issues/69)
|
||||
let output = self.registry.bind::<wl_output::WlOutput>(1, name)
|
||||
.expect("Registry cannot be dead");
|
||||
evqh.register::<_, WaylandEnv>(&output, self.my_id);
|
||||
self.monitors.push(OutputInfo::new(output, name));
|
||||
} else if interface == "wl_seat" && self.seat.is_none() {
|
||||
// Only grab the first seat
|
||||
// TODO: Handle multi-seat-setup?
|
||||
assert!(version >= 5, "Version 5 of seat interface is needed by glutin.");
|
||||
let seat = self.registry.bind::<wl_seat::WlSeat>(5, name)
|
||||
.expect("Registry cannot be dead");
|
||||
evqh.register::<_, WaylandEnv>(&seat, self.my_id);
|
||||
self.seat = Some(seat);
|
||||
}
|
||||
self.inner.global(evqh, registry, name, interface, version);
|
||||
}
|
||||
|
||||
fn global_remove(&mut self,
|
||||
evqh: &mut EventQueueHandle,
|
||||
registry: &wl_registry::WlRegistry,
|
||||
name: u32)
|
||||
{
|
||||
// prune old monitors
|
||||
self.monitors.retain(|m| m.id != name);
|
||||
self.inner.global_remove(evqh, registry, name);
|
||||
}
|
||||
}
|
||||
|
||||
declare_handler!(WaylandEnv, wl_registry::Handler, wl_registry::WlRegistry);
|
||||
|
||||
impl wl_output::Handler for WaylandEnv {
|
||||
fn geometry(&mut self,
|
||||
_: &mut EventQueueHandle,
|
||||
proxy: &wl_output::WlOutput,
|
||||
_x: i32, _y: i32,
|
||||
_physical_width: i32, _physical_height: i32,
|
||||
_subpixel: wl_output::Subpixel,
|
||||
make: String, model: String,
|
||||
_transform: wl_output::Transform)
|
||||
{
|
||||
for m in self.monitors.iter_mut().filter(|m| m.output.equals(proxy)) {
|
||||
m.name = format!("{} ({})", model, make);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fn mode(&mut self,
|
||||
_: &mut EventQueueHandle,
|
||||
proxy: &wl_output::WlOutput,
|
||||
flags: wl_output::Mode,
|
||||
width: i32, height: i32,
|
||||
_refresh: i32)
|
||||
{
|
||||
if flags.contains(wl_output::Current) {
|
||||
for m in self.monitors.iter_mut().filter(|m| m.output.equals(proxy)) {
|
||||
m.pix_size = (width as u32, height as u32);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fn scale(&mut self,
|
||||
_: &mut EventQueueHandle,
|
||||
proxy: &wl_output::WlOutput,
|
||||
factor: i32)
|
||||
{
|
||||
for m in self.monitors.iter_mut().filter(|m| m.output.equals(proxy)) {
|
||||
m.scale = factor as f32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare_handler!(WaylandEnv, wl_output::Handler, wl_output::WlOutput);
|
||||
|
||||
/*
|
||||
* Main context struct
|
||||
*/
|
||||
|
||||
pub struct WaylandContext {
|
||||
inner: InnerEnv,
|
||||
iterator: Mutex<EventIterator>,
|
||||
monitors: Vec<(WlOutput, u32, u32, String)>,
|
||||
queues: Mutex<HashMap<ProxyId, Arc<Mutex<VecDeque<GlutinEvent>>>>>,
|
||||
known_surfaces: Mutex<HashSet<ProxyId>>,
|
||||
focuses: Mutex<WaylandFocuses>
|
||||
pub display: wl_display::WlDisplay,
|
||||
evq: Mutex<EventQueue>,
|
||||
env_id: usize,
|
||||
}
|
||||
|
||||
impl WaylandContext {
|
||||
fn init() -> Option<WaylandContext> {
|
||||
let display = match get_display() {
|
||||
Some(display) => display,
|
||||
None => return None
|
||||
pub fn init() -> Option<WaylandContext> {
|
||||
// attempt to connect to the wayland server
|
||||
// this handles both "no libwayland" and "no compositor" cases
|
||||
let (display, mut event_queue) = match default_connect() {
|
||||
Ok(ret) => ret,
|
||||
Err(e) => return None
|
||||
};
|
||||
|
||||
let (mut inner_env, iterator) = InnerEnv::init(display);
|
||||
|
||||
let outputs_events = EventIterator::new();
|
||||
|
||||
let mut monitors = inner_env.globals.iter()
|
||||
.flat_map(|&(id, _, _)| inner_env.rebind_id::<WlOutput>(id))
|
||||
.map(|(mut monitor, _)| {
|
||||
monitor.set_evt_iterator(&outputs_events);
|
||||
(monitor, 0, 0, String::new())
|
||||
}).collect();
|
||||
|
||||
inner_env.display.sync_roundtrip().unwrap();
|
||||
|
||||
super::monitor::init_monitors(&mut monitors, outputs_events);
|
||||
// this "expect" cannot trigger (see https://github.com/vberger/wayland-client-rs/issues/69)
|
||||
let registry = display.get_registry().expect("Display cannot be already destroyed.");
|
||||
let env_id = event_queue.add_handler_with_init(WaylandEnv::new(registry));
|
||||
// two syncs fully initialize
|
||||
event_queue.sync_roundtrip().expect("Wayland connection unexpectedly lost");
|
||||
event_queue.sync_roundtrip().expect("Wayland connection unexpectedly lost");
|
||||
|
||||
Some(WaylandContext {
|
||||
inner: inner_env,
|
||||
iterator: Mutex::new(iterator),
|
||||
monitors: monitors,
|
||||
queues: Mutex::new(HashMap::new()),
|
||||
known_surfaces: Mutex::new(HashSet::new()),
|
||||
focuses: Mutex::new(WaylandFocuses {
|
||||
pointer: None,
|
||||
pointer_on: None,
|
||||
pointer_at: None,
|
||||
keyboard: None,
|
||||
keyboard_on: None
|
||||
})
|
||||
evq: Mutex::new(event_queue),
|
||||
display: display,
|
||||
env_id: env_id
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_surface(&self) -> Option<(WlSurface, Arc<Mutex<VecDeque<GlutinEvent>>>)> {
|
||||
self.inner.compositor.as_ref().map(|c| {
|
||||
let s = c.0.create_surface();
|
||||
let id = s.id();
|
||||
let queue = {
|
||||
let mut q = VecDeque::new();
|
||||
q.push_back(GlutinEvent::Refresh);
|
||||
Arc::new(Mutex::new(q))
|
||||
};
|
||||
self.queues.lock().unwrap().insert(id, queue.clone());
|
||||
self.known_surfaces.lock().unwrap().insert(id);
|
||||
(s, queue)
|
||||
})
|
||||
pub fn dispatch_pending(&self) {
|
||||
let mut guard = self.evq.lock().unwrap();
|
||||
guard.dispatch_pending().expect("Wayland connection unexpectedly lost");
|
||||
}
|
||||
|
||||
pub fn dropped_surface(&self, id: ProxyId) {
|
||||
self.queues.lock().unwrap().remove(&id);
|
||||
self.known_surfaces.lock().unwrap().remove(&id);
|
||||
pub fn dispatch(&self) {
|
||||
let mut guard = self.evq.lock().unwrap();
|
||||
guard.dispatch().expect("Wayland connection unexpectedly lost");
|
||||
}
|
||||
|
||||
pub fn decorated_from(&self, surface: &WlSurface, width: i32, height: i32) -> Option<DecoratedSurface> {
|
||||
let inner = &self.inner;
|
||||
match (&inner.compositor, &inner.subcompositor, &inner.shm, &inner.shell) {
|
||||
(&Some(ref compositor), &Some(ref subcompositor), &Some(ref shm), &Some(ref shell)) => {
|
||||
DecoratedSurface::new(
|
||||
surface, width, height,
|
||||
&compositor.0, &subcompositor.0, &shm.0, &shell.0,
|
||||
self.inner.rebind::<WlSeat>().map(|(seat, _)| seat)
|
||||
).ok()
|
||||
}
|
||||
_ => None
|
||||
pub fn flush(&self) {
|
||||
self.display.flush();
|
||||
}
|
||||
|
||||
pub fn with_output<F>(&self, id: MonitorId, f: F) where F: FnOnce(&wl_output::WlOutput) {
|
||||
let mut guard = self.evq.lock().unwrap();
|
||||
let state = guard.state();
|
||||
let env = state.get_handler::<WaylandEnv>(self.env_id);
|
||||
for m in env.monitors.iter().filter(|m| m.id == id.id) {
|
||||
f(&m.output);
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
pub fn plain_from(&self, surface: &WlSurface, fullscreen: Option<ProxyId>) -> Option<WlShellSurface> {
|
||||
use wayland_client::wayland::shell::WlShellSurfaceFullscreenMethod;
|
||||
|
||||
let inner = &self.inner;
|
||||
if let Some((ref shell, _)) = inner.shell {
|
||||
let shell_surface = shell.get_shell_surface(surface);
|
||||
if let Some(monitor_id) = fullscreen {
|
||||
for m in &self.monitors {
|
||||
if m.0.id() == monitor_id {
|
||||
shell_surface.set_fullscreen(
|
||||
WlShellSurfaceFullscreenMethod::Default,
|
||||
0,
|
||||
Some(&m.0)
|
||||
);
|
||||
return Some(shell_surface)
|
||||
}
|
||||
}
|
||||
}
|
||||
shell_surface.set_toplevel();
|
||||
Some(shell_surface)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
pub fn create_window<H: wayland_window::Handler>(&self)
|
||||
-> (Arc<wl_surface::WlSurface>, Arc<Mutex<VecDeque<Event>>>, wayland_window::DecoratedSurface<H>)
|
||||
{
|
||||
let mut guard = self.evq.lock().unwrap();
|
||||
let mut state = guard.state();
|
||||
let env = state.get_mut_handler::<WaylandEnv>(self.env_id);
|
||||
// this "expect" cannot trigger (see https://github.com/vberger/wayland-client-rs/issues/69)
|
||||
let surface = Arc::new(env.inner.compositor.create_surface().expect("Compositor cannot be dead"));
|
||||
let eventiter = Arc::new(Mutex::new(VecDeque::new()));
|
||||
env.windows.push((surface.clone(), eventiter.clone()));
|
||||
let decorated = wayland_window::DecoratedSurface::new(
|
||||
&*surface, 800, 600,
|
||||
&env.inner.compositor,
|
||||
&env.inner.subcompositor,
|
||||
&env.inner.shm,
|
||||
&env.inner.shell,
|
||||
env.get_seat(),
|
||||
false
|
||||
).expect("Failed to create a tmpfile buffer.");
|
||||
(surface, eventiter, decorated)
|
||||
}
|
||||
|
||||
pub fn display_ptr(&self) -> *const c_void {
|
||||
self.inner.display.ptr() as *const _
|
||||
}
|
||||
|
||||
pub fn dispatch_events(&self) {
|
||||
self.inner.display.dispatch_pending().unwrap();
|
||||
let mut iterator = self.iterator.lock().unwrap();
|
||||
let mut focuses = self.focuses.lock().unwrap();
|
||||
let known_surfaces = self.known_surfaces.lock().unwrap();
|
||||
let queues = self.queues.lock().unwrap();
|
||||
// first, keyboard events
|
||||
let kdb_evts = super::keyboard::translate_kbd_events(&mut *focuses, &known_surfaces);
|
||||
for (evt, id) in kdb_evts {
|
||||
if let Some(q) = queues.get(&id) {
|
||||
q.lock().unwrap().push_back(evt);
|
||||
}
|
||||
}
|
||||
// then, the rest
|
||||
for evt in &mut *iterator {
|
||||
if let Some((evt, id)) = super::events::translate_event(
|
||||
evt, &mut *focuses, &known_surfaces,
|
||||
self.inner.seat.as_ref().map(|s| &s.0))
|
||||
{
|
||||
if let Some(q) = queues.get(&id) {
|
||||
q.lock().unwrap().push_back(evt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn flush_events(&self) -> ::std::io::Result<i32> {
|
||||
self.inner.display.flush()
|
||||
}
|
||||
|
||||
pub fn read_events(&self) -> ::std::io::Result<Option<i32>> {
|
||||
let guard = match self.inner.display.prepare_read() {
|
||||
Some(g) => g,
|
||||
None => return Ok(None)
|
||||
};
|
||||
return guard.read_events().map(|i| Some(i));
|
||||
}
|
||||
|
||||
pub fn monitor_ids(&self) -> Vec<ProxyId> {
|
||||
self.monitors.iter().map(|o| o.0.id()).collect()
|
||||
}
|
||||
|
||||
pub fn monitor_name(&self, pid: ProxyId) -> Option<String> {
|
||||
for o in &self.monitors {
|
||||
if o.0.id() == pid {
|
||||
return Some(o.3.clone())
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn monitor_dimensions(&self, pid: ProxyId) -> Option<(u32, u32)> {
|
||||
for o in &self.monitors {
|
||||
if o.0.id() == pid {
|
||||
return Some((o.1, o.2))
|
||||
}
|
||||
}
|
||||
None
|
||||
pub fn prune_dead_windows(&self) {
|
||||
let mut guard = self.evq.lock().unwrap();
|
||||
let mut state = guard.state();
|
||||
let env = state.get_mut_handler::<WaylandEnv>(self.env_id);
|
||||
env.windows.retain(|w| w.0.is_alive());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Monitors API
|
||||
*/
|
||||
|
||||
pub fn get_primary_monitor(ctxt: &Arc<WaylandContext>) -> MonitorId {
|
||||
let mut guard = ctxt.evq.lock().unwrap();
|
||||
let state = guard.state();
|
||||
let env = state.get_handler::<WaylandEnv>(ctxt.env_id);
|
||||
if let Some(ref monitor) = env.monitors.iter().next() {
|
||||
MonitorId {
|
||||
id: monitor.id,
|
||||
ctxt: ctxt.clone()
|
||||
}
|
||||
} else {
|
||||
panic!("No monitor is available.")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_available_monitors(ctxt: &Arc<WaylandContext>) -> VecDeque<MonitorId> {
|
||||
let mut guard = ctxt.evq.lock().unwrap();
|
||||
let state = guard.state();
|
||||
let env = state.get_handler::<WaylandEnv>(ctxt.env_id);
|
||||
env.monitors.iter()
|
||||
.map(|m| MonitorId { id: m.id, ctxt: ctxt.clone() })
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MonitorId {
|
||||
id: u32,
|
||||
ctxt: Arc<WaylandContext>
|
||||
}
|
||||
|
||||
impl MonitorId {
|
||||
pub fn get_name(&self) -> Option<String> {
|
||||
let mut guard = self.ctxt.evq.lock().unwrap();
|
||||
let state = guard.state();
|
||||
let env = state.get_handler::<WaylandEnv>(self.ctxt.env_id);
|
||||
for m in env.monitors.iter().filter(|m| m.id == self.id) {
|
||||
return Some(m.name.clone())
|
||||
}
|
||||
// if we reach here, this monitor does not exist any more
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_native_identifier(&self) -> ::native_monitor::NativeMonitorId {
|
||||
::native_monitor::NativeMonitorId::Unavailable
|
||||
}
|
||||
|
||||
pub fn get_dimensions(&self) -> (u32, u32) {
|
||||
let mut guard = self.ctxt.evq.lock().unwrap();
|
||||
let state = guard.state();
|
||||
let env = state.get_handler::<WaylandEnv>(self.ctxt.env_id);
|
||||
for m in env.monitors.iter().filter(|m| m.id == self.id) {
|
||||
return m.pix_size
|
||||
}
|
||||
// if we reach here, this monitor does not exist any more
|
||||
(0,0)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Input Handling
|
||||
*/
|
||||
|
||||
impl wl_seat::Handler for WaylandEnv {
|
||||
fn capabilities(&mut self,
|
||||
evqh: &mut EventQueueHandle,
|
||||
seat: &wl_seat::WlSeat,
|
||||
capabilities: wl_seat::Capability)
|
||||
{
|
||||
// create pointer if applicable
|
||||
if capabilities.contains(wl_seat::Pointer) && self.mouse.is_none() {
|
||||
let pointer = seat.get_pointer().expect("Seat is not dead");
|
||||
evqh.register::<_, WaylandEnv>(&pointer, self.my_id);
|
||||
self.mouse = Some(pointer);
|
||||
}
|
||||
// destroy pointer if applicable
|
||||
if !capabilities.contains(wl_seat::Pointer) {
|
||||
if let Some(pointer) = self.mouse.take() {
|
||||
pointer.release();
|
||||
}
|
||||
}
|
||||
// create keyboard if applicable
|
||||
if capabilities.contains(wl_seat::Keyboard) && self.kbd.is_none() {
|
||||
let kbd = seat.get_keyboard().expect("Seat is not dead");
|
||||
evqh.register::<_, WaylandEnv>(&kbd, self.my_id);
|
||||
self.kbd = Some(kbd);
|
||||
}
|
||||
// destroy keyboard if applicable
|
||||
if !capabilities.contains(wl_seat::Keyboard) {
|
||||
if let Some(kbd) = self.kbd.take() {
|
||||
kbd.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare_handler!(WaylandEnv, wl_seat::Handler, wl_seat::WlSeat);
|
||||
|
||||
/*
|
||||
* Pointer Handling
|
||||
*/
|
||||
|
||||
impl wl_pointer::Handler for WaylandEnv {
|
||||
fn enter(&mut self,
|
||||
_evqh: &mut EventQueueHandle,
|
||||
_proxy: &wl_pointer::WlPointer,
|
||||
_serial: u32,
|
||||
surface: &wl_surface::WlSurface,
|
||||
surface_x: f64,
|
||||
surface_y: f64)
|
||||
{
|
||||
self.mouse_location = (surface_x as i32, surface_y as i32);
|
||||
for &(ref window, ref eviter) in &self.windows {
|
||||
if window.equals(surface) {
|
||||
self.mouse_focus = Some(eviter.clone());
|
||||
let (w, h) = self.mouse_location;
|
||||
eviter.lock().unwrap().push_back(
|
||||
Event::MouseMoved(w, h)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn leave(&mut self,
|
||||
_evqh: &mut EventQueueHandle,
|
||||
_proxy: &wl_pointer::WlPointer,
|
||||
_serial: u32,
|
||||
_surface: &wl_surface::WlSurface)
|
||||
{
|
||||
self.mouse_focus = None
|
||||
}
|
||||
|
||||
fn motion(&mut self,
|
||||
_evqh: &mut EventQueueHandle,
|
||||
_proxy: &wl_pointer::WlPointer,
|
||||
_time: u32,
|
||||
surface_x: f64,
|
||||
surface_y: f64)
|
||||
{
|
||||
self.mouse_location = (surface_x as i32, surface_y as i32);
|
||||
if let Some(ref eviter) = self.mouse_focus {
|
||||
let (w,h) = self.mouse_location;
|
||||
eviter.lock().unwrap().push_back(
|
||||
Event::MouseMoved(w, h)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn button(&mut self,
|
||||
_evqh: &mut EventQueueHandle,
|
||||
_proxy: &wl_pointer::WlPointer,
|
||||
_serial: u32,
|
||||
_time: u32,
|
||||
button: u32,
|
||||
state: wl_pointer::ButtonState)
|
||||
{
|
||||
if let Some(ref eviter) = self.mouse_focus {
|
||||
let state = match state {
|
||||
wl_pointer::ButtonState::Pressed => ElementState::Pressed,
|
||||
wl_pointer::ButtonState::Released => ElementState::Released
|
||||
};
|
||||
let button = match button {
|
||||
0x110 => MouseButton::Left,
|
||||
0x111 => MouseButton::Right,
|
||||
0x112 => MouseButton::Middle,
|
||||
// TODO figure out the translation ?
|
||||
_ => return
|
||||
};
|
||||
eviter.lock().unwrap().push_back(
|
||||
Event::MouseInput(state, button)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn axis(&mut self,
|
||||
_evqh: &mut EventQueueHandle,
|
||||
_proxy: &wl_pointer::WlPointer,
|
||||
_time: u32,
|
||||
axis: wl_pointer::Axis,
|
||||
value: f64)
|
||||
{
|
||||
let (mut x, mut y) = self.axis_buffer.unwrap_or((0.0, 0.0));
|
||||
match axis {
|
||||
wl_pointer::Axis::VerticalScroll => y += value as f32,
|
||||
wl_pointer::Axis::HorizontalScroll => x += value as f32
|
||||
}
|
||||
self.axis_buffer = Some((x,y));
|
||||
self.axis_state = match self.axis_state {
|
||||
TouchPhase::Started | TouchPhase::Moved => TouchPhase::Moved,
|
||||
_ => TouchPhase::Started
|
||||
}
|
||||
}
|
||||
|
||||
fn frame(&mut self,
|
||||
_evqh: &mut EventQueueHandle,
|
||||
_proxy: &wl_pointer::WlPointer)
|
||||
{
|
||||
let axis_buffer = self.axis_buffer.take();
|
||||
let axis_discrete_buffer = self.axis_discrete_buffer.take();
|
||||
if let Some(ref eviter) = self.mouse_focus {
|
||||
if let Some((x, y)) = axis_discrete_buffer {
|
||||
eviter.lock().unwrap().push_back(
|
||||
Event::MouseWheel(
|
||||
MouseScrollDelta::LineDelta(x as f32, y as f32),
|
||||
self.axis_state
|
||||
)
|
||||
);
|
||||
} else if let Some((x, y)) = axis_buffer {
|
||||
eviter.lock().unwrap().push_back(
|
||||
Event::MouseWheel(
|
||||
MouseScrollDelta::PixelDelta(x as f32, y as f32),
|
||||
self.axis_state
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn axis_source(&mut self,
|
||||
_evqh: &mut EventQueueHandle,
|
||||
_proxy: &wl_pointer::WlPointer,
|
||||
axis_source: wl_pointer::AxisSource)
|
||||
{
|
||||
}
|
||||
|
||||
fn axis_stop(&mut self,
|
||||
_evqh: &mut EventQueueHandle,
|
||||
_proxy: &wl_pointer::WlPointer,
|
||||
_time: u32,
|
||||
axis: wl_pointer::Axis)
|
||||
{
|
||||
self.axis_state = TouchPhase::Ended;
|
||||
}
|
||||
|
||||
fn axis_discrete(&mut self,
|
||||
_evqh: &mut EventQueueHandle,
|
||||
_proxy: &wl_pointer::WlPointer,
|
||||
axis: wl_pointer::Axis,
|
||||
discrete: i32)
|
||||
{
|
||||
let (mut x, mut y) = self.axis_discrete_buffer.unwrap_or((0,0));
|
||||
match axis {
|
||||
wl_pointer::Axis::VerticalScroll => y += discrete,
|
||||
wl_pointer::Axis::HorizontalScroll => x += discrete
|
||||
}
|
||||
self.axis_discrete_buffer = Some((x,y));
|
||||
self.axis_state = match self.axis_state {
|
||||
TouchPhase::Started | TouchPhase::Moved => TouchPhase::Moved,
|
||||
_ => TouchPhase::Started
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare_handler!(WaylandEnv, wl_pointer::Handler, wl_pointer::WlPointer);
|
||||
|
||||
/*
|
||||
* Keyboard Handling
|
||||
*/
|
||||
|
||||
impl wl_keyboard::Handler for WaylandEnv {
|
||||
// mostly pass-through
|
||||
fn keymap(&mut self,
|
||||
evqh: &mut EventQueueHandle,
|
||||
proxy: &wl_keyboard::WlKeyboard,
|
||||
format: wl_keyboard::KeymapFormat,
|
||||
fd: ::std::os::unix::io::RawFd,
|
||||
size: u32)
|
||||
{
|
||||
match self.kbd_handler {
|
||||
KbdType::Mapped(ref mut h) => h.keymap(evqh, proxy, format, fd, size),
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn enter(&mut self,
|
||||
evqh: &mut EventQueueHandle,
|
||||
proxy: &wl_keyboard::WlKeyboard,
|
||||
serial: u32,
|
||||
surface: &wl_surface::WlSurface,
|
||||
keys: Vec<u8>)
|
||||
{
|
||||
let mut opt_eviter = None;
|
||||
for &(ref window, ref eviter) in &self.windows {
|
||||
if window.equals(surface) {
|
||||
opt_eviter = Some(eviter.clone());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if let Some(ref eviter) = opt_eviter {
|
||||
// send focused event
|
||||
let mut guard = eviter.lock().unwrap();
|
||||
guard.push_back(Event::Focused(true));
|
||||
}
|
||||
match self.kbd_handler {
|
||||
KbdType::Mapped(ref mut h) => {
|
||||
h.handler().target = opt_eviter;
|
||||
h.enter(evqh, proxy, serial, surface, keys);
|
||||
},
|
||||
KbdType::Plain(ref mut opt) => { *opt = opt_eviter; }
|
||||
}
|
||||
}
|
||||
|
||||
fn leave(&mut self,
|
||||
evqh: &mut EventQueueHandle,
|
||||
proxy: &wl_keyboard::WlKeyboard,
|
||||
serial: u32,
|
||||
surface: &wl_surface::WlSurface)
|
||||
{
|
||||
let opt_eviter = match self.kbd_handler {
|
||||
KbdType::Mapped(ref mut h) => {
|
||||
let eviter = h.handler().target.take();
|
||||
h.leave(evqh, proxy, serial, surface);
|
||||
eviter
|
||||
},
|
||||
KbdType::Plain(ref mut opt) => opt.take()
|
||||
};
|
||||
if let Some(eviter) = opt_eviter {
|
||||
let mut guard = eviter.lock().unwrap();
|
||||
guard.push_back(Event::Focused(false));
|
||||
}
|
||||
}
|
||||
|
||||
fn key(&mut self,
|
||||
evqh: &mut EventQueueHandle,
|
||||
proxy: &wl_keyboard::WlKeyboard,
|
||||
serial: u32,
|
||||
time: u32,
|
||||
key: u32,
|
||||
state: wl_keyboard::KeyState)
|
||||
{
|
||||
match self.kbd_handler {
|
||||
KbdType::Mapped(ref mut h) => h.key(evqh, proxy, serial, time, key, state),
|
||||
KbdType::Plain(Some(ref eviter)) => {
|
||||
let state = match state {
|
||||
wl_keyboard::KeyState::Pressed => ElementState::Pressed,
|
||||
wl_keyboard::KeyState::Released => ElementState::Released,
|
||||
};
|
||||
let mut guard = eviter.lock().unwrap();
|
||||
guard.push_back(Event::KeyboardInput(
|
||||
state,
|
||||
key as u8,
|
||||
None
|
||||
));
|
||||
},
|
||||
KbdType::Plain(None) => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn modifiers(&mut self,
|
||||
evqh: &mut EventQueueHandle,
|
||||
proxy: &wl_keyboard::WlKeyboard,
|
||||
serial: u32,
|
||||
mods_depressed: u32,
|
||||
mods_latched: u32,
|
||||
mods_locked: u32,
|
||||
group: u32)
|
||||
{
|
||||
match self.kbd_handler {
|
||||
KbdType::Mapped(ref mut h) => h.modifiers(evqh, proxy, serial, mods_depressed,
|
||||
mods_latched, mods_locked, group),
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn repeat_info(&mut self,
|
||||
evqh: &mut EventQueueHandle,
|
||||
proxy: &wl_keyboard::WlKeyboard,
|
||||
rate: i32,
|
||||
delay: i32)
|
||||
{
|
||||
match self.kbd_handler {
|
||||
KbdType::Mapped(ref mut h) => h.repeat_info(evqh, proxy, rate, delay),
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare_handler!(WaylandEnv, wl_keyboard::Handler, wl_keyboard::WlKeyboard);
|
||||
|
|
|
@ -1,112 +0,0 @@
|
|||
use std::collections::HashSet;
|
||||
|
||||
use TouchPhase;
|
||||
use Event as GlutinEvent;
|
||||
use ElementState;
|
||||
use MouseButton;
|
||||
use MouseScrollDelta;
|
||||
|
||||
use wayland_client::Event as WaylandEvent;
|
||||
use wayland_client::ProxyId;
|
||||
use wayland_client::wayland::WaylandProtocolEvent as WPE;
|
||||
use wayland_client::wayland::seat::{WlSeat, WlSeatEvent, WlPointerEvent,
|
||||
WlPointerButtonState,
|
||||
WlPointerAxis, WlSeatCapability};
|
||||
|
||||
use super::wayland_kbd::MappedKeyboard;
|
||||
|
||||
use super::context::WaylandFocuses;
|
||||
|
||||
pub fn translate_event(
|
||||
evt: WaylandEvent,
|
||||
focuses: &mut WaylandFocuses,
|
||||
known_surfaces: &HashSet<ProxyId>,
|
||||
seat: Option<&WlSeat>,
|
||||
) -> Option<(GlutinEvent, ProxyId)>
|
||||
{
|
||||
let WaylandEvent::Wayland(wayland_evt) = evt;
|
||||
match wayland_evt {
|
||||
WPE::WlSeat(_, seat_evt) => match seat_evt {
|
||||
WlSeatEvent::Capabilities(cap) => {
|
||||
if cap.contains(WlSeatCapability::Pointer) && focuses.pointer.is_none() {
|
||||
if let Some(seat) = seat {
|
||||
focuses.pointer = Some(seat.get_pointer());
|
||||
}
|
||||
}
|
||||
if cap.contains(WlSeatCapability::Keyboard) && focuses.keyboard.is_none() {
|
||||
if let Some(seat) = seat {
|
||||
match MappedKeyboard::new(seat) {
|
||||
Ok(mk) => {
|
||||
focuses.keyboard = Some(mk)
|
||||
},
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
},
|
||||
_ => None
|
||||
},
|
||||
WPE::WlPointer(_, pointer_evt) => match pointer_evt {
|
||||
WlPointerEvent::Enter(_, surface, x, y) => {
|
||||
if known_surfaces.contains(&surface) {
|
||||
focuses.pointer_on = Some(surface);
|
||||
focuses.pointer_at = Some((x, y));
|
||||
Some((GlutinEvent::MouseMoved(x as i32, y as i32), surface))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
WlPointerEvent::Leave(_, _) => {
|
||||
focuses.pointer_on = None;
|
||||
focuses.pointer_at = None;
|
||||
None
|
||||
}
|
||||
WlPointerEvent::Motion(_, x, y) => {
|
||||
if let Some(surface) = focuses.pointer_on {
|
||||
focuses.pointer_at = Some((x, y));
|
||||
Some((GlutinEvent::MouseMoved(x as i32, y as i32), surface))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
WlPointerEvent::Button(_, _, button, state) => {
|
||||
if let Some(surface) = focuses.pointer_on {
|
||||
Some((GlutinEvent::MouseInput(
|
||||
match state {
|
||||
WlPointerButtonState::Pressed => ElementState::Pressed,
|
||||
WlPointerButtonState::Released => ElementState::Released
|
||||
},
|
||||
match button {
|
||||
0x110 => MouseButton::Left,
|
||||
0x111 => MouseButton::Right,
|
||||
0x112 => MouseButton::Middle,
|
||||
// TODO figure out the translation ?
|
||||
_ => return None
|
||||
}
|
||||
), surface))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
WlPointerEvent::Axis(_, axis, amplitude) => {
|
||||
if let Some(surface) = focuses.pointer_on {
|
||||
Some((GlutinEvent::MouseWheel(
|
||||
match axis {
|
||||
WlPointerAxis::VerticalScroll => {
|
||||
MouseScrollDelta::PixelDelta(amplitude as f32, 0.0)
|
||||
}
|
||||
WlPointerAxis::HorizontalScroll => {
|
||||
MouseScrollDelta::PixelDelta(0.0, amplitude as f32)
|
||||
}
|
||||
},
|
||||
TouchPhase::Moved
|
||||
), surface))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => None
|
||||
}
|
||||
}
|
|
@ -1,83 +1,70 @@
|
|||
use std::collections::HashSet;
|
||||
use std::collections::VecDeque;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use Event as GlutinEvent;
|
||||
use ElementState;
|
||||
use VirtualKeyCode;
|
||||
use {VirtualKeyCode, ElementState, Event};
|
||||
|
||||
use wayland_client::ProxyId;
|
||||
use wayland_client::wayland::seat::{WlKeyboardEvent,WlKeyboardKeyState};
|
||||
use super::wayland_kbd;
|
||||
use wayland_client::EventQueueHandle;
|
||||
use wayland_client::protocol::wl_keyboard;
|
||||
|
||||
use super::wayland_kbd::MappedKeyboardEvent;
|
||||
pub struct KbdHandler {
|
||||
pub target: Option<Arc<Mutex<VecDeque<Event>>>>
|
||||
}
|
||||
|
||||
use super::context::WaylandFocuses;
|
||||
impl KbdHandler {
|
||||
pub fn new() -> KbdHandler {
|
||||
KbdHandler { target: None }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn translate_kbd_events(
|
||||
focuses: &mut WaylandFocuses,
|
||||
known_surfaces: &HashSet<ProxyId>,
|
||||
) -> Vec<(GlutinEvent, ProxyId)> {
|
||||
let mut out = Vec::new();
|
||||
if let Some(mkbd) = focuses.keyboard.as_mut() {
|
||||
for evt in mkbd {
|
||||
match evt {
|
||||
MappedKeyboardEvent::KeyEvent(kevt) => {
|
||||
if let Some(surface) = focuses.keyboard_on {
|
||||
let vkcode = match kevt.keycode {
|
||||
1 => Some(VirtualKeyCode::Escape),
|
||||
2 => Some(VirtualKeyCode::Key1),
|
||||
3 => Some(VirtualKeyCode::Key2),
|
||||
4 => Some(VirtualKeyCode::Key3),
|
||||
5 => Some(VirtualKeyCode::Key4),
|
||||
6 => Some(VirtualKeyCode::Key5),
|
||||
7 => Some(VirtualKeyCode::Key6),
|
||||
8 => Some(VirtualKeyCode::Key7),
|
||||
9 => Some(VirtualKeyCode::Key8),
|
||||
10 => Some(VirtualKeyCode::Key9),
|
||||
11 => Some(VirtualKeyCode::Key0),
|
||||
_ => kevt.as_symbol().and_then(keysym_to_vkey)
|
||||
};
|
||||
let text = kevt.as_utf8();
|
||||
out.push((
|
||||
GlutinEvent::KeyboardInput(
|
||||
match kevt.keystate {
|
||||
WlKeyboardKeyState::Pressed => ElementState::Pressed,
|
||||
WlKeyboardKeyState::Released =>ElementState::Released
|
||||
},
|
||||
(kevt.keycode & 0xff) as u8,
|
||||
vkcode
|
||||
),
|
||||
surface
|
||||
));
|
||||
if let Some(c) = text.and_then(|s| s.chars().next()) {
|
||||
out.push((
|
||||
GlutinEvent::ReceivedCharacter(c),
|
||||
surface
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
MappedKeyboardEvent::Other(oevt) => match oevt {
|
||||
WlKeyboardEvent::Enter(_, surface, _) => {
|
||||
if known_surfaces.contains(&surface) {
|
||||
focuses.keyboard_on = Some(surface);
|
||||
out.push((GlutinEvent::Focused(true), surface));
|
||||
}
|
||||
},
|
||||
WlKeyboardEvent::Leave(_, surface) => {
|
||||
if known_surfaces.contains(&surface) {
|
||||
focuses.keyboard_on = None;
|
||||
out.push((GlutinEvent::Focused(false), surface));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
impl wayland_kbd::Handler for KbdHandler {
|
||||
fn key(&mut self,
|
||||
_evqh: &mut EventQueueHandle,
|
||||
_proxy: &wl_keyboard::WlKeyboard,
|
||||
_serial: u32,
|
||||
_time: u32,
|
||||
rawkey: u32,
|
||||
keysym: u32,
|
||||
state: wl_keyboard::KeyState,
|
||||
utf8: Option<String>)
|
||||
{
|
||||
if let Some(ref eviter) = self.target {
|
||||
let state = match state {
|
||||
wl_keyboard::KeyState::Pressed => ElementState::Pressed,
|
||||
wl_keyboard::KeyState::Released => ElementState::Released,
|
||||
};
|
||||
let vkcode = key_to_vkey(rawkey, keysym);
|
||||
let mut guard = eviter.lock().unwrap();
|
||||
guard.push_back(Event::KeyboardInput(state, rawkey as u8, vkcode));
|
||||
// send char event only on key press, not release
|
||||
if let ElementState::Released = state { return }
|
||||
if let Some(txt) = utf8 {
|
||||
for chr in txt.chars() {
|
||||
guard.push_back(Event::ReceivedCharacter(chr));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
pub fn keysym_to_vkey(keysym: u32) -> Option<VirtualKeyCode> {
|
||||
fn key_to_vkey(rawkey: u32, keysym: u32) -> Option<VirtualKeyCode> {
|
||||
match rawkey {
|
||||
1 => Some(VirtualKeyCode::Escape),
|
||||
2 => Some(VirtualKeyCode::Key1),
|
||||
3 => Some(VirtualKeyCode::Key2),
|
||||
4 => Some(VirtualKeyCode::Key3),
|
||||
5 => Some(VirtualKeyCode::Key4),
|
||||
6 => Some(VirtualKeyCode::Key5),
|
||||
7 => Some(VirtualKeyCode::Key6),
|
||||
8 => Some(VirtualKeyCode::Key7),
|
||||
9 => Some(VirtualKeyCode::Key8),
|
||||
10 => Some(VirtualKeyCode::Key9),
|
||||
11 => Some(VirtualKeyCode::Key0),
|
||||
_ => keysym_to_vkey(keysym)
|
||||
}
|
||||
}
|
||||
|
||||
fn keysym_to_vkey(keysym: u32) -> Option<VirtualKeyCode> {
|
||||
use super::wayland_kbd::keysyms;
|
||||
match keysym {
|
||||
// letters
|
||||
|
@ -226,4 +213,4 @@ pub fn keysym_to_vkey(keysym: u32) -> Option<VirtualKeyCode> {
|
|||
// fallback
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,12 @@
|
|||
#![cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
|
||||
|
||||
pub use self::monitor::{MonitorId, get_available_monitors, get_primary_monitor};
|
||||
pub use self::window::{PollEventsIterator, WaitEventsIterator, Window, WindowProxy};
|
||||
pub use self::context::{WaylandContext, MonitorId, get_available_monitors,
|
||||
get_primary_monitor};
|
||||
|
||||
extern crate wayland_kbd;
|
||||
extern crate wayland_window;
|
||||
|
||||
mod context;
|
||||
mod events;
|
||||
mod keyboard;
|
||||
mod monitor;
|
||||
mod window;
|
||||
|
||||
#[inline]
|
||||
pub fn is_available() -> bool {
|
||||
context::WAYLAND_CONTEXT.is_some()
|
||||
}
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
use std::collections::VecDeque;
|
||||
|
||||
use wayland_client::{ProxyId, EventIterator};
|
||||
use wayland_client::wayland::output::WlOutput;
|
||||
|
||||
use super::context::WAYLAND_CONTEXT;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MonitorId(ProxyId);
|
||||
|
||||
#[inline]
|
||||
pub fn get_available_monitors() -> VecDeque<MonitorId> {
|
||||
WAYLAND_CONTEXT.as_ref().map(|ctxt|
|
||||
ctxt.monitor_ids().into_iter().map(MonitorId).collect()
|
||||
).unwrap_or(VecDeque::new())
|
||||
}
|
||||
#[inline]
|
||||
pub fn get_primary_monitor() -> MonitorId {
|
||||
WAYLAND_CONTEXT.as_ref().and_then(|ctxt|
|
||||
ctxt.monitor_ids().into_iter().next().map(MonitorId)
|
||||
).expect("wayland: No monitor available.")
|
||||
}
|
||||
|
||||
impl MonitorId {
|
||||
pub fn get_name(&self) -> Option<String> {
|
||||
WAYLAND_CONTEXT.as_ref().and_then(|ctxt| ctxt.monitor_name(self.0))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_native_identifier(&self) -> ::native_monitor::NativeMonitorId {
|
||||
::native_monitor::NativeMonitorId::Unavailable
|
||||
}
|
||||
|
||||
pub fn get_dimensions(&self) -> (u32, u32) {
|
||||
WAYLAND_CONTEXT.as_ref().and_then(|ctxt| ctxt.monitor_dimensions(self.0)).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn proxid_from_monitorid(x: &MonitorId) -> ProxyId {
|
||||
x.0
|
||||
}
|
||||
|
||||
pub fn init_monitors(outputs: &mut Vec<(WlOutput, u32, u32, String)>, evts: EventIterator) {
|
||||
use wayland_client::{Event, Proxy};
|
||||
use wayland_client::wayland::WaylandProtocolEvent;
|
||||
use wayland_client::wayland::output::{WlOutputEvent, WlOutputMode};
|
||||
|
||||
for evt in evts {
|
||||
match evt {
|
||||
Event::Wayland(WaylandProtocolEvent::WlOutput(pid, oevt)) => match oevt {
|
||||
WlOutputEvent::Geometry(_, _, _, _, _, maker, model, _) => {
|
||||
for o in outputs.iter_mut() {
|
||||
if o.0.id() == pid {
|
||||
o.3 = format!("{} - {}", maker, model);
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
WlOutputEvent::Mode(flags, width, height, _) => {
|
||||
if flags.contains(WlOutputMode::Current) {
|
||||
for o in outputs.iter_mut() {
|
||||
if o.0.id() == pid {
|
||||
o.1 = width as u32;
|
||||
o.2 = height as u32;
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,83 +1,39 @@
|
|||
use std::collections::VecDeque;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use libc;
|
||||
use wayland_client::{EventQueue, EventQueueHandle, Init};
|
||||
use wayland_client::protocol::{wl_display,wl_surface,wl_shell_surface};
|
||||
|
||||
use {CreationError, CursorState, Event, MouseCursor, WindowAttributes};
|
||||
use {CreationError, MouseCursor, CursorState, Event, WindowAttributes};
|
||||
use platform::MonitorId as PlatformMonitorId;
|
||||
|
||||
use wayland_client::EventIterator;
|
||||
use wayland_client::wayland::compositor::WlSurface;
|
||||
use wayland_client::wayland::shell::WlShellSurface;
|
||||
use super::wayland_window::{DecoratedSurface, add_borders, substract_borders};
|
||||
use super::context::{WaylandContext, WAYLAND_CONTEXT};
|
||||
use super::WaylandContext;
|
||||
use super::wayland_window;
|
||||
use super::wayland_window::DecoratedSurface;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct WindowProxy;
|
||||
pub struct WindowProxy {
|
||||
ctxt: Arc<WaylandContext>,
|
||||
eviter: Arc<Mutex<VecDeque<Event>>>,
|
||||
}
|
||||
|
||||
impl WindowProxy {
|
||||
#[inline]
|
||||
pub fn wakeup_event_loop(&self) {
|
||||
unimplemented!()
|
||||
// Send a sync event, so that any waiting "dispatch" will return
|
||||
self.ctxt.display.sync();
|
||||
self.eviter.lock().unwrap().push_back(Event::Awakened);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Window {
|
||||
wayland_context: &'static WaylandContext,
|
||||
surface: WlSurface,
|
||||
shell_window: Mutex<ShellWindow>,
|
||||
evt_queue: Arc<Mutex<VecDeque<Event>>>,
|
||||
inner_size: Mutex<(i32, i32)>,
|
||||
resize_callback: Option<fn(u32, u32)>,
|
||||
}
|
||||
|
||||
impl Window {
|
||||
fn next_event(&self) -> Option<Event> {
|
||||
use wayland_client::Event as WEvent;
|
||||
use wayland_client::wayland::WaylandProtocolEvent;
|
||||
use wayland_client::wayland::shell::WlShellSurfaceEvent;
|
||||
|
||||
let mut newsize = None;
|
||||
let mut evt_queue_guard = self.evt_queue.lock().unwrap();
|
||||
|
||||
let mut shell_window_guard = self.shell_window.lock().unwrap();
|
||||
match *shell_window_guard {
|
||||
ShellWindow::Decorated(ref mut deco) => {
|
||||
for (_, w, h) in deco {
|
||||
newsize = Some((w, h));
|
||||
}
|
||||
},
|
||||
ShellWindow::Plain(ref plain, ref mut evtiter) => {
|
||||
for evt in evtiter {
|
||||
if let WEvent::Wayland(WaylandProtocolEvent::WlShellSurface(_, ssevt)) = evt {
|
||||
match ssevt {
|
||||
WlShellSurfaceEvent::Ping(u) => {
|
||||
plain.pong(u);
|
||||
},
|
||||
WlShellSurfaceEvent::Configure(_, w, h) => {
|
||||
newsize = Some((w, h));
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((w, h)) = newsize {
|
||||
let (w, h) = substract_borders(w, h);
|
||||
*self.inner_size.lock().unwrap() = (w, h);
|
||||
if let ShellWindow::Decorated(ref mut deco) = *shell_window_guard {
|
||||
deco.resize(w, h);
|
||||
}
|
||||
if let Some(f) = self.resize_callback {
|
||||
f(w as u32, h as u32);
|
||||
}
|
||||
Some(Event::Resized(w as u32, h as u32))
|
||||
} else {
|
||||
evt_queue_guard.pop_front()
|
||||
}
|
||||
}
|
||||
ctxt: Arc<WaylandContext>,
|
||||
evq: Mutex<EventQueue>,
|
||||
eviter: Arc<Mutex<VecDeque<Event>>>,
|
||||
surface: Arc<wl_surface::WlSurface>,
|
||||
size: Mutex<(u32, u32)>,
|
||||
handler_id: usize,
|
||||
decorated_id: usize
|
||||
}
|
||||
|
||||
pub struct PollEventsIterator<'a> {
|
||||
|
@ -88,13 +44,7 @@ impl<'a> Iterator for PollEventsIterator<'a> {
|
|||
type Item = Event;
|
||||
|
||||
fn next(&mut self) -> Option<Event> {
|
||||
match self.window.next_event() {
|
||||
Some(evt) => return Some(evt),
|
||||
None => {}
|
||||
}
|
||||
// the queue was empty, try a dispatch and see the result
|
||||
self.window.wayland_context.dispatch_events();
|
||||
return self.window.next_event();
|
||||
self.window.next_event(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,93 +56,130 @@ impl<'a> Iterator for WaitEventsIterator<'a> {
|
|||
type Item = Event;
|
||||
|
||||
fn next(&mut self) -> Option<Event> {
|
||||
loop {
|
||||
match self.window.next_event() {
|
||||
Some(evt) => return Some(evt),
|
||||
None => {}
|
||||
}
|
||||
// the queue was empty, try a dispatch & read and see the result
|
||||
self.window.wayland_context.flush_events().expect("Connexion with the wayland compositor lost.");
|
||||
match self.window.wayland_context.read_events() {
|
||||
Ok(_) => {
|
||||
// events were read or dispatch is needed, in both cases, we dispatch
|
||||
self.window.wayland_context.dispatch_events()
|
||||
}
|
||||
Err(_) => panic!("Connexion with the wayland compositor lost.")
|
||||
}
|
||||
}
|
||||
self.window.next_event(true)
|
||||
}
|
||||
}
|
||||
|
||||
enum ShellWindow {
|
||||
Plain(WlShellSurface, EventIterator),
|
||||
Decorated(DecoratedSurface)
|
||||
}
|
||||
|
||||
impl Window {
|
||||
pub fn new(window: &WindowAttributes) -> Result<Window, CreationError>
|
||||
pub fn new(ctxt: Arc<WaylandContext>, attributes: &WindowAttributes) -> Result<Window, CreationError>
|
||||
{
|
||||
use wayland_client::Proxy;
|
||||
// not implemented
|
||||
assert!(window.min_dimensions.is_none());
|
||||
assert!(window.max_dimensions.is_none());
|
||||
let (width, height) = attributes.dimensions.unwrap_or((800,600));
|
||||
|
||||
let wayland_context = match *WAYLAND_CONTEXT {
|
||||
Some(ref c) => c,
|
||||
None => return Err(CreationError::NotSupported),
|
||||
};
|
||||
let mut evq = ctxt.display.create_event_queue();
|
||||
|
||||
let (w, h) = window.dimensions.unwrap_or((800, 600));
|
||||
let (surface, eviter, decorated) = ctxt.create_window::<DecoratedHandler>();
|
||||
|
||||
let (surface, evt_queue) = match wayland_context.new_surface() {
|
||||
Some(t) => t,
|
||||
None => return Err(CreationError::NotSupported)
|
||||
};
|
||||
// init DecoratedSurface
|
||||
let decorated_id = evq.add_handler_with_init(decorated);
|
||||
{
|
||||
let mut state = evq.state();
|
||||
let decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(decorated_id);
|
||||
*(decorated.handler()) = Some(DecoratedHandler::new());
|
||||
|
||||
let shell_window = if let Some(PlatformMonitorId::Wayland(ref monitor_id)) = window.monitor {
|
||||
let pid = super::monitor::proxid_from_monitorid(monitor_id);
|
||||
match wayland_context.plain_from(&surface, Some(pid)) {
|
||||
Some(mut s) => {
|
||||
let iter = EventIterator::new();
|
||||
s.set_evt_iterator(&iter);
|
||||
ShellWindow::Plain(s, iter)
|
||||
},
|
||||
None => return Err(CreationError::NotSupported)
|
||||
if let Some(PlatformMonitorId::Wayland(ref monitor_id)) = attributes.monitor {
|
||||
ctxt.with_output(monitor_id.clone(), |output| {
|
||||
decorated.set_fullscreen(
|
||||
wl_shell_surface::FullscreenMethod::Default,
|
||||
0,
|
||||
Some(output)
|
||||
)
|
||||
});
|
||||
} else if attributes.decorations {
|
||||
decorated.set_decorate(true);
|
||||
}
|
||||
} else if window.decorations {
|
||||
match wayland_context.decorated_from(&surface, w as i32, h as i32) {
|
||||
Some(s) => ShellWindow::Decorated(s),
|
||||
None => return Err(CreationError::NotSupported)
|
||||
}
|
||||
} else {
|
||||
match wayland_context.plain_from(&surface, None) {
|
||||
Some(mut s) => {
|
||||
let iter = EventIterator::new();
|
||||
s.set_evt_iterator(&iter);
|
||||
ShellWindow::Plain(s, iter)
|
||||
},
|
||||
None => return Err(CreationError::NotSupported)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// init general handler
|
||||
let handler = WindowHandler::new();
|
||||
let handler_id = evq.add_handler_with_init(handler);
|
||||
|
||||
Ok(Window {
|
||||
wayland_context: wayland_context,
|
||||
ctxt: ctxt,
|
||||
evq: Mutex::new(evq),
|
||||
eviter: eviter,
|
||||
surface: surface,
|
||||
shell_window: Mutex::new(shell_window),
|
||||
evt_queue: evt_queue,
|
||||
inner_size: Mutex::new((w as i32, h as i32)),
|
||||
resize_callback: None,
|
||||
size: Mutex::new((width, height)),
|
||||
handler_id: handler_id,
|
||||
decorated_id: decorated_id
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_title(&self, title: &str) {
|
||||
let guard = self.shell_window.lock().unwrap();
|
||||
match *guard {
|
||||
ShellWindow::Plain(ref plain, _) => { plain.set_title(title.into()); },
|
||||
ShellWindow::Decorated(ref deco) => { deco.set_title(title.into()); }
|
||||
fn process_resize(&self) {
|
||||
use std::cmp::max;
|
||||
let mut evq_guard = self.evq.lock().unwrap();
|
||||
let mut state = evq_guard.state();
|
||||
let newsize = {
|
||||
let decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(self.decorated_id);
|
||||
let newsize = decorated.handler().as_mut().and_then(|h| h.take_newsize());
|
||||
if let Some((w, h)) = newsize {
|
||||
decorated.resize(w as i32, h as i32);
|
||||
*self.size.lock().unwrap() = (w, h);
|
||||
}
|
||||
newsize
|
||||
};
|
||||
// callback_resize if any
|
||||
if let Some((w, h)) = newsize {
|
||||
let mut handler = state.get_mut_handler::<WindowHandler>(self.handler_id);
|
||||
if let Some(ref callback) = handler.resize_callback {
|
||||
callback(w, h);
|
||||
}
|
||||
self.eviter.lock().unwrap().push_back(Event::Resized(w,h));
|
||||
}
|
||||
}
|
||||
|
||||
fn next_event(&self, block: bool) -> Option<Event> {
|
||||
let mut evt = {
|
||||
let mut guard = self.eviter.lock().unwrap();
|
||||
guard.pop_front()
|
||||
};
|
||||
if evt.is_some() { return evt }
|
||||
|
||||
// There is no event in the queue, we need to fetch more
|
||||
|
||||
// flush the display
|
||||
self.ctxt.flush();
|
||||
|
||||
// read some events if some are waiting & queue is empty
|
||||
if let Some(guard) = self.evq.lock().unwrap().prepare_read() {
|
||||
guard.read_events();
|
||||
}
|
||||
|
||||
// try a pending dispatch
|
||||
{
|
||||
self.ctxt.dispatch_pending();
|
||||
self.evq.lock().unwrap().dispatch_pending();
|
||||
// some events were dispatched, need to process a potential resising
|
||||
self.process_resize();
|
||||
}
|
||||
|
||||
let mut evt = {
|
||||
let mut guard = self.eviter.lock().unwrap();
|
||||
guard.pop_front()
|
||||
};
|
||||
|
||||
while block && evt.is_none() {
|
||||
// no event waiting, need to repopulate!
|
||||
{
|
||||
self.ctxt.flush();
|
||||
self.ctxt.dispatch();
|
||||
self.evq.lock().unwrap().dispatch_pending();
|
||||
// some events were dispatched, need to process a potential resising
|
||||
self.process_resize();
|
||||
}
|
||||
// try again
|
||||
let mut guard = self.eviter.lock().unwrap();
|
||||
evt = guard.pop_front();
|
||||
}
|
||||
evt
|
||||
}
|
||||
|
||||
pub fn set_title(&self, title: &str) {
|
||||
let mut guard = self.evq.lock().unwrap();
|
||||
let mut state = guard.state();
|
||||
let mut decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(self.decorated_id);
|
||||
decorated.set_title(title.into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn show(&self) {
|
||||
// TODO
|
||||
|
@ -215,29 +202,31 @@ impl Window {
|
|||
}
|
||||
|
||||
pub fn get_inner_size(&self) -> Option<(u32, u32)> {
|
||||
let (w, h) = *self.inner_size.lock().unwrap();
|
||||
Some((w as u32, h as u32))
|
||||
Some(self.size.lock().unwrap().clone())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_outer_size(&self) -> Option<(u32, u32)> {
|
||||
let (w, h) = *self.inner_size.lock().unwrap();
|
||||
let (w, h) = add_borders(w, h);
|
||||
let (w, h) = self.size.lock().unwrap().clone();
|
||||
let (w, h) = super::wayland_window::add_borders(w as i32, h as i32);
|
||||
Some((w as u32, h as u32))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
// NOTE: This will only resize the borders, the contents must be updated by the user
|
||||
pub fn set_inner_size(&self, x: u32, y: u32) {
|
||||
let mut guard = self.shell_window.lock().unwrap();
|
||||
match *guard {
|
||||
ShellWindow::Decorated(ref mut deco) => { deco.resize(x as i32, y as i32); },
|
||||
_ => {}
|
||||
}
|
||||
let mut guard = self.evq.lock().unwrap();
|
||||
let mut state = guard.state();
|
||||
let mut decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(self.decorated_id);
|
||||
decorated.resize(x as i32, y as i32);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn create_window_proxy(&self) -> WindowProxy {
|
||||
WindowProxy
|
||||
WindowProxy {
|
||||
ctxt: self.ctxt.clone(),
|
||||
eviter: self.eviter.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -256,7 +245,10 @@ impl Window {
|
|||
|
||||
#[inline]
|
||||
pub fn set_window_resize_callback(&mut self, callback: Option<fn(u32, u32)>) {
|
||||
self.resize_callback = callback;
|
||||
let mut guard = self.evq.lock().unwrap();
|
||||
let mut state = guard.state();
|
||||
let mut handler = state.get_mut_handler::<WindowHandler>(self.handler_id);
|
||||
handler.resize_callback = callback;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -277,6 +269,7 @@ impl Window {
|
|||
|
||||
#[inline]
|
||||
pub fn hidpi_factor(&self) -> f32 {
|
||||
// TODO
|
||||
1.0
|
||||
}
|
||||
|
||||
|
@ -285,35 +278,61 @@ impl Window {
|
|||
// TODO: not yet possible on wayland
|
||||
Err(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_wayland_display(&self) -> *mut libc::c_void {
|
||||
WAYLAND_CONTEXT.as_ref().unwrap() // context exists if window was created
|
||||
.display_ptr() as *mut libc::c_void
|
||||
|
||||
pub fn get_display(&self) -> &wl_display::WlDisplay {
|
||||
&self.ctxt.display
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_wayland_surface(&self) -> *mut libc::c_void {
|
||||
use wayland_client::Proxy;
|
||||
self.surface.ptr() as *mut libc::c_void
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn platform_display(&self) -> *mut libc::c_void {
|
||||
WAYLAND_CONTEXT.as_ref().unwrap() // context exists if window was created
|
||||
.display_ptr() as *mut libc::c_void
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn platform_window(&self) -> *mut libc::c_void {
|
||||
use wayland_client::Proxy;
|
||||
self.surface.ptr() as *mut libc::c_void
|
||||
|
||||
pub fn get_surface(&self) -> &wl_surface::WlSurface {
|
||||
&self.surface
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Window {
|
||||
fn drop(&mut self) {
|
||||
use wayland_client::Proxy;
|
||||
self.wayland_context.dropped_surface(self.surface.id());
|
||||
self.surface.destroy();
|
||||
self.ctxt.prune_dead_windows();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct DecoratedHandler {
|
||||
newsize: Option<(u32, u32)>
|
||||
}
|
||||
|
||||
impl DecoratedHandler {
|
||||
fn new() -> DecoratedHandler { DecoratedHandler { newsize: None }}
|
||||
fn take_newsize(&mut self) -> Option<(u32, u32)> {
|
||||
self.newsize.take()
|
||||
}
|
||||
}
|
||||
|
||||
impl wayland_window::Handler for DecoratedHandler {
|
||||
fn configure(&mut self,
|
||||
_: &mut EventQueueHandle,
|
||||
_: wl_shell_surface::Resize,
|
||||
width: i32, height: i32)
|
||||
{
|
||||
use std::cmp::max;
|
||||
self.newsize = Some((max(width,1) as u32, max(height,1) as u32));
|
||||
}
|
||||
}
|
||||
|
||||
struct WindowHandler {
|
||||
my_id: usize,
|
||||
resize_callback: Option<fn(u32,u32)>,
|
||||
}
|
||||
|
||||
impl WindowHandler {
|
||||
fn new() -> WindowHandler {
|
||||
WindowHandler {
|
||||
my_id: 0,
|
||||
resize_callback: None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Init for WindowHandler {
|
||||
fn init(&mut self, evqh: &mut EventQueueHandle, index: usize) {
|
||||
self.my_id = index;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ extern crate core_graphics;
|
|||
#[cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
|
||||
extern crate x11_dl;
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd"))]
|
||||
#[macro_use(wayland_env)]
|
||||
#[macro_use(wayland_env,declare_handler)]
|
||||
extern crate wayland_client;
|
||||
|
||||
pub use events::*;
|
||||
|
|
|
@ -5,6 +5,9 @@ use Window;
|
|||
use platform::Window as LinuxWindow;
|
||||
use WindowBuilder;
|
||||
|
||||
use wayland_client::protocol::wl_display::WlDisplay;
|
||||
use wayland_client::protocol::wl_surface::WlSurface;
|
||||
|
||||
/// Additional methods on `Window` that are specific to Unix.
|
||||
pub trait WindowExt {
|
||||
/// Returns a pointer to the `Window` object of xlib that is used by this window.
|
||||
|
@ -42,6 +45,24 @@ pub trait WindowExt {
|
|||
///
|
||||
/// The pointer will become invalid when the glutin `Window` is destroyed.
|
||||
fn get_wayland_display(&self) -> Option<*mut libc::c_void>;
|
||||
|
||||
/// Returns a reference to the `WlSurface` object of wayland that is used by this window.
|
||||
///
|
||||
/// For use with the `wayland-client` crate.
|
||||
///
|
||||
/// **This function is not part of winit's public API.**
|
||||
///
|
||||
/// Returns `None` if the window doesn't use wayland (if it uses xlib for example).
|
||||
fn get_wayland_client_surface(&self) -> Option<&WlSurface>;
|
||||
|
||||
/// Returns a pointer to the `WlDisplay` object of wayland that is used by this window.
|
||||
///
|
||||
/// For use with the `wayland-client` crate.
|
||||
///
|
||||
/// **This function is not part of winit's public API.**
|
||||
///
|
||||
/// Returns `None` if the window doesn't use wayland (if it uses xlib for example).
|
||||
fn get_wayland_client_display(&self) -> Option<&WlDisplay>;
|
||||
}
|
||||
|
||||
impl WindowExt for Window {
|
||||
|
@ -70,16 +91,29 @@ impl WindowExt for Window {
|
|||
|
||||
#[inline]
|
||||
fn get_wayland_surface(&self) -> Option<*mut libc::c_void> {
|
||||
use wayland_client::Proxy;
|
||||
self.get_wayland_client_surface().map(|p| p.ptr() as *mut _)
|
||||
}
|
||||
|
||||
|
||||
#[inline]
|
||||
fn get_wayland_display(&self) -> Option<*mut libc::c_void> {
|
||||
use wayland_client::Proxy;
|
||||
self.get_wayland_client_display().map(|p| p.ptr() as *mut _)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_wayland_client_surface(&self) -> Option<&WlSurface> {
|
||||
match self.window {
|
||||
LinuxWindow::Wayland(ref w) => Some(w.get_wayland_surface()),
|
||||
LinuxWindow::Wayland(ref w) => Some(w.get_surface()),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_wayland_display(&self) -> Option<*mut libc::c_void> {
|
||||
fn get_wayland_client_display(&self) -> Option<&WlDisplay> {
|
||||
match self.window {
|
||||
LinuxWindow::Wayland(ref w) => Some(w.get_wayland_display()),
|
||||
LinuxWindow::Wayland(ref w) => Some(w.get_display()),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
/*pub use api::x11::{Window, WindowProxy, MonitorId, get_available_monitors, get_primary_monitor};
|
||||
pub use api::x11::{WaitEventsIterator, PollEventsIterator};*/
|
||||
|
||||
use std::collections::VecDeque;
|
||||
use std::sync::Arc;
|
||||
|
||||
|
@ -22,15 +19,15 @@ pub struct PlatformSpecificWindowBuilderAttributes;
|
|||
|
||||
enum Backend {
|
||||
X(Arc<XConnection>),
|
||||
Wayland,
|
||||
Wayland(Arc<wayland::WaylandContext>),
|
||||
Error(XNotSupported),
|
||||
}
|
||||
|
||||
lazy_static!(
|
||||
static ref BACKEND: Backend = {
|
||||
// Wayland backend is not production-ready yet so we disable it
|
||||
if wayland::is_available() {
|
||||
Backend::Wayland
|
||||
if let Some(ctxt) = wayland::WaylandContext::init() {
|
||||
Backend::Wayland(Arc::new(ctxt))
|
||||
} else {
|
||||
match XConnection::new(Some(x_error_callback)) {
|
||||
Ok(x) => Backend::X(Arc::new(x)),
|
||||
|
@ -78,7 +75,7 @@ pub enum MonitorId {
|
|||
#[inline]
|
||||
pub fn get_available_monitors() -> VecDeque<MonitorId> {
|
||||
match *BACKEND {
|
||||
Backend::Wayland => wayland::get_available_monitors()
|
||||
Backend::Wayland(ref ctxt) => wayland::get_available_monitors(ctxt)
|
||||
.into_iter()
|
||||
.map(MonitorId::Wayland)
|
||||
.collect(),
|
||||
|
@ -93,7 +90,7 @@ pub fn get_available_monitors() -> VecDeque<MonitorId> {
|
|||
#[inline]
|
||||
pub fn get_primary_monitor() -> MonitorId {
|
||||
match *BACKEND {
|
||||
Backend::Wayland => MonitorId::Wayland(wayland::get_primary_monitor()),
|
||||
Backend::Wayland(ref ctxt) => MonitorId::Wayland(wayland::get_primary_monitor(ctxt)),
|
||||
Backend::X(ref connec) => MonitorId::X(x11::get_primary_monitor(connec)),
|
||||
Backend::Error(_) => MonitorId::None,
|
||||
}
|
||||
|
@ -173,8 +170,8 @@ impl Window {
|
|||
-> Result<Window, CreationError>
|
||||
{
|
||||
match *BACKEND {
|
||||
Backend::Wayland => {
|
||||
wayland::Window::new(window).map(Window::Wayland)
|
||||
Backend::Wayland(ref ctxt) => {
|
||||
wayland::Window::new(ctxt.clone(), window).map(Window::Wayland)
|
||||
},
|
||||
|
||||
Backend::X(ref connec) => {
|
||||
|
@ -318,17 +315,19 @@ impl Window {
|
|||
|
||||
#[inline]
|
||||
pub fn platform_display(&self) -> *mut libc::c_void {
|
||||
use wayland_client::Proxy;
|
||||
match self {
|
||||
&Window::X(ref w) => w.platform_display(),
|
||||
&Window::Wayland(ref w) => w.platform_display()
|
||||
&Window::Wayland(ref w) => w.get_display().ptr() as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn platform_window(&self) -> *mut libc::c_void {
|
||||
use wayland_client::Proxy;
|
||||
match self {
|
||||
&Window::X(ref w) => w.platform_window(),
|
||||
&Window::Wayland(ref w) => w.platform_window()
|
||||
&Window::Wayland(ref w) => w.get_surface().ptr() as *mut _
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue