Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion winit-core/src/event_loop/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ use crate::as_any::AsAny;
use crate::cursor::{CustomCursor, CustomCursorSource};
use crate::error::RequestError;
use crate::monitor::MonitorHandle;
use crate::window::{Theme, Window, WindowAttributes};
use crate::popup::PopupAttributes;
use crate::window::{Theme, Window, WindowAttributes, WindowId};

pub trait ActiveEventLoop: AsAny + fmt::Debug {
/// Creates an [`EventLoopProxy`] that can be used to dispatch user events
Expand All @@ -35,6 +36,16 @@ pub trait ActiveEventLoop: AsAny + fmt::Debug {
window_attributes: WindowAttributes,
) -> Result<Box<dyn Window>, RequestError>;

/// Create a popup.
///
/// Possible causes of error include denied permission, incompatible system, and lack of memory.
fn create_popup(
&self,
window_attributes: WindowAttributes,
popup_attributes: PopupAttributes,
parent: WindowId,
) -> Result<Box<dyn Window>, RequestError>;

/// Create custom cursor.
///
/// ## Platform-specific
Expand Down
1 change: 1 addition & 0 deletions winit-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub mod event_loop;
pub mod icon;
pub mod keyboard;
pub mod monitor;
pub mod popup;
pub mod window;

// `Instant` is not actually available on `wasm32-unknown-unknown`, the `std` implementation there
Expand Down
48 changes: 48 additions & 0 deletions winit-core/src/popup.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use bitflags::bitflags;
use dpi::{PhysicalPosition, PhysicalSize, Position, Size};

pub enum Direction {
None,
Top,
Bottom,
Left,
Right,
TopLeft,
BottomLeft,
TopRight,
BottomRight,
}

bitflags! {
pub struct AnchorHints: u8 {
const SlideX = 1;
const SlideY = 2;
const Slide = AnchorHints::SlideX.bits() | AnchorHints::SlideY.bits();
const FlipX = 4;
const FlipY = 8;
const Flip = AnchorHints::FlipX.bits() | AnchorHints::FlipY.bits();
const ResizeX = 16;
const ResizeY = 32;
const Resize = AnchorHints::ResizeX.bits() | AnchorHints::ResizeY.bits();
}
}

pub struct PopupAttributes {
pub anchor_size: Size,
pub anchor: Direction,
pub gravity: Direction,
pub anchor_hints: AnchorHints,
pub offset: Position,
}

impl Default for PopupAttributes {
fn default() -> PopupAttributes {
PopupAttributes {
anchor_size: PhysicalSize::<u32>::default().into(),
anchor: Direction::None,
gravity: Direction::None,
anchor_hints: AnchorHints::empty(),
offset: PhysicalPosition::<i32>::default().into(),
}
}
}
42 changes: 28 additions & 14 deletions winit-wayland/src/event_loop/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use std::thread::JoinHandle;
use std::time::{Duration, Instant};

use calloop::ping::Ping;
use dpi::LogicalSize;
use rustix::event::{PollFd, PollFlags};
use rustix::pipe::{self, PipeFlags};
use sctk::reexports::calloop_wayland_source::WaylandSource;
Expand All @@ -27,9 +26,11 @@ use winit_core::event_loop::{
OwnedDisplayHandle as CoreOwnedDisplayHandle,
};
use winit_core::monitor::MonitorHandle as CoreMonitorHandle;
use winit_core::popup::PopupAttributes;
use winit_core::window::Theme;

use crate::types::cursor::WaylandCustomCursor;
use crate::window::state::AnyWindowState;

mod proxy;
pub mod sink;
Expand Down Expand Up @@ -343,7 +344,7 @@ impl EventLoop {
if compositor_update.scale_changed {
let (physical_size, scale_factor) = self.with_state(|state| {
let windows = state.windows.get_mut();
let window = windows.get(&window_id).unwrap().lock().unwrap();
let window = windows.get(&window_id).unwrap().lock();
let scale_factor = window.scale_factor();
let size = logical_to_physical_rounded(window.surface_size(), scale_factor);
(size, scale_factor)
Expand All @@ -366,12 +367,16 @@ impl EventLoop {
// Resize the window when user altered the size.
if old_physical_size != physical_size {
self.with_state(|state| {
let windows = state.windows.get_mut();
let mut window = windows.get(&window_id).unwrap().lock().unwrap();

let new_logical_size: LogicalSize<f64> =
physical_size.to_logical(scale_factor);
window.request_surface_size(new_logical_size.into());
let surface_size = physical_size.to_logical::<f64>(scale_factor).into();

match state.windows.get_mut().get(&window_id).unwrap() {
AnyWindowState::TopLevel(window) => {
window.lock().unwrap().request_surface_size(surface_size)
},
AnyWindowState::Popup(window) => {
window.lock().unwrap().request_surface_size(surface_size)
},
}
});

// Make it queue resize.
Expand All @@ -384,7 +389,7 @@ impl EventLoop {
if compositor_update.resized || compositor_update.scale_changed {
let physical_size = self.with_state(|state| {
let windows = state.windows.get_mut();
let window = windows.get(&window_id).unwrap().lock().unwrap();
let window = windows.get(&window_id).unwrap().lock();

let scale_factor = window.scale_factor();
let size = logical_to_physical_rounded(window.surface_size(), scale_factor);
Expand Down Expand Up @@ -454,15 +459,14 @@ impl EventLoop {
return Some(WindowEvent::Destroyed);
}

let mut window =
state.windows.get_mut().get_mut(window_id).unwrap().lock().unwrap();
let mut window = state.windows.get_mut().get_mut(window_id).unwrap().lock();

if window.frame_callback_state() == FrameCallbackState::Requested {
if *window.frame_callback_state() == FrameCallbackState::Requested {
return None;
}

// Reset the frame callbacks state.
window.frame_callback_reset();
*window.frame_callback_state() = FrameCallbackState::None;
let mut redraw_requested =
window_requests.get(window_id).unwrap().take_redraw_requested();

Expand Down Expand Up @@ -490,7 +494,7 @@ impl EventLoop {
for window_id in window_ids.drain(..) {
wake_up |= self.with_state(|state| match state.windows.get_mut().get_mut(&window_id) {
Some(window) => {
let refresh = window.lock().unwrap().refresh_frame();
let refresh = window.lock().refresh_frame();
if refresh {
state
.window_requests
Expand Down Expand Up @@ -655,6 +659,16 @@ impl RootActiveEventLoop for ActiveEventLoop {
Ok(Box::new(window))
}

fn create_popup(
&self,
window_attributes: winit_core::window::WindowAttributes,
popup_attributes: PopupAttributes,
parent: WindowId,
) -> Result<Box<dyn winit_core::window::Window>, RequestError> {
let window = crate::Window::new_popup(self, window_attributes, parent, popup_attributes)?;
Ok(Box::new(window))
}

fn available_monitors(&self) -> Box<dyn Iterator<Item = CoreMonitorHandle>> {
Box::new(
self.state
Expand Down
4 changes: 3 additions & 1 deletion winit-wayland/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ use std::ptr::NonNull;
use dpi::{LogicalSize, PhysicalSize};
use sctk::reexports::client::Proxy;
use sctk::reexports::client::protocol::wl_surface::WlSurface;
pub use sctk::shell::xdg::popup::Popup as SctkPopup;
pub use sctk::shell::xdg::window::Window as SctkWindow;
use sctk::shm::slot::{Buffer, CreateBufferError, SlotPool};
use wayland_client::protocol::wl_shm::Format;
use winit_core::event_loop::ActiveEventLoop as CoreActiveEventLoop;
Expand Down Expand Up @@ -83,7 +85,7 @@ pub trait WindowExtWayland {
impl WindowExtWayland for dyn CoreWindow + '_ {
#[inline]
fn xdg_toplevel(&self) -> Option<NonNull<c_void>> {
self.cast_ref::<Window>()?.xdg_toplevel()
self.cast_ref::<Window<SctkWindow>>()?.xdg_toplevel()
}
}

Expand Down
15 changes: 12 additions & 3 deletions winit-wayland/src/seat/keyboard/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use winit_core::keyboard::ModifiersState;
use crate::WindowId;
use crate::event_loop::sink::EventSink;
use crate::state::WinitState;
use crate::window::state::AnyWindowStateLocked;

impl Dispatch<WlKeyboard, KeyboardData, WinitState> for WinitState {
fn event(
Expand Down Expand Up @@ -65,9 +66,17 @@ impl Dispatch<WlKeyboard, KeyboardData, WinitState> for WinitState {
// Mark the window as focused.
let was_unfocused = match state.windows.get_mut().get(&window_id) {
Some(window) => {
let mut window = window.lock().unwrap();
let window = window.lock();
let was_unfocused = !window.has_focus();
window.add_seat_focus(data.seat.id());
let object_id = data.seat.id();
match window {
AnyWindowStateLocked::TopLevel(mut window) => {
window.add_seat_focus(object_id)
},
AnyWindowStateLocked::Popup(mut window) => {
window.add_seat_focus(object_id)
},
}
was_unfocused
},
None => return,
Expand Down Expand Up @@ -108,7 +117,7 @@ impl Dispatch<WlKeyboard, KeyboardData, WinitState> for WinitState {
// nil surface, regardless of what protocol says.
let focused = match state.windows.get_mut().get(&window_id) {
Some(window) => {
let mut window = window.lock().unwrap();
let mut window = window.lock();
window.remove_seat_focus(&data.seat.id());
window.has_focus()
},
Expand Down
2 changes: 1 addition & 1 deletion winit-wayland/src/seat/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ impl SeatHandler for WinitState {
impl WinitState {
fn on_keyboard_destroy(&mut self, seat: &ObjectId) {
for (window_id, window) in self.windows.get_mut() {
let mut window = window.lock().unwrap();
let mut window = window.lock();
let had_focus = window.has_focus();
window.remove_seat_focus(seat);
if had_focus != window.has_focus() {
Expand Down
23 changes: 19 additions & 4 deletions winit-wayland/src/seat/pointer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use winit_core::event::{

use crate::state::WinitState;
use crate::WindowId;
use crate::window::state::AnyWindowStateLocked;

pub mod pointer_gesture;
pub mod relative_pointer;
Expand Down Expand Up @@ -76,8 +77,8 @@ impl PointerHandler for WinitState {
let window_id = crate::make_wid(parent_surface);

// Ensure that window exists.
let mut window = match self.windows.get_mut().get_mut(&window_id) {
Some(window) => window.lock().unwrap(),
let window = match self.windows.get_mut().get_mut(&window_id) {
Some(window) => window.lock(),
None => continue,
};

Expand All @@ -90,6 +91,8 @@ impl PointerHandler for WinitState {
PointerEventKind::Enter { .. } | PointerEventKind::Motion { .. }
if parent_surface != surface =>
{
let AnyWindowStateLocked::TopLevel(mut window) = window else { continue };

if let Some(icon) = window.frame_point_moved(
seat,
surface,
Expand All @@ -101,12 +104,16 @@ impl PointerHandler for WinitState {
}
},
PointerEventKind::Leave { .. } if parent_surface != surface => {
let AnyWindowStateLocked::TopLevel(mut window) = window else { continue };

window.frame_point_left();
},
ref kind @ PointerEventKind::Press { button, serial, time }
| ref kind @ PointerEventKind::Release { button, serial, time }
if parent_surface != surface =>
{
let AnyWindowStateLocked::TopLevel(mut window) = window else { continue };

let click = match wayland_button_to_winit(button) {
ButtonSource::Mouse(MouseButton::Left) => FrameClick::Normal,
ButtonSource::Mouse(MouseButton::Right) => FrameClick::Alternate,
Expand Down Expand Up @@ -137,13 +144,21 @@ impl PointerHandler for WinitState {
window_id,
);

window.pointer_entered(Arc::downgrade(themed_pointer));
let added = Arc::downgrade(themed_pointer);
match window {
AnyWindowStateLocked::TopLevel(mut window) => window.pointer_entered(added),
AnyWindowStateLocked::Popup(mut window) => window.pointer_entered(added),
}

// Set the currently focused surface.
pointer.winit_data().inner.lock().unwrap().surface = Some(window_id);
},
PointerEventKind::Leave { .. } => {
window.pointer_left(Arc::downgrade(themed_pointer));
let removed = Arc::downgrade(themed_pointer);
match window {
AnyWindowStateLocked::TopLevel(mut window) => window.pointer_left(removed),
AnyWindowStateLocked::Popup(mut window) => window.pointer_left(removed),
}

// Remove the active surface.
pointer.winit_data().inner.lock().unwrap().surface = None;
Expand Down
2 changes: 1 addition & 1 deletion winit-wayland/src/seat/pointer/pointer_gesture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ impl Dispatch<ZwpPointerGesturePinchV1, PointerGestureData, WinitState> for Poin
};

let scale_factor = match state.windows.get_mut().get_mut(&window_id) {
Some(window) => window.lock().unwrap().scale_factor(),
Some(window) => window.lock().scale_factor(),
None => return,
};

Expand Down
27 changes: 20 additions & 7 deletions winit-wayland/src/seat/text_input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use winit_core::window::{
};

use crate::state::WinitState;
use crate::window::state::AnyWindowStateLocked;

#[derive(Debug)]
pub struct TextInputState {
Expand Down Expand Up @@ -68,8 +69,8 @@ impl Dispatch<ZwpTextInputV3, TextInputData, WinitState> for TextInputState {
let window_id = crate::make_wid(&surface);
text_input_data.surface = Some(surface);

let mut window = match windows.get(&window_id) {
Some(window) => window.lock().unwrap(),
let window = match windows.get(&window_id) {
Some(window) => window.lock(),
None => return,
};

Expand All @@ -80,7 +81,14 @@ impl Dispatch<ZwpTextInputV3, TextInputData, WinitState> for TextInputState {
state.events_sink.push_window_event(WindowEvent::Ime(Ime::Enabled), window_id);
}

window.text_input_entered(text_input);
match window {
AnyWindowStateLocked::TopLevel(mut window) => {
window.text_input_entered(text_input)
},
AnyWindowStateLocked::Popup(mut window) => {
window.text_input_entered(text_input)
},
}
},
TextInputEvent::Leave { surface } => {
text_input_data.surface = None;
Expand All @@ -94,12 +102,17 @@ impl Dispatch<ZwpTextInputV3, TextInputData, WinitState> for TextInputState {

// XXX this check is essential, because `leave` could have a
// reference to nil surface...
let mut window = match windows.get(&window_id) {
Some(window) => window.lock().unwrap(),
let window = match windows.get(&window_id) {
Some(window) => window.lock(),
None => return,
};

window.text_input_left(text_input);
match window {
AnyWindowStateLocked::TopLevel(mut window) => {
window.text_input_left(text_input)
},
AnyWindowStateLocked::Popup(mut window) => window.text_input_left(text_input),
}

state.events_sink.push_window_event(WindowEvent::Ime(Ime::Disabled), window_id);
},
Expand Down Expand Up @@ -132,7 +145,7 @@ impl Dispatch<ZwpTextInputV3, TextInputData, WinitState> for TextInputState {

// Just in case some IME sends an event for the disabled window.
if let Some(window) = windows.get(&window_id) {
if window.lock().unwrap().text_input_state().is_none() {
if window.lock().text_input_state().is_none() {
return;
}
};
Expand Down
Loading
Loading