chore(rustfmt): use nightly (#2325)

Stable rustfmt lacks a lot of features resulting in worse formatted
code, thus use nightly formatter.
This commit is contained in:
Kirill Chibisov 2024-04-26 19:11:44 +04:00 committed by GitHub
parent 7006c7ceca
commit 7b0c7b6cb2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
154 changed files with 3439 additions and 5891 deletions

View file

@ -5,7 +5,8 @@
//! X11 has a "startup notification" specification similar to Wayland's, see this URL:
//! <https://specifications.freedesktop.org/startup-notification-spec/startup-notification-latest.txt>
use super::{atoms::*, VoidCookie, X11Error, XConnection};
use super::atoms::*;
use super::{VoidCookie, X11Error, XConnection};
use std::ffi::CString;
use std::fmt::Write;
@ -105,11 +106,9 @@ impl XConnection {
0,
xproto::WindowClass::INPUT_OUTPUT,
screen.root_visual,
&xproto::CreateWindowAux::new()
.override_redirect(1)
.event_mask(
xproto::EventMask::STRUCTURE_NOTIFY | xproto::EventMask::PROPERTY_CHANGE,
),
&xproto::CreateWindowAux::new().override_redirect(1).event_mask(
xproto::EventMask::STRUCTURE_NOTIFY | xproto::EventMask::PROPERTY_CHANGE,
),
)?;
// Serialize the messages in 20-byte chunks.
@ -130,12 +129,7 @@ impl XConnection {
.try_for_each(|event| {
// Send each event in order.
self.xcb_connection()
.send_event(
false,
screen.root,
xproto::EventMask::PROPERTY_CHANGE,
event,
)
.send_event(false, screen.root, xproto::EventMask::PROPERTY_CHANGE, event)
.map(VoidCookie::ignore_error)
})?;

View file

@ -1,18 +1,15 @@
use std::{
io,
os::raw::*,
path::{Path, PathBuf},
str::Utf8Error,
sync::Arc,
};
use std::io;
use std::os::raw::*;
use std::path::{Path, PathBuf};
use std::str::Utf8Error;
use std::sync::Arc;
use percent_encoding::percent_decode;
use x11rb::protocol::xproto::{self, ConnectionExt};
use super::{
atoms::{AtomName::None as DndNone, *},
util, CookieResultExt, X11Error, XConnection,
};
use super::atoms::AtomName::None as DndNone;
use super::atoms::*;
use super::{util, CookieResultExt, X11Error, XConnection};
#[derive(Debug, Clone, Copy)]
pub enum DndState {
@ -54,13 +51,7 @@ pub struct Dnd {
impl Dnd {
pub fn new(xconn: Arc<XConnection>) -> Result<Self, X11Error> {
Ok(Dnd {
xconn,
version: None,
type_list: None,
source_window: None,
result: None,
})
Ok(Dnd { xconn, version: None, type_list: None, source_window: None, result: None })
}
pub fn reset(&mut self) {
@ -82,13 +73,13 @@ impl Dnd {
DndState::Rejected => (0, atoms[DndNone]),
};
self.xconn
.send_client_msg(
target_window,
target_window,
atoms[XdndStatus] as _,
None,
[this_window, accepted, 0, 0, action as _],
)?
.send_client_msg(target_window, target_window, atoms[XdndStatus] as _, None, [
this_window,
accepted,
0,
0,
action as _,
])?
.ignore_error();
Ok(())
@ -106,13 +97,13 @@ impl Dnd {
DndState::Rejected => (0, atoms[DndNone]),
};
self.xconn
.send_client_msg(
target_window,
target_window,
atoms[XdndFinished] as _,
None,
[this_window, accepted, action as _, 0, 0],
)?
.send_client_msg(target_window, target_window, atoms[XdndFinished] as _, None, [
this_window,
accepted,
action as _,
0,
0,
])?
.ignore_error();
Ok(())
@ -149,8 +140,7 @@ impl Dnd {
window: xproto::Window,
) -> Result<Vec<c_uchar>, util::GetPropertyError> {
let atoms = self.xconn.atoms();
self.xconn
.get_property(window, atoms[XdndSelection], atoms[TextUriList])
self.xconn.get_property(window, atoms[XdndSelection], atoms[TextUriList])
}
pub fn parse_data(&self, data: &mut [c_uchar]) -> Result<Vec<PathBuf>, DndDataParseError> {

View file

@ -16,16 +16,14 @@ use x11_dl::xlib::{
use x11rb::protocol::xinput;
use x11rb::protocol::xkb::ID as XkbId;
use x11rb::protocol::xproto::{self, ConnectionExt as _, ModMask};
use x11rb::x11_utils::ExtensionInformation;
use x11rb::x11_utils::Serialize;
use x11rb::x11_utils::{ExtensionInformation, Serialize};
use xkbcommon_dl::xkb_mod_mask_t;
use crate::dpi::{PhysicalPosition, PhysicalSize};
use crate::event::{
DeviceEvent, ElementState, Event, Ime, MouseScrollDelta, RawKeyEvent, Touch, TouchPhase,
WindowEvent,
DeviceEvent, ElementState, Event, Ime, InnerSizeWriter, MouseButton, MouseScrollDelta,
RawKeyEvent, Touch, TouchPhase, WindowEvent,
};
use crate::event::{InnerSizeWriter, MouseButton};
use crate::event_loop::ActiveEventLoop as RootAEL;
use crate::keyboard::ModifiersState;
use crate::platform_impl::common::xkb::{self, XkbState};
@ -33,10 +31,11 @@ use crate::platform_impl::platform::common::xkb::Context;
use crate::platform_impl::platform::x11::ime::{ImeEvent, ImeEventReceiver, ImeRequest};
use crate::platform_impl::platform::x11::ActiveEventLoop;
use crate::platform_impl::platform::ActiveEventLoop as PlatformActiveEventLoop;
use crate::platform_impl::x11::atoms::*;
use crate::platform_impl::x11::util::cookie::GenericEventCookie;
use crate::platform_impl::x11::{
atoms::*, mkdid, mkwid, util, CookieResultExt, Device, DeviceId, DeviceInfo, Dnd, DndState,
ImeReceiver, ScrollOrientation, UnownedWindow, WindowId,
mkdid, mkwid, util, CookieResultExt, Device, DeviceId, DeviceInfo, Dnd, DndState, ImeReceiver,
ScrollOrientation, UnownedWindow, WindowId,
};
/// The maximum amount of X modifiers to replay.
@ -91,10 +90,10 @@ impl EventProcessor {
match request {
ImeRequest::Position(window_id, x, y) => {
ime.send_xim_spot(window_id, x, y);
}
},
ImeRequest::Allow(window_id, allowed) => {
ime.set_ime_allowed(window_id, allowed);
}
},
}
}
@ -106,19 +105,19 @@ impl EventProcessor {
ImeEvent::Start => {
self.is_composing = true;
WindowEvent::Ime(Ime::Preedit("".to_owned(), None))
}
},
ImeEvent::Update(text, position) if self.is_composing => {
WindowEvent::Ime(Ime::Preedit(text, Some((position, position))))
}
},
ImeEvent::End => {
self.is_composing = false;
// Issue empty preedit on `Done`.
WindowEvent::Ime(Ime::Preedit(String::new(), None))
}
},
ImeEvent::Disabled => {
self.is_composing = false;
WindowEvent::Ime(Ime::Disabled)
}
},
_ => continue,
};
@ -182,7 +181,7 @@ impl EventProcessor {
};
self.xinput_key_input(xev.as_mut(), state, &mut callback);
}
},
xlib::GenericEvent => {
let wt = Self::window_target(&self.target);
let xev: GenericEventCookie =
@ -209,7 +208,7 @@ impl EventProcessor {
&mut callback,
);
self.xinput2_button_input(xev, state, &mut callback);
}
},
xinput2::XI_Motion => {
let xev: &XIDeviceEvent = unsafe { xev.as_event() };
self.update_mods_from_xinput2_event(
@ -219,11 +218,11 @@ impl EventProcessor {
&mut callback,
);
self.xinput2_mouse_motion(xev, &mut callback);
}
},
xinput2::XI_Enter => {
let xev: &XIEnterEvent = unsafe { xev.as_event() };
self.xinput2_mouse_enter(xev, &mut callback);
}
},
xinput2::XI_Leave => {
let xev: &XILeaveEvent = unsafe { xev.as_event() };
self.update_mods_from_xinput2_event(
@ -233,15 +232,15 @@ impl EventProcessor {
&mut callback,
);
self.xinput2_mouse_left(xev, &mut callback);
}
},
xinput2::XI_FocusIn => {
let xev: &XIFocusInEvent = unsafe { xev.as_event() };
self.xinput2_focused(xev, &mut callback);
}
},
xinput2::XI_FocusOut => {
let xev: &XIFocusOutEvent = unsafe { xev.as_event() };
self.xinput2_unfocused(xev, &mut callback);
}
},
xinput2::XI_TouchBegin | xinput2::XI_TouchUpdate | xinput2::XI_TouchEnd => {
let phase = match evtype {
xinput2::XI_TouchBegin => TouchPhase::Started,
@ -252,7 +251,7 @@ impl EventProcessor {
let xev: &XIDeviceEvent = unsafe { xev.as_event() };
self.xinput2_touch(xev, phase, &mut callback);
}
},
xinput2::XI_RawButtonPress | xinput2::XI_RawButtonRelease => {
let state = match evtype {
xinput2::XI_RawButtonPress => ElementState::Pressed,
@ -262,11 +261,11 @@ impl EventProcessor {
let xev: &XIRawEvent = unsafe { xev.as_event() };
self.xinput2_raw_button_input(xev, state, &mut callback);
}
},
xinput2::XI_RawMotion => {
let xev: &XIRawEvent = unsafe { xev.as_event() };
self.xinput2_raw_mouse_motion(xev, &mut callback);
}
},
xinput2::XI_RawKeyPress | xinput2::XI_RawKeyRelease => {
let state = match evtype {
xinput2::XI_RawKeyPress => ElementState::Pressed,
@ -276,15 +275,15 @@ impl EventProcessor {
let xev: &xinput2::XIRawEvent = unsafe { xev.as_event() };
self.xinput2_raw_key_input(xev, state, &mut callback);
}
},
xinput2::XI_HierarchyChanged => {
let xev: &XIHierarchyEvent = unsafe { xev.as_event() };
self.xinput2_hierarchy_changed(xev, &mut callback);
}
_ => {}
},
_ => {},
}
}
},
_ => {
if event_type == self.xkbext.first_event as _ {
let xev: &XkbAnyEvent = unsafe { &*(xev as *const _ as *const XkbAnyEvent) };
@ -293,7 +292,7 @@ impl EventProcessor {
if event_type == self.randr_event_offset as c_int {
self.process_dpi_change(&mut callback);
}
}
},
}
}
@ -399,10 +398,7 @@ impl EventProcessor {
let window_id = mkwid(window);
if xev.data.get_long(0) as xproto::Atom == wt.wm_delete_window {
let event = Event::WindowEvent {
window_id,
event: WindowEvent::CloseRequested,
};
let event = Event::WindowEvent { window_id, event: WindowEvent::CloseRequested };
callback(&self.target, event);
return;
}
@ -467,16 +463,16 @@ impl EventProcessor {
// where `shift = mem::size_of::<c_short>() * 8`
// Note that coordinates are in "desktop space", not "window space"
// (in X11 parlance, they're root window coordinates)
//let packed_coordinates = xev.data.get_long(2);
//let shift = mem::size_of::<libc::c_short>() * 8;
//let x = packed_coordinates >> shift;
//let y = packed_coordinates & !(x << shift);
// let packed_coordinates = xev.data.get_long(2);
// let shift = mem::size_of::<libc::c_short>() * 8;
// let x = packed_coordinates >> shift;
// let y = packed_coordinates & !(x << shift);
// By our own state flow, `version` should never be `None` at this point.
let version = self.dnd.version.unwrap_or(5);
// Action is specified in versions 2 and up, though we don't need it anyway.
//let action = xev.data.get_long(4);
// let action = xev.data.get_long(4);
let accepted = if let Some(ref type_list) = self.dnd.type_list {
type_list.contains(&atoms[TextUriList])
@ -533,8 +529,8 @@ impl EventProcessor {
}
(source_window, DndState::Accepted)
} else {
// `source_window` won't be part of our DND state if we already rejected the drop in our
// `XdndPosition` handler.
// `source_window` won't be part of our DND state if we already rejected the drop in
// our `XdndPosition` handler.
let source_window = xev.data.get_long(0) as xproto::Window;
(source_window, DndState::Rejected)
};
@ -551,10 +547,7 @@ impl EventProcessor {
if xev.message_type == atoms[XdndLeave] as c_ulong {
self.dnd.reset();
let event = Event::WindowEvent {
window_id,
event: WindowEvent::HoveredFileCancelled,
};
let event = Event::WindowEvent { window_id, event: WindowEvent::HoveredFileCancelled };
callback(&self.target, event);
}
}
@ -628,8 +621,8 @@ impl EventProcessor {
util::maybe_change(&mut shared_state_lock.inner_position, new_inner_position)
} else {
// Detect when frame extents change.
// Since this isn't synthetic, as per the notes above, this position is relative to the
// parent window.
// Since this isn't synthetic, as per the notes above, this position is relative to
// the parent window.
let rel_parent = new_inner_position;
if util::maybe_change(&mut shared_state_lock.inner_position_rel_parent, rel_parent)
{
@ -651,11 +644,8 @@ impl EventProcessor {
let mut shared_state_lock = window.shared_state_lock();
// We need to convert client area position to window position.
let frame_extents = shared_state_lock
.frame_extents
.as_ref()
.cloned()
.unwrap_or_else(|| {
let frame_extents =
shared_state_lock.frame_extents.as_ref().cloned().unwrap_or_else(|| {
let frame_extents = wt.xconn.get_frame_extents_heuristic(xwindow, wt.root);
shared_state_lock.frame_extents = Some(frame_extents.clone());
frame_extents
@ -668,24 +658,21 @@ impl EventProcessor {
drop(shared_state_lock);
if moved {
callback(
&self.target,
Event::WindowEvent {
window_id,
event: WindowEvent::Moved(outer.into()),
},
);
callback(&self.target, Event::WindowEvent {
window_id,
event: WindowEvent::Moved(outer.into()),
});
}
outer
};
if is_synthetic {
let mut shared_state_lock = window.shared_state_lock();
// If we don't use the existing adjusted value when available, then the user can screw up the
// resizing by dragging across monitors *without* dropping the window.
let (width, height) = shared_state_lock
.dpi_adjusted
.unwrap_or((xev.width as u32, xev.height as u32));
// If we don't use the existing adjusted value when available, then the user can screw
// up the resizing by dragging across monitors *without* dropping the
// window.
let (width, height) =
shared_state_lock.dpi_adjusted.unwrap_or((xev.width as u32, xev.height as u32));
let last_scale_factor = shared_state_lock.last_monitor.scale_factor;
let new_scale_factor = {
@ -719,16 +706,13 @@ impl EventProcessor {
drop(shared_state_lock);
let inner_size = Arc::new(Mutex::new(new_inner_size));
callback(
&self.target,
Event::WindowEvent {
window_id,
event: WindowEvent::ScaleFactorChanged {
scale_factor: new_scale_factor,
inner_size_writer: InnerSizeWriter::new(Arc::downgrade(&inner_size)),
},
callback(&self.target, Event::WindowEvent {
window_id,
event: WindowEvent::ScaleFactorChanged {
scale_factor: new_scale_factor,
inner_size_writer: InnerSizeWriter::new(Arc::downgrade(&inner_size)),
},
);
});
let new_inner_size = *inner_size.lock().unwrap();
drop(inner_size);
@ -775,13 +759,10 @@ impl EventProcessor {
}
if resized {
callback(
&self.target,
Event::WindowEvent {
window_id,
event: WindowEvent::Resized(new_inner_size.into()),
},
);
callback(&self.target, Event::WindowEvent {
window_id,
event: WindowEvent::Resized(new_inner_size.into()),
});
}
}
@ -812,13 +793,8 @@ impl EventProcessor {
// The purpose of it is to deliver initial focused state of the newly created
// window, given that we can't rely on `CreateNotify`, due to it being not
// sent.
let focus = self
.with_window(window, |window| window.has_focus())
.unwrap_or_default();
let event = Event::WindowEvent {
window_id,
event: WindowEvent::Focused(focus),
};
let focus = self.with_window(window, |window| window.has_focus()).unwrap_or_default();
let event = Event::WindowEvent { window_id, event: WindowEvent::Focused(focus) };
callback(&self.target, event);
}
@ -844,13 +820,7 @@ impl EventProcessor {
.expect("Failed to destroy input context");
}
callback(
&self.target,
Event::WindowEvent {
window_id,
event: WindowEvent::Destroyed,
},
);
callback(&self.target, Event::WindowEvent { window_id, event: WindowEvent::Destroyed });
}
fn property_notify<T: 'static, F>(&mut self, xev: &XPropertyEvent, mut callback: F)
@ -895,10 +865,7 @@ impl EventProcessor {
let window = xev.window as xproto::Window;
let window_id = mkwid(window);
let event = Event::WindowEvent {
window_id,
event: WindowEvent::RedrawRequested,
};
let event = Event::WindowEvent { window_id, event: WindowEvent::RedrawRequested };
callback(&self.target, event);
}
@ -937,11 +904,8 @@ impl EventProcessor {
// Only keys that can repeat should change the held_key_press state since a
// continuously held repeatable key may continue repeating after the press of a
// non-repeatable key.
let key_repeats = self
.xkb_context
.keymap_mut()
.map(|k| k.key_repeats(keycode))
.unwrap_or(false);
let key_repeats =
self.xkb_context.keymap_mut().map(|k| k.key_repeats(keycode)).unwrap_or(false);
let repeat = if key_repeats {
let is_latest_held = self.held_key_press == Some(keycode);
@ -964,16 +928,12 @@ impl EventProcessor {
// NOTE: When the modifier was captured by the XFilterEvents the modifiers for the modifier
// itself are out of sync due to XkbState being delivered before XKeyEvent, since it's
// being replayed by the XIM, thus we should replay ourselves.
let replay = if let Some(position) = self
.xfiltered_modifiers
.iter()
.rev()
.position(|&s| s == xev.serial)
let replay = if let Some(position) =
self.xfiltered_modifiers.iter().rev().position(|&s| s == xev.serial)
{
// We don't have to replay modifiers pressed before the current event if some events
// were not forwarded to us, since their state is irrelevant.
self.xfiltered_modifiers
.resize(self.xfiltered_modifiers.len() - 1 - position, 0);
self.xfiltered_modifiers.resize(self.xfiltered_modifiers.len() - 1 - position, 0);
true
} else {
false
@ -994,11 +954,7 @@ impl EventProcessor {
let event = key_processor.process_key_event(keycode, state, repeat);
let event = Event::WindowEvent {
window_id,
event: WindowEvent::KeyboardInput {
device_id,
event,
is_synthetic: false,
},
event: WindowEvent::KeyboardInput { device_id, event, is_synthetic: false },
};
callback(&self.target, event);
}
@ -1013,10 +969,8 @@ impl EventProcessor {
let wt = Self::window_target(&self.target);
if let Some(ic) = wt
.ime
.as_ref()
.and_then(|ime| ime.borrow().get_context(window as XWindow))
if let Some(ic) =
wt.ime.as_ref().and_then(|ime| ime.borrow().get_context(window as XWindow))
{
let written = wt.xconn.lookup_utf8(ic, xev);
if !written.is_empty() {
@ -1026,10 +980,8 @@ impl EventProcessor {
};
callback(&self.target, event);
let event = Event::WindowEvent {
window_id,
event: WindowEvent::Ime(Ime::Commit(written)),
};
let event =
Event::WindowEvent { window_id, event: WindowEvent::Ime(Ime::Commit(written)) };
self.is_composing = false;
callback(&self.target, event);
@ -1064,10 +1016,8 @@ impl EventProcessor {
xkb_state.update_modifiers(mask, 0, 0, 0, 0, Self::core_keyboard_group(state));
let mods: ModifiersState = xkb_state.modifiers().into();
let event = Event::WindowEvent {
window_id,
event: WindowEvent::ModifiersChanged(mods.into()),
};
let event =
Event::WindowEvent { window_id, event: WindowEvent::ModifiersChanged(mods.into()) };
callback(&self.target, event);
}
@ -1093,26 +1043,21 @@ impl EventProcessor {
}
let event = match event.detail as u32 {
xlib::Button1 => WindowEvent::MouseInput {
device_id,
state,
button: MouseButton::Left,
xlib::Button1 => {
WindowEvent::MouseInput { device_id, state, button: MouseButton::Left }
},
xlib::Button2 => WindowEvent::MouseInput {
device_id,
state,
button: MouseButton::Middle,
xlib::Button2 => {
WindowEvent::MouseInput { device_id, state, button: MouseButton::Middle }
},
xlib::Button3 => WindowEvent::MouseInput {
device_id,
state,
button: MouseButton::Right,
xlib::Button3 => {
WindowEvent::MouseInput { device_id, state, button: MouseButton::Right }
},
// Suppress emulated scroll wheel clicks, since we handle the real motion events for those.
// In practice, even clicky scroll wheels appear to be reported by evdev (and XInput2 in
// turn) as axis motion, so we don't otherwise special-case these button presses.
// Suppress emulated scroll wheel clicks, since we handle the real motion events for
// those. In practice, even clicky scroll wheels appear to be reported by
// evdev (and XInput2 in turn) as axis motion, so we don't otherwise
// special-case these button presses.
4..=7 => WindowEvent::MouseWheel {
device_id,
delta: match event.detail {
@ -1124,22 +1069,10 @@ impl EventProcessor {
},
phase: TouchPhase::Moved,
},
8 => WindowEvent::MouseInput {
device_id,
state,
button: MouseButton::Back,
},
8 => WindowEvent::MouseInput { device_id, state, button: MouseButton::Back },
9 => WindowEvent::MouseInput {
device_id,
state,
button: MouseButton::Forward,
},
x => WindowEvent::MouseInput {
device_id,
state,
button: MouseButton::Other(x as u16),
},
9 => WindowEvent::MouseInput { device_id, state, button: MouseButton::Forward },
x => WindowEvent::MouseInput { device_id, state, button: MouseButton::Other(x as u16) },
};
let event = Event::WindowEvent { window_id, event };
@ -1170,10 +1103,7 @@ impl EventProcessor {
let event = Event::WindowEvent {
window_id,
event: WindowEvent::CursorMoved {
device_id,
position,
},
event: WindowEvent::CursorMoved { device_id, position },
};
callback(&self.target, event);
} else if cursor_moved.is_none() {
@ -1199,10 +1129,8 @@ impl EventProcessor {
let x = unsafe { *value };
let event = if let Some(&mut (_, ref mut info)) = physical_device
.scroll_axes
.iter_mut()
.find(|&&mut (axis, _)| axis == i as _)
let event = if let Some(&mut (_, ref mut info)) =
physical_device.scroll_axes.iter_mut().find(|&&mut (axis, _)| axis == i as _)
{
let delta = (x - info.position) / info.increment;
info.position = x;
@ -1210,21 +1138,13 @@ impl EventProcessor {
let delta = match info.orientation {
ScrollOrientation::Horizontal => {
MouseScrollDelta::LineDelta(-delta as f32, 0.0)
}
},
ScrollOrientation::Vertical => MouseScrollDelta::LineDelta(0.0, -delta as f32),
};
WindowEvent::MouseWheel {
device_id,
delta,
phase: TouchPhase::Moved,
}
WindowEvent::MouseWheel { device_id, delta, phase: TouchPhase::Moved }
} else {
WindowEvent::AxisMotion {
device_id,
axis: i as u32,
value: unsafe { *value },
}
WindowEvent::AxisMotion { device_id, axis: i as u32, value: unsafe { *value } }
};
events.push(Event::WindowEvent { window_id, event });
@ -1253,12 +1173,11 @@ impl EventProcessor {
if let Some(all_info) = DeviceInfo::get(&wt.xconn, super::ALL_DEVICES.into()) {
let mut devices = self.devices.borrow_mut();
for device_info in all_info.iter() {
// The second expression is need for resetting to work correctly on i3, and
// presumably some other WMs. On those, `XI_Enter` doesn't include the physical
// device ID, so both `sourceid` and `deviceid` are the virtual device.
if device_info.deviceid == event.sourceid
// This is needed for resetting to work correctly on i3, and
// presumably some other WMs. On those, `XI_Enter` doesn't include
// the physical device ID, so both `sourceid` and `deviceid` are
// the virtual device.
|| device_info.attachment == event.sourceid
|| device_info.attachment == event.sourceid
{
let device_id = DeviceId(device_info.deviceid as _);
if let Some(device) = devices.get_mut(&device_id) {
@ -1271,18 +1190,13 @@ impl EventProcessor {
if self.window_exists(window) {
let position = PhysicalPosition::new(event.event_x, event.event_y);
let event = Event::WindowEvent {
window_id,
event: WindowEvent::CursorEntered { device_id },
};
let event =
Event::WindowEvent { window_id, event: WindowEvent::CursorEntered { device_id } };
callback(&self.target, event);
let event = Event::WindowEvent {
window_id,
event: WindowEvent::CursorMoved {
device_id,
position,
},
event: WindowEvent::CursorMoved { device_id, position },
};
callback(&self.target, event);
}
@ -1322,9 +1236,7 @@ impl EventProcessor {
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
if let Some(ime) = wt.ime.as_ref() {
ime.borrow_mut()
.focus(xev.event)
.expect("Failed to focus input context");
ime.borrow_mut().focus(xev.event).expect("Failed to focus input context");
}
if self.active_window == Some(window) {
@ -1342,10 +1254,7 @@ impl EventProcessor {
window.shared_state_lock().has_focus = true;
}
let event = Event::WindowEvent {
window_id,
event: WindowEvent::Focused(true),
};
let event = Event::WindowEvent { window_id, event: WindowEvent::Focused(true) };
callback(&self.target, event);
// Issue key press events for all pressed keys
@ -1370,10 +1279,7 @@ impl EventProcessor {
let event = Event::WindowEvent {
window_id,
event: WindowEvent::CursorMoved {
device_id: mkdid(pointer_id as _),
position,
},
event: WindowEvent::CursorMoved { device_id: mkdid(pointer_id as _), position },
};
callback(&self.target, event);
}
@ -1393,9 +1299,7 @@ impl EventProcessor {
}
if let Some(ime) = wt.ime.as_ref() {
ime.borrow_mut()
.unfocus(xev.event)
.expect("Failed to unfocus input context");
ime.borrow_mut().unfocus(xev.event).expect("Failed to unfocus input context");
}
if self.active_window.take() == Some(window) {
@ -1427,10 +1331,7 @@ impl EventProcessor {
window.shared_state_lock().has_focus = false;
}
let event = Event::WindowEvent {
window_id,
event: WindowEvent::Focused(false),
};
let event = Event::WindowEvent { window_id, event: WindowEvent::Focused(false) };
callback(&self.target, event)
}
}
@ -1497,10 +1398,7 @@ impl EventProcessor {
if xev.flags & xinput2::XIPointerEmulated == 0 {
let event = Event::DeviceEvent {
device_id: mkdid(xev.deviceid as xinput::DeviceId),
event: DeviceEvent::Button {
state,
button: xev.detail as u32,
},
event: DeviceEvent::Button { state, button: xev.detail as u32 },
};
callback(&self.target, event);
}
@ -1535,15 +1433,12 @@ impl EventProcessor {
1 => mouse_delta.set_y(x),
2 => scroll_delta.set_x(x as f32),
3 => scroll_delta.set_y(x as f32),
_ => {}
_ => {},
}
let event = Event::DeviceEvent {
device_id: did,
event: DeviceEvent::Motion {
axis: i as u32,
value: x,
},
event: DeviceEvent::Motion { axis: i as u32, value: x },
};
callback(&self.target, event);
@ -1589,16 +1484,10 @@ impl EventProcessor {
}
let physical_key = xkb::raw_keycode_to_physicalkey(keycode);
callback(
&self.target,
Event::DeviceEvent {
device_id,
event: DeviceEvent::Key(RawKeyEvent {
physical_key,
state,
}),
},
);
callback(&self.target, Event::DeviceEvent {
device_id,
event: DeviceEvent::Key(RawKeyEvent { physical_key, state }),
});
}
fn xinput2_hierarchy_changed<T: 'static, F>(&mut self, xev: &XIHierarchyEvent, mut callback: F)
@ -1613,21 +1502,15 @@ impl EventProcessor {
for info in infos {
if 0 != info.flags & (xinput2::XISlaveAdded | xinput2::XIMasterAdded) {
self.init_device(info.deviceid as xinput::DeviceId);
callback(
&self.target,
Event::DeviceEvent {
device_id: mkdid(info.deviceid as xinput::DeviceId),
event: DeviceEvent::Added,
},
);
callback(&self.target, Event::DeviceEvent {
device_id: mkdid(info.deviceid as xinput::DeviceId),
event: DeviceEvent::Added,
});
} else if 0 != info.flags & (xinput2::XISlaveRemoved | xinput2::XIMasterRemoved) {
callback(
&self.target,
Event::DeviceEvent {
device_id: mkdid(info.deviceid as xinput::DeviceId),
event: DeviceEvent::Removed,
},
);
callback(&self.target, Event::DeviceEvent {
device_id: mkdid(info.deviceid as xinput::DeviceId),
event: DeviceEvent::Removed,
});
let mut devices = self.devices.borrow_mut();
devices.remove(&DeviceId(info.deviceid as xinput::DeviceId));
}
@ -1669,7 +1552,7 @@ impl EventProcessor {
self.send_modifiers(window_id, mods, true, &mut callback);
}
}
}
},
xlib::XkbMapNotify => {
let xcb = wt.xconn.xcb_connection().get_raw_xcb_connection();
self.xkb_context.set_keymap_from_x11(xcb);
@ -1683,7 +1566,7 @@ impl EventProcessor {
let mods = state.modifiers().into();
self.send_modifiers(window_id, mods, true, &mut callback);
}
}
},
xlib::XkbStateNotify => {
let xev = unsafe { &*(xev as *const _ as *const xlib::XkbStateNotifyEvent) };
@ -1708,8 +1591,8 @@ impl EventProcessor {
let mods = state.modifiers().into();
self.send_modifiers(window_id, mods, true, &mut callback);
}
}
_ => {}
},
_ => {},
}
}
@ -1825,22 +1708,13 @@ impl EventProcessor {
// Build the XKB modifiers from the regular state.
let mut depressed = 0u32;
if let Some(shift) = mods_indices
.shift
.filter(|_| ModMask::SHIFT.intersects(state))
{
if let Some(shift) = mods_indices.shift.filter(|_| ModMask::SHIFT.intersects(state)) {
depressed |= 1 << shift;
}
if let Some(caps) = mods_indices
.caps
.filter(|_| ModMask::LOCK.intersects(state))
{
if let Some(caps) = mods_indices.caps.filter(|_| ModMask::LOCK.intersects(state)) {
depressed |= 1 << caps;
}
if let Some(ctrl) = mods_indices
.ctrl
.filter(|_| ModMask::CONTROL.intersects(state))
{
if let Some(ctrl) = mods_indices.ctrl.filter(|_| ModMask::CONTROL.intersects(state)) {
depressed |= 1 << ctrl;
}
if let Some(alt) = mods_indices.alt.filter(|_| ModMask::M1.intersects(state)) {
@ -1897,10 +1771,7 @@ impl EventProcessor {
// Update modifiers state and emit key events based on which keys are currently pressed.
let window_target = Self::window_target(target);
let xcb = window_target
.xconn
.xcb_connection()
.get_raw_xcb_connection();
let xcb = window_target.xconn.xcb_connection().get_raw_xcb_connection();
let keymap = match xkb_context.keymap_mut() {
Some(keymap) => keymap,
@ -1917,20 +1788,13 @@ impl EventProcessor {
None => return,
};
for keycode in window_target
.xconn
.query_keymap()
.into_iter()
.filter(|k| *k >= KEYCODE_OFFSET)
for keycode in
window_target.xconn.query_keymap().into_iter().filter(|k| *k >= KEYCODE_OFFSET)
{
let event = key_processor.process_key_event(keycode as u32, state, false);
let event = Event::WindowEvent {
window_id,
event: WindowEvent::KeyboardInput {
device_id,
event,
is_synthetic: true,
},
event: WindowEvent::KeyboardInput { device_id, event, is_synthetic: true },
};
callback(target, event);
}
@ -1941,9 +1805,7 @@ impl EventProcessor {
F: FnMut(&RootAEL, Event<T>),
{
let wt = Self::window_target(&self.target);
wt.xconn
.reload_database()
.expect("failed to reload Xft database");
wt.xconn.reload_database().expect("failed to reload Xft database");
// In the future, it would be quite easy to emit monitor hotplug events.
let prev_list = {
@ -1954,10 +1816,7 @@ impl EventProcessor {
}
};
let new_list = wt
.xconn
.available_monitors()
.expect("Failed to get monitor list");
let new_list = wt.xconn.available_monitors().expect("Failed to get monitor list");
for new_monitor in new_list {
// Previous list may be empty, in case of disconnecting and
// reconnecting the only one monitor. We still need to emit events in
@ -1988,13 +1847,13 @@ fn is_first_touch(first: &mut Option<u64>, num: &mut u32, id: u64, phase: TouchP
*first = Some(id);
}
*num += 1;
}
},
TouchPhase::Cancelled | TouchPhase::Ended => {
if *first == Some(id) {
*first = None;
}
*num = num.saturating_sub(1);
}
},
_ => (),
}

View file

@ -1 +1,5 @@
pub use x11_dl::{error::OpenError, xcursor::*, xinput2::*, xlib::*, xlib_xcb::*};
pub use x11_dl::error::OpenError;
pub use x11_dl::xcursor::*;
pub use x11_dl::xinput2::*;
pub use x11_dl::xlib::*;
pub use x11_dl::xlib_xcb::*;

View file

@ -1,12 +1,13 @@
use std::{collections::HashMap, os::raw::c_char, ptr, sync::Arc};
use std::collections::HashMap;
use std::os::raw::c_char;
use std::ptr;
use std::sync::Arc;
use super::{ffi, XConnection, XError};
use super::{
context::{ImeContext, ImeContextCreationError},
inner::{close_im, ImeInner},
input_method::PotentialInputMethods,
};
use super::context::{ImeContext, ImeContextCreationError};
use super::inner::{close_im, ImeInner};
use super::input_method::PotentialInputMethods;
pub(crate) unsafe fn xim_set_callback(
xconn: &Arc<XConnection>,
@ -24,8 +25,8 @@ pub(crate) unsafe fn xim_set_callback(
// available. Note that this has nothing to do with what input methods are open or able to be
// opened, and simply uses the modifiers that are set when the callback is set.
// * This is called per locale modifier, not per input method opened with that locale modifier.
// * Trying to set this for multiple locale modifiers causes problems, i.e. one of the rebuilt
// input contexts would always silently fail to use the input method.
// * Trying to set this for multiple locale modifiers causes problems, i.e. one of the rebuilt input
// contexts would always silently fail to use the input method.
pub(crate) unsafe fn set_instantiate_callback(
xconn: &Arc<XConnection>,
client_data: ffi::XPointer,
@ -119,18 +120,12 @@ unsafe fn replace_im(inner: *mut ImeInner) -> Result<(), ReplaceImError> {
let spot = old_context.as_ref().map(|old_context| old_context.ic_spot);
// Check if the IME was allowed on that context.
let is_allowed = old_context
.as_ref()
.map(|old_context| old_context.is_allowed())
.unwrap_or_default();
let is_allowed =
old_context.as_ref().map(|old_context| old_context.is_allowed()).unwrap_or_default();
// We can't use the style from the old context here, since it may change on reload, so
// pick style from the new XIM based on the old state.
let style = if is_allowed {
new_im.preedit_style
} else {
new_im.none_style
};
let style = if is_allowed { new_im.preedit_style } else { new_im.none_style };
let new_context = {
let result = unsafe {
@ -208,7 +203,7 @@ pub unsafe extern "C" fn xim_destroy_callback(
Err(err) => {
// We have no usable input methods!
panic!("Failed to open fallback input method: {err:?}");
}
},
}
}
}

View file

@ -26,10 +26,7 @@ type XIMProcNonnull = unsafe extern "C" fn(ffi::XIM, ffi::XPointer, ffi::XPointe
/// Wrapper for creating XIM callbacks.
#[inline]
fn create_xim_callback(client_data: ffi::XPointer, callback: XIMProcNonnull) -> ffi::XIMCallback {
XIMCallback {
client_data,
callback: Some(callback),
}
XIMCallback { client_data, callback: Some(callback) }
}
/// The server started preedit.
@ -68,9 +65,7 @@ extern "C" fn preedit_done_callback(
}
fn calc_byte_position(text: &[char], pos: usize) -> usize {
text.iter()
.take(pos)
.fold(0, |byte_pos, text| byte_pos + text.len_utf8())
text.iter().take(pos).fold(0, |byte_pos, text| byte_pos + text.len_utf8())
}
/// Preedit text information to be drawn inline by the client.
@ -112,9 +107,7 @@ extern "C" fn preedit_draw_callback(
let new_text = unsafe { CStr::from_ptr(new_text) };
String::from(new_text.to_str().expect("Invalid UTF-8 String from IME"))
.chars()
.collect()
String::from(new_text.to_str().expect("Invalid UTF-8 String from IME")).chars().collect()
};
let mut old_text_tail = client_data.text.split_off(chg_range.end);
client_data.text.truncate(chg_range.start);
@ -171,12 +164,7 @@ impl PreeditCallbacks {
let caret_callback = create_xim_callback(client_data, preedit_caret_callback);
let draw_callback = create_xim_callback(client_data, preedit_draw_callback);
PreeditCallbacks {
start_callback,
done_callback,
caret_callback,
draw_callback,
}
PreeditCallbacks { start_callback, done_callback, caret_callback, draw_callback }
}
}
@ -195,8 +183,8 @@ pub struct ImeContext {
pub(crate) ic: ffi::XIC,
pub(crate) ic_spot: ffi::XPoint,
pub(crate) style: Style,
// Since the data is passed shared between X11 XIM callbacks, but couldn't be directly free from
// there we keep the pointer to automatically deallocate it.
// Since the data is passed shared between X11 XIM callbacks, but couldn't be directly free
// from there we keep the pointer to automatically deallocate it.
_client_data: Box<ImeContextClientData>,
}
@ -233,9 +221,7 @@ impl ImeContext {
}
.ok_or(ImeContextCreationError::Null)?;
xconn
.check_errors()
.map_err(ImeContextCreationError::XError)?;
xconn.check_errors().map_err(ImeContextCreationError::XError)?;
let mut context = ImeContext {
ic,

View file

@ -1,11 +1,11 @@
use std::{collections::HashMap, mem, sync::Arc};
use std::collections::HashMap;
use std::mem;
use std::sync::Arc;
use super::{ffi, XConnection, XError};
use super::{
context::ImeContext,
input_method::{InputMethod, PotentialInputMethods},
};
use super::context::ImeContext;
use super::input_method::{InputMethod, PotentialInputMethods};
use crate::platform_impl::platform::x11::ime::ImeEventSender;
pub(crate) unsafe fn close_im(xconn: &Arc<XConnection>, im: ffi::XIM) -> Result<(), XError> {

View file

@ -1,13 +1,10 @@
use std::{
env,
ffi::{CStr, CString, IntoStringError},
fmt,
os::raw::{c_char, c_ulong, c_ushort},
ptr,
sync::{Arc, Mutex},
};
use std::ffi::{CStr, CString, IntoStringError};
use std::os::raw::{c_char, c_ulong, c_ushort};
use std::sync::{Arc, Mutex};
use std::{env, fmt, ptr};
use super::{super::atoms::*, ffi, util, XConnection, XError};
use super::super::atoms::*;
use super::{ffi, util, XConnection, XError};
use x11rb::protocol::xproto;
static GLOBAL_LOCK: Mutex<()> = Mutex::new(());
@ -18,17 +15,12 @@ unsafe fn open_im(xconn: &Arc<XConnection>, locale_modifiers: &CStr) -> Option<f
// XSetLocaleModifiers returns...
// * The current locale modifiers if it's given a NULL pointer.
// * The new locale modifiers if we succeeded in setting them.
// * NULL if the locale modifiers string is malformed or if the
// current locale is not supported by Xlib.
// * NULL if the locale modifiers string is malformed or if the current locale is not supported
// by Xlib.
unsafe { (xconn.xlib.XSetLocaleModifiers)(locale_modifiers.as_ptr()) };
let im = unsafe {
(xconn.xlib.XOpenIM)(
xconn.display,
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
)
(xconn.xlib.XOpenIM)(xconn.display, ptr::null_mut(), ptr::null_mut(), ptr::null_mut())
};
if im.is_null() {
@ -73,10 +65,10 @@ impl InputMethod {
.for_each(|style| match *style {
XIM_PREEDIT_STYLE => {
preedit_style = Some(Style::Preedit(*style));
}
},
XIM_NOTHING_STYLE if preedit_style.is_none() => {
preedit_style = Some(Style::Nothing(*style))
}
},
XIM_NONE_STYLE => none_style = Some(Style::None(*style)),
_ => (),
});
@ -91,12 +83,7 @@ impl InputMethod {
let preedit_style = preedit_style.unwrap_or_else(|| none_style.unwrap());
let none_style = none_style.unwrap_or(preedit_style);
Some(InputMethod {
im,
_name: name,
preedit_style,
none_style,
})
Some(InputMethod { im, _name: name, preedit_style, none_style })
}
}
@ -232,10 +219,7 @@ impl InputMethodName {
pub fn from_str(string: &str) -> Self {
let c_string =
CString::new(string).expect("String used to construct CString contained null byte");
InputMethodName {
c_string,
string: string.to_owned(),
}
InputMethodName { c_string, string: string.to_owned() }
}
}
@ -253,17 +237,11 @@ struct PotentialInputMethod {
impl PotentialInputMethod {
pub fn from_string(string: String) -> Self {
PotentialInputMethod {
name: InputMethodName::from_string(string),
successful: None,
}
PotentialInputMethod { name: InputMethodName::from_string(string), successful: None }
}
pub fn from_str(string: &str) -> Self {
PotentialInputMethod {
name: InputMethodName::from_str(string),
successful: None,
}
PotentialInputMethod { name: InputMethodName::from_str(string), successful: None }
}
pub fn reset(&mut self) {
@ -297,9 +275,7 @@ pub(crate) struct PotentialInputMethods {
impl PotentialInputMethods {
pub fn new(xconn: &Arc<XConnection>) -> Self {
let xmodifiers = env::var("XMODIFIERS")
.ok()
.map(PotentialInputMethod::from_string);
let xmodifiers = env::var("XMODIFIERS").ok().map(PotentialInputMethod::from_string);
PotentialInputMethods {
// Since passing "" to XSetLocaleModifiers results in it defaulting to the value of
// XMODIFIERS, it's worth noting what happens if XMODIFIERS is also "". If simply

View file

@ -5,10 +5,8 @@ mod context;
mod inner;
mod input_method;
use std::sync::{
mpsc::{Receiver, Sender},
Arc,
};
use std::sync::mpsc::{Receiver, Sender};
use std::sync::Arc;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
@ -16,13 +14,11 @@ use tracing::debug;
use super::{ffi, util, XConnection, XError};
use self::callbacks::*;
use self::context::ImeContext;
pub use self::context::ImeContextCreationError;
use self::{
callbacks::*,
context::ImeContext,
inner::{close_im, ImeInner},
input_method::{PotentialInputMethods, Style},
};
use self::inner::{close_im, ImeInner};
use self::input_method::{PotentialInputMethods, Style};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
@ -73,10 +69,8 @@ impl Ime {
let mut inner = Box::new(ImeInner::new(xconn, potential_input_methods, event_sender));
let inner_ptr = Box::into_raw(inner);
let client_data = inner_ptr as _;
let destroy_callback = ffi::XIMCallback {
client_data,
callback: Some(xim_destroy_callback),
};
let destroy_callback =
ffi::XIMCallback { client_data, callback: Some(xim_destroy_callback) };
inner = unsafe { Box::from_raw(inner_ptr) };
inner.destroy_callback = destroy_callback;
(inner, client_data)
@ -105,9 +99,7 @@ impl Ime {
inner.im = Some(input_method);
Ok(Ime { xconn, inner })
} else {
Err(ImeCreationError::OpenFailure(Box::new(
inner.potential_input_methods,
)))
Err(ImeCreationError::OpenFailure(Box::new(inner.potential_input_methods)))
}
}
@ -129,11 +121,7 @@ impl Ime {
None
} else {
let im = self.inner.im.as_ref().unwrap();
let style = if with_preedit {
im.preedit_style
} else {
im.none_style
};
let style = if with_preedit { im.preedit_style } else { im.none_style };
let context = unsafe {
ImeContext::new(
@ -159,10 +147,7 @@ impl Ime {
ImeEvent::Enabled
};
self.inner
.event_sender
.send((window, event))
.expect("Failed to send enabled event");
self.inner.event_sender.send((window, event)).expect("Failed to send enabled event");
Some(context)
};

View file

@ -3,7 +3,6 @@
use std::cell::{Cell, RefCell};
use std::collections::{HashMap, HashSet, VecDeque};
use std::ffi::CStr;
use std::fmt;
use std::marker::PhantomData;
use std::mem::MaybeUninit;
use std::ops::Deref;
@ -12,11 +11,11 @@ use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
use std::sync::mpsc::{self, Receiver, Sender, TryRecvError};
use std::sync::{Arc, Weak};
use std::time::{Duration, Instant};
use std::{ptr, slice, str};
use std::{fmt, ptr, slice, str};
use calloop::generic::Generic;
use calloop::EventLoop as Loop;
use calloop::{ping::Ping, Readiness};
use calloop::ping::Ping;
use calloop::{EventLoop as Loop, Readiness};
use libc::{setlocale, LC_CTYPE};
use tracing::warn;
@ -78,10 +77,7 @@ struct WakeSender<T> {
impl<T> Clone for WakeSender<T> {
fn clone(&self) -> Self {
Self {
sender: self.sender.clone(),
waker: self.waker.clone(),
}
Self { sender: self.sender.clone(), waker: self.waker.clone() }
}
}
@ -104,6 +100,7 @@ impl<T> PeekableReceiver<T> {
pub fn from_recv(recv: Receiver<T>) -> Self {
Self { recv, first: None }
}
pub fn has_incoming(&mut self) -> bool {
if self.first.is_some() {
return true;
@ -113,14 +110,15 @@ impl<T> PeekableReceiver<T> {
Ok(v) => {
self.first = Some(v);
true
}
},
Err(TryRecvError::Empty) => false,
Err(TryRecvError::Disconnected) => {
warn!("Channel was disconnected when checking incoming");
false
}
},
}
}
pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
if let Some(first) = self.first.take() {
return Ok(first);
@ -171,9 +169,7 @@ pub struct EventLoopProxy<T: 'static> {
impl<T: 'static> Clone for EventLoopProxy<T> {
fn clone(&self) -> Self {
EventLoopProxy {
user_sender: self.user_sender.clone(),
}
EventLoopProxy { user_sender: self.user_sender.clone() }
}
}
@ -223,9 +219,8 @@ impl<T: 'static> EventLoop<T> {
let ime = ime.ok().map(RefCell::new);
let randr_event_offset = xconn
.select_xrandr_input(root)
.expect("Failed to query XRandR extension");
let randr_event_offset =
xconn.select_xrandr_input(root).expect("Failed to query XRandR extension");
let xi2ext = xconn
.xcb_connection()
@ -315,10 +310,8 @@ impl<T: 'static> EventLoop<T> {
// Set initial device event filter.
window_target.update_listen_device_events(true);
let root_window_target = RootAEL {
p: PlatformActiveEventLoop::X(window_target),
_marker: PhantomData,
};
let root_window_target =
RootAEL { p: PlatformActiveEventLoop::X(window_target), _marker: PhantomData };
let event_processor = EventProcessor {
target: root_window_target,
@ -372,18 +365,13 @@ impl<T: 'static> EventLoop<T> {
activation_receiver: PeekableReceiver::from_recv(activation_token_channel),
user_receiver: PeekableReceiver::from_recv(user_channel),
user_sender,
state: EventLoopState {
x11_readiness: Readiness::EMPTY,
},
state: EventLoopState { x11_readiness: Readiness::EMPTY },
}
}
pub fn create_proxy(&self) -> EventLoopProxy<T> {
EventLoopProxy {
user_sender: WakeSender {
sender: self.user_sender.clone(),
waker: self.waker.clone(),
},
user_sender: WakeSender { sender: self.user_sender.clone(), waker: self.waker.clone() },
}
}
@ -399,13 +387,13 @@ impl<T: 'static> EventLoop<T> {
match self.pump_events(None, &mut event_handler) {
PumpStatus::Exit(0) => {
break Ok(());
}
},
PumpStatus::Exit(code) => {
break Err(EventLoopError::ExitFailure(code));
}
},
_ => {
continue;
}
},
}
};
@ -471,17 +459,15 @@ impl<T: 'static> EventLoop<T> {
ControlFlow::Poll => Some(Duration::ZERO),
ControlFlow::WaitUntil(wait_deadline) => {
Some(wait_deadline.saturating_duration_since(start))
}
},
};
min_timeout(control_flow_timeout, timeout)
};
self.state.x11_readiness = Readiness::EMPTY;
if let Err(error) = self
.event_loop
.dispatch(timeout, &mut self.state)
.map_err(std::io::Error::from)
if let Err(error) =
self.event_loop.dispatch(timeout, &mut self.state).map_err(std::io::Error::from)
{
tracing::error!("Failed to poll for events: {error:?}");
let exit_code = error.raw_os_error().unwrap_or(1);
@ -493,23 +479,14 @@ impl<T: 'static> EventLoop<T> {
// to be considered here
let cause = match self.control_flow() {
ControlFlow::Poll => StartCause::Poll,
ControlFlow::Wait => StartCause::WaitCancelled {
start,
requested_resume: None,
},
ControlFlow::Wait => StartCause::WaitCancelled { start, requested_resume: None },
ControlFlow::WaitUntil(deadline) => {
if Instant::now() < deadline {
StartCause::WaitCancelled {
start,
requested_resume: Some(deadline),
}
StartCause::WaitCancelled { start, requested_resume: Some(deadline) }
} else {
StartCause::ResumeTimeReached {
start,
requested_resume: deadline,
}
StartCause::ResumeTimeReached { start, requested_resume: deadline }
}
}
},
};
// False positive / spurious wake ups could lead to us spamming
@ -521,10 +498,7 @@ impl<T: 'static> EventLoop<T> {
// running a loop iteration.
// If we don't have any pending `_receiver`
if !self.has_pending()
&& !matches!(
&cause,
StartCause::ResumeTimeReached { .. } | StartCause::Poll
)
&& !matches!(&cause, StartCause::ResumeTimeReached { .. } | StartCause::Poll)
{
return;
}
@ -549,11 +523,9 @@ impl<T: 'static> EventLoop<T> {
// Empty activation tokens.
while let Ok((window_id, serial)) = self.activation_receiver.try_recv() {
let token = self
.event_processor
.with_window(window_id.0 as xproto::Window, |window| {
window.generate_activation_token()
});
let token = self.event_processor.with_window(window_id.0 as xproto::Window, |window| {
window.generate_activation_token()
});
match token {
Some(Ok(token)) => {
@ -565,11 +537,11 @@ impl<T: 'static> EventLoop<T> {
},
};
callback(event, &self.event_processor.target)
}
},
Some(Err(e)) => {
tracing::error!("Failed to get activation token: {}", e);
}
None => {}
},
None => {},
}
}
@ -591,10 +563,7 @@ impl<T: 'static> EventLoop<T> {
for window_id in windows {
let window_id = crate::window::WindowId(window_id);
callback(
Event::WindowEvent {
window_id,
event: WindowEvent::RedrawRequested,
},
Event::WindowEvent { window_id, event: WindowEvent::RedrawRequested },
&self.event_processor.target,
);
}
@ -614,19 +583,18 @@ impl<T: 'static> EventLoop<T> {
while unsafe { self.event_processor.poll_one_event(xev.as_mut_ptr()) } {
let mut xev = unsafe { xev.assume_init() };
self.event_processor
.process_event(&mut xev, |window_target, event| {
if let Event::WindowEvent {
window_id: crate::window::WindowId(wid),
event: WindowEvent::RedrawRequested,
} = event
{
let window_target = EventProcessor::window_target(window_target);
window_target.redraw_sender.send(wid).unwrap();
} else {
callback(event, window_target);
}
});
self.event_processor.process_event(&mut xev, |window_target, event| {
if let Event::WindowEvent {
window_id: crate::window::WindowId(wid),
event: WindowEvent::RedrawRequested,
} = event
{
let window_target = EventProcessor::window_target(window_target);
window_target.redraw_sender.send(wid).unwrap();
} else {
callback(event, window_target);
}
});
}
}
@ -679,9 +647,7 @@ impl ActiveEventLoop {
}
pub(crate) fn create_custom_cursor(&self, cursor: CustomCursorSource) -> RootCustomCursor {
RootCustomCursor {
inner: PlatformCustomCursor::X(CustomCursor::new(self, cursor.inner)),
}
RootCustomCursor { inner: PlatformCustomCursor::X(CustomCursor::new(self, cursor.inner)) }
}
pub fn listen_device_events(&self, allowed: DeviceEvents) {
@ -761,9 +727,7 @@ impl ActiveEventLoop {
impl<T: 'static> EventLoopProxy<T> {
pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed<T>> {
self.user_sender
.send(event)
.map_err(|e| EventLoopClosed(e.0))
self.user_sender.send(event).map_err(|e| EventLoopClosed(e.0))
}
}
@ -783,11 +747,7 @@ impl<'a> DeviceInfo<'a> {
if info.is_null() || count == 0 {
None
} else {
Some(DeviceInfo {
xconn,
info,
count: count as usize,
})
Some(DeviceInfo { xconn, info, count: count as usize })
}
}
}
@ -802,6 +762,7 @@ impl<'a> Drop for DeviceInfo<'a> {
impl<'a> Deref for DeviceInfo<'a> {
type Target = [ffi::XIDeviceInfo];
fn deref(&self) -> &Self::Target {
unsafe { slice::from_raw_parts(self.info, self.count) }
}
@ -821,6 +782,7 @@ pub(crate) struct Window(Arc<UnownedWindow>);
impl Deref for Window {
type Target = UnownedWindow;
#[inline]
fn deref(&self) -> &UnownedWindow {
&self.0
@ -833,10 +795,7 @@ impl Window {
attribs: WindowAttributes,
) -> Result<Self, RootOsError> {
let window = Arc::new(UnownedWindow::new(event_loop, attribs)?);
event_loop
.windows
.borrow_mut()
.insert(window.id(), Arc::downgrade(&window));
event_loop.windows.borrow_mut().insert(window.id(), Arc::downgrade(&window));
Ok(Window(window))
}
}
@ -846,10 +805,7 @@ impl Drop for Window {
let window = self.deref();
let xconn = &window.xconn;
if let Ok(c) = xconn
.xcb_connection()
.destroy_window(window.id().0 as xproto::Window)
{
if let Ok(c) = xconn.xcb_connection().destroy_window(window.id().0 as xproto::Window) {
c.ignore_error();
}
}
@ -909,15 +865,11 @@ impl fmt::Display for X11Error {
),
X11Error::MissingExtension(s) => write!(f, "Missing X11 extension: {}", s),
X11Error::NoSuchVisual(visualid) => {
write!(
f,
"Could not find a matching X11 visual for ID `{:x}`",
visualid
)
}
write!(f, "Could not find a matching X11 visual for ID `{:x}`", visualid)
},
X11Error::XsettingsParse(err) => {
write!(f, "Failed to parse xsettings: {:?}", err)
}
},
}
}
}
@ -1053,27 +1005,21 @@ impl Device {
let ty = unsafe { (*class_ptr)._type };
if ty == ffi::XIScrollClass {
let info = unsafe { &*(class_ptr as *const ffi::XIScrollClassInfo) };
scroll_axes.push((
info.number,
ScrollAxis {
increment: info.increment,
orientation: match info.scroll_type {
ffi::XIScrollTypeHorizontal => ScrollOrientation::Horizontal,
ffi::XIScrollTypeVertical => ScrollOrientation::Vertical,
_ => unreachable!(),
},
position: 0.0,
scroll_axes.push((info.number, ScrollAxis {
increment: info.increment,
orientation: match info.scroll_type {
ffi::XIScrollTypeHorizontal => ScrollOrientation::Horizontal,
ffi::XIScrollTypeVertical => ScrollOrientation::Vertical,
_ => unreachable!(),
},
));
position: 0.0,
}));
}
}
}
let mut device = Device {
_name: name.into_owned(),
scroll_axes,
attachment: info.attachment,
};
let mut device =
Device { _name: name.into_owned(), scroll_axes, attachment: info.attachment };
device.reset_scroll_position(info);
device
}
@ -1084,10 +1030,8 @@ impl Device {
let ty = unsafe { (*class_ptr)._type };
if ty == ffi::XIValuatorClass {
let info = unsafe { &*(class_ptr as *const ffi::XIValuatorClassInfo) };
if let Some(&mut (_, ref mut axis)) = self
.scroll_axes
.iter_mut()
.find(|&&mut (axis, _)| axis == info.number)
if let Some(&mut (_, ref mut axis)) =
self.scroll_axes.iter_mut().find(|&&mut (axis, _)| axis == info.number)
{
axis.position = info.value;
}

View file

@ -1,15 +1,9 @@
use super::{util, X11Error, XConnection};
use crate::{
dpi::{PhysicalPosition, PhysicalSize},
platform_impl::VideoModeHandle as PlatformVideoModeHandle,
};
use x11rb::{
connection::RequestConnection,
protocol::{
randr::{self, ConnectionExt as _},
xproto,
},
};
use crate::dpi::{PhysicalPosition, PhysicalSize};
use crate::platform_impl::VideoModeHandle as PlatformVideoModeHandle;
use x11rb::connection::RequestConnection;
use x11rb::protocol::randr::{self, ConnectionExt as _};
use x11rb::protocol::xproto;
// Used for testing. This should always be committed as false.
const DISABLE_MONITOR_LIST_CACHING: bool = false;
@ -240,18 +234,12 @@ impl XConnection {
// Pipeline all of the get-crtc requests.
let mut crtc_cookies = Vec::with_capacity(resources.crtcs().len());
for &crtc in resources.crtcs() {
crtc_cookies.push(
self.xcb_connection()
.randr_get_crtc_info(crtc, x11rb::CURRENT_TIME)?,
);
crtc_cookies
.push(self.xcb_connection().randr_get_crtc_info(crtc, x11rb::CURRENT_TIME)?);
}
// Do this here so we do all of our requests in one shot.
let primary = self
.xcb_connection()
.randr_get_output_primary(root.root)?
.reply()?
.output;
let primary = self.xcb_connection().randr_get_output_primary(root.root)?.reply()?.output;
let mut crtc_infos = Vec::with_capacity(crtc_cookies.len());
for cookie in crtc_cookies {
@ -293,7 +281,7 @@ impl XConnection {
*monitors_lock = Some(monitors.clone());
}
Ok(monitors)
}
},
}
}
@ -347,9 +335,7 @@ impl ScreenResources {
(major_version, minor_version): (u32, u32),
) -> Result<Self, X11Error> {
if (major_version == 1 && minor_version >= 3) || major_version > 1 {
let reply = conn
.randr_get_screen_resources_current(root.root)?
.reply()?;
let reply = conn.randr_get_screen_resources_current(root.root)?.reply()?;
Ok(Self::from_get_screen_resources_current_reply(reply))
} else {
let reply = conn.randr_get_screen_resources(root.root)?.reply()?;
@ -358,18 +344,12 @@ impl ScreenResources {
}
pub(crate) fn from_get_screen_resources_reply(reply: randr::GetScreenResourcesReply) -> Self {
Self {
modes: reply.modes,
crtcs: reply.crtcs,
}
Self { modes: reply.modes, crtcs: reply.crtcs }
}
pub(crate) fn from_get_screen_resources_current_reply(
reply: randr::GetScreenResourcesCurrentReply,
) -> Self {
Self {
modes: reply.modes,
crtcs: reply.crtcs,
}
Self { modes: reply.modes, crtcs: reply.crtcs }
}
}

View file

@ -1,13 +1,12 @@
use std::{
ffi::CString,
hash::{Hash, Hasher},
iter, slice,
sync::Arc,
};
use std::ffi::CString;
use std::hash::{Hash, Hasher};
use std::sync::Arc;
use std::{iter, slice};
use x11rb::connection::Connection;
use crate::{platform_impl::PlatformCustomCursorSource, window::CursorIcon};
use crate::platform_impl::PlatformCustomCursorSource;
use crate::window::CursorIcon;
use super::super::ActiveEventLoop;
use super::*;
@ -21,13 +20,11 @@ impl XConnection {
.entry(cursor)
.or_insert_with(|| self.get_cursor(cursor));
self.update_cursor(window, cursor)
.expect("Failed to set cursor");
self.update_cursor(window, cursor).expect("Failed to set cursor");
}
pub(crate) fn set_custom_cursor(&self, window: xproto::Window, cursor: &CustomCursor) {
self.update_cursor(window, cursor.inner.cursor)
.expect("Failed to set cursor");
self.update_cursor(window, cursor.inner.cursor).expect("Failed to set cursor");
}
fn create_empty_cursor(&self) -> ffi::Cursor {
@ -151,12 +148,7 @@ impl CustomCursor {
let cursor =
(event_loop.xconn.xcursor.XcursorImageLoadCursor)(event_loop.xconn.display, ximage);
(event_loop.xconn.xcursor.XcursorImageDestroy)(ximage);
Self {
inner: Arc::new(CustomCursorInner {
xconn: event_loop.xconn.clone(),
cursor,
}),
}
Self { inner: Arc::new(CustomCursorInner { xconn: event_loop.xconn.clone(), cursor }) }
}
}
}

View file

@ -15,12 +15,7 @@ impl AaRect {
pub fn new((x, y): (i32, i32), (width, height): (u32, u32)) -> Self {
let (x, y) = (x as i64, y as i64);
let (width, height) = (width as i64, height as i64);
AaRect {
x,
y,
width,
height,
}
AaRect { x, y, width, height }
}
pub fn contains_point(&self, x: i64, y: i64) -> bool {
@ -50,12 +45,7 @@ pub struct FrameExtents {
impl FrameExtents {
pub fn new(left: u32, right: u32, top: u32, bottom: u32) -> Self {
FrameExtents {
left,
right,
top,
bottom,
}
FrameExtents { left, right, top, bottom }
}
pub fn from_border(border: u32) -> Self {
@ -80,10 +70,7 @@ impl FrameExtentsHeuristic {
pub fn inner_pos_to_outer(&self, x: i32, y: i32) -> (i32, i32) {
use self::FrameExtentsHeuristicPath::*;
if self.heuristic_path != UnsupportedBordered {
(
x - self.frame_extents.left as i32,
y - self.frame_extents.top as i32,
)
(x - self.frame_extents.left as i32, y - self.frame_extents.top as i32)
} else {
(x, y)
}
@ -92,14 +79,10 @@ impl FrameExtentsHeuristic {
pub fn inner_size_to_outer(&self, width: u32, height: u32) -> (u32, u32) {
(
width.saturating_add(
self.frame_extents
.left
.saturating_add(self.frame_extents.right) as _,
self.frame_extents.left.saturating_add(self.frame_extents.right) as _
),
height.saturating_add(
self.frame_extents
.top
.saturating_add(self.frame_extents.bottom) as _,
self.frame_extents.top.saturating_add(self.frame_extents.bottom) as _
),
)
}
@ -112,10 +95,7 @@ impl XConnection {
window: xproto::Window,
root: xproto::Window,
) -> Result<xproto::TranslateCoordinatesReply, X11Error> {
self.xcb_connection()
.translate_coordinates(window, root, 0, 0)?
.reply()
.map_err(Into::into)
self.xcb_connection().translate_coordinates(window, root, 0, 0)?.reply().map_err(Into::into)
}
// This is adequate for inner_size
@ -123,10 +103,7 @@ impl XConnection {
&self,
window: xproto::Window,
) -> Result<xproto::GetGeometryReply, X11Error> {
self.xcb_connection()
.get_geometry(window)?
.reply()
.map_err(Into::into)
self.xcb_connection().get_geometry(window)?.reply().map_err(Into::into)
}
fn get_frame_extents(&self, window: xproto::Window) -> Option<FrameExtents> {
@ -141,11 +118,7 @@ impl XConnection {
// support this. As this is part of EWMH (Extended Window Manager Hints), it's likely to
// be unsupported by many smaller WMs.
let extents: Option<Vec<u32>> = self
.get_property(
window,
extents_atom,
xproto::Atom::from(xproto::AtomEnum::CARDINAL),
)
.get_property(window, extents_atom, xproto::Atom::from(xproto::AtomEnum::CARDINAL))
.ok();
extents.and_then(|extents| {
@ -171,11 +144,7 @@ impl XConnection {
}
let client_list: Option<Vec<xproto::Window>> = self
.get_property(
root,
client_list_atom,
xproto::Atom::from(xproto::AtomEnum::WINDOW),
)
.get_property(root, client_list_atom, xproto::Atom::from(xproto::AtomEnum::WINDOW))
.ok();
client_list.map(|client_list| client_list.contains(&(window as xproto::Window)))
@ -221,14 +190,9 @@ impl XConnection {
};
let (width, height, border) = {
let inner_geometry = self
.get_geometry(window)
.expect("Failed to get inner window geometry");
(
inner_geometry.width,
inner_geometry.height,
inner_geometry.border_width,
)
let inner_geometry =
self.get_geometry(window).expect("Failed to get inner window geometry");
(inner_geometry.width, inner_geometry.height, inner_geometry.border_width)
};
// The first condition is only false for un-nested windows, but isn't always false for
@ -253,39 +217,29 @@ impl XConnection {
// known discrepancies:
// * Mutter/Muffin/Budgie gives decorated windows a margin of 9px (only 7px on top) in
// addition to a 1px semi-transparent border. The margin can be easily observed by
// using a screenshot tool to get a screenshot of a selected window, and is
// presumably used for drawing drop shadows. Getting window geometry information
// via hierarchy-climbing results in this margin being included in both the
// position and outer size, so a window positioned at (0, 0) would be reported as
// having a position (-10, -8).
// * Compiz has a drop shadow margin just like Mutter/Muffin/Budgie, though it's 10px
// on all sides, and there's no additional border.
// * Enlightenment otherwise gets a y position equivalent to inner_y_rel_root.
// Without decorations, there's no difference. This is presumably related to
// Enlightenment's fairly unique concept of window position; it interprets
// positions given to XMoveWindow as a client area position rather than a position
// of the overall window.
// using a screenshot tool to get a screenshot of a selected window, and is presumably
// used for drawing drop shadows. Getting window geometry information via
// hierarchy-climbing results in this margin being included in both the position and
// outer size, so a window positioned at (0, 0) would be reported as having a position
// (-10, -8).
// * Compiz has a drop shadow margin just like Mutter/Muffin/Budgie, though it's 10px on
// all sides, and there's no additional border.
// * Enlightenment otherwise gets a y position equivalent to inner_y_rel_root. Without
// decorations, there's no difference. This is presumably related to Enlightenment's
// fairly unique concept of window position; it interprets positions given to
// XMoveWindow as a client area position rather than a position of the overall window.
FrameExtentsHeuristic {
frame_extents,
heuristic_path: Supported,
}
FrameExtentsHeuristic { frame_extents, heuristic_path: Supported }
} else if nested {
// If the position value we have is for a nested window used as the client area, we'll
// just climb up the hierarchy and get the geometry of the outermost window we're
// nested in.
let outer_window = self
.climb_hierarchy(window, root)
.expect("Failed to climb window hierarchy");
let outer_window =
self.climb_hierarchy(window, root).expect("Failed to climb window hierarchy");
let (outer_y, outer_width, outer_height) = {
let outer_geometry = self
.get_geometry(outer_window)
.expect("Failed to get outer window geometry");
(
outer_geometry.y,
outer_geometry.width,
outer_geometry.height,
)
let outer_geometry =
self.get_geometry(outer_window).expect("Failed to get outer window geometry");
(outer_geometry.y, outer_geometry.width, outer_geometry.height)
};
// Since we have the geometry of the outermost window and the geometry of the client
@ -300,18 +254,12 @@ impl XConnection {
let bottom = diff_y.saturating_sub(offset_y);
let frame_extents = FrameExtents::new(left, right, top, bottom);
FrameExtentsHeuristic {
frame_extents,
heuristic_path: UnsupportedNested,
}
FrameExtentsHeuristic { frame_extents, heuristic_path: UnsupportedNested }
} else {
// This is the case for xmonad and dwm, AKA the only WMs tested that supplied a
// border value. This is convenient, since we can use it to get an accurate frame.
let frame_extents = FrameExtents::from_border(border.into());
FrameExtentsHeuristic {
frame_extents,
heuristic_path: UnsupportedBordered,
}
FrameExtentsHeuristic { frame_extents, heuristic_path: UnsupportedBordered }
}
}
}

View file

@ -76,13 +76,7 @@ mod mwm {
impl MotifHints {
pub fn new() -> MotifHints {
MotifHints {
hints: MwmHints {
flags: 0,
functions: 0,
decorations: 0,
input_mode: 0,
status: 0,
},
hints: MwmHints { flags: 0, functions: 0, decorations: 0, input_mode: 0, status: 0 },
}
}

View file

@ -1,8 +1,6 @@
use std::{slice, str};
use x11rb::protocol::{
xinput::{self, ConnectionExt as _},
xkb,
};
use x11rb::protocol::xinput::{self, ConnectionExt as _};
use x11rb::protocol::xkb;
use super::*;
@ -22,13 +20,10 @@ impl XConnection {
mask: xinput::XIEventMask,
) -> Result<VoidCookie<'_>, X11Error> {
self.xcb_connection()
.xinput_xi_select_events(
window,
&[xinput::EventMask {
deviceid: device_id,
mask: vec![mask],
}],
)
.xinput_xi_select_events(window, &[xinput::EventMask {
deviceid: device_id,
mask: vec![mask],
}])
.map_err(Into::into)
}

View file

@ -1,4 +1,5 @@
use std::{iter::Enumerate, slice::Iter};
use std::iter::Enumerate;
use std::slice::Iter;
use super::*;
@ -14,17 +15,13 @@ pub struct KeymapIter<'a> {
impl Keymap {
pub fn iter(&self) -> KeymapIter<'_> {
KeymapIter {
iter: self.keys.iter().enumerate(),
index: 0,
item: None,
}
KeymapIter { iter: self.keys.iter().enumerate(), index: 0, item: None }
}
}
impl<'a> IntoIterator for &'a Keymap {
type Item = ffi::KeyCode;
type IntoIter = KeymapIter<'a>;
type Item = ffi::KeyCode;
fn into_iter(self) -> Self::IntoIter {
self.iter()

View file

@ -1,11 +1,9 @@
// Welcome to the util module, where we try to keep you from shooting yourself in the foot.
// *results may vary
use std::{
mem::{self, MaybeUninit},
ops::BitAnd,
os::raw::*,
};
use std::mem::{self, MaybeUninit};
use std::ops::BitAnd;
use std::os::raw::*;
mod client_msg;
pub mod cookie;
@ -22,12 +20,17 @@ mod window_property;
mod wm;
mod xmodmap;
pub use self::{
cursor::*, geometry::*, hint::*, input::*, mouse::*, window_property::*, wm::*,
xmodmap::ModifierKeymap,
};
pub use self::cursor::*;
pub use self::geometry::*;
pub use self::hint::*;
pub use self::input::*;
pub use self::mouse::*;
pub use self::window_property::*;
pub use self::wm::*;
pub use self::xmodmap::ModifierKeymap;
use super::{atoms::*, ffi, VoidCookie, X11Error, XConnection, XError};
use super::atoms::*;
use super::{ffi, VoidCookie, X11Error, XConnection, XError};
use x11rb::protocol::xproto::{self, ConnectionExt as _};
pub fn maybe_change<T: PartialEq>(field: &mut Option<T>, value: T) -> bool {
@ -54,12 +57,13 @@ impl XConnection {
// 1. `XPending`, `XNextEvent`, and `XWindowEvent` flush "as needed"
// 2. `XFlush` explicitly flushes
// 3. `XSync` flushes and blocks until all requests are responded to
// 4. Calls that have a return dependent on a response (i.e. `XGetWindowProperty`) sync internally.
// When in doubt, check the X11 source; if a function calls `_XReply`, it flushes and waits.
// 4. Calls that have a return dependent on a response (i.e. `XGetWindowProperty`) sync
// internally. When in doubt, check the X11 source; if a function calls `_XReply`, it flushes
// and waits.
// All util functions that abstract an async function will return a `Flusher`.
pub fn flush_requests(&self) -> Result<(), XError> {
unsafe { (self.xlib.XFlush)(self.display) };
//println!("XFlush");
// println!("XFlush");
// This isn't necessarily a useful time to check for errors (since our request hasn't
// necessarily been processed yet)
self.check_errors()
@ -67,7 +71,7 @@ impl XConnection {
pub fn sync_with_server(&self) -> Result<(), XError> {
unsafe { (self.xlib.XSync)(self.display, ffi::False) };
//println!("XSync");
// println!("XSync");
self.check_errors()
}
}

View file

@ -8,10 +8,7 @@ pub struct Delta<T> {
impl<T: Default> Default for Delta<T> {
fn default() -> Self {
Self {
x: Default::default(),
y: Default::default(),
}
Self { x: Default::default(), y: Default::default() }
}
}

View file

@ -1,8 +1,9 @@
use std::{env, str, str::FromStr};
use std::str::FromStr;
use std::{env, str};
use super::*;
use crate::platform_impl::platform::x11::monitor;
use crate::{dpi::validate_scale_factor, platform_impl::platform::x11::VideoModeHandle};
use crate::dpi::validate_scale_factor;
use crate::platform_impl::platform::x11::{monitor, VideoModeHandle};
use tracing::warn;
use x11rb::protocol::randr::{self, ConnectionExt as _};
@ -42,16 +43,14 @@ impl XConnection {
if let Some(xsettings_screen) = self.xsettings_screen() {
match self.xsettings_dpi(xsettings_screen) {
Ok(Some(dpi)) => return Some(dpi),
Ok(None) => {}
Ok(None) => {},
Err(err) => {
tracing::warn!("failed to fetch XSettings: {err}");
}
},
}
}
self.database()
.get_string("Xft.dpi", "")
.and_then(|s| f64::from_str(s).ok())
self.database().get_string("Xft.dpi", "").and_then(|s| f64::from_str(s).ok())
}
pub fn get_output_info(
@ -69,7 +68,7 @@ impl XConnection {
Err(err) => {
warn!("Failed to get output info: {:?}", err);
return None;
}
},
};
let bit_depth = self.default_root().root_depth;
@ -100,14 +99,15 @@ impl XConnection {
Err(err) => {
warn!("Failed to get output name: {:?}", err);
return None;
}
},
};
// Override DPI if `WINIT_X11_SCALE_FACTOR` variable is set
let deprecated_dpi_override = env::var("WINIT_HIDPI_FACTOR").ok();
if deprecated_dpi_override.is_some() {
warn!(
"The WINIT_HIDPI_FACTOR environment variable is deprecated; use WINIT_X11_SCALE_FACTOR"
)
"The WINIT_HIDPI_FACTOR environment variable is deprecated; use \
WINIT_X11_SCALE_FACTOR"
)
}
let dpi_env = env::var("WINIT_X11_SCALE_FACTOR").ok().map_or_else(
|| EnvVarDPI::NotSet,
@ -120,7 +120,8 @@ impl XConnection {
EnvVarDPI::NotSet
} else {
panic!(
"`WINIT_X11_SCALE_FACTOR` invalid; DPI factors must be either normal floats greater than 0, or `randr`. Got `{var}`"
"`WINIT_X11_SCALE_FACTOR` invalid; DPI factors must be either normal \
floats greater than 0, or `randr`. Got `{var}`"
);
}
},
@ -134,11 +135,12 @@ impl XConnection {
EnvVarDPI::Scale(dpi_override) => {
if !validate_scale_factor(dpi_override) {
panic!(
"`WINIT_X11_SCALE_FACTOR` invalid; DPI factors must be either normal floats greater than 0, or `randr`. Got `{dpi_override}`",
"`WINIT_X11_SCALE_FACTOR` invalid; DPI factors must be either normal \
floats greater than 0, or `randr`. Got `{dpi_override}`",
);
}
dpi_override
}
},
EnvVarDPI::NotSet => {
if let Some(dpi) = self.get_xft_dpi() {
dpi / 96.
@ -148,7 +150,7 @@ impl XConnection {
(output_info.mm_width as _, output_info.mm_height as _),
)
}
}
},
};
Some((name, scale_factor, modes))
@ -159,10 +161,8 @@ impl XConnection {
crtc_id: randr::Crtc,
mode_id: randr::Mode,
) -> Result<(), X11Error> {
let crtc = self
.xcb_connection()
.randr_get_crtc_info(crtc_id, x11rb::CURRENT_TIME)?
.reply()?;
let crtc =
self.xcb_connection().randr_get_crtc_info(crtc_id, x11rb::CURRENT_TIME)?.reply()?;
self.xcb_connection()
.randr_set_crtc_config(
@ -181,10 +181,6 @@ impl XConnection {
}
pub fn get_crtc_mode(&self, crtc_id: randr::Crtc) -> Result<randr::Mode, X11Error> {
Ok(self
.xcb_connection()
.randr_get_crtc_info(crtc_id, x11rb::CURRENT_TIME)?
.reply()?
.mode)
Ok(self.xcb_connection().randr_get_crtc_info(crtc_id, x11rb::CURRENT_TIME)?.reply()?.mode)
}
}

View file

@ -87,10 +87,7 @@ impl XConnection {
property,
property_type,
(mem::size_of::<T>() * 8) as u8,
new_value
.len()
.try_into()
.expect("too many items for property"),
new_value.len().try_into().expect("too many items for property"),
bytemuck::cast_slice::<T, u8>(new_value),
)
.map_err(Into::into)

View file

@ -38,12 +38,8 @@ impl XConnection {
fn get_supported_hints(&self, root: xproto::Window) -> Vec<xproto::Atom> {
let atoms = self.atoms();
let supported_atom = atoms[_NET_SUPPORTED];
self.get_property(
root,
supported_atom,
xproto::Atom::from(xproto::AtomEnum::ATOM),
)
.unwrap_or_else(|_| Vec::with_capacity(0))
self.get_property(root, supported_atom, xproto::Atom::from(xproto::AtomEnum::ATOM))
.unwrap_or_else(|_| Vec::with_capacity(0))
}
#[allow(clippy::useless_conversion)]
@ -57,22 +53,22 @@ impl XConnection {
// inavailability of time machines, we'll just try to get _NET_SUPPORTING_WM_CHECK
// regardless of whether or not the WM claims to support it.
//
// Blackbox 0.70 also incorrectly reports not supporting this, though that appears to be fixed
// in 0.72.
/*if !supported_hints.contains(&check_atom) {
return None;
}*/
// Blackbox 0.70 also incorrectly reports not supporting this, though that appears to be
// fixed in 0.72.
// if !supported_hints.contains(&check_atom) {
// return None;
// }
// IceWM (1.3.x and earlier) doesn't report supporting _NET_WM_NAME, but will nonetheless
// provide us with a value for it. Note that the unofficial 1.4 fork of IceWM works fine.
/*if !supported_hints.contains(&wm_name_atom) {
return None;
}*/
// if !supported_hints.contains(&wm_name_atom) {
// return None;
// }
// Of the WMs tested, only xmonad and dwm fail to provide a WM name.
// Querying this property on the root window will give us the ID of a child window created by
// the WM.
// Querying this property on the root window will give us the ID of a child window created
// by the WM.
let root_window_wm_check = {
let result = self.get_property::<xproto::Window>(
root,

View file

@ -1,50 +1,40 @@
use std::{
cmp, env,
ffi::CString,
mem::replace,
os::raw::*,
path::Path,
sync::{Arc, Mutex, MutexGuard},
};
use std::ffi::CString;
use std::mem::replace;
use std::os::raw::*;
use std::path::Path;
use std::sync::{Arc, Mutex, MutexGuard};
use std::{cmp, env};
use tracing::{debug, info, warn};
use x11rb::{
connection::Connection,
properties::{WmHints, WmSizeHints, WmSizeHintsSpecification},
protocol::{
randr,
shape::SK,
xfixes::{ConnectionExt, RegionWrapper},
xinput,
xproto::{self, ConnectionExt as _, Rectangle},
},
};
use crate::{
cursor::{Cursor, CustomCursor as RootCustomCursor},
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
error::{ExternalError, NotSupportedError, OsError as RootOsError},
event::{Event, InnerSizeWriter, WindowEvent},
event_loop::AsyncRequestSerial,
platform::x11::WindowType,
platform_impl::{
x11::{
atoms::*, xinput_fp1616_to_float, MonitorHandle as X11MonitorHandle, WakeSender,
X11Error,
},
Fullscreen, MonitorHandle as PlatformMonitorHandle, OsError, PlatformCustomCursor,
PlatformIcon, VideoModeHandle as PlatformVideoModeHandle,
},
window::{
CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, WindowAttributes,
WindowButtons, WindowLevel,
},
use x11rb::connection::Connection;
use x11rb::properties::{WmHints, WmSizeHints, WmSizeHintsSpecification};
use x11rb::protocol::shape::SK;
use x11rb::protocol::xfixes::{ConnectionExt, RegionWrapper};
use x11rb::protocol::xproto::{self, ConnectionExt as _, Rectangle};
use x11rb::protocol::{randr, xinput};
use crate::cursor::{Cursor, CustomCursor as RootCustomCursor};
use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size};
use crate::error::{ExternalError, NotSupportedError, OsError as RootOsError};
use crate::event::{Event, InnerSizeWriter, WindowEvent};
use crate::event_loop::AsyncRequestSerial;
use crate::platform::x11::WindowType;
use crate::platform_impl::x11::atoms::*;
use crate::platform_impl::x11::{
xinput_fp1616_to_float, MonitorHandle as X11MonitorHandle, WakeSender, X11Error,
};
use crate::platform_impl::{
Fullscreen, MonitorHandle as PlatformMonitorHandle, OsError, PlatformCustomCursor,
PlatformIcon, VideoModeHandle as PlatformVideoModeHandle,
};
use crate::window::{
CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, WindowAttributes,
WindowButtons, WindowLevel,
};
use super::util::{self, SelectedCursor};
use super::{
ffi,
util::{self, SelectedCursor},
ActiveEventLoop, CookieResultExt, ImeRequest, ImeSender, VoidCookie, WindowId, XConnection,
ffi, ActiveEventLoop, CookieResultExt, ImeRequest, ImeSender, VoidCookie, WindowId, XConnection,
};
#[derive(Debug)]
@ -86,11 +76,8 @@ pub enum Visibility {
impl SharedState {
fn new(last_monitor: X11MonitorHandle, window_attributes: &WindowAttributes) -> Mutex<Self> {
let visibility = if window_attributes.visible {
Visibility::YesWait
} else {
Visibility::No
};
let visibility =
if window_attributes.visible { Visibility::YesWait } else { Visibility::No };
Mutex::new(SharedState {
last_monitor,
@ -191,16 +178,13 @@ impl UnownedWindow {
info!("Guessed window scale factor: {}", scale_factor);
let max_inner_size: Option<(u32, u32)> = window_attrs
.max_inner_size
.map(|size| size.to_physical::<u32>(scale_factor).into());
let min_inner_size: Option<(u32, u32)> = window_attrs
.min_inner_size
.map(|size| size.to_physical::<u32>(scale_factor).into());
let max_inner_size: Option<(u32, u32)> =
window_attrs.max_inner_size.map(|size| size.to_physical::<u32>(scale_factor).into());
let min_inner_size: Option<(u32, u32)> =
window_attrs.min_inner_size.map(|size| size.to_physical::<u32>(scale_factor).into());
let position = window_attrs
.position
.map(|position| position.to_physical::<i32>(scale_factor));
let position =
window_attrs.position.map(|position| position.to_physical::<i32>(scale_factor));
let dimensions = {
// x11 only applies constraints when the window is actively resized
@ -219,10 +203,7 @@ impl UnownedWindow {
dimensions.0 = cmp::max(dimensions.0, min.0);
dimensions.1 = cmp::max(dimensions.1, min.1);
}
debug!(
"Calculated physical dimensions: {}x{}",
dimensions.0, dimensions.1
);
debug!("Calculated physical dimensions: {}x{}", dimensions.0, dimensions.1);
dimensions
};
@ -238,41 +219,37 @@ impl UnownedWindow {
.roots
.iter()
.flat_map(|root| &root.allowed_depths)
.flat_map(|depth| {
depth
.visuals
.iter()
.map(move |visual| (visual, depth.depth))
});
.flat_map(|depth| depth.visuals.iter().map(move |visual| (visual, depth.depth)));
// creating
let (visualtype, depth, require_colormap) = match window_attrs
.platform_specific
.x11
.visual_id
{
Some(vi) => {
// Find this specific visual.
let (visualtype, depth) = all_visuals
.find(|(visual, _)| visual.visual_id == vi)
.ok_or_else(|| os_error!(OsError::XError(X11Error::NoSuchVisual(vi).into())))?;
let (visualtype, depth, require_colormap) =
match window_attrs.platform_specific.x11.visual_id {
Some(vi) => {
// Find this specific visual.
let (visualtype, depth) =
all_visuals.find(|(visual, _)| visual.visual_id == vi).ok_or_else(
|| os_error!(OsError::XError(X11Error::NoSuchVisual(vi).into())),
)?;
(Some(visualtype), depth, true)
}
None if window_attrs.transparent => {
// Find a suitable visual, true color with 32 bits of depth.
all_visuals
.find_map(|(visual, depth)| {
(depth == 32 && visual.class == xproto::VisualClass::TRUE_COLOR)
.then_some((Some(visual), depth, true))
})
.unwrap_or_else(|| {
debug!("Could not set transparency, because XMatchVisualInfo returned zero for the required parameters");
(None as _, x11rb::COPY_FROM_PARENT as _, false)
})
}
_ => (None, x11rb::COPY_FROM_PARENT as _, false),
};
(Some(visualtype), depth, true)
},
None if window_attrs.transparent => {
// Find a suitable visual, true color with 32 bits of depth.
all_visuals
.find_map(|(visual, depth)| {
(depth == 32 && visual.class == xproto::VisualClass::TRUE_COLOR)
.then_some((Some(visual), depth, true))
})
.unwrap_or_else(|| {
debug!(
"Could not set transparency, because XMatchVisualInfo returned \
zero for the required parameters"
);
(None as _, x11rb::COPY_FROM_PARENT as _, false)
})
},
_ => (None, x11rb::COPY_FROM_PARENT as _, false),
};
let mut visual = visualtype.map_or(x11rb::COPY_FROM_PARENT, |v| v.visual_id);
let window_attributes = {
@ -320,11 +297,7 @@ impl UnownedWindow {
};
// Figure out the window's parent.
let parent = window_attrs
.platform_specific
.x11
.embed_window
.unwrap_or(root);
let parent = window_attrs.platform_specific.x11.embed_window.unwrap_or(root);
// finally creating the window
let xwindow = {
@ -419,9 +392,7 @@ impl UnownedWindow {
.map(|bin_name| bin_name.to_owned())
.unwrap_or_else(|| window_attrs.title.clone());
// This environment variable is extraordinarily unlikely to actually be used...
let instance = env::var("RESOURCE_NAME")
.ok()
.unwrap_or_else(|| class.clone());
let instance = env::var("RESOURCE_NAME").ok().unwrap_or_else(|| class.clone());
(instance, class)
};
@ -444,12 +415,10 @@ impl UnownedWindow {
.ignore_error();
// Set size hints.
let mut min_inner_size = window_attrs
.min_inner_size
.map(|size| size.to_physical::<u32>(scale_factor));
let mut max_inner_size = window_attrs
.max_inner_size
.map(|size| size.to_physical::<u32>(scale_factor));
let mut min_inner_size =
window_attrs.min_inner_size.map(|size| size.to_physical::<u32>(scale_factor));
let mut max_inner_size =
window_attrs.max_inner_size.map(|size| size.to_physical::<u32>(scale_factor));
if !window_attrs.resizable {
if util::wm_name_is_one_of(&["Xfwm4"]) {
@ -534,9 +503,7 @@ impl UnownedWindow {
&mut supported_ptr,
);
if supported_ptr == ffi::False {
return Err(os_error!(OsError::Misc(
"`XkbSetDetectableAutoRepeat` failed"
)));
return Err(os_error!(OsError::Misc("`XkbSetDetectableAutoRepeat` failed")));
}
}
@ -556,9 +523,7 @@ impl UnownedWindow {
// Try to create input context for the window.
if let Some(ime) = event_loop.ime.as_ref() {
let result = ime
.borrow_mut()
.create_context(window.xwindow as ffi::Window, false);
let result = ime.borrow_mut().create_context(window.xwindow as ffi::Window, false);
leap!(result);
}
@ -647,10 +612,7 @@ impl UnownedWindow {
fn set_window_types(&self, window_types: Vec<WindowType>) -> Result<VoidCookie<'_>, X11Error> {
let atoms = self.xconn.atoms();
let hint_atom = atoms[_NET_WM_WINDOW_TYPE];
let atoms: Vec<_> = window_types
.iter()
.map(|t| t.as_atom(&self.xconn))
.collect();
let atoms: Vec<_> = window_types.iter().map(|t| t.as_atom(&self.xconn)).collect();
self.xconn.change_property(
self.xwindow,
@ -682,13 +644,9 @@ impl UnownedWindow {
#[inline]
pub fn set_theme(&self, theme: Option<Theme>) {
self.set_theme_inner(theme)
.expect("Failed to change window theme")
.ignore_error();
self.set_theme_inner(theme).expect("Failed to change window theme").ignore_error();
self.xconn
.flush_requests()
.expect("Failed to change window theme");
self.xconn.flush_requests().expect("Failed to change window theme");
}
fn set_netwm(
@ -703,13 +661,7 @@ impl UnownedWindow {
self.root,
state_atom,
Some(xproto::EventMask::SUBSTRUCTURE_REDIRECT | xproto::EventMask::SUBSTRUCTURE_NOTIFY),
[
operation as u32,
properties.0,
properties.1,
properties.2,
properties.3,
],
[operation as u32, properties.0, properties.1, properties.2, properties.3],
)
}
@ -723,11 +675,7 @@ impl UnownedWindow {
// locking up the user's display.
self.xconn
.xcb_connection()
.set_input_focus(
xproto::InputFocus::PARENT,
self.xwindow,
x11rb::CURRENT_TIME,
)?
.set_input_focus(xproto::InputFocus::PARENT, self.xwindow, x11rb::CURRENT_TIME)?
.ignore_error();
}
@ -745,7 +693,7 @@ impl UnownedWindow {
Visibility::No | Visibility::YesWait => {
shared_state_lock.desired_fullscreen = Some(fullscreen);
return Ok(None);
}
},
Visibility::Yes => (),
}
@ -768,11 +716,9 @@ impl UnownedWindow {
let monitor = video_mode.monitor.as_ref().unwrap();
shared_state_lock.desktop_video_mode = Some((
monitor.id,
self.xconn
.get_crtc_mode(monitor.id)
.expect("Failed to get desktop video mode"),
self.xconn.get_crtc_mode(monitor.id).expect("Failed to get desktop video mode"),
));
}
},
// Restore desktop video mode upon exiting exclusive fullscreen
(&Some(Fullscreen::Exclusive(_)), &None)
| (&Some(Fullscreen::Exclusive(_)), &Some(Fullscreen::Borderless(_))) => {
@ -780,7 +726,7 @@ impl UnownedWindow {
self.xconn
.set_crtc_config(monitor_id, mode_id)
.expect("failed to restore desktop video mode");
}
},
_ => (),
}
@ -796,18 +742,18 @@ impl UnownedWindow {
.expect_then_ignore_error("Failed to restore window position");
}
flusher.map(Some)
}
},
Some(fullscreen) => {
let (video_mode, monitor) = match fullscreen {
Fullscreen::Exclusive(PlatformVideoModeHandle::X(ref video_mode)) => {
(Some(video_mode), video_mode.monitor.clone().unwrap())
}
},
Fullscreen::Borderless(Some(PlatformMonitorHandle::X(monitor))) => {
(None, monitor)
}
},
Fullscreen::Borderless(None) => {
(None, self.shared_state_lock().last_monitor.clone())
}
},
#[cfg(wayland_platform)]
_ => unreachable!(),
};
@ -854,7 +800,7 @@ impl UnownedWindow {
self.set_position_inner(monitor_origin.0, monitor_origin.1)
.expect_then_ignore_error("Failed to set window position");
self.set_fullscreen_hint(true).map(Some)
}
},
}
}
@ -862,21 +808,15 @@ impl UnownedWindow {
pub(crate) fn fullscreen(&self) -> Option<Fullscreen> {
let shared_state = self.shared_state_lock();
shared_state
.desired_fullscreen
.clone()
.unwrap_or_else(|| shared_state.fullscreen.clone())
shared_state.desired_fullscreen.clone().unwrap_or_else(|| shared_state.fullscreen.clone())
}
#[inline]
pub(crate) fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
if let Some(flusher) = self
.set_fullscreen_inner(fullscreen)
.expect("Failed to change window fullscreen state")
if let Some(flusher) =
self.set_fullscreen_inner(fullscreen).expect("Failed to change window fullscreen state")
{
flusher
.check()
.expect("Failed to change window fullscreen state");
flusher.check().expect("Failed to change window fullscreen state");
self.invalidate_cached_frame_extents();
}
}
@ -899,7 +839,7 @@ impl UnownedWindow {
drop(shared_state);
self.set_fullscreen(fullscreen);
}
}
},
}
}
@ -908,17 +848,11 @@ impl UnownedWindow {
}
pub fn available_monitors(&self) -> Vec<X11MonitorHandle> {
self.xconn
.available_monitors()
.expect("Failed to get available monitors")
self.xconn.available_monitors().expect("Failed to get available monitors")
}
pub fn primary_monitor(&self) -> Option<X11MonitorHandle> {
Some(
self.xconn
.primary_monitor()
.expect("Failed to get primary monitor"),
)
Some(self.xconn.primary_monitor().expect("Failed to get primary monitor"))
}
#[inline]
@ -933,9 +867,9 @@ impl UnownedWindow {
let hidden_atom = atoms[_NET_WM_STATE_HIDDEN];
Some(match state {
Ok(atoms) => atoms
.iter()
.any(|atom: &xproto::Atom| *atom as xproto::Atom == hidden_atom),
Ok(atoms) => {
atoms.iter().any(|atom: &xproto::Atom| *atom as xproto::Atom == hidden_atom)
},
_ => false,
})
}
@ -1020,9 +954,7 @@ impl UnownedWindow {
self.set_minimized_inner(minimized)
.expect_then_ignore_error("Failed to change window minimization");
self.xconn
.flush_requests()
.expect("Failed to change window minimization");
self.xconn.flush_requests().expect("Failed to change window minimization");
}
#[inline]
@ -1041,7 +973,7 @@ impl UnownedWindow {
let horz_maximized = atoms.iter().any(|atom: &xproto::Atom| *atom == horz_atom);
let vert_maximized = atoms.iter().any(|atom: &xproto::Atom| *atom == vert_atom);
horz_maximized && vert_maximized
}
},
_ => false,
}
}
@ -1058,9 +990,7 @@ impl UnownedWindow {
pub fn set_maximized(&self, maximized: bool) {
self.set_maximized_inner(maximized)
.expect_then_ignore_error("Failed to change window maximization");
self.xconn
.flush_requests()
.expect("Failed to change window maximization");
self.xconn.flush_requests().expect("Failed to change window maximization");
self.invalidate_cached_frame_extents();
}
@ -1088,12 +1018,9 @@ impl UnownedWindow {
#[inline]
pub fn set_title(&self, title: &str) {
self.set_title_inner(title)
.expect_then_ignore_error("Failed to set window title");
self.set_title_inner(title).expect_then_ignore_error("Failed to set window title");
self.xconn
.flush_requests()
.expect("Failed to set window title");
self.xconn.flush_requests().expect("Failed to set window title");
}
#[inline]
@ -1115,9 +1042,7 @@ impl UnownedWindow {
pub fn set_decorations(&self, decorations: bool) {
self.set_decorations_inner(decorations)
.expect_then_ignore_error("Failed to set decoration state");
self.xconn
.flush_requests()
.expect("Failed to set decoration state");
self.xconn.flush_requests().expect("Failed to set decoration state");
self.invalidate_cached_frame_extents();
}
@ -1141,8 +1066,7 @@ impl UnownedWindow {
}
fn set_window_level_inner(&self, level: WindowLevel) -> Result<VoidCookie<'_>, X11Error> {
self.toggle_atom(_NET_WM_STATE_ABOVE, level == WindowLevel::AlwaysOnTop)?
.ignore_error();
self.toggle_atom(_NET_WM_STATE_ABOVE, level == WindowLevel::AlwaysOnTop)?.ignore_error();
self.toggle_atom(_NET_WM_STATE_BELOW, level == WindowLevel::AlwaysOnBottom)
}
@ -1150,9 +1074,7 @@ impl UnownedWindow {
pub fn set_window_level(&self, level: WindowLevel) {
self.set_window_level_inner(level)
.expect_then_ignore_error("Failed to set window-level state");
self.xconn
.flush_requests()
.expect("Failed to set window-level state");
self.xconn.flush_requests().expect("Failed to set window-level state");
}
fn set_icon_inner(&self, icon: PlatformIcon) -> Result<VoidCookie<'_>, X11Error> {
@ -1199,7 +1121,7 @@ impl UnownedWindow {
match (visible, shared_state.visibility) {
(true, Visibility::Yes) | (true, Visibility::YesWait) | (false, Visibility::No) => {
return
}
},
_ => (),
}
@ -1215,18 +1137,14 @@ impl UnownedWindow {
&xproto::ConfigureWindowAux::new().stack_mode(xproto::StackMode::ABOVE),
)
.expect_then_ignore_error("Failed to call `xcb_configure_window`");
self.xconn
.flush_requests()
.expect("Failed to call XMapRaised");
self.xconn.flush_requests().expect("Failed to call XMapRaised");
shared_state.visibility = Visibility::YesWait;
} else {
self.xconn
.xcb_connection()
.unmap_window(self.xwindow)
.expect_then_ignore_error("Failed to call `xcb_unmap_window`");
self.xconn
.flush_requests()
.expect("Failed to call XUnmapWindow");
self.xconn.flush_requests().expect("Failed to call XUnmapWindow");
shared_state.visibility = Visibility::No;
}
}
@ -1237,9 +1155,7 @@ impl UnownedWindow {
}
fn update_cached_frame_extents(&self) {
let extents = self
.xconn
.get_frame_extents_heuristic(self.xwindow, self.root);
let extents = self.xconn.get_frame_extents_heuristic(self.xwindow, self.root);
self.shared_state_lock().frame_extents = Some(extents);
}
@ -1309,8 +1225,7 @@ impl UnownedWindow {
}
pub(crate) fn set_position_physical(&self, x: i32, y: i32) {
self.set_position_inner(x, y)
.expect_then_ignore_error("Failed to call `XMoveWindow`");
self.set_position_inner(x, y).expect_then_ignore_error("Failed to call `XMoveWindow`");
}
#[inline]
@ -1350,14 +1265,10 @@ impl UnownedWindow {
.xcb_connection()
.configure_window(
self.xwindow,
&xproto::ConfigureWindowAux::new()
.width(width)
.height(height),
&xproto::ConfigureWindowAux::new().width(width).height(height),
)
.expect_then_ignore_error("Failed to call `xcb_configure_window`");
self.xconn
.flush_requests()
.expect("Failed to call XResizeWindow");
self.xconn.flush_requests().expect("Failed to call XResizeWindow");
// cursor_hittest needs to be reapplied after each window resize.
if self.shared_state_lock().cursor_hittest.unwrap_or(false) {
let _ = self.set_cursor_hittest(true);
@ -1488,19 +1399,17 @@ impl UnownedWindow {
pub fn set_resizable(&self, resizable: bool) {
if util::wm_name_is_one_of(&["Xfwm4"]) {
// Making the window unresizable on Xfwm prevents further changes to `WM_NORMAL_HINTS` from being detected.
// This makes it impossible for resizing to be re-enabled, and also breaks DPI scaling. As such, we choose
// the lesser of two evils and do nothing.
// Making the window unresizable on Xfwm prevents further changes to `WM_NORMAL_HINTS`
// from being detected. This makes it impossible for resizing to be
// re-enabled, and also breaks DPI scaling. As such, we choose the lesser of
// two evils and do nothing.
warn!("To avoid a WM bug, disabling resizing has no effect on Xfwm4");
return;
}
let (min_size, max_size) = if resizable {
let shared_state_lock = self.shared_state_lock();
(
shared_state_lock.min_inner_size,
shared_state_lock.max_inner_size,
)
(shared_state_lock.min_inner_size, shared_state_lock.max_inner_size)
} else {
let window_size = Some(Size::from(self.inner_size()));
(window_size, window_size)
@ -1559,21 +1468,19 @@ impl UnownedWindow {
{
self.xconn.set_cursor_icon(self.xwindow, Some(icon));
}
}
Cursor::Custom(RootCustomCursor {
inner: PlatformCustomCursor::X(cursor),
}) => {
},
Cursor::Custom(RootCustomCursor { inner: PlatformCustomCursor::X(cursor) }) => {
#[allow(clippy::mutex_atomic)]
if *self.cursor_visible.lock().unwrap() {
self.xconn.set_custom_cursor(self.xwindow, &cursor);
}
*self.selected_cursor.lock().unwrap() = SelectedCursor::Custom(cursor);
}
},
#[cfg(wayland_platform)]
Cursor::Custom(RootCustomCursor {
inner: PlatformCustomCursor::Wayland(_),
}) => tracing::error!("passed a Wayland cursor to X11 backend"),
Cursor::Custom(RootCustomCursor { inner: PlatformCustomCursor::Wayland(_) }) => {
tracing::error!("passed a Wayland cursor to X11 backend")
},
}
}
@ -1629,23 +1536,23 @@ impl UnownedWindow {
xproto::GrabStatus::SUCCESS => Ok(()),
xproto::GrabStatus::ALREADY_GRABBED => {
Err("Cursor could not be confined: already confined by another client")
}
},
xproto::GrabStatus::INVALID_TIME => {
Err("Cursor could not be confined: invalid time")
}
},
xproto::GrabStatus::NOT_VIEWABLE => {
Err("Cursor could not be confined: confine location not viewable")
}
},
xproto::GrabStatus::FROZEN => {
Err("Cursor could not be confined: frozen by another client")
}
},
_ => unreachable!(),
}
.map_err(|err| ExternalError::Os(os_error!(OsError::Misc(err))))
}
},
CursorGrabMode::Locked => {
return Err(ExternalError::NotSupported(NotSupportedError::new()));
}
},
};
if result.is_ok() {
@ -1662,23 +1569,20 @@ impl UnownedWindow {
if visible == *visible_lock {
return;
}
let cursor = if visible {
Some((*self.selected_cursor.lock().unwrap()).clone())
} else {
None
};
let cursor =
if visible { Some((*self.selected_cursor.lock().unwrap()).clone()) } else { None };
*visible_lock = visible;
drop(visible_lock);
match cursor {
Some(SelectedCursor::Custom(cursor)) => {
self.xconn.set_custom_cursor(self.xwindow, &cursor);
}
},
Some(SelectedCursor::Named(cursor)) => {
self.xconn.set_cursor_icon(self.xwindow, Some(cursor));
}
},
None => {
self.xconn.set_cursor_icon(self.xwindow, None);
}
},
}
}
@ -1831,8 +1735,7 @@ impl UnownedWindow {
let state_atom = atoms[WM_STATE];
let state_type_atom = atoms[CARD32];
let is_minimized = if let Ok(state) =
self.xconn
.get_property::<u32>(self.xwindow, state_atom, state_type_atom)
self.xconn.get_property::<u32>(self.xwindow, state_atom, state_type_atom)
{
state.contains(&super::ICONIC_STATE)
} else {
@ -1915,9 +1818,7 @@ impl UnownedWindow {
#[inline]
pub fn request_redraw(&self) {
self.redraw_sender
.send(WindowId(self.xwindow as _))
.unwrap();
self.redraw_sender.send(WindowId(self.xwindow as _)).unwrap();
}
#[inline]
@ -2001,10 +1902,7 @@ fn cast_dimension_to_hint(val: u32) -> i32 {
/// Use the above strategy to cast a physical size into a hinted size.
fn cast_physical_size_to_hint(size: PhysicalSize<u32>) -> (i32, i32) {
let PhysicalSize { width, height } = size;
(
cast_dimension_to_hint(width),
cast_dimension_to_hint(height),
)
(cast_dimension_to_hint(width), cast_dimension_to_hint(height))
}
/// Use the above strategy to cast a size into a hinted size.

View file

@ -1,25 +1,19 @@
use std::{
collections::HashMap,
error::Error,
fmt, ptr,
sync::{
atomic::{AtomicU32, Ordering},
Arc, Mutex, RwLock, RwLockReadGuard,
},
};
use std::collections::HashMap;
use std::error::Error;
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::{Arc, Mutex, RwLock, RwLockReadGuard};
use std::{fmt, ptr};
use crate::window::CursorIcon;
use super::{atoms::Atoms, ffi, monitor::MonitorHandle};
use x11rb::{
connection::Connection,
protocol::{
randr::ConnectionExt as _,
xproto::{self, ConnectionExt},
},
resource_manager,
xcb_ffi::XCBConnection,
};
use super::atoms::Atoms;
use super::ffi;
use super::monitor::MonitorHandle;
use x11rb::connection::Connection;
use x11rb::protocol::randr::ConnectionExt as _;
use x11rb::protocol::xproto::{self, ConnectionExt};
use x11rb::resource_manager;
use x11rb::xcb_ffi::XCBConnection;
/// A connection to an X server.
pub struct XConnection {
@ -158,14 +152,9 @@ impl XConnection {
.atom;
// Get PropertyNotify events from the XSETTINGS window.
// TODO: The XSETTINGS window here can change. In the future, listen for DestroyNotify on this window
// in order to accommodate for a changed window here.
let selector_window = xcb
.get_selection_owner(xsettings_screen)
.ok()?
.reply()
.ok()?
.owner;
// TODO: The XSETTINGS window here can change. In the future, listen for DestroyNotify on
// this window in order to accommodate for a changed window here.
let selector_window = xcb.get_selection_owner(xsettings_screen).ok()?.reply().ok()?.owner;
xcb.change_window_attributes(
selector_window,
@ -198,9 +187,7 @@ impl XConnection {
/// Get the underlying XCB connection.
#[inline]
pub fn xcb_connection(&self) -> &XCBConnection {
self.xcb
.as_ref()
.expect("xcb_connection somehow called after drop?")
self.xcb.as_ref().expect("xcb_connection somehow called after drop?")
}
/// Get the list of atoms.

View file

@ -9,7 +9,8 @@ use std::num::NonZeroUsize;
use x11rb::protocol::xproto::{self, ConnectionExt};
use super::{atoms::*, XConnection};
use super::atoms::*;
use super::XConnection;
type Result<T> = core::result::Result<T, ParserError>;
@ -27,17 +28,11 @@ impl XConnection {
let atoms = self.atoms();
// Get the current owner of the screen's settings.
let owner = self
.xcb_connection()
.get_selection_owner(xsettings_screen)?
.reply()?;
let owner = self.xcb_connection().get_selection_owner(xsettings_screen)?.reply()?;
// Read the _XSETTINGS_SETTINGS property.
let data: Vec<u8> = self.get_property(
owner.owner,
atoms[_XSETTINGS_SETTINGS],
atoms[_XSETTINGS_SETTINGS],
)?;
let data: Vec<u8> =
self.get_property(owner.owner, atoms[_XSETTINGS_SETTINGS], atoms[_XSETTINGS_SETTINGS])?;
// Parse the property.
let dpi_setting = read_settings(&data)?
@ -48,10 +43,10 @@ impl XConnection {
SettingData::Integer(dpi) => dpi as f64,
SettingData::String(_) => {
return Err(ParserError::BadType(SettingType::String).into())
}
},
SettingData::Color(_) => {
return Err(ParserError::BadType(SettingType::Color).into())
}
},
};
Ok(Some(base_dpi / DPI_MULTIPLIER))
@ -111,7 +106,7 @@ impl<'a> Setting<'a> {
SettingType::Integer => {
// Read a 32-bit integer.
SettingData::Integer(parser.i32()?)
}
},
SettingType::String => {
// Read the data.
@ -120,7 +115,7 @@ impl<'a> Setting<'a> {
parser.pad(data.len(), 4)?;
SettingData::String(data)
}
},
SettingType::Color => {
// Read i16's of color.
@ -128,7 +123,7 @@ impl<'a> Setting<'a> {
(parser.i16()?, parser.i16()?, parser.i16()?, parser.i16()?);
SettingData::Color([red, blue, green, alpha])
}
},
};
Ok(Setting { name, data })
@ -164,9 +159,7 @@ struct Parser<'a> {
impl<'a> Parser<'a> {
/// Create a new parser.
fn new(bytes: &'a [u8]) -> Result<Self> {
let (endianness, bytes) = bytes
.split_first()
.ok_or_else(|| ParserError::ran_out(1, 0))?;
let (endianness, bytes) = bytes.split_first().ok_or_else(|| ParserError::ran_out(1, 0))?;
let endianness = match *endianness {
BIG_ENDIAN => Endianness::Big,
LITTLE_ENDIAN => Endianness::Little,
@ -175,9 +168,7 @@ impl<'a> Parser<'a> {
Ok(Self {
// Ignore three bytes of padding and the four-byte serial.
bytes: bytes
.get(7..)
.ok_or_else(|| ParserError::ran_out(7, bytes.len()))?,
bytes: bytes.get(7..).ok_or_else(|| ParserError::ran_out(7, bytes.len()))?,
endianness,
})
}
@ -255,10 +246,7 @@ impl Endianness {
#[derive(Debug)]
pub enum ParserError {
/// Ran out of bytes.
NoMoreBytes {
expected: NonZeroUsize,
found: usize,
},
NoMoreBytes { expected: NonZeroUsize, found: usize },
/// Invalid type.
InvalidType(i8),
@ -291,7 +279,7 @@ mod tests {
ParserError::NoMoreBytes { expected, found } => {
assert_eq!(expected.get(), 1);
assert_eq!(found, 0);
}
},
_ => panic!(),
}
@ -308,10 +296,7 @@ mod tests {
})
.collect::<Vec<_>>();
let settings = read_settings(&data)
.unwrap()
.collect::<Result<Vec<_>>>()
.unwrap();
let settings = read_settings(&data).unwrap().collect::<Result<Vec<_>>>().unwrap();
let dpi = settings.iter().find(|s| s.name == b"Xft/DPI").unwrap();
assert_int(&dpi.data, 96 * 1024);
@ -320,10 +305,7 @@ mod tests {
let rgba = settings.iter().find(|s| s.name == b"Xft/RGBA").unwrap();
assert_string(&rgba.data, "rgb");
let lcd = settings
.iter()
.find(|s| s.name == b"Xft/Lcdfilter")
.unwrap();
let lcd = settings.iter().find(|s| s.name == b"Xft/Lcdfilter").unwrap();
assert_string(&lcd.data, "lcddefault");
}