linux/x11: implement window focus (#8002)

Release Notes:
- N/A
This commit is contained in:
Dzmitry Malyshau 2024-02-19 17:54:54 -08:00 committed by GitHub
parent fddb778e5f
commit b00b65b330
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 47 additions and 14 deletions

View File

@ -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:?}");
}

View File

@ -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()
}