Implement DPI Usability Upgrades for X11 and Wayland (#1098)
* Fix compile errors * Use `mio` for the X11 event loop * Removes `calloop` from the X11 event loop, as the method of draining a source using a closure provided to the `calloop::EventLoop` instance conflicts with the need to deliver events directly to the callback provided to `EventLoop::run`, in order to respond to the value provided by `WindowEvent::HiDpiFactorChanged`. * Implement interactive `HiDpiFactorChanged` event for X11 * Implement interactive `HiDpiFactorChanged` event for Wayland * Run cargo fmt * Fix Wayland not processing events from EventQueue * Backport #981
This commit is contained in:
parent
6bb7db7c11
commit
7b43b0bc94
12 changed files with 563 additions and 627 deletions
|
|
@ -2,11 +2,16 @@ use std::{
|
|||
cell::RefCell,
|
||||
collections::VecDeque,
|
||||
fmt,
|
||||
io::ErrorKind,
|
||||
rc::Rc,
|
||||
sync::{Arc, Mutex},
|
||||
time::Instant,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use mio::{Events, Poll, PollOpt, Ready, Token};
|
||||
|
||||
use mio_extras::channel::{channel, Receiver, SendError, Sender};
|
||||
|
||||
use smithay_client_toolkit::reexports::protocols::unstable::pointer_constraints::v1::client::{
|
||||
zwp_locked_pointer_v1::ZwpLockedPointerV1, zwp_pointer_constraints_v1::ZwpPointerConstraintsV1,
|
||||
};
|
||||
|
|
@ -21,15 +26,17 @@ use smithay_client_toolkit::reexports::client::protocol::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
dpi::{PhysicalPosition, PhysicalSize},
|
||||
event::ModifiersState,
|
||||
dpi::{LogicalSize, PhysicalPosition, PhysicalSize},
|
||||
event::{
|
||||
DeviceEvent, DeviceId as RootDeviceId, Event, ModifiersState, StartCause, WindowEvent,
|
||||
},
|
||||
event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW},
|
||||
monitor::{MonitorHandle as RootMonitorHandle, VideoMode as RootVideoMode},
|
||||
platform_impl::platform::{
|
||||
sticky_exit_callback, MonitorHandle as PlatformMonitorHandle,
|
||||
VideoMode as PlatformVideoMode,
|
||||
sticky_exit_callback, DeviceId as PlatformDeviceId, MonitorHandle as PlatformMonitorHandle,
|
||||
VideoMode as PlatformVideoMode, WindowId as PlatformWindowId,
|
||||
},
|
||||
window::CursorIcon,
|
||||
window::{CursorIcon, WindowId as RootWindowId},
|
||||
};
|
||||
|
||||
use super::{window::WindowStore, DeviceId, WindowId};
|
||||
|
|
@ -43,43 +50,37 @@ use smithay_client_toolkit::{
|
|||
Environment,
|
||||
};
|
||||
|
||||
pub struct WindowEventsSink<T> {
|
||||
buffer: VecDeque<crate::event::Event<T>>,
|
||||
const KBD_TOKEN: Token = Token(0);
|
||||
const USER_TOKEN: Token = Token(1);
|
||||
const EVQ_TOKEN: Token = Token(2);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct EventsSink {
|
||||
sender: Sender<Event<'static, ()>>,
|
||||
}
|
||||
|
||||
impl<T> WindowEventsSink<T> {
|
||||
pub fn new() -> WindowEventsSink<T> {
|
||||
WindowEventsSink {
|
||||
buffer: VecDeque::new(),
|
||||
}
|
||||
impl EventsSink {
|
||||
pub fn new(sender: Sender<Event<'static, ()>>) -> EventsSink {
|
||||
EventsSink { sender }
|
||||
}
|
||||
|
||||
pub fn send_event(&mut self, evt: crate::event::Event<T>) {
|
||||
self.buffer.push_back(evt);
|
||||
pub fn send_event(&self, event: Event<'static, ()>) {
|
||||
self.sender.send(event).unwrap()
|
||||
}
|
||||
|
||||
pub fn send_window_event(&mut self, evt: crate::event::WindowEvent, wid: WindowId) {
|
||||
self.buffer.push_back(crate::event::Event::WindowEvent {
|
||||
event: evt,
|
||||
window_id: crate::window::WindowId(crate::platform_impl::WindowId::Wayland(wid)),
|
||||
pub fn send_device_event(&self, event: DeviceEvent, device_id: DeviceId) {
|
||||
self.send_event(Event::DeviceEvent {
|
||||
event,
|
||||
device_id: RootDeviceId(PlatformDeviceId::Wayland(device_id)),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn send_device_event(&mut self, evt: crate::event::DeviceEvent, dev_id: DeviceId) {
|
||||
self.buffer.push_back(crate::event::Event::DeviceEvent {
|
||||
event: evt,
|
||||
device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(dev_id)),
|
||||
pub fn send_window_event(&self, event: WindowEvent<'static>, window_id: WindowId) {
|
||||
self.send_event(Event::WindowEvent {
|
||||
event,
|
||||
window_id: RootWindowId(PlatformWindowId::Wayland(window_id)),
|
||||
});
|
||||
}
|
||||
|
||||
fn empty_with<F>(&mut self, mut callback: F)
|
||||
where
|
||||
F: FnMut(crate::event::Event<T>),
|
||||
{
|
||||
for evt in self.buffer.drain(..) {
|
||||
callback(evt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CursorManager {
|
||||
|
|
@ -230,21 +231,17 @@ impl CursorManager {
|
|||
}
|
||||
|
||||
pub struct EventLoop<T: 'static> {
|
||||
// The loop
|
||||
inner_loop: ::calloop::EventLoop<()>,
|
||||
// Poll instance
|
||||
poll: Poll,
|
||||
// The wayland display
|
||||
pub display: Arc<Display>,
|
||||
// The output manager
|
||||
pub outputs: OutputMgr,
|
||||
// Our sink, shared with some handlers, buffering the events
|
||||
sink: Arc<Mutex<WindowEventsSink<T>>>,
|
||||
pending_user_events: Rc<RefCell<VecDeque<T>>>,
|
||||
// The cursor manager
|
||||
cursor_manager: Arc<Mutex<CursorManager>>,
|
||||
// Utility for grabbing the cursor and changing visibility
|
||||
_user_source: ::calloop::Source<::calloop::channel::Channel<T>>,
|
||||
user_sender: ::calloop::channel::Sender<T>,
|
||||
_kbd_source: ::calloop::Source<::calloop::channel::Channel<crate::event::Event<()>>>,
|
||||
kbd_channel: Receiver<Event<'static, ()>>,
|
||||
user_channel: Receiver<T>,
|
||||
user_sender: Sender<T>,
|
||||
window_target: RootELW<T>,
|
||||
}
|
||||
|
||||
|
|
@ -252,12 +249,12 @@ pub struct EventLoop<T: 'static> {
|
|||
//
|
||||
// We should only try and wake up the `EventLoop` if it still exists, so we hold Weak ptrs.
|
||||
pub struct EventLoopProxy<T: 'static> {
|
||||
user_sender: calloop::channel::Sender<T>,
|
||||
user_sender: Sender<T>,
|
||||
}
|
||||
|
||||
pub struct EventLoopWindowTarget<T> {
|
||||
// The event queue
|
||||
pub evq: RefCell<::calloop::Source<EventQueue>>,
|
||||
// the event queue
|
||||
pub evq: RefCell<EventQueue>,
|
||||
// The window store
|
||||
pub store: Arc<Mutex<WindowStore>>,
|
||||
// The cursor manager
|
||||
|
|
@ -284,7 +281,7 @@ impl<T: 'static> Clone for EventLoopProxy<T> {
|
|||
impl<T: 'static> EventLoopProxy<T> {
|
||||
pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed<T>> {
|
||||
self.user_sender.send(event).map_err(|e| {
|
||||
EventLoopClosed(if let ::calloop::channel::SendError::Disconnected(x) = e {
|
||||
EventLoopClosed(if let SendError::Disconnected(x) = e {
|
||||
x
|
||||
} else {
|
||||
unreachable!()
|
||||
|
|
@ -298,33 +295,26 @@ impl<T: 'static> EventLoop<T> {
|
|||
let (display, mut event_queue) = Display::connect_to_env()?;
|
||||
|
||||
let display = Arc::new(display);
|
||||
let sink = Arc::new(Mutex::new(WindowEventsSink::new()));
|
||||
let store = Arc::new(Mutex::new(WindowStore::new()));
|
||||
let seats = Arc::new(Mutex::new(Vec::new()));
|
||||
|
||||
let inner_loop = ::calloop::EventLoop::new().unwrap();
|
||||
let poll = Poll::new().unwrap();
|
||||
|
||||
let (kbd_sender, kbd_channel) = ::calloop::channel::channel::<crate::event::Event<()>>();
|
||||
let kbd_sink = sink.clone();
|
||||
let kbd_source = inner_loop
|
||||
.handle()
|
||||
.insert_source(kbd_channel, move |evt, &mut ()| {
|
||||
if let ::calloop::channel::Event::Msg(evt) = evt {
|
||||
let evt = evt.map_nonuser_event().ok().unwrap();
|
||||
kbd_sink.lock().unwrap().send_event(evt);
|
||||
}
|
||||
})
|
||||
let (kbd_sender, kbd_channel) = channel();
|
||||
|
||||
let sink = EventsSink::new(kbd_sender);
|
||||
|
||||
poll.register(&kbd_channel, KBD_TOKEN, Ready::readable(), PollOpt::level())
|
||||
.unwrap();
|
||||
|
||||
let pointer_constraints_proxy = Arc::new(Mutex::new(None));
|
||||
|
||||
let mut seat_manager = SeatManager {
|
||||
sink: sink.clone(),
|
||||
relative_pointer_manager_proxy: Rc::new(RefCell::new(None)),
|
||||
pointer_constraints_proxy: pointer_constraints_proxy.clone(),
|
||||
sink,
|
||||
store: store.clone(),
|
||||
seats: seats.clone(),
|
||||
kbd_sender,
|
||||
relative_pointer_manager_proxy: Rc::new(RefCell::new(None)),
|
||||
pointer_constraints_proxy: pointer_constraints_proxy.clone(),
|
||||
cursor_manager: Arc::new(Mutex::new(CursorManager::new(pointer_constraints_proxy))),
|
||||
};
|
||||
|
||||
|
|
@ -404,39 +394,31 @@ impl<T: 'static> EventLoop<T> {
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
let source = inner_loop
|
||||
.handle()
|
||||
.insert_source(event_queue, |(), &mut ()| {})
|
||||
poll.register(&event_queue, EVQ_TOKEN, Ready::readable(), PollOpt::level())
|
||||
.unwrap();
|
||||
|
||||
let pending_user_events = Rc::new(RefCell::new(VecDeque::new()));
|
||||
let pending_user_events2 = pending_user_events.clone();
|
||||
let (user_sender, user_channel) = channel();
|
||||
|
||||
let (user_sender, user_channel) = ::calloop::channel::channel();
|
||||
|
||||
let user_source = inner_loop
|
||||
.handle()
|
||||
.insert_source(user_channel, move |evt, &mut ()| {
|
||||
if let ::calloop::channel::Event::Msg(msg) = evt {
|
||||
pending_user_events2.borrow_mut().push_back(msg);
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
poll.register(
|
||||
&user_channel,
|
||||
USER_TOKEN,
|
||||
Ready::readable(),
|
||||
PollOpt::level(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let cursor_manager_clone = cursor_manager.clone();
|
||||
Ok(EventLoop {
|
||||
inner_loop,
|
||||
sink,
|
||||
pending_user_events,
|
||||
poll,
|
||||
display: display.clone(),
|
||||
outputs: env.outputs.clone(),
|
||||
_user_source: user_source,
|
||||
user_sender,
|
||||
user_channel,
|
||||
kbd_channel,
|
||||
cursor_manager,
|
||||
_kbd_source: kbd_source,
|
||||
window_target: RootELW {
|
||||
p: crate::platform_impl::EventLoopWindowTarget::Wayland(EventLoopWindowTarget {
|
||||
evq: RefCell::new(source),
|
||||
evq: RefCell::new(event_queue),
|
||||
store,
|
||||
env,
|
||||
cursor_manager: cursor_manager_clone,
|
||||
|
|
@ -458,7 +440,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
|
||||
pub fn run<F>(mut self, callback: F) -> !
|
||||
where
|
||||
F: 'static + FnMut(crate::event::Event<T>, &RootELW<T>, &mut ControlFlow),
|
||||
F: 'static + FnMut(Event<'_, T>, &RootELW<T>, &mut ControlFlow),
|
||||
{
|
||||
self.run_return(callback);
|
||||
std::process::exit(0);
|
||||
|
|
@ -466,53 +448,60 @@ impl<T: 'static> EventLoop<T> {
|
|||
|
||||
pub fn run_return<F>(&mut self, mut callback: F)
|
||||
where
|
||||
F: FnMut(crate::event::Event<T>, &RootELW<T>, &mut ControlFlow),
|
||||
F: FnMut(Event<'_, T>, &RootELW<T>, &mut ControlFlow),
|
||||
{
|
||||
// send pending events to the server
|
||||
self.display.flush().expect("Wayland connection lost.");
|
||||
|
||||
let mut control_flow = ControlFlow::default();
|
||||
|
||||
let sink = self.sink.clone();
|
||||
let user_events = self.pending_user_events.clone();
|
||||
let mut events = Events::with_capacity(8);
|
||||
|
||||
callback(
|
||||
crate::event::Event::NewEvents(crate::event::StartCause::Init),
|
||||
Event::NewEvents(StartCause::Init),
|
||||
&self.window_target,
|
||||
&mut control_flow,
|
||||
);
|
||||
|
||||
loop {
|
||||
self.post_dispatch_triggers();
|
||||
// Read events from the event queue
|
||||
{
|
||||
let mut evq = get_target(&self.window_target).evq.borrow_mut();
|
||||
|
||||
// empty buffer of events
|
||||
{
|
||||
let mut guard = sink.lock().unwrap();
|
||||
guard.empty_with(|evt| {
|
||||
sticky_exit_callback(
|
||||
evt,
|
||||
&self.window_target,
|
||||
&mut control_flow,
|
||||
&mut callback,
|
||||
);
|
||||
});
|
||||
}
|
||||
// empty user events
|
||||
{
|
||||
let mut guard = user_events.borrow_mut();
|
||||
for evt in guard.drain(..) {
|
||||
sticky_exit_callback(
|
||||
crate::event::Event::UserEvent(evt),
|
||||
&self.window_target,
|
||||
&mut control_flow,
|
||||
&mut callback,
|
||||
);
|
||||
evq.dispatch_pending()
|
||||
.expect("failed to dispatch wayland events");
|
||||
|
||||
if let Some(read) = evq.prepare_read() {
|
||||
if let Err(e) = read.read_events() {
|
||||
if e.kind() != ErrorKind::WouldBlock {
|
||||
panic!("failed to read wayland events: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
evq.dispatch_pending()
|
||||
.expect("failed to dispatch wayland events");
|
||||
}
|
||||
}
|
||||
|
||||
self.post_dispatch_triggers(&mut callback, &mut control_flow);
|
||||
|
||||
while let Ok(event) = self.kbd_channel.try_recv() {
|
||||
let event = event.map_nonuser_event().unwrap();
|
||||
sticky_exit_callback(event, &self.window_target, &mut control_flow, &mut callback);
|
||||
}
|
||||
|
||||
while let Ok(event) = self.user_channel.try_recv() {
|
||||
sticky_exit_callback(
|
||||
Event::UserEvent(event),
|
||||
&self.window_target,
|
||||
&mut control_flow,
|
||||
&mut callback,
|
||||
);
|
||||
}
|
||||
|
||||
// send Events cleared
|
||||
{
|
||||
sticky_exit_callback(
|
||||
crate::event::Event::MainEventsCleared,
|
||||
Event::MainEventsCleared,
|
||||
&self.window_target,
|
||||
&mut control_flow,
|
||||
&mut callback,
|
||||
|
|
@ -523,7 +512,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
{
|
||||
self.redraw_triggers(|wid, window_target| {
|
||||
sticky_exit_callback(
|
||||
crate::event::Event::RedrawRequested(crate::window::WindowId(
|
||||
Event::RedrawRequested(crate::window::WindowId(
|
||||
crate::platform_impl::WindowId::Wayland(wid),
|
||||
)),
|
||||
window_target,
|
||||
|
|
@ -536,7 +525,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
// send RedrawEventsCleared
|
||||
{
|
||||
sticky_exit_callback(
|
||||
crate::event::Event::RedrawEventsCleared,
|
||||
Event::RedrawEventsCleared,
|
||||
&self.window_target,
|
||||
&mut control_flow,
|
||||
&mut callback,
|
||||
|
|
@ -569,24 +558,25 @@ impl<T: 'static> EventLoop<T> {
|
|||
ControlFlow::Exit => break,
|
||||
ControlFlow::Poll => {
|
||||
// non-blocking dispatch
|
||||
self.inner_loop
|
||||
.dispatch(Some(::std::time::Duration::from_millis(0)), &mut ())
|
||||
self.poll
|
||||
.poll(&mut events, Some(Duration::from_millis(0)))
|
||||
.unwrap();
|
||||
events.clear();
|
||||
|
||||
callback(
|
||||
crate::event::Event::NewEvents(crate::event::StartCause::Poll),
|
||||
Event::NewEvents(StartCause::Poll),
|
||||
&self.window_target,
|
||||
&mut control_flow,
|
||||
);
|
||||
}
|
||||
ControlFlow::Wait => {
|
||||
let timeout = if instant_wakeup {
|
||||
Some(::std::time::Duration::from_millis(0))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
self.inner_loop.dispatch(timeout, &mut ()).unwrap();
|
||||
if !instant_wakeup {
|
||||
self.poll.poll(&mut events, None).unwrap();
|
||||
events.clear();
|
||||
}
|
||||
|
||||
callback(
|
||||
crate::event::Event::NewEvents(crate::event::StartCause::WaitCancelled {
|
||||
Event::NewEvents(StartCause::WaitCancelled {
|
||||
start: Instant::now(),
|
||||
requested_resume: None,
|
||||
}),
|
||||
|
|
@ -600,29 +590,27 @@ impl<T: 'static> EventLoop<T> {
|
|||
let duration = if deadline > start && !instant_wakeup {
|
||||
deadline - start
|
||||
} else {
|
||||
::std::time::Duration::from_millis(0)
|
||||
Duration::from_millis(0)
|
||||
};
|
||||
self.inner_loop.dispatch(Some(duration), &mut ()).unwrap();
|
||||
self.poll.poll(&mut events, Some(duration)).unwrap();
|
||||
events.clear();
|
||||
|
||||
let now = Instant::now();
|
||||
if now < deadline {
|
||||
callback(
|
||||
crate::event::Event::NewEvents(
|
||||
crate::event::StartCause::WaitCancelled {
|
||||
start,
|
||||
requested_resume: Some(deadline),
|
||||
},
|
||||
),
|
||||
Event::NewEvents(StartCause::WaitCancelled {
|
||||
start,
|
||||
requested_resume: Some(deadline),
|
||||
}),
|
||||
&self.window_target,
|
||||
&mut control_flow,
|
||||
);
|
||||
} else {
|
||||
callback(
|
||||
crate::event::Event::NewEvents(
|
||||
crate::event::StartCause::ResumeTimeReached {
|
||||
start,
|
||||
requested_resume: deadline,
|
||||
},
|
||||
),
|
||||
Event::NewEvents(StartCause::ResumeTimeReached {
|
||||
start,
|
||||
requested_resume: deadline,
|
||||
}),
|
||||
&self.window_target,
|
||||
&mut control_flow,
|
||||
);
|
||||
|
|
@ -631,11 +619,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
}
|
||||
}
|
||||
|
||||
callback(
|
||||
crate::event::Event::LoopDestroyed,
|
||||
&self.window_target,
|
||||
&mut control_flow,
|
||||
);
|
||||
callback(Event::LoopDestroyed, &self.window_target, &mut control_flow);
|
||||
}
|
||||
|
||||
pub fn primary_monitor(&self) -> MonitorHandle {
|
||||
|
|
@ -687,12 +671,19 @@ impl<T> EventLoop<T> {
|
|||
)
|
||||
}
|
||||
|
||||
fn post_dispatch_triggers(&mut self) {
|
||||
let mut sink = self.sink.lock().unwrap();
|
||||
fn post_dispatch_triggers<F>(&mut self, mut callback: F, control_flow: &mut ControlFlow)
|
||||
where
|
||||
F: FnMut(Event<'_, T>, &RootELW<T>, &mut ControlFlow),
|
||||
{
|
||||
let window_target = match self.window_target.p {
|
||||
crate::platform_impl::EventLoopWindowTarget::Wayland(ref wt) => wt,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let mut callback = |event: Event<'_, T>| {
|
||||
sticky_exit_callback(event, &self.window_target, control_flow, &mut callback);
|
||||
};
|
||||
|
||||
// prune possible dead windows
|
||||
{
|
||||
let mut cleanup_needed = window_target.cleanup_needed.lock().unwrap();
|
||||
|
|
@ -700,41 +691,67 @@ impl<T> EventLoop<T> {
|
|||
let pruned = window_target.store.lock().unwrap().cleanup();
|
||||
*cleanup_needed = false;
|
||||
for wid in pruned {
|
||||
sink.send_window_event(crate::event::WindowEvent::Destroyed, wid);
|
||||
callback(Event::WindowEvent {
|
||||
window_id: crate::window::WindowId(
|
||||
crate::platform_impl::WindowId::Wayland(wid),
|
||||
),
|
||||
event: WindowEvent::Destroyed,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
// process pending resize/refresh
|
||||
window_target.store.lock().unwrap().for_each(|window| {
|
||||
let window_id =
|
||||
crate::window::WindowId(crate::platform_impl::WindowId::Wayland(window.wid));
|
||||
if let Some(frame) = window.frame {
|
||||
if let Some(newsize) = window.newsize {
|
||||
let (w, h) = newsize;
|
||||
if let Some((w, h)) = window.newsize {
|
||||
// mutter (GNOME Wayland) relies on `set_geometry` to reposition window in case
|
||||
// it overlaps mutter's `bounding box`, so we can't avoid this resize call,
|
||||
// which calls `set_geometry` under the hood, for now.
|
||||
frame.resize(w, h);
|
||||
frame.refresh();
|
||||
|
||||
// Don't send resize event downstream if the new size is identical to the
|
||||
// current one.
|
||||
if newsize != *window.size {
|
||||
if (w, h) != *window.size {
|
||||
let logical_size = crate::dpi::LogicalSize::new(w as f64, h as f64);
|
||||
sink.send_window_event(
|
||||
crate::event::WindowEvent::Resized(logical_size),
|
||||
window.wid,
|
||||
);
|
||||
let physical_size = logical_size
|
||||
.to_physical(window.new_dpi.unwrap_or(window.prev_dpi) as f64);
|
||||
|
||||
callback(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::Resized(physical_size),
|
||||
});
|
||||
*window.size = (w, h);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(dpi) = window.new_dpi {
|
||||
let dpi = dpi as f64;
|
||||
let logical_size = LogicalSize::from(*window.size);
|
||||
let mut new_inner_size = Some(logical_size.to_physical(dpi));
|
||||
|
||||
callback(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::HiDpiFactorChanged {
|
||||
hidpi_factor: dpi,
|
||||
new_inner_size: &mut new_inner_size,
|
||||
},
|
||||
});
|
||||
|
||||
if let Some(new_size) = new_inner_size {
|
||||
let (w, h) = new_size.to_logical(dpi).into();
|
||||
frame.resize(w, h);
|
||||
*window.size = (w, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(dpi) = window.new_dpi {
|
||||
sink.send_window_event(
|
||||
crate::event::WindowEvent::HiDpiFactorChanged(dpi as f64),
|
||||
window.wid,
|
||||
);
|
||||
}
|
||||
if window.closed {
|
||||
sink.send_window_event(crate::event::WindowEvent::CloseRequested, window.wid);
|
||||
callback(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::CloseRequested,
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(grab_cursor) = window.grab_cursor {
|
||||
|
|
@ -749,21 +766,27 @@ impl<T> EventLoop<T> {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_target<T>(target: &RootELW<T>) -> &EventLoopWindowTarget<T> {
|
||||
match target.p {
|
||||
crate::platform_impl::EventLoopWindowTarget::Wayland(ref wt) => wt,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Wayland protocol implementations
|
||||
*/
|
||||
|
||||
struct SeatManager<T: 'static> {
|
||||
sink: Arc<Mutex<WindowEventsSink<T>>>,
|
||||
struct SeatManager {
|
||||
sink: EventsSink,
|
||||
store: Arc<Mutex<WindowStore>>,
|
||||
seats: Arc<Mutex<Vec<(u32, wl_seat::WlSeat)>>>,
|
||||
kbd_sender: ::calloop::channel::Sender<crate::event::Event<()>>,
|
||||
relative_pointer_manager_proxy: Rc<RefCell<Option<ZwpRelativePointerManagerV1>>>,
|
||||
pointer_constraints_proxy: Arc<Mutex<Option<ZwpPointerConstraintsV1>>>,
|
||||
cursor_manager: Arc<Mutex<CursorManager>>,
|
||||
}
|
||||
|
||||
impl<T: 'static> SeatManager<T> {
|
||||
impl SeatManager {
|
||||
fn add_seat(&mut self, id: u32, version: u32, registry: wl_registry::WlRegistry) {
|
||||
use std::cmp::min;
|
||||
|
||||
|
|
@ -775,7 +798,6 @@ impl<T: 'static> SeatManager<T> {
|
|||
relative_pointer_manager_proxy: self.relative_pointer_manager_proxy.clone(),
|
||||
keyboard: None,
|
||||
touch: None,
|
||||
kbd_sender: self.kbd_sender.clone(),
|
||||
modifiers_tracker: Arc::new(Mutex::new(ModifiersState::default())),
|
||||
cursor_manager: self.cursor_manager.clone(),
|
||||
};
|
||||
|
|
@ -799,10 +821,9 @@ impl<T: 'static> SeatManager<T> {
|
|||
}
|
||||
}
|
||||
|
||||
struct SeatData<T> {
|
||||
sink: Arc<Mutex<WindowEventsSink<T>>>,
|
||||
struct SeatData {
|
||||
sink: EventsSink,
|
||||
store: Arc<Mutex<WindowStore>>,
|
||||
kbd_sender: ::calloop::channel::Sender<crate::event::Event<()>>,
|
||||
pointer: Option<wl_pointer::WlPointer>,
|
||||
relative_pointer: Option<ZwpRelativePointerV1>,
|
||||
relative_pointer_manager_proxy: Rc<RefCell<Option<ZwpRelativePointerManagerV1>>>,
|
||||
|
|
@ -812,7 +833,7 @@ struct SeatData<T> {
|
|||
cursor_manager: Arc<Mutex<CursorManager>>,
|
||||
}
|
||||
|
||||
impl<T: 'static> SeatData<T> {
|
||||
impl SeatData {
|
||||
fn receive(&mut self, evt: wl_seat::Event, seat: wl_seat::WlSeat) {
|
||||
match evt {
|
||||
wl_seat::Event::Name { .. } => (),
|
||||
|
|
@ -858,7 +879,7 @@ impl<T: 'static> SeatData<T> {
|
|||
if capabilities.contains(wl_seat::Capability::Keyboard) && self.keyboard.is_none() {
|
||||
self.keyboard = Some(super::keyboard::init_keyboard(
|
||||
&seat,
|
||||
self.kbd_sender.clone(),
|
||||
self.sink.clone(),
|
||||
self.modifiers_tracker.clone(),
|
||||
))
|
||||
}
|
||||
|
|
@ -892,7 +913,7 @@ impl<T: 'static> SeatData<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for SeatData<T> {
|
||||
impl Drop for SeatData {
|
||||
fn drop(&mut self) {
|
||||
if let Some(pointer) = self.pointer.take() {
|
||||
if pointer.as_ref().version() >= 3 {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use super::{make_wid, DeviceId};
|
||||
use super::{event_loop::EventsSink, make_wid, DeviceId};
|
||||
use smithay_client_toolkit::{
|
||||
keyboard::{
|
||||
self, map_keyboard_auto_with_repeat, Event as KbEvent, KeyRepeatEvent, KeyRepeatKind,
|
||||
|
|
@ -9,12 +9,12 @@ use smithay_client_toolkit::{
|
|||
};
|
||||
|
||||
use crate::event::{
|
||||
DeviceEvent, ElementState, Event, KeyboardInput, ModifiersState, VirtualKeyCode, WindowEvent,
|
||||
DeviceEvent, ElementState, KeyboardInput, ModifiersState, VirtualKeyCode, WindowEvent,
|
||||
};
|
||||
|
||||
pub fn init_keyboard(
|
||||
seat: &wl_seat::WlSeat,
|
||||
sink: ::calloop::channel::Sender<crate::event::Event<()>>,
|
||||
sink: EventsSink,
|
||||
modifiers_tracker: Arc<Mutex<ModifiersState>>,
|
||||
) -> wl_keyboard::WlKeyboard {
|
||||
// { variables to be captured by the closures
|
||||
|
|
@ -31,22 +31,12 @@ pub fn init_keyboard(
|
|||
match evt {
|
||||
KbEvent::Enter { surface, .. } => {
|
||||
let wid = make_wid(&surface);
|
||||
my_sink
|
||||
.send(Event::WindowEvent {
|
||||
window_id: mk_root_wid(wid),
|
||||
event: WindowEvent::Focused(true),
|
||||
})
|
||||
.unwrap();
|
||||
my_sink.send_window_event(WindowEvent::Focused(true), wid);
|
||||
*target.lock().unwrap() = Some(wid);
|
||||
}
|
||||
KbEvent::Leave { surface, .. } => {
|
||||
let wid = make_wid(&surface);
|
||||
my_sink
|
||||
.send(Event::WindowEvent {
|
||||
window_id: mk_root_wid(wid),
|
||||
event: WindowEvent::Focused(false),
|
||||
})
|
||||
.unwrap();
|
||||
my_sink.send_window_event(WindowEvent::Focused(false), wid);
|
||||
*target.lock().unwrap() = None;
|
||||
}
|
||||
KbEvent::Key {
|
||||
|
|
@ -63,33 +53,28 @@ pub fn init_keyboard(
|
|||
_ => unreachable!(),
|
||||
};
|
||||
let vkcode = key_to_vkey(rawkey, keysym);
|
||||
my_sink
|
||||
.send(Event::WindowEvent {
|
||||
window_id: mk_root_wid(wid),
|
||||
event: WindowEvent::KeyboardInput {
|
||||
device_id: device_id(),
|
||||
input: KeyboardInput {
|
||||
state,
|
||||
scancode: rawkey,
|
||||
virtual_keycode: vkcode,
|
||||
modifiers: modifiers_tracker.lock().unwrap().clone(),
|
||||
},
|
||||
is_synthetic: false,
|
||||
my_sink.send_window_event(
|
||||
WindowEvent::KeyboardInput {
|
||||
device_id: crate::event::DeviceId(
|
||||
crate::platform_impl::DeviceId::Wayland(DeviceId),
|
||||
),
|
||||
input: KeyboardInput {
|
||||
state,
|
||||
scancode: rawkey,
|
||||
virtual_keycode: vkcode,
|
||||
modifiers: modifiers_tracker.lock().unwrap().clone(),
|
||||
},
|
||||
})
|
||||
.unwrap();
|
||||
is_synthetic: false,
|
||||
},
|
||||
wid,
|
||||
);
|
||||
// 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() {
|
||||
my_sink
|
||||
.send(Event::WindowEvent {
|
||||
window_id: mk_root_wid(wid),
|
||||
event: WindowEvent::ReceivedCharacter(chr),
|
||||
})
|
||||
.unwrap();
|
||||
my_sink.send_window_event(WindowEvent::ReceivedCharacter(chr), wid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -102,12 +87,7 @@ pub fn init_keyboard(
|
|||
|
||||
*modifiers_tracker.lock().unwrap() = modifiers;
|
||||
|
||||
my_sink
|
||||
.send(Event::DeviceEvent {
|
||||
device_id: device_id(),
|
||||
event: DeviceEvent::ModifiersChanged(modifiers),
|
||||
})
|
||||
.unwrap();
|
||||
my_sink.send_device_event(DeviceEvent::ModifiersChanged(modifiers), DeviceId);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -115,29 +95,24 @@ pub fn init_keyboard(
|
|||
if let Some(wid) = *repeat_target.lock().unwrap() {
|
||||
let state = ElementState::Pressed;
|
||||
let vkcode = key_to_vkey(repeat_event.rawkey, repeat_event.keysym);
|
||||
repeat_sink
|
||||
.send(Event::WindowEvent {
|
||||
window_id: mk_root_wid(wid),
|
||||
event: WindowEvent::KeyboardInput {
|
||||
device_id: device_id(),
|
||||
input: KeyboardInput {
|
||||
state,
|
||||
scancode: repeat_event.rawkey,
|
||||
virtual_keycode: vkcode,
|
||||
modifiers: my_modifiers.lock().unwrap().clone(),
|
||||
},
|
||||
is_synthetic: false,
|
||||
repeat_sink.send_window_event(
|
||||
WindowEvent::KeyboardInput {
|
||||
device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(
|
||||
DeviceId,
|
||||
)),
|
||||
input: KeyboardInput {
|
||||
state,
|
||||
scancode: repeat_event.rawkey,
|
||||
virtual_keycode: vkcode,
|
||||
modifiers: my_modifiers.lock().unwrap().clone(),
|
||||
},
|
||||
})
|
||||
.unwrap();
|
||||
is_synthetic: false,
|
||||
},
|
||||
wid,
|
||||
);
|
||||
if let Some(txt) = repeat_event.utf8 {
|
||||
for chr in txt.chars() {
|
||||
repeat_sink
|
||||
.send(Event::WindowEvent {
|
||||
window_id: mk_root_wid(wid),
|
||||
event: WindowEvent::ReceivedCharacter(chr),
|
||||
})
|
||||
.unwrap();
|
||||
repeat_sink.send_window_event(WindowEvent::ReceivedCharacter(chr), wid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -164,22 +139,12 @@ pub fn init_keyboard(
|
|||
move |evt, _| match evt {
|
||||
wl_keyboard::Event::Enter { surface, .. } => {
|
||||
let wid = make_wid(&surface);
|
||||
my_sink
|
||||
.send(Event::WindowEvent {
|
||||
window_id: mk_root_wid(wid),
|
||||
event: WindowEvent::Focused(true),
|
||||
})
|
||||
.unwrap();
|
||||
my_sink.send_window_event(WindowEvent::Focused(true), wid);
|
||||
target = Some(wid);
|
||||
}
|
||||
wl_keyboard::Event::Leave { surface, .. } => {
|
||||
let wid = make_wid(&surface);
|
||||
my_sink
|
||||
.send(Event::WindowEvent {
|
||||
window_id: mk_root_wid(wid),
|
||||
event: WindowEvent::Focused(false),
|
||||
})
|
||||
.unwrap();
|
||||
my_sink.send_window_event(WindowEvent::Focused(false), wid);
|
||||
target = None;
|
||||
}
|
||||
wl_keyboard::Event::Key { key, state, .. } => {
|
||||
|
|
@ -189,21 +154,21 @@ pub fn init_keyboard(
|
|||
wl_keyboard::KeyState::Released => ElementState::Released,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
my_sink
|
||||
.send(Event::WindowEvent {
|
||||
window_id: mk_root_wid(wid),
|
||||
event: WindowEvent::KeyboardInput {
|
||||
device_id: device_id(),
|
||||
input: KeyboardInput {
|
||||
state,
|
||||
scancode: key,
|
||||
virtual_keycode: None,
|
||||
modifiers: ModifiersState::default(),
|
||||
},
|
||||
is_synthetic: false,
|
||||
my_sink.send_window_event(
|
||||
WindowEvent::KeyboardInput {
|
||||
device_id: crate::event::DeviceId(
|
||||
crate::platform_impl::DeviceId::Wayland(DeviceId),
|
||||
),
|
||||
input: KeyboardInput {
|
||||
state,
|
||||
scancode: key,
|
||||
virtual_keycode: None,
|
||||
modifiers: ModifiersState::default(),
|
||||
},
|
||||
})
|
||||
.unwrap();
|
||||
is_synthetic: false,
|
||||
},
|
||||
wid,
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
|
|
@ -412,11 +377,3 @@ impl ModifiersState {
|
|||
m
|
||||
}
|
||||
}
|
||||
|
||||
fn device_id() -> crate::event::DeviceId {
|
||||
crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(DeviceId))
|
||||
}
|
||||
|
||||
fn mk_root_wid(wid: crate::platform_impl::wayland::WindowId) -> crate::window::WindowId {
|
||||
crate::window::WindowId(crate::platform_impl::WindowId::Wayland(wid))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,7 @@
|
|||
target_os = "netbsd", target_os = "openbsd"))]
|
||||
|
||||
pub use self::{
|
||||
event_loop::{
|
||||
EventLoop, EventLoopProxy, EventLoopWindowTarget, MonitorHandle, VideoMode,
|
||||
WindowEventsSink,
|
||||
},
|
||||
event_loop::{EventLoop, EventLoopProxy, EventLoopWindowTarget, MonitorHandle, VideoMode},
|
||||
window::Window,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use crate::event::{
|
|||
};
|
||||
|
||||
use super::{
|
||||
event_loop::{CursorManager, WindowEventsSink},
|
||||
event_loop::{CursorManager, EventsSink},
|
||||
window::WindowStore,
|
||||
DeviceId,
|
||||
};
|
||||
|
|
@ -28,9 +28,9 @@ use smithay_client_toolkit::reexports::protocols::unstable::pointer_constraints:
|
|||
|
||||
use smithay_client_toolkit::reexports::client::protocol::wl_surface::WlSurface;
|
||||
|
||||
pub fn implement_pointer<T: 'static>(
|
||||
pub fn implement_pointer(
|
||||
seat: &wl_seat::WlSeat,
|
||||
sink: Arc<Mutex<WindowEventsSink<T>>>,
|
||||
sink: EventsSink,
|
||||
store: Arc<Mutex<WindowStore>>,
|
||||
modifiers_tracker: Arc<Mutex<ModifiersState>>,
|
||||
cursor_manager: Arc<Mutex<CursorManager>>,
|
||||
|
|
@ -43,7 +43,6 @@ pub fn implement_pointer<T: 'static>(
|
|||
|
||||
pointer.implement_closure(
|
||||
move |evt, pointer| {
|
||||
let mut sink = sink.lock().unwrap();
|
||||
let store = store.lock().unwrap();
|
||||
let mut cursor_manager = cursor_manager.lock().unwrap();
|
||||
match evt {
|
||||
|
|
@ -242,20 +241,18 @@ pub fn implement_pointer<T: 'static>(
|
|||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn implement_relative_pointer<T: 'static>(
|
||||
sink: Arc<Mutex<WindowEventsSink<T>>>,
|
||||
pub fn implement_relative_pointer(
|
||||
sink: EventsSink,
|
||||
pointer: &WlPointer,
|
||||
manager: &ZwpRelativePointerManagerV1,
|
||||
) -> Result<ZwpRelativePointerV1, ()> {
|
||||
manager.get_relative_pointer(pointer, |rel_pointer| {
|
||||
rel_pointer.implement_closure(
|
||||
move |evt, _rel_pointer| {
|
||||
let mut sink = sink.lock().unwrap();
|
||||
match evt {
|
||||
Event::RelativeMotion { dx, dy, .. } => sink
|
||||
.send_device_event(DeviceEvent::MouseMotion { delta: (dx, dy) }, DeviceId),
|
||||
_ => unreachable!(),
|
||||
move |evt, _rel_pointer| match evt {
|
||||
Event::RelativeMotion { dx, dy, .. } => {
|
||||
sink.send_device_event(DeviceEvent::MouseMotion { delta: (dx, dy) }, DeviceId)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
},
|
||||
(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::sync::{Arc, Mutex};
|
|||
|
||||
use crate::event::{TouchPhase, WindowEvent};
|
||||
|
||||
use super::{event_loop::WindowEventsSink, window::WindowStore, DeviceId, WindowId};
|
||||
use super::{event_loop::EventsSink, window::WindowStore, DeviceId, WindowId};
|
||||
|
||||
use smithay_client_toolkit::reexports::client::protocol::{
|
||||
wl_seat,
|
||||
|
|
@ -15,16 +15,15 @@ struct TouchPoint {
|
|||
id: i32,
|
||||
}
|
||||
|
||||
pub(crate) fn implement_touch<T: 'static>(
|
||||
pub(crate) fn implement_touch(
|
||||
seat: &wl_seat::WlSeat,
|
||||
sink: Arc<Mutex<WindowEventsSink<T>>>,
|
||||
sink: EventsSink,
|
||||
store: Arc<Mutex<WindowStore>>,
|
||||
) -> WlTouch {
|
||||
let mut pending_ids = Vec::new();
|
||||
seat.get_touch(|touch| {
|
||||
touch.implement_closure(
|
||||
move |evt, _| {
|
||||
let mut sink = sink.lock().unwrap();
|
||||
let store = store.lock().unwrap();
|
||||
match evt {
|
||||
TouchEvent::Down {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use std::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
dpi::{LogicalPosition, LogicalSize},
|
||||
dpi::{LogicalSize, PhysicalPosition, PhysicalSize, Position, Size},
|
||||
error::{ExternalError, NotSupportedError, OsError as RootOsError},
|
||||
monitor::MonitorHandle as RootMonitorHandle,
|
||||
platform_impl::{
|
||||
|
|
@ -49,11 +49,7 @@ impl Window {
|
|||
attributes: WindowAttributes,
|
||||
pl_attribs: PlAttributes,
|
||||
) -> Result<Window, RootOsError> {
|
||||
let (width, height) = attributes.inner_size.map(Into::into).unwrap_or((800, 600));
|
||||
// Create the window
|
||||
let size = Arc::new(Mutex::new((width, height)));
|
||||
let fullscreen = Arc::new(Mutex::new(false));
|
||||
|
||||
// Create the surface first to get initial DPI
|
||||
let window_store = evlp.store.clone();
|
||||
let cursor_manager = evlp.cursor_manager.clone();
|
||||
let surface = evlp.env.create_surface(move |dpi, surface| {
|
||||
|
|
@ -61,7 +57,18 @@ impl Window {
|
|||
surface.set_buffer_scale(dpi);
|
||||
});
|
||||
|
||||
let dpi = get_dpi_factor(&surface) as f64;
|
||||
let (width, height) = attributes
|
||||
.inner_size
|
||||
.map(|size| size.to_logical(dpi).into())
|
||||
.unwrap_or((800, 600));
|
||||
|
||||
// Create the window
|
||||
let size = Arc::new(Mutex::new((width, height)));
|
||||
let fullscreen = Arc::new(Mutex::new(false));
|
||||
|
||||
let window_store = evlp.store.clone();
|
||||
|
||||
let my_surface = surface.clone();
|
||||
let mut frame = SWindow::<ConceptFrame>::init_from_env(
|
||||
&evlp.env,
|
||||
|
|
@ -137,8 +144,16 @@ impl Window {
|
|||
frame.set_title(attributes.title);
|
||||
|
||||
// min-max dimensions
|
||||
frame.set_min_size(attributes.min_inner_size.map(Into::into));
|
||||
frame.set_max_size(attributes.max_inner_size.map(Into::into));
|
||||
frame.set_min_size(
|
||||
attributes
|
||||
.min_inner_size
|
||||
.map(|size| size.to_logical(dpi).into()),
|
||||
);
|
||||
frame.set_max_size(
|
||||
attributes
|
||||
.max_inner_size
|
||||
.map(|size| size.to_logical(dpi).into()),
|
||||
);
|
||||
|
||||
let kill_switch = Arc::new(Mutex::new(false));
|
||||
let need_frame_refresh = Arc::new(Mutex::new(true));
|
||||
|
|
@ -191,22 +206,24 @@ impl Window {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn outer_position(&self) -> Result<LogicalPosition, NotSupportedError> {
|
||||
pub fn outer_position(&self) -> Result<PhysicalPosition, NotSupportedError> {
|
||||
Err(NotSupportedError::new())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn inner_position(&self) -> Result<LogicalPosition, NotSupportedError> {
|
||||
pub fn inner_position(&self) -> Result<PhysicalPosition, NotSupportedError> {
|
||||
Err(NotSupportedError::new())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_outer_position(&self, _pos: LogicalPosition) {
|
||||
pub fn set_outer_position(&self, _pos: Position) {
|
||||
// Not possible with wayland
|
||||
}
|
||||
|
||||
pub fn inner_size(&self) -> LogicalSize {
|
||||
self.size.lock().unwrap().clone().into()
|
||||
pub fn inner_size(&self) -> PhysicalSize {
|
||||
let dpi = self.hidpi_factor() as f64;
|
||||
let size = LogicalSize::from(*self.size.lock().unwrap());
|
||||
size.to_physical(dpi)
|
||||
}
|
||||
|
||||
pub fn request_redraw(&self) {
|
||||
|
|
@ -214,34 +231,39 @@ impl Window {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn outer_size(&self) -> LogicalSize {
|
||||
pub fn outer_size(&self) -> PhysicalSize {
|
||||
let dpi = self.hidpi_factor() as f64;
|
||||
let (w, h) = self.size.lock().unwrap().clone();
|
||||
// let (w, h) = super::wayland_window::add_borders(w as i32, h as i32);
|
||||
(w, h).into()
|
||||
let size = LogicalSize::from((w, h));
|
||||
size.to_physical(dpi)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
// NOTE: This will only resize the borders, the contents must be updated by the user
|
||||
pub fn set_inner_size(&self, size: LogicalSize) {
|
||||
let (w, h) = size.into();
|
||||
pub fn set_inner_size(&self, size: Size) {
|
||||
let dpi = self.hidpi_factor() as f64;
|
||||
let (w, h) = size.to_logical(dpi).into();
|
||||
self.frame.lock().unwrap().resize(w, h);
|
||||
*(self.size.lock().unwrap()) = (w, h);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_min_inner_size(&self, dimensions: Option<LogicalSize>) {
|
||||
pub fn set_min_inner_size(&self, dimensions: Option<Size>) {
|
||||
let dpi = self.hidpi_factor() as f64;
|
||||
self.frame
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_min_size(dimensions.map(Into::into));
|
||||
.set_min_size(dimensions.map(|dim| dim.to_logical(dpi).into()));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_max_inner_size(&self, dimensions: Option<LogicalSize>) {
|
||||
pub fn set_max_inner_size(&self, dimensions: Option<Size>) {
|
||||
let dpi = self.hidpi_factor() as f64;
|
||||
self.frame
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_max_size(dimensions.map(Into::into));
|
||||
.set_max_size(dimensions.map(|dim| dim.to_logical(dpi).into()));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -325,7 +347,7 @@ impl Window {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_cursor_position(&self, _pos: LogicalPosition) -> Result<(), ExternalError> {
|
||||
pub fn set_cursor_position(&self, _pos: Position) -> Result<(), ExternalError> {
|
||||
Err(ExternalError::NotSupported(NotSupportedError::new()))
|
||||
}
|
||||
|
||||
|
|
@ -375,6 +397,7 @@ impl Drop for Window {
|
|||
|
||||
struct InternalWindow {
|
||||
surface: wl_surface::WlSurface,
|
||||
// TODO: CONVERT TO LogicalSize<u32>s
|
||||
newsize: Option<(u32, u32)>,
|
||||
size: Arc<Mutex<(u32, u32)>>,
|
||||
need_refresh: Arc<Mutex<bool>>,
|
||||
|
|
@ -395,6 +418,7 @@ pub struct WindowStore {
|
|||
pub struct WindowStoreForEach<'a> {
|
||||
pub newsize: Option<(u32, u32)>,
|
||||
pub size: &'a mut (u32, u32),
|
||||
pub prev_dpi: i32,
|
||||
pub new_dpi: Option<i32>,
|
||||
pub closed: bool,
|
||||
pub grab_cursor: Option<bool>,
|
||||
|
|
@ -460,6 +484,7 @@ impl WindowStore {
|
|||
f(WindowStoreForEach {
|
||||
newsize: window.newsize.take(),
|
||||
size: &mut *(window.size.lock().unwrap()),
|
||||
prev_dpi: window.current_dpi,
|
||||
new_dpi: window.new_dpi,
|
||||
closed: window.closed,
|
||||
grab_cursor: window.cursor_grab_changed.lock().unwrap().take(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue