Update smithay-client-toolkit to 'v0.15.0'

This commit also drops 'Theme' trait with its support types
in favor of 'FallbackFrame' meaning that winit will use some
predefined frame for the time being, since porting 'ConceptFrame'
will require adding font rendering librarires right into winit,
which is not desired.

Fixes #1889.
This commit is contained in:
Kirill Chibisov 2021-08-15 22:31:59 +03:00 committed by GitHub
parent ceab0f8c40
commit c9520deef8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 116 additions and 346 deletions

View file

@ -9,6 +9,9 @@
- On Windows, prevent ghost window from showing up in the taskbar after either several hours of use or restarting `explorer.exe`. - On Windows, prevent ghost window from showing up in the taskbar after either several hours of use or restarting `explorer.exe`.
- On macOS, fix issue where `ReceivedCharacter` was not being emitted during some key repeat events. - On macOS, fix issue where `ReceivedCharacter` was not being emitted during some key repeat events.
- On Wayland, load cursor icons `hand2` and `hand1` for `CursorIcon::Hand`. - On Wayland, load cursor icons `hand2` and `hand1` for `CursorIcon::Hand`.
- **Breaking:** On Wayland, Theme trait and its support types are dropped.
- On Wayland, bump `smithay-client-toolkit` to 0.15.
# 0.25.0 (2021-05-15) # 0.25.0 (2021-05-15)

View file

@ -84,7 +84,7 @@ features = [
[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies] [target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies]
wayland-client = { version = "0.28", features = [ "dlopen"] , optional = true } wayland-client = { version = "0.28", features = [ "dlopen"] , optional = true }
sctk = { package = "smithay-client-toolkit", version = "0.12.3", optional = true } sctk = { package = "smithay-client-toolkit", version = "0.15.0", optional = true }
mio = { version = "0.7", features = ["os-ext"], optional = true } mio = { version = "0.7", features = ["os-ext"], optional = true }
mio-misc = { version = "1.0", optional = true } mio-misc = { version = "1.0", optional = true }
x11-dl = { version = "2.18.5", optional = true } x11-dl = { version = "2.18.5", optional = true }

View file

@ -237,10 +237,6 @@ pub trait WindowExtUnix {
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
fn wayland_display(&self) -> Option<*mut raw::c_void>; fn wayland_display(&self) -> Option<*mut raw::c_void>;
/// Sets the color theme of the client side window decorations on wayland
#[cfg(feature = "wayland")]
fn set_wayland_theme<T: Theme>(&self, theme: T);
/// Check if the window is ready for drawing /// Check if the window is ready for drawing
/// ///
/// It is a remnant of a previous implementation detail for the /// It is a remnant of a previous implementation detail for the
@ -323,16 +319,6 @@ impl WindowExtUnix for Window {
} }
} }
#[inline]
#[cfg(feature = "wayland")]
fn set_wayland_theme<T: Theme>(&self, theme: T) {
match self.window {
LinuxWindow::Wayland(ref w) => w.set_theme(theme),
#[cfg(feature = "x11")]
_ => {}
}
}
#[inline] #[inline]
fn is_ready(&self) -> bool { fn is_ready(&self) -> bool {
true true
@ -454,78 +440,3 @@ impl MonitorHandleExtUnix for MonitorHandle {
self.inner.native_identifier() self.inner.native_identifier()
} }
} }
/// A theme for a Wayland's client side decorations.
#[cfg(feature = "wayland")]
pub trait Theme: Send + 'static {
/// Title bar color.
fn element_color(&self, element: Element, window_active: bool) -> ARGBColor;
/// Color for a given button part.
fn button_color(
&self,
button: Button,
state: ButtonState,
foreground: bool,
window_active: bool,
) -> ARGBColor;
/// Font name and the size for the title bar.
///
/// By default the font is `sans-serif` at the size of 17.
///
/// Returning `None` means that title won't be drawn.
fn font(&self) -> Option<(String, f32)> {
// Not having any title isn't something desirable for the users, so setting it to
// something generic.
Some((String::from("sans-serif"), 17.))
}
}
/// A button on Wayland's client side decorations.
#[cfg(feature = "wayland")]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Button {
/// Button that maximizes the window.
Maximize,
/// Button that minimizes the window.
Minimize,
/// Button that closes the window.
Close,
}
/// A button state of the button on Wayland's client side decorations.
#[cfg(feature = "wayland")]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ButtonState {
/// Button is being hovered over by pointer.
Hovered,
/// Button is not being hovered over by pointer.
Idle,
/// Button is disabled.
Disabled,
}
#[cfg(feature = "wayland")]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Element {
/// Bar itself.
Bar,
/// Separator between window and title bar.
Separator,
/// Title bar text.
Text,
}
#[cfg(feature = "wayland")]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ARGBColor {
pub a: u8,
pub r: u8,
pub g: u8,
pub b: u8,
}

View file

@ -407,7 +407,7 @@ impl Window {
pub fn set_always_on_top(&self, _always_on_top: bool) { pub fn set_always_on_top(&self, _always_on_top: bool) {
match self { match self {
#[cfg(feature = "x11")] #[cfg(feature = "x11")]
&Window::X(ref w) => w.set_always_on_top(_always_on_top), Window::X(ref w) => w.set_always_on_top(_always_on_top),
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
_ => (), _ => (),
} }
@ -417,7 +417,7 @@ impl Window {
pub fn set_window_icon(&self, _window_icon: Option<Icon>) { pub fn set_window_icon(&self, _window_icon: Option<Icon>) {
match self { match self {
#[cfg(feature = "x11")] #[cfg(feature = "x11")]
&Window::X(ref w) => w.set_window_icon(_window_icon), Window::X(ref w) => w.set_window_icon(_window_icon),
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
_ => (), _ => (),
} }
@ -432,7 +432,7 @@ impl Window {
pub fn focus_window(&self) { pub fn focus_window(&self) {
match self { match self {
#[cfg(feature = "x11")] #[cfg(feature = "x11")]
&Window::X(ref w) => w.focus_window(), Window::X(ref w) => w.focus_window(),
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
_ => (), _ => (),
} }
@ -440,7 +440,7 @@ impl Window {
pub fn request_user_attention(&self, _request_type: Option<UserAttentionType>) { pub fn request_user_attention(&self, _request_type: Option<UserAttentionType>) {
match self { match self {
#[cfg(feature = "x11")] #[cfg(feature = "x11")]
&Window::X(ref w) => w.request_user_attention(_request_type), Window::X(ref w) => w.request_user_attention(_request_type),
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
_ => (), _ => (),
} }
@ -455,14 +455,14 @@ impl Window {
pub fn current_monitor(&self) -> Option<RootMonitorHandle> { pub fn current_monitor(&self) -> Option<RootMonitorHandle> {
match self { match self {
#[cfg(feature = "x11")] #[cfg(feature = "x11")]
&Window::X(ref window) => { Window::X(ref window) => {
let current_monitor = MonitorHandle::X(window.current_monitor()); let current_monitor = MonitorHandle::X(window.current_monitor());
Some(RootMonitorHandle { Some(RootMonitorHandle {
inner: current_monitor, inner: current_monitor,
}) })
} }
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
&Window::Wayland(ref window) => { Window::Wayland(ref window) => {
let current_monitor = MonitorHandle::Wayland(window.current_monitor()?); let current_monitor = MonitorHandle::Wayland(window.current_monitor()?);
Some(RootMonitorHandle { Some(RootMonitorHandle {
inner: current_monitor, inner: current_monitor,
@ -475,13 +475,13 @@ impl Window {
pub fn available_monitors(&self) -> VecDeque<MonitorHandle> { pub fn available_monitors(&self) -> VecDeque<MonitorHandle> {
match self { match self {
#[cfg(feature = "x11")] #[cfg(feature = "x11")]
&Window::X(ref window) => window Window::X(ref window) => window
.available_monitors() .available_monitors()
.into_iter() .into_iter()
.map(MonitorHandle::X) .map(MonitorHandle::X)
.collect(), .collect(),
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
&Window::Wayland(ref window) => window Window::Wayland(ref window) => window
.available_monitors() .available_monitors()
.into_iter() .into_iter()
.map(MonitorHandle::Wayland) .map(MonitorHandle::Wayland)
@ -493,23 +493,23 @@ impl Window {
pub fn primary_monitor(&self) -> Option<RootMonitorHandle> { pub fn primary_monitor(&self) -> Option<RootMonitorHandle> {
match self { match self {
#[cfg(feature = "x11")] #[cfg(feature = "x11")]
&Window::X(ref window) => { Window::X(ref window) => {
let primary_monitor = MonitorHandle::X(window.primary_monitor()); let primary_monitor = MonitorHandle::X(window.primary_monitor());
Some(RootMonitorHandle { Some(RootMonitorHandle {
inner: primary_monitor, inner: primary_monitor,
}) })
} }
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
&Window::Wayland(ref window) => window.primary_monitor(), Window::Wayland(ref window) => window.primary_monitor(),
} }
} }
pub fn raw_window_handle(&self) -> RawWindowHandle { pub fn raw_window_handle(&self) -> RawWindowHandle {
match self { match self {
#[cfg(feature = "x11")] #[cfg(feature = "x11")]
&Window::X(ref window) => RawWindowHandle::Xlib(window.raw_window_handle()), Window::X(ref window) => RawWindowHandle::Xlib(window.raw_window_handle()),
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
&Window::Wayland(ref window) => RawWindowHandle::Wayland(window.raw_window_handle()), Window::Wayland(ref window) => RawWindowHandle::Wayland(window.raw_window_handle()),
} }
} }
} }

View file

@ -1,6 +1,7 @@
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
use std::error::Error; use std::error::Error;
use std::io::Result as IOResult;
use std::process; use std::process;
use std::rc::Rc; use std::rc::Rc;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
@ -18,6 +19,7 @@ use sctk::WaylandSource;
use crate::event::{Event, StartCause, WindowEvent}; use crate::event::{Event, StartCause, WindowEvent};
use crate::event_loop::{ControlFlow, EventLoopWindowTarget as RootEventLoopWindowTarget}; use crate::event_loop::{ControlFlow, EventLoopWindowTarget as RootEventLoopWindowTarget};
use crate::platform_impl::platform::sticky_exit_callback; use crate::platform_impl::platform::sticky_exit_callback;
use crate::platform_impl::EventLoopWindowTarget as PlatformEventLoopWindowTarget;
use super::env::{WindowingFeatures, WinitEnv}; use super::env::{WindowingFeatures, WinitEnv};
use super::output::OutputManager; use super::output::OutputManager;
@ -34,6 +36,8 @@ pub use state::WinitState;
use sink::EventSink; use sink::EventSink;
type WinitDispatcher = calloop::Dispatcher<'static, WaylandSource, WinitState>;
pub struct EventLoopWindowTarget<T> { pub struct EventLoopWindowTarget<T> {
/// Wayland display. /// Wayland display.
pub display: Display, pub display: Display,
@ -42,7 +46,7 @@ pub struct EventLoopWindowTarget<T> {
pub env: Environment<WinitEnv>, pub env: Environment<WinitEnv>,
/// Event loop handle. /// Event loop handle.
pub event_loop_handle: calloop::LoopHandle<WinitState>, pub event_loop_handle: calloop::LoopHandle<'static, WinitState>,
/// Output manager. /// Output manager.
pub output_manager: OutputManager, pub output_manager: OutputManager,
@ -50,8 +54,8 @@ pub struct EventLoopWindowTarget<T> {
/// State that we share across callbacks. /// State that we share across callbacks.
pub state: RefCell<WinitState>, pub state: RefCell<WinitState>,
/// Wayland source. /// Dispatcher of Wayland events.
pub wayland_source: Rc<calloop::Source<WaylandSource>>, pub wayland_dispatcher: WinitDispatcher,
/// A proxy to wake up event loop. /// A proxy to wake up event loop.
pub event_loop_awakener: calloop::ping::Ping, pub event_loop_awakener: calloop::ping::Ping,
@ -70,7 +74,7 @@ pub struct EventLoopWindowTarget<T> {
pub struct EventLoop<T: 'static> { pub struct EventLoop<T: 'static> {
/// Event loop. /// Event loop.
event_loop: calloop::EventLoop<WinitState>, event_loop: calloop::EventLoop<'static, WinitState>,
/// Wayland display. /// Wayland display.
display: Display, display: Display,
@ -81,8 +85,8 @@ pub struct EventLoop<T: 'static> {
/// Sender of user events. /// Sender of user events.
user_events_sender: calloop::channel::Sender<T>, user_events_sender: calloop::channel::Sender<T>,
/// Wayland source of events. /// Dispatcher of Wayland events.
wayland_source: Rc<calloop::Source<WaylandSource>>, pub wayland_dispatcher: WinitDispatcher,
/// Window target. /// Window target.
window_target: RootEventLoopWindowTarget<T>, window_target: RootEventLoopWindowTarget<T>,
@ -102,7 +106,7 @@ impl<T: 'static> EventLoop<T> {
let env = Environment::new(&display_proxy, &mut event_queue, WinitEnv::new())?; let env = Environment::new(&display_proxy, &mut event_queue, WinitEnv::new())?;
// Create event loop. // Create event loop.
let event_loop = calloop::EventLoop::<WinitState>::new()?; let event_loop = calloop::EventLoop::<'static, WinitState>::try_new()?;
// Build windowing features. // Build windowing features.
let windowing_features = WindowingFeatures::new(&env); let windowing_features = WindowingFeatures::new(&env);
@ -116,8 +120,22 @@ impl<T: 'static> EventLoop<T> {
let output_manager = OutputManager::new(&env); let output_manager = OutputManager::new(&env);
// A source of events that we plug into our event loop. // A source of events that we plug into our event loop.
let wayland_source = WaylandSource::new(event_queue).quick_insert(event_loop.handle())?; let wayland_source = WaylandSource::new(event_queue);
let wayland_source = Rc::new(wayland_source); let wayland_dispatcher =
calloop::Dispatcher::new(wayland_source, |_, queue, winit_state| {
queue.dispatch_pending(winit_state, |event, object, _| {
panic!(
"[calloop] Encountered an orphan event: {}@{} : {}",
event.interface,
object.as_ref().id(),
event.name
);
})
});
let _wayland_source_dispatcher = event_loop
.handle()
.register_dispatcher(wayland_dispatcher.clone())?;
// A source of user events. // A source of user events.
let pending_user_events = Rc::new(RefCell::new(Vec::new())); let pending_user_events = Rc::new(RefCell::new(Vec::new()));
@ -161,7 +179,7 @@ impl<T: 'static> EventLoop<T> {
event_loop_handle, event_loop_handle,
output_manager, output_manager,
event_loop_awakener, event_loop_awakener,
wayland_source: wayland_source.clone(), wayland_dispatcher: wayland_dispatcher.clone(),
windowing_features, windowing_features,
theme_manager, theme_manager,
_marker: std::marker::PhantomData, _marker: std::marker::PhantomData,
@ -172,11 +190,11 @@ impl<T: 'static> EventLoop<T> {
event_loop, event_loop,
display, display,
pending_user_events, pending_user_events,
wayland_source, wayland_dispatcher,
_seat_manager: seat_manager, _seat_manager: seat_manager,
user_events_sender, user_events_sender,
window_target: RootEventLoopWindowTarget { window_target: RootEventLoopWindowTarget {
p: crate::platform_impl::EventLoopWindowTarget::Wayland(event_loop_window_target), p: PlatformEventLoopWindowTarget::Wayland(event_loop_window_target),
_marker: std::marker::PhantomData, _marker: std::marker::PhantomData,
}, },
}; };
@ -243,7 +261,7 @@ impl<T: 'static> EventLoop<T> {
for (window_id, window_update) in window_updates.iter_mut() { for (window_id, window_update) in window_updates.iter_mut() {
if let Some(scale_factor) = window_update.scale_factor.map(|f| f as f64) { if let Some(scale_factor) = window_update.scale_factor.map(|f| f as f64) {
let mut physical_size = self.with_state(|state| { let mut physical_size = self.with_state(|state| {
let window_handle = state.window_map.get(&window_id).unwrap(); let window_handle = state.window_map.get(window_id).unwrap();
let mut size = window_handle.size.lock().unwrap(); let mut size = window_handle.size.lock().unwrap();
// Update the new logical size if it was changed. // Update the new logical size if it was changed.
@ -276,7 +294,7 @@ impl<T: 'static> EventLoop<T> {
if let Some(size) = window_update.size.take() { if let Some(size) = window_update.size.take() {
let physical_size = self.with_state(|state| { let physical_size = self.with_state(|state| {
let window_handle = state.window_map.get_mut(&window_id).unwrap(); let window_handle = state.window_map.get_mut(window_id).unwrap();
let mut window_size = window_handle.size.lock().unwrap(); let mut window_size = window_handle.size.lock().unwrap();
// Always issue resize event on scale factor change. // Always issue resize event on scale factor change.
@ -287,7 +305,7 @@ impl<T: 'static> EventLoop<T> {
} else { } else {
*window_size = size; *window_size = size;
let scale_factor = let scale_factor =
sctk::get_surface_scale_factor(&window_handle.window.surface()); sctk::get_surface_scale_factor(window_handle.window.surface());
let physical_size = size.to_physical(scale_factor as f64); let physical_size = size.to_physical(scale_factor as f64);
Some(physical_size) Some(physical_size)
}; };
@ -363,7 +381,7 @@ impl<T: 'static> EventLoop<T> {
// Handle refresh of the frame. // Handle refresh of the frame.
if window_update.refresh_frame { if window_update.refresh_frame {
self.with_state(|state| { self.with_state(|state| {
let window_handle = state.window_map.get_mut(&window_id).unwrap(); let window_handle = state.window_map.get_mut(window_id).unwrap();
window_handle.window.refresh(); window_handle.window.refresh();
if !window_update.redraw_requested { if !window_update.redraw_requested {
window_handle.window.surface().commit(); window_handle.window.surface().commit();
@ -403,16 +421,17 @@ impl<T: 'static> EventLoop<T> {
// woken up by messages arriving from the Wayland socket, to avoid delaying the // woken up by messages arriving from the Wayland socket, to avoid delaying the
// dispatch of these events until we're woken up again. // dispatch of these events until we're woken up again.
let instant_wakeup = { let instant_wakeup = {
let handle = self.event_loop.handle(); let mut wayland_source = self.wayland_dispatcher.as_source_mut();
let source = self.wayland_source.clone();
let dispatched = handle.with_source(&source, |wayland_source| {
let queue = wayland_source.queue(); let queue = wayland_source.queue();
self.with_state(|state| { let state = match &mut self.window_target.p {
queue.dispatch_pending(state, |_, _, _| unimplemented!()) PlatformEventLoopWindowTarget::Wayland(window_target) => {
}) window_target.state.get_mut()
}); }
#[cfg(feature = "x11")]
_ => unreachable!(),
};
if let Ok(dispatched) = dispatched { if let Ok(dispatched) = queue.dispatch_pending(state, |_, _, _| unimplemented!()) {
dispatched > 0 dispatched > 0
} else { } else {
break; break;
@ -508,9 +527,7 @@ impl<T: 'static> EventLoop<T> {
fn with_state<U, F: FnOnce(&mut WinitState) -> U>(&mut self, f: F) -> U { fn with_state<U, F: FnOnce(&mut WinitState) -> U>(&mut self, f: F) -> U {
let state = match &mut self.window_target.p { let state = match &mut self.window_target.p {
crate::platform_impl::EventLoopWindowTarget::Wayland(ref mut window_target) => { PlatformEventLoopWindowTarget::Wayland(window_target) => window_target.state.get_mut(),
window_target.state.get_mut()
}
#[cfg(feature = "x11")] #[cfg(feature = "x11")]
_ => unreachable!(), _ => unreachable!(),
}; };
@ -518,14 +535,9 @@ impl<T: 'static> EventLoop<T> {
f(state) f(state)
} }
fn loop_dispatch<D: Into<Option<std::time::Duration>>>( fn loop_dispatch<D: Into<Option<std::time::Duration>>>(&mut self, timeout: D) -> IOResult<()> {
&mut self,
timeout: D,
) -> std::io::Result<()> {
let mut state = match &mut self.window_target.p { let mut state = match &mut self.window_target.p {
crate::platform_impl::EventLoopWindowTarget::Wayland(ref mut window_target) => { PlatformEventLoopWindowTarget::Wayland(window_target) => window_target.state.get_mut(),
window_target.state.get_mut()
}
#[cfg(feature = "x11")] #[cfg(feature = "x11")]
_ => unreachable!(), _ => unreachable!(),
}; };

View file

@ -112,7 +112,7 @@ impl Eq for MonitorHandle {}
impl PartialOrd for MonitorHandle { impl PartialOrd for MonitorHandle {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(&other)) Some(self.cmp(other))
} }
} }

View file

@ -7,9 +7,9 @@ use sctk::reexports::client::protocol::wl_keyboard::WlKeyboard;
use sctk::reexports::client::protocol::wl_seat::WlSeat; use sctk::reexports::client::protocol::wl_seat::WlSeat;
use sctk::reexports::client::Attached; use sctk::reexports::client::Attached;
use sctk::reexports::calloop::{LoopHandle, Source}; use sctk::reexports::calloop::{LoopHandle, RegistrationToken};
use sctk::seat::keyboard::{self, RepeatSource}; use sctk::seat::keyboard;
use crate::event::ModifiersState; use crate::event::ModifiersState;
use crate::platform_impl::wayland::event_loop::WinitState; use crate::platform_impl::wayland::event_loop::WinitState;
@ -22,22 +22,22 @@ pub(crate) struct Keyboard {
pub keyboard: WlKeyboard, pub keyboard: WlKeyboard,
/// The source for repeat keys. /// The source for repeat keys.
pub repeat_source: Option<Source<RepeatSource>>, pub repeat_token: Option<RegistrationToken>,
/// LoopHandle to drop `RepeatSource`, when dropping the keyboard. /// LoopHandle to drop `RepeatSource`, when dropping the keyboard.
pub loop_handle: LoopHandle<WinitState>, pub loop_handle: LoopHandle<'static, WinitState>,
} }
impl Keyboard { impl Keyboard {
pub fn new( pub fn new(
seat: &Attached<WlSeat>, seat: &Attached<WlSeat>,
loop_handle: LoopHandle<WinitState>, loop_handle: LoopHandle<'static, WinitState>,
modifiers_state: Rc<RefCell<ModifiersState>>, modifiers_state: Rc<RefCell<ModifiersState>>,
) -> Option<Self> { ) -> Option<Self> {
let mut inner = KeyboardInner::new(modifiers_state); let mut inner = KeyboardInner::new(modifiers_state);
let keyboard_data = keyboard::map_keyboard_repeat( let keyboard_data = keyboard::map_keyboard_repeat(
loop_handle.clone(), loop_handle.clone(),
&seat, seat,
None, None,
keyboard::RepeatKind::System, keyboard::RepeatKind::System,
move |event, _, mut dispatch_data| { move |event, _, mut dispatch_data| {
@ -46,12 +46,12 @@ impl Keyboard {
}, },
); );
let (keyboard, repeat_source) = keyboard_data.ok()?; let (keyboard, repeat_token) = keyboard_data.ok()?;
Some(Self { Some(Self {
keyboard, keyboard,
loop_handle, loop_handle,
repeat_source: Some(repeat_source), repeat_token: Some(repeat_token),
}) })
} }
} }
@ -62,8 +62,8 @@ impl Drop for Keyboard {
self.keyboard.release(); self.keyboard.release();
} }
if let Some(repeat_source) = self.repeat_source.take() { if let Some(repeat_token) = self.repeat_token.take() {
self.loop_handle.remove(repeat_source); self.loop_handle.remove(repeat_token);
} }
} }
} }

View file

@ -37,7 +37,7 @@ pub struct SeatManager {
impl SeatManager { impl SeatManager {
pub fn new( pub fn new(
env: &Environment<WinitEnv>, env: &Environment<WinitEnv>,
loop_handle: LoopHandle<WinitState>, loop_handle: LoopHandle<'static, WinitState>,
theme_manager: ThemeManager, theme_manager: ThemeManager,
) -> Self { ) -> Self {
let relative_pointer_manager = env.get_global::<ZwpRelativePointerManagerV1>(); let relative_pointer_manager = env.get_global::<ZwpRelativePointerManagerV1>();
@ -63,7 +63,7 @@ impl SeatManager {
} }
let seat_listener = env.listen_for_seats(move |seat, seat_data, _| { let seat_listener = env.listen_for_seats(move |seat, seat_data, _| {
inner.process_seat_update(&seat, &seat_data); inner.process_seat_update(&seat, seat_data);
}); });
Self { Self {
@ -78,7 +78,7 @@ struct SeatManagerInner {
seats: Vec<SeatInfo>, seats: Vec<SeatInfo>,
/// Loop handle. /// Loop handle.
loop_handle: LoopHandle<WinitState>, loop_handle: LoopHandle<'static, WinitState>,
/// Relative pointer manager. /// Relative pointer manager.
relative_pointer_manager: Option<Attached<ZwpRelativePointerManagerV1>>, relative_pointer_manager: Option<Attached<ZwpRelativePointerManagerV1>>,
@ -99,7 +99,7 @@ impl SeatManagerInner {
relative_pointer_manager: Option<Attached<ZwpRelativePointerManagerV1>>, relative_pointer_manager: Option<Attached<ZwpRelativePointerManagerV1>>,
pointer_constraints: Option<Attached<ZwpPointerConstraintsV1>>, pointer_constraints: Option<Attached<ZwpPointerConstraintsV1>>,
text_input_manager: Option<Attached<ZwpTextInputManagerV3>>, text_input_manager: Option<Attached<ZwpTextInputManagerV3>>,
loop_handle: LoopHandle<WinitState>, loop_handle: LoopHandle<'static, WinitState>,
) -> Self { ) -> Self {
Self { Self {
seats: Vec::new(), seats: Vec::new(),
@ -127,7 +127,7 @@ impl SeatManagerInner {
if seat_data.has_pointer && !seat_data.defunct { if seat_data.has_pointer && !seat_data.defunct {
if seat_info.pointer.is_none() { if seat_info.pointer.is_none() {
seat_info.pointer = Some(Pointers::new( seat_info.pointer = Some(Pointers::new(
&seat, seat,
&self.theme_manager, &self.theme_manager,
&self.relative_pointer_manager, &self.relative_pointer_manager,
&self.pointer_constraints, &self.pointer_constraints,
@ -142,7 +142,7 @@ impl SeatManagerInner {
if seat_data.has_keyboard && !seat_data.defunct { if seat_data.has_keyboard && !seat_data.defunct {
if seat_info.keyboard.is_none() { if seat_info.keyboard.is_none() {
seat_info.keyboard = Keyboard::new( seat_info.keyboard = Keyboard::new(
&seat, seat,
self.loop_handle.clone(), self.loop_handle.clone(),
seat_info.modifiers_state.clone(), seat_info.modifiers_state.clone(),
); );
@ -154,7 +154,7 @@ impl SeatManagerInner {
// Handle touch. // Handle touch.
if seat_data.has_touch && !seat_data.defunct { if seat_data.has_touch && !seat_data.defunct {
if seat_info.touch.is_none() { if seat_info.touch.is_none() {
seat_info.touch = Some(Touch::new(&seat)); seat_info.touch = Some(Touch::new(seat));
} }
} else { } else {
seat_info.touch = None; seat_info.touch = None;
@ -165,7 +165,7 @@ impl SeatManagerInner {
if seat_data.defunct { if seat_data.defunct {
seat_info.text_input = None; seat_info.text_input = None;
} else if seat_info.text_input.is_none() { } else if seat_info.text_input.is_none() {
seat_info.text_input = Some(TextInput::new(&seat, &text_input_manager)); seat_info.text_input = Some(TextInput::new(seat, text_input_manager));
} }
} }
} }

View file

@ -129,7 +129,7 @@ pub(super) fn handle_pointer(
let window_id = wayland::make_wid(surface); let window_id = wayland::make_wid(surface);
let scale_factor = sctk::get_surface_scale_factor(&surface) as f64; let scale_factor = sctk::get_surface_scale_factor(surface) as f64;
let position = LogicalPosition::new(surface_x, surface_y).to_physical(scale_factor); let position = LogicalPosition::new(surface_x, surface_y).to_physical(scale_factor);
event_sink.push_window_event( event_sink.push_window_event(
@ -186,7 +186,7 @@ pub(super) fn handle_pointer(
None => return, None => return,
}; };
let window_id = wayland::make_wid(&surface); let window_id = wayland::make_wid(surface);
if pointer.as_ref().version() < 5 { if pointer.as_ref().version() < 5 {
let (mut x, mut y) = (0.0, 0.0); let (mut x, mut y) = (0.0, 0.0);
@ -199,7 +199,7 @@ pub(super) fn handle_pointer(
_ => unreachable!(), _ => unreachable!(),
} }
let scale_factor = sctk::get_surface_scale_factor(&surface) as f64; let scale_factor = sctk::get_surface_scale_factor(surface) as f64;
let delta = LogicalPosition::new(x as f64, y as f64).to_physical(scale_factor); let delta = LogicalPosition::new(x as f64, y as f64).to_physical(scale_factor);
event_sink.push_window_event( event_sink.push_window_event(
@ -262,7 +262,7 @@ pub(super) fn handle_pointer(
Some(surface) => surface, Some(surface) => surface,
None => return, None => return,
}; };
let window_id = wayland::make_wid(&surface); let window_id = wayland::make_wid(surface);
let window_event = if let Some((x, y)) = axis_discrete_buffer { let window_event = if let Some((x, y)) = axis_discrete_buffer {
WindowEvent::MouseWheel { WindowEvent::MouseWheel {
@ -274,7 +274,7 @@ pub(super) fn handle_pointer(
modifiers: *pointer_data.modifiers_state.borrow(), modifiers: *pointer_data.modifiers_state.borrow(),
} }
} else if let Some((x, y)) = axis_buffer { } else if let Some((x, y)) = axis_buffer {
let scale_factor = sctk::get_surface_scale_factor(&surface) as f64; let scale_factor = sctk::get_surface_scale_factor(surface) as f64;
let delta = LogicalPosition::new(x, y).to_physical(scale_factor); let delta = LogicalPosition::new(x, y).to_physical(scale_factor);
WindowEvent::MouseWheel { WindowEvent::MouseWheel {

View file

@ -13,7 +13,7 @@ use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_p
use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_confined_pointer_v1::ZwpConfinedPointerV1; use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_confined_pointer_v1::ZwpConfinedPointerV1;
use sctk::seat::pointer::{ThemeManager, ThemedPointer}; use sctk::seat::pointer::{ThemeManager, ThemedPointer};
use sctk::window::{ConceptFrame, Window}; use sctk::window::{FallbackFrame, Window};
use crate::event::ModifiersState; use crate::event::ModifiersState;
use crate::platform_impl::wayland::event_loop::WinitState; use crate::platform_impl::wayland::event_loop::WinitState;
@ -129,8 +129,8 @@ impl WinitPointer {
}; };
*confined_pointer.borrow_mut() = Some(init_confined_pointer( *confined_pointer.borrow_mut() = Some(init_confined_pointer(
&pointer_constraints, pointer_constraints,
&surface, surface,
&*self.pointer, &*self.pointer,
)); ));
} }
@ -150,7 +150,7 @@ impl WinitPointer {
} }
} }
pub fn drag_window(&self, window: &Window<ConceptFrame>) { pub fn drag_window(&self, window: &Window<FallbackFrame>) {
window.start_interactive_move(&self.seat, self.latest_serial.get()); window.start_interactive_move(&self.seat, self.latest_serial.get());
} }
} }
@ -197,12 +197,11 @@ impl Pointers {
); );
// Setup relative_pointer if it's available. // Setup relative_pointer if it's available.
let relative_pointer = match relative_pointer_manager.as_ref() { let relative_pointer = relative_pointer_manager
Some(relative_pointer_manager) => { .as_ref()
Some(init_relative_pointer(&relative_pointer_manager, &*pointer)) .map(|relative_pointer_manager| {
} init_relative_pointer(relative_pointer_manager, &*pointer)
None => None, });
};
Self { Self {
pointer, pointer,
@ -250,7 +249,7 @@ pub(super) fn init_confined_pointer(
pointer: &WlPointer, pointer: &WlPointer,
) -> ZwpConfinedPointerV1 { ) -> ZwpConfinedPointerV1 {
let confined_pointer = let confined_pointer =
pointer_constraints.confine_pointer(surface, pointer, None, Lifetime::Persistent.to_raw()); pointer_constraints.confine_pointer(surface, pointer, None, Lifetime::Persistent);
confined_pointer.quick_assign(move |_, _, _| {}); confined_pointer.quick_assign(move |_, _, _| {});

View file

@ -7,16 +7,12 @@ use sctk::reexports::client::Display;
use sctk::reexports::calloop; use sctk::reexports::calloop;
use sctk::window::{
ARGBColor, ButtonColorSpec, ColorSpec, ConceptConfig, ConceptFrame, Decorations,
};
use raw_window_handle::unix::WaylandHandle; use raw_window_handle::unix::WaylandHandle;
use sctk::window::{Decorations, FallbackFrame};
use crate::dpi::{LogicalSize, PhysicalPosition, PhysicalSize, Position, Size}; use crate::dpi::{LogicalSize, PhysicalPosition, PhysicalSize, Position, Size};
use crate::error::{ExternalError, NotSupportedError, OsError as RootOsError}; use crate::error::{ExternalError, NotSupportedError, OsError as RootOsError};
use crate::monitor::MonitorHandle as RootMonitorHandle; use crate::monitor::MonitorHandle as RootMonitorHandle;
use crate::platform::unix::{ARGBColor as LocalARGBColor, Button, ButtonState, Element, Theme};
use crate::platform_impl::{ use crate::platform_impl::{
MonitorHandle as PlatformMonitorHandle, OsError, MonitorHandle as PlatformMonitorHandle, OsError,
PlatformSpecificWindowBuilderAttributes as PlatformAttributes, PlatformSpecificWindowBuilderAttributes as PlatformAttributes,
@ -103,7 +99,7 @@ impl Window {
let theme_manager = event_loop_window_target.theme_manager.clone(); let theme_manager = event_loop_window_target.theme_manager.clone();
let mut window = event_loop_window_target let mut window = event_loop_window_target
.env .env
.create_window::<ConceptFrame, _>( .create_window::<FallbackFrame, _>(
surface.clone(), surface.clone(),
Some(theme_manager), Some(theme_manager),
(width, height), (width, height),
@ -213,17 +209,14 @@ impl Window {
let windowing_features = event_loop_window_target.windowing_features; let windowing_features = event_loop_window_target.windowing_features;
// Send all updates to the server.
let wayland_source = &event_loop_window_target.wayland_source;
let event_loop_handle = &event_loop_window_target.event_loop_handle;
// To make our window usable for drawing right away we must `ack` a `configure` // To make our window usable for drawing right away we must `ack` a `configure`
// from the server, the acking part here is done by SCTK window frame, so we just // from the server, the acking part here is done by SCTK window frame, so we just
// need to sync with server so it'll be done automatically for us. // need to sync with server so it'll be done automatically for us.
event_loop_handle.with_source(&wayland_source, |event_queue| { {
let event_queue = event_queue.queue(); let mut wayland_source = event_loop_window_target.wayland_dispatcher.as_source_mut();
let event_queue = wayland_source.queue();
let _ = event_queue.sync_roundtrip(&mut *winit_state, |_, _, _| unreachable!()); let _ = event_queue.sync_roundtrip(&mut *winit_state, |_, _, _| unreachable!());
}); }
// We all praise GNOME for these 3 lines of pure magic. If we don't do that, // We all praise GNOME for these 3 lines of pure magic. If we don't do that,
// GNOME will shrink our window a bit for the size of the decorations. I guess it // GNOME will shrink our window a bit for the size of the decorations. I guess it
@ -428,129 +421,6 @@ impl Window {
self.event_loop_awakener.ping(); self.event_loop_awakener.ping();
} }
#[inline]
pub fn set_theme<T: Theme>(&self, theme: T) {
// First buttons is minimize, then maximize, and then close.
let buttons: Vec<(ButtonColorSpec, ButtonColorSpec)> =
[Button::Minimize, Button::Maximize, Button::Close]
.iter()
.map(|button| {
let button = *button;
let idle_active_bg = theme
.button_color(button, ButtonState::Idle, false, true)
.into();
let idle_inactive_bg = theme
.button_color(button, ButtonState::Idle, false, false)
.into();
let idle_active_icon = theme
.button_color(button, ButtonState::Idle, true, true)
.into();
let idle_inactive_icon = theme
.button_color(button, ButtonState::Idle, true, false)
.into();
let idle_bg = ColorSpec {
active: idle_active_bg,
inactive: idle_inactive_bg,
};
let idle_icon = ColorSpec {
active: idle_active_icon,
inactive: idle_inactive_icon,
};
let hovered_active_bg = theme
.button_color(button, ButtonState::Hovered, false, true)
.into();
let hovered_inactive_bg = theme
.button_color(button, ButtonState::Hovered, false, false)
.into();
let hovered_active_icon = theme
.button_color(button, ButtonState::Hovered, true, true)
.into();
let hovered_inactive_icon = theme
.button_color(button, ButtonState::Hovered, true, false)
.into();
let hovered_bg = ColorSpec {
active: hovered_active_bg,
inactive: hovered_inactive_bg,
};
let hovered_icon = ColorSpec {
active: hovered_active_icon,
inactive: hovered_inactive_icon,
};
let disabled_active_bg = theme
.button_color(button, ButtonState::Disabled, false, true)
.into();
let disabled_inactive_bg = theme
.button_color(button, ButtonState::Disabled, false, false)
.into();
let disabled_active_icon = theme
.button_color(button, ButtonState::Disabled, true, true)
.into();
let disabled_inactive_icon = theme
.button_color(button, ButtonState::Disabled, true, false)
.into();
let disabled_bg = ColorSpec {
active: disabled_active_bg,
inactive: disabled_inactive_bg,
};
let disabled_icon = ColorSpec {
active: disabled_active_icon,
inactive: disabled_inactive_icon,
};
let button_bg = ButtonColorSpec {
idle: idle_bg,
hovered: hovered_bg,
disabled: disabled_bg,
};
let button_icon = ButtonColorSpec {
idle: idle_icon,
hovered: hovered_icon,
disabled: disabled_icon,
};
(button_icon, button_bg)
})
.collect();
let minimize_button = Some(buttons[0]);
let maximize_button = Some(buttons[1]);
let close_button = Some(buttons[2]);
// The first color is bar, then separator, and then text color.
let titlebar_colors: Vec<ColorSpec> = [Element::Bar, Element::Separator, Element::Text]
.iter()
.map(|element| {
let element = *element;
let active = theme.element_color(element, true).into();
let inactive = theme.element_color(element, false).into();
ColorSpec { active, inactive }
})
.collect();
let primary_color = titlebar_colors[0];
let secondary_color = titlebar_colors[1];
let title_color = titlebar_colors[2];
let title_font = theme.font();
let concept_config = ConceptConfig {
primary_color,
secondary_color,
title_color,
title_font,
minimize_button,
maximize_button,
close_button,
};
let theme_request = WindowRequest::Theme(concept_config);
self.window_requests.lock().unwrap().push(theme_request);
self.event_loop_awakener.ping();
}
#[inline] #[inline]
pub fn set_cursor_icon(&self, cursor: CursorIcon) { pub fn set_cursor_icon(&self, cursor: CursorIcon) {
let cursor_icon_request = WindowRequest::NewCursorIcon(cursor); let cursor_icon_request = WindowRequest::NewCursorIcon(cursor);
@ -662,16 +532,6 @@ impl Window {
} }
} }
impl From<LocalARGBColor> for ARGBColor {
fn from(color: LocalARGBColor) -> Self {
let a = color.a;
let r = color.r;
let g = color.g;
let b = color.b;
Self { a, r, g, b }
}
}
impl Drop for Window { impl Drop for Window {
fn drop(&mut self) { fn drop(&mut self) {
let close_request = WindowRequest::Close; let close_request = WindowRequest::Close;

View file

@ -3,7 +3,7 @@ use std::sync::{Arc, Mutex};
use sctk::reexports::client::protocol::wl_output::WlOutput; use sctk::reexports::client::protocol::wl_output::WlOutput;
use sctk::window::{ConceptConfig, ConceptFrame, Decorations, Window}; use sctk::window::{Decorations, FallbackFrame, Window};
use crate::dpi::{LogicalPosition, LogicalSize}; use crate::dpi::{LogicalPosition, LogicalSize};
@ -67,9 +67,6 @@ pub enum WindowRequest {
/// Redraw was requested. /// Redraw was requested.
Redraw, Redraw,
/// A new theme for a concept frame was requested.
Theme(ConceptConfig),
/// Window should be closed. /// Window should be closed.
Close, Close,
} }
@ -131,7 +128,7 @@ impl WindowUpdate {
/// and react to events. /// and react to events.
pub struct WindowHandle { pub struct WindowHandle {
/// An actual window. /// An actual window.
pub window: Window<ConceptFrame>, pub window: Window<FallbackFrame>,
/// The current size of the window. /// The current size of the window.
pub size: Arc<Mutex<LogicalSize<u32>>>, pub size: Arc<Mutex<LogicalSize<u32>>>,
@ -157,7 +154,7 @@ pub struct WindowHandle {
impl WindowHandle { impl WindowHandle {
pub fn new( pub fn new(
window: Window<ConceptFrame>, window: Window<FallbackFrame>,
size: Arc<Mutex<LogicalSize<u32>>>, size: Arc<Mutex<LogicalSize<u32>>>,
pending_window_requests: Arc<Mutex<Vec<WindowRequest>>>, pending_window_requests: Arc<Mutex<Vec<WindowRequest>>>,
) -> Self { ) -> Self {
@ -184,7 +181,7 @@ impl WindowHandle {
for pointer in self.pointers.iter() { for pointer in self.pointers.iter() {
if self.confined.get() { if self.confined.get() {
let surface = self.window.surface(); let surface = self.window.surface();
pointer.confine(&surface); pointer.confine(surface);
} else { } else {
pointer.unconfine(); pointer.unconfine();
} }
@ -198,7 +195,7 @@ impl WindowHandle {
if position.is_none() { if position.is_none() {
if self.confined.get() { if self.confined.get() {
let surface = self.window.surface(); let surface = self.window.surface();
pointer.confine(&surface); pointer.confine(surface);
} }
self.pointers.push(pointer); self.pointers.push(pointer);
} }
@ -222,12 +219,7 @@ impl WindowHandle {
} }
pub fn text_input_entered(&mut self, text_input: TextInputHandler) { pub fn text_input_entered(&mut self, text_input: TextInputHandler) {
if self if !self.text_inputs.iter().any(|t| *t == text_input) {
.text_inputs
.iter()
.find(|t| *t == &text_input)
.is_none()
{
self.text_inputs.push(text_input); self.text_inputs.push(text_input);
} }
} }
@ -330,35 +322,35 @@ pub fn handle_window_requests(winit_state: &mut WinitState) {
window_handle.window.set_decorate(decorations); window_handle.window.set_decorate(decorations);
// We should refresh the frame to apply decorations change. // We should refresh the frame to apply decorations change.
let window_update = window_updates.get_mut(&window_id).unwrap(); let window_update = window_updates.get_mut(window_id).unwrap();
window_update.refresh_frame = true; window_update.refresh_frame = true;
} }
WindowRequest::Resizeable(resizeable) => { WindowRequest::Resizeable(resizeable) => {
window_handle.window.set_resizable(resizeable); window_handle.window.set_resizable(resizeable);
// We should refresh the frame to update button state. // We should refresh the frame to update button state.
let window_update = window_updates.get_mut(&window_id).unwrap(); let window_update = window_updates.get_mut(window_id).unwrap();
window_update.refresh_frame = true; window_update.refresh_frame = true;
} }
WindowRequest::Title(title) => { WindowRequest::Title(title) => {
window_handle.window.set_title(title); window_handle.window.set_title(title);
// We should refresh the frame to draw new title. // We should refresh the frame to draw new title.
let window_update = window_updates.get_mut(&window_id).unwrap(); let window_update = window_updates.get_mut(window_id).unwrap();
window_update.refresh_frame = true; window_update.refresh_frame = true;
} }
WindowRequest::MinSize(size) => { WindowRequest::MinSize(size) => {
let size = size.map(|size| (size.width, size.height)); let size = size.map(|size| (size.width, size.height));
window_handle.window.set_min_size(size); window_handle.window.set_min_size(size);
let window_update = window_updates.get_mut(&window_id).unwrap(); let window_update = window_updates.get_mut(window_id).unwrap();
window_update.redraw_requested = true; window_update.redraw_requested = true;
} }
WindowRequest::MaxSize(size) => { WindowRequest::MaxSize(size) => {
let size = size.map(|size| (size.width, size.height)); let size = size.map(|size| (size.width, size.height));
window_handle.window.set_max_size(size); window_handle.window.set_max_size(size);
let window_update = window_updates.get_mut(&window_id).unwrap(); let window_update = window_updates.get_mut(window_id).unwrap();
window_update.redraw_requested = true; window_update.redraw_requested = true;
} }
WindowRequest::FrameSize(size) => { WindowRequest::FrameSize(size) => {
@ -366,20 +358,13 @@ pub fn handle_window_requests(winit_state: &mut WinitState) {
window_handle.window.resize(size.width, size.height); window_handle.window.resize(size.width, size.height);
// We should refresh the frame after resize. // We should refresh the frame after resize.
let window_update = window_updates.get_mut(&window_id).unwrap(); let window_update = window_updates.get_mut(window_id).unwrap();
window_update.refresh_frame = true; window_update.refresh_frame = true;
} }
WindowRequest::Redraw => { WindowRequest::Redraw => {
let window_update = window_updates.get_mut(&window_id).unwrap(); let window_update = window_updates.get_mut(window_id).unwrap();
window_update.redraw_requested = true; window_update.redraw_requested = true;
} }
WindowRequest::Theme(concept_config) => {
window_handle.window.set_frame_config(concept_config);
// We should refresh the frame to apply new theme.
let window_update = window_updates.get_mut(&window_id).unwrap();
window_update.refresh_frame = true;
}
WindowRequest::Close => { WindowRequest::Close => {
// The window was requested to be closed. // The window was requested to be closed.
windows_to_close.push(*window_id); windows_to_close.push(*window_id);