Skip to content
Merged
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: 4 additions & 9 deletions examples/open_parented/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@ impl ParentWindowHandler {
let size = window.size().physical;
surface.resize(size.width.try_into()?, size.height.try_into()?)?;

let window_open_options = WindowSettings::new()
.with_size(LogicalSize::new(256, 256))
.with_parent(&window)
.with_title("baseview child");
let window_open_options =
WindowSettings::new().with_size(size).with_parent(&window).with_title("baseview child");

let child_window = Window::create(window_open_options, ChildWindowHandler::new)?;
child_window.show()?;
Expand All @@ -37,7 +35,7 @@ impl WindowHandler for ParentWindowHandler {
let mut surface = self.surface.borrow_mut();
let mut buf = surface.buffer_mut()?;
if self.damaged.get() {
buf.fill(0xFFAAAAAA);
buf.fill(0xFFAA0000);
self.damaged.set(false);
}
buf.present()?;
Expand All @@ -55,10 +53,7 @@ impl WindowHandler for ParentWindowHandler {
self.damaged.set(true);
}

let child_size =
LogicalSize::new(new_size.logical.width / 2., new_size.logical.height / 2.);
self.child_window.suggest_fallback_scale_factor(new_size.scale_factor)?;
self.child_window.resize(child_size)?;
Ok(())
}

Expand Down Expand Up @@ -95,7 +90,7 @@ impl WindowHandler for ChildWindowHandler {
let mut surface = self.surface.borrow_mut();
let mut buf = surface.buffer_mut()?;
if self.damaged.get() {
buf.fill(0xFFAA0000);
buf.fill(0xFFAAAAAA);
self.damaged.set(false);
}
buf.present()?;
Expand Down
126 changes: 88 additions & 38 deletions src/platform/x11/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ pub(crate) struct EventLoop {
handler: Box<dyn WindowHandler>,
window: Rc<WindowInner>,

new_physical_size: Option<PhysicalSize<u16>>,
new_size: Option<PhysicalSize<u16>>,
new_parent_size: Option<PhysicalSize<u16>>,
exposed: bool,

loop_signal: LoopSignal,
Expand Down Expand Up @@ -90,7 +91,8 @@ impl EventLoop {
Ok(Self {
loop_signal: inner.get_signal(),
handler,
new_physical_size: None,
new_size: None,
new_parent_size: None,
exposed: false,
drag_n_drop: DragNDropState::NoCurrentSession,
xkb_state: XkbcommonState::new(&window.connection),
Expand Down Expand Up @@ -148,7 +150,7 @@ impl EventLoop {
}
self.exposed = false;

if !self.window.is_mapped.get() {
if !self.window.visibility_state.own_window_is_viewable() {
return;
}

Expand All @@ -162,7 +164,20 @@ impl EventLoop {
}

fn handle_coalesced_resize_events(&mut self) -> Result<(), FatalError> {
let Some(new_size) = self.new_physical_size.take() else { return Ok(()) };
if let Some(new_parent_size) = self.new_parent_size.take() {
if new_parent_size != self.window.get_size() {
// The parent was resized, which means we should resize ourselves too.
if let Err(e) = self.window.xcb_window.resize(new_parent_size.cast()) {
crate::warn!("Failed to resize window: {}", e);
} else {
// Makes the rest of this function run on the new parent size immediately (without waiting for a ConfigureNotify round-trip)
// Also overrides any new sizes we may have received this event loop iteration,it would probably be invalidated anyway
self.new_size = Some(new_parent_size);
}
}
}

let Some(new_size) = self.new_size.take() else { return Ok(()) };
let previous = self.window.store_size(new_size);

if previous == new_size {
Expand Down Expand Up @@ -346,7 +361,7 @@ impl EventLoop {
////
// window
////
XEvent::ClientMessage(event) => {
XEvent::ClientMessage(event) if event.window == self.window.raw_id() => {
if event.format != 32 {
return Ok(());
}
Expand Down Expand Up @@ -386,15 +401,21 @@ impl EventLoop {

XEvent::ConfigureNotify(event) => {
// These are coalesced and then handled asynchronously at the end of the event loop
self.new_physical_size = Some(PhysicalSize::new(event.width, event.height));
if event.window == self.window.raw_id() {
self.new_size = Some(PhysicalSize::new(event.width, event.height));
} else if Some(event.window) == self.window.visibility_state.parent_id() {
// Also resize the window if the parent is resized
// This works around some hosts that might not call set_size() right away (or at all...)
self.new_parent_size = Some(PhysicalSize::new(event.width, event.height));
}
}

XEvent::Expose(_) => self.exposed = true,
XEvent::Expose(e) if e.window == self.window.raw_id() => self.exposed = true,

////
// mouse
////
XEvent::MotionNotify(event) => {
XEvent::MotionNotify(event) if event.event == self.window.raw_id() => {
let physical_pos = PhysicalPosition::new(event.event_x, event.event_y);

self.handle_event(Event::Mouse(MouseEvent::CursorMoved {
Expand All @@ -403,7 +424,7 @@ impl EventLoop {
}));
}

XEvent::EnterNotify(event) => {
XEvent::EnterNotify(event) if event.event == self.window.raw_id() => {
self.handle_event(Event::Mouse(MouseEvent::CursorEntered));
// since no `MOTION_NOTIFY` event is generated when `ENTER_NOTIFY` is generated,
// we generate a CursorMoved as well, so the mouse position from here isn't lost
Expand All @@ -414,32 +435,36 @@ impl EventLoop {
}));
}

XEvent::LeaveNotify(_) => {
XEvent::LeaveNotify(event) if event.event == self.window.raw_id() => {
self.handle_event(Event::Mouse(MouseEvent::CursorLeft));
}

XEvent::ButtonPress(event) => match event.detail {
4..=7 => {
self.handle_event(Event::Mouse(MouseEvent::WheelScrolled {
delta: match event.detail {
4 => ScrollDelta::Lines { x: 0.0, y: 1.0 },
5 => ScrollDelta::Lines { x: 0.0, y: -1.0 },
6 => ScrollDelta::Lines { x: -1.0, y: 0.0 },
7 => ScrollDelta::Lines { x: 1.0, y: 0.0 },
_ => unreachable!(),
},
modifiers: key_mods(event.state),
}));
XEvent::ButtonPress(event) if event.event == self.window.raw_id() => {
match event.detail {
4..=7 => {
self.handle_event(Event::Mouse(MouseEvent::WheelScrolled {
delta: match event.detail {
4 => ScrollDelta::Lines { x: 0.0, y: 1.0 },
5 => ScrollDelta::Lines { x: 0.0, y: -1.0 },
6 => ScrollDelta::Lines { x: -1.0, y: 0.0 },
7 => ScrollDelta::Lines { x: 1.0, y: 0.0 },
_ => unreachable!(),
},
modifiers: key_mods(event.state),
}));
}
detail => {
self.handle_event(Event::Mouse(MouseEvent::ButtonPressed {
button: mouse_id(detail),
modifiers: key_mods(event.state),
}));
}
}
detail => {
self.handle_event(Event::Mouse(MouseEvent::ButtonPressed {
button: mouse_id(detail),
modifiers: key_mods(event.state),
}));
}
},
}

XEvent::ButtonRelease(event) if !(4..=7).contains(&event.detail) => {
XEvent::ButtonRelease(event)
if event.event == self.window.raw_id() && !(4..=7).contains(&event.detail) =>
{
let button_id = mouse_id(event.detail);
self.handle_event(Event::Mouse(MouseEvent::ButtonReleased {
button: button_id,
Expand All @@ -450,31 +475,56 @@ impl EventLoop {
////
// keys
////
XEvent::KeyPress(event) => {
XEvent::KeyPress(event) if event.event == self.window.raw_id() => {
let ev = Event::Keyboard(convert_key_press_event(&event, &mut self.xkb_state));
self.handle_event(ev);
}

XEvent::KeyRelease(event) => {
XEvent::KeyRelease(event) if event.event == self.window.raw_id() => {
let ev = Event::Keyboard(convert_key_release_event(&event, &mut self.xkb_state));
self.handle_event(ev);
}

XEvent::FocusIn(_) => {
XEvent::FocusIn(event) if event.event == self.window.raw_id() => {
self.window.is_focused.set(true);
self.handle_event(Event::Window(WindowEvent::Focused));
}

XEvent::FocusOut(_) => {
XEvent::FocusOut(e) if e.event == self.window.raw_id() => {
self.window.is_focused.set(false);
self.handle_event(Event::Window(WindowEvent::Unfocused));
}

XEvent::MapNotify(_) => {
self.window.is_mapped.set(true);
self.exposed = true;
XEvent::MapNotify(e) => {
if e.window == self.window.raw_id() {
self.window.is_mapped.set(true);
}

let became_viewable = self.window.visibility_state.window_mapped(e.window);

if became_viewable {
self.exposed = true;
}
}

XEvent::UnmapNotify(e) => {
if e.window == self.window.raw_id() {
self.window.is_mapped.set(false)
}

self.window.visibility_state.window_unmapped(e.window);
}
XEvent::UnmapNotify(_) => self.window.is_mapped.set(false),

XEvent::ReparentNotify(e) => self.window.visibility_state.window_reparented(
e.window,
e.parent,
&self.window.connection.conn,
),

XEvent::DestroyNotify(e) => self
.window
.visibility_state
.window_destroyed(e.window, &self.window.connection.conn),

_ => {}
}
Expand Down
1 change: 1 addition & 0 deletions src/platform/x11/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ mod keyboard;
mod visual_info;
mod xcb_window;

mod visibility_tree;
mod window_shared;
mod window_thread;

Expand Down
Loading