Skip to content

Commit 3d3deca

Browse files
committed
X11 impl
1 parent 943a1a9 commit 3d3deca

6 files changed

Lines changed: 81 additions & 6 deletions

File tree

examples/open_window/src/main.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::cell::{Cell, RefCell};
22
use std::num::NonZeroU32;
3+
use std::thread;
34
use std::time::Duration;
45

56
use rtrb::{Consumer, RingBuffer};
@@ -8,8 +9,8 @@ use rtrb::{Consumer, RingBuffer};
89
use baseview::copy_to_clipboard;
910
use baseview::dpi::{LogicalSize, PhysicalPosition};
1011
use baseview::{
11-
Event, EventStatus, HandlerError, MouseEvent, Window, WindowContext, WindowHandler,
12-
WindowSettings, WindowSize,
12+
Event, EventStatus, HandlerError, MouseEvent, Notification, Window, WindowContext,
13+
WindowHandler, WindowSettings, WindowSize,
1314
};
1415

1516
#[derive(Debug, Clone)]
@@ -46,6 +47,8 @@ impl WindowHandler for OpenWindowExample {
4647
return Ok(());
4748
}
4849

50+
eprintln!("Redraw!");
51+
4952
let mut surface = self.surface.borrow_mut();
5053
let mut pixels = surface.buffer_mut()?;
5154
let size = self.window_context.size();
@@ -137,6 +140,14 @@ impl WindowHandler for OpenWindowExample {
137140

138141
EventStatus::Captured
139142
}
143+
144+
fn notify(&self, notification: Notification) -> Result<(), HandlerError> {
145+
if let Notification::Shown = notification {
146+
self.damaged.set(true);
147+
}
148+
149+
Ok(())
150+
}
140151
}
141152

142153
fn main() -> Result<(), baseview::Error> {
@@ -152,7 +163,7 @@ fn main() -> Result<(), baseview::Error> {
152163
}
153164
});
154165

155-
Window::create(window_open_options, |window| {
166+
let w = Window::create(window_open_options, |window| {
156167
let ctx = softbuffer::Context::new(window.clone())?;
157168
let mut surface = softbuffer::Surface::new(&ctx, window.clone())?;
158169
let size = window.size().physical;
@@ -166,8 +177,11 @@ fn main() -> Result<(), baseview::Error> {
166177
is_cursor_inside: false.into(),
167178
damaged: true.into(),
168179
})
169-
})?
170-
.run_until_closed()?;
180+
})?;
181+
182+
thread::sleep(Duration::from_secs(1));
183+
184+
w.run_until_closed()?;
171185

172186
Ok(())
173187
}

src/context.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,15 @@ impl WindowContext {
6464
self.inner.size()
6565
}
6666

67+
/// Returns whether the window has been shown to the user.
68+
///
69+
/// Note that this is distinct to whether the window is actually visible.
70+
/// For instance, this will still return `true` if the window is minimized, or obscured by other
71+
/// window.
72+
pub fn is_shown(&self) -> bool {
73+
self.inner.is_shown()
74+
}
75+
6776
/// Returns a new lightweight [`PlatformHandle`] to this window.
6877
///
6978
/// It can be sent across threads to access the underlying platform window and display connection.

src/event.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,15 @@ pub enum EventStatus {
164164
/// result in [DropEffect]
165165
AcceptDrop(DropEffect),
166166
}
167+
168+
/// A notification given to a [`WindowHandler`](crate::WindowHandler), via its
169+
/// [`notify`](crate::WindowHandler::notify) method.
170+
///
171+
/// These differ from [`Event`]s, in that the platform does not expect any kind of [`EventStatus`] as
172+
/// a result of handling (or not) a notification.
173+
#[non_exhaustive]
174+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
175+
pub enum Notification {
176+
Shown,
177+
Hidden,
178+
}

src/handler.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,24 @@ pub trait WindowHandler: 'static {
2121
/// previous size, but this is only a best-effort attempt since those operations can also fail.
2222
fn resized(&self, new_size: WindowSize) -> core::result::Result<(), HandlerError>;
2323
fn on_event(&self, event: Event) -> EventStatus;
24+
25+
/// Notifies the window handler about a given event.
26+
///
27+
/// Unlike [`on_event`](Self::on_event), this method indicates that the platform does not need
28+
/// any kind of return value from the [`WindowHandler`], and doesn't care whether the notification
29+
/// has been processed in any way.
30+
///
31+
/// # Errors
32+
///
33+
/// If this operation fails, the failure reason will be logged, if the `tracing` feature is enabled.
34+
/// Otherwise, the error is completely ignored.
35+
///
36+
/// Implementations should be able to gracefully continue execution in case this method returns
37+
/// an error.
38+
fn notify(&self, notification: Notification) -> core::result::Result<(), HandlerError> {
39+
let _ = notification;
40+
Ok(())
41+
}
2442
}
2543

2644
type DynBuilderResult = core::result::Result<Box<dyn WindowHandler>, HandlerError>;

src/platform/x11/event_loop.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ use crate::platform::x11::error::FatalError;
88
use crate::platform::x11::window_thread::{
99
HostCallback, WindowThreadRequest, WindowThreadResponseMessage,
1010
};
11-
use crate::warn;
1211
use crate::wrappers::xkbcommon::XkbcommonState;
12+
use crate::{warn, Notification};
1313
use crate::{Event, MouseButton, MouseEvent, ScrollDelta, WindowEvent, WindowHandler, WindowSize};
1414
use calloop::generic::Generic;
1515
use calloop::timer::{TimeoutAction, Timer};
@@ -319,6 +319,16 @@ impl EventLoop {
319319
}
320320
}
321321

322+
XEvent::MapNotify(_) => {
323+
self.window.is_mapped.set(true);
324+
self.handle_notify(Notification::Shown);
325+
}
326+
327+
XEvent::UnmapNotify(_) => {
328+
self.window.is_mapped.set(false);
329+
self.handle_notify(Notification::Hidden);
330+
}
331+
322332
XEvent::SelectionNotify(event) => {
323333
if event.property == self.window.connection.atoms.XdndSelection {
324334
self.drag_n_drop.handle_selection_notify_event(
@@ -425,6 +435,12 @@ impl EventLoop {
425435
fn handle_event(&mut self, event: Event) {
426436
self.handler.on_event(event);
427437
}
438+
439+
fn handle_notify(&self, notification: Notification) {
440+
if let Err(e) = self.handler.notify(notification) {
441+
crate::warn!("Failed to handle notification {:?}: {}", notification, e);
442+
}
443+
}
428444
}
429445

430446
fn mouse_id(id: u8) -> MouseButton {

src/platform/x11/window_shared.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ pub(crate) struct WindowInner {
5656
pub(crate) visual_id: Visualid,
5757

5858
pub(crate) is_focused: Cell<bool>,
59+
pub(crate) is_mapped: Cell<bool>,
5960
pub(crate) loop_signal: LoopSignal,
6061

6162
pub(crate) main_thread_shared: Arc<WindowThreadShared>,
@@ -134,6 +135,7 @@ impl WindowInner {
134135
loop_signal: ev_loop.get_signal(),
135136

136137
is_focused: false.into(),
138+
is_mapped: false.into(),
137139
main_thread_shared: shared,
138140

139141
#[cfg(feature = "opengl")]
@@ -265,4 +267,8 @@ impl WindowInner {
265267
pub fn size(&self) -> WindowSize {
266268
WindowSize::from_physical(self.window_size.get().cast(), self.scaling_factor.get())
267269
}
270+
271+
pub fn is_shown(&self) -> bool {
272+
self.is_mapped.get()
273+
}
268274
}

0 commit comments

Comments
 (0)