@@ -11,7 +11,8 @@ use crate::platform::{
LinuxPlatformInner, PlatformWindow, X11Display, X11Window, X11WindowState, XcbAtoms,
};
use crate::{
- AnyWindowHandle, Bounds, DisplayId, PlatformDisplay, PlatformInput, Point, Size, WindowOptions,
+ AnyWindowHandle, Bounds, DisplayId, PlatformDisplay, PlatformInput, Point, ScrollDelta, Size,
+ TouchPhase, WindowOptions,
};
pub(crate) struct X11ClientState {
@@ -106,6 +107,14 @@ impl Client for X11Client {
window.request_refresh();
}
xcb::Event::Present(xcb::present::Event::IdleNotify(_ev)) => {}
+ xcb::Event::X(x::Event::FocusIn(ev)) => {
+ let window = self.get_window(ev.event());
+ window.set_focused(true);
+ }
+ xcb::Event::X(x::Event::FocusOut(ev)) => {
+ let window = self.get_window(ev.event());
+ window.set_focused(false);
+ }
xcb::Event::X(x::Event::KeyPress(ev)) => {
let window = self.get_window(ev.event());
let modifiers = super::modifiers_from_state(ev.state());
@@ -155,6 +164,15 @@ impl Client for X11Client {
modifiers,
click_count: 1,
}));
+ } else if ev.detail() >= 4 && ev.detail() <= 5 {
+ // https://stackoverflow.com/questions/15510472/scrollwheel-event-in-x11
+ let delta_x = if ev.detail() == 4 { 1.0 } else { -1.0 };
+ window.handle_input(PlatformInput::ScrollWheel(crate::ScrollWheelEvent {
+ position,
+ delta: ScrollDelta::Lines(Point::new(0.0, delta_x)),
+ modifiers,
+ touch_phase: TouchPhase::default(),
+ }));
} else {
log::warn!("Unknown button press: {ev:?}");
}
@@ -2,9 +2,9 @@
#![allow(unused)]
use crate::{
- platform::blade::BladeRenderer, size, Bounds, GlobalPixels, Pixels, PlatformDisplay,
- PlatformInput, PlatformInputHandler, PlatformWindow, Point, Size, WindowAppearance,
- WindowBounds, WindowOptions, X11Display,
+ platform::blade::BladeRenderer, size, Bounds, GlobalPixels, Modifiers, Pixels, PlatformAtlas,
+ PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point, PromptLevel,
+ Scene, Size, WindowAppearance, WindowBounds, WindowOptions, X11Display,
};
use blade_graphics as gpu;
use parking_lot::Mutex;
@@ -27,7 +27,7 @@ use std::{
#[derive(Default)]
struct Callbacks {
request_frame: Option<Box<dyn FnMut()>>,
- input: Option<Box<dyn FnMut(crate::PlatformInput) -> bool>>,
+ input: Option<Box<dyn FnMut(PlatformInput) -> bool>>,
active_status_change: Option<Box<dyn FnMut(bool)>>,
resize: Option<Box<dyn FnMut(Size<Pixels>, f32)>>,
fullscreen: Option<Box<dyn FnMut(bool)>>,
@@ -155,6 +155,9 @@ impl X11WindowState {
x::Cw::EventMask(
x::EventMask::EXPOSURE
| x::EventMask::STRUCTURE_NOTIFY
+ | x::EventMask::ENTER_WINDOW
+ | x::EventMask::LEAVE_WINDOW
+ | x::EventMask::FOCUS_CHANGE
| x::EventMask::KEY_PRESS
| x::EventMask::KEY_RELEASE
| x::EventMask::BUTTON_PRESS
@@ -345,6 +348,12 @@ impl X11WindowState {
}
}
}
+
+ pub fn set_focused(&self, focus: bool) {
+ if let Some(ref mut fun) = self.callbacks.lock().active_status_change {
+ fun(focus);
+ }
+ }
}
impl PlatformWindow for X11Window {
@@ -374,14 +383,20 @@ impl PlatformWindow for X11Window {
Rc::clone(&self.0.display)
}
- //todo!(linux)
fn mouse_position(&self) -> Point<Pixels> {
- Point::default()
+ let cookie = self.0.xcb_connection.send_request(&x::QueryPointer {
+ window: self.0.x_window,
+ });
+ let reply: x::QueryPointerReply = self.0.xcb_connection.wait_for_reply(cookie).unwrap();
+ Point::new(
+ (reply.root_x() as u32).into(),
+ (reply.root_y() as u32).into(),
+ )
}
//todo!(linux)
- fn modifiers(&self) -> crate::Modifiers {
- crate::Modifiers::default()
+ fn modifiers(&self) -> Modifiers {
+ Modifiers::default()
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
@@ -399,7 +414,7 @@ impl PlatformWindow for X11Window {
//todo!(linux)
fn prompt(
&self,
- _level: crate::PromptLevel,
+ _level: PromptLevel,
_msg: &str,
_detail: Option<&str>,
_answers: &[&str],
@@ -456,7 +471,7 @@ impl PlatformWindow for X11Window {
self.0.callbacks.lock().request_frame = Some(callback);
}
- fn on_input(&self, callback: Box<dyn FnMut(crate::PlatformInput) -> bool>) {
+ fn on_input(&self, callback: Box<dyn FnMut(PlatformInput) -> bool>) {
self.0.callbacks.lock().input = Some(callback);
}
@@ -489,16 +504,16 @@ impl PlatformWindow for X11Window {
}
//todo!(linux)
- fn is_topmost_for_position(&self, _position: crate::Point<Pixels>) -> bool {
+ fn is_topmost_for_position(&self, _position: Point<Pixels>) -> bool {
unimplemented!()
}
- fn draw(&self, scene: &crate::Scene) {
+ fn draw(&self, scene: &Scene) {
let mut inner = self.0.inner.lock();
inner.renderer.draw(scene);
}
- fn sprite_atlas(&self) -> sync::Arc<dyn crate::PlatformAtlas> {
+ fn sprite_atlas(&self) -> sync::Arc<dyn PlatformAtlas> {
let inner = self.0.inner.lock();
inner.renderer.sprite_atlas().clone()
}