Use regular X11 rather than XFIXES to hide cursor
The semantics of the XFIXES cursor hide deal are annoying and make things harder.
This commit is contained in:
parent
344907f55a
commit
a516a25a9f
@ -1,8 +1,8 @@
|
||||
use log::{debug, warn};
|
||||
use std::{cmp, cell::RefCell};
|
||||
use xcb::{x, randr, xfixes, Xid};
|
||||
use std::cmp;
|
||||
use xcb::{x, randr, Xid};
|
||||
|
||||
use bscreensaver_util::{BSCREENSAVER_WM_CLASS, create_atom};
|
||||
use bscreensaver_util::{BSCREENSAVER_WM_CLASS, create_atom, destroy_pixmap};
|
||||
|
||||
const BACKLIGHT_ATOM_NAME: &[u8] = b"Backlight";
|
||||
const BACKLIGHT_FALLBACK_ATOM_NAME: &[u8] = b"BACKLIGHT";
|
||||
@ -20,12 +20,11 @@ pub struct Monitor {
|
||||
pub output: randr::Output,
|
||||
pub blanker_window: x::Window,
|
||||
pub unlock_window: x::Window,
|
||||
pub blank_cursor: x::Cursor,
|
||||
pub x: i16,
|
||||
pub y: i16,
|
||||
pub width: u16,
|
||||
pub height: u16,
|
||||
// RefCell used here to avoid requiring '&mut self' on blank/unblank
|
||||
cursor_hidden: RefCell<u32>,
|
||||
backlight_control: Option<BacklightControl>,
|
||||
}
|
||||
|
||||
@ -52,6 +51,7 @@ impl Monitor {
|
||||
let reply = conn.wait_for_reply(cookie)?;
|
||||
|
||||
let (blanker_window, unlock_window) = create_windows(conn, &screen, &reply)?;
|
||||
let blank_cursor = create_blank_cursor(conn, &screen)?;
|
||||
|
||||
let black_gc: x::Gcontext = conn.generate_id();
|
||||
conn.send_and_check_request(&x::CreateGc {
|
||||
@ -74,11 +74,11 @@ impl Monitor {
|
||||
output: *output,
|
||||
blanker_window,
|
||||
unlock_window,
|
||||
blank_cursor,
|
||||
x: reply.x(),
|
||||
y: reply.y(),
|
||||
width: reply.width(),
|
||||
height: reply.height(),
|
||||
cursor_hidden: RefCell::new(0),
|
||||
backlight_control: backlight_control.ok().flatten(),
|
||||
});
|
||||
}
|
||||
@ -196,25 +196,24 @@ impl Monitor {
|
||||
}
|
||||
|
||||
pub fn show_cursor(&self, conn: &xcb::Connection) {
|
||||
let ok = self.cursor_hidden.try_borrow().map(|ch| *ch > 0).unwrap_or(true);
|
||||
if ok {
|
||||
if let Err(err) = conn.send_and_check_request(&xfixes::ShowCursor {
|
||||
if let Err(err) = conn.send_and_check_request(&x::ChangeWindowAttributes {
|
||||
window: self.blanker_window,
|
||||
value_list: &[
|
||||
x::Cw::Cursor(x::CURSOR_NONE),
|
||||
],
|
||||
}) {
|
||||
warn!("Failed to show cursor: {}", err);
|
||||
} else {
|
||||
let _ = self.cursor_hidden.try_borrow_mut().map(|mut ch| *ch -= 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hide_cursor(&self, conn: &xcb::Connection) {
|
||||
if let Err(err) = conn.send_and_check_request(&xfixes::HideCursor {
|
||||
if let Err(err) = conn.send_and_check_request(&x::ChangeWindowAttributes {
|
||||
window: self.blanker_window,
|
||||
value_list: &[
|
||||
x::Cw::Cursor(self.blank_cursor),
|
||||
],
|
||||
}) {
|
||||
warn!("Failed to hide cursor: {}", err);
|
||||
} else {
|
||||
let _ = self.cursor_hidden.try_borrow_mut().map(|mut ch| *ch += 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -353,6 +352,37 @@ fn create_windows(conn: &xcb::Connection, screen: &x::Screen, crtc_info: &randr:
|
||||
Ok((blanker_window, unlock_window))
|
||||
}
|
||||
|
||||
fn create_blank_cursor(conn: &xcb::Connection, screen: &x::Screen) -> xcb::Result<x::Cursor> {
|
||||
let blank_cursor: x::Cursor = conn.generate_id();
|
||||
let pixmap: x::Pixmap = conn.generate_id();
|
||||
|
||||
conn.send_and_check_request(&x::CreatePixmap {
|
||||
pid: pixmap,
|
||||
drawable: x::Drawable::Window(screen.root()),
|
||||
depth: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
})?;
|
||||
|
||||
conn.send_and_check_request(&x::CreateCursor {
|
||||
cid: blank_cursor,
|
||||
source: pixmap,
|
||||
mask: x::PIXMAP_NONE,
|
||||
fore_red: 0,
|
||||
fore_green: 0,
|
||||
fore_blue: 0,
|
||||
back_red: 0,
|
||||
back_green: 0,
|
||||
back_blue: 0,
|
||||
x: 0,
|
||||
y: 0,
|
||||
})?;
|
||||
|
||||
destroy_pixmap(conn, pixmap)?;
|
||||
|
||||
Ok(blank_cursor)
|
||||
}
|
||||
|
||||
fn find_backlight_control(conn: &xcb::Connection, output: randr::Output) -> xcb::Result<Option<BacklightControl>> {
|
||||
for prop_name in [BACKLIGHT_ATOM_NAME, BACKLIGHT_FALLBACK_ATOM_NAME] {
|
||||
let property = create_atom(conn, prop_name)?;
|
||||
|
@ -32,6 +32,20 @@ pub fn create_atom(conn: &xcb::Connection, name: &[u8]) -> xcb::Result<x::Atom>
|
||||
Ok(conn.wait_for_reply(cookie)?.atom())
|
||||
}
|
||||
|
||||
pub fn destroy_pixmap(conn: &xcb::Connection, pixmap: x::Pixmap) -> xcb::Result<()> {
|
||||
conn.send_and_check_request(&x::FreePixmap {
|
||||
pixmap,
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn destroy_cursor(conn: &xcb::Connection, cursor: x::Cursor) -> xcb::Result<()> {
|
||||
conn.send_and_check_request(&x::FreeCursor {
|
||||
cursor,
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn destroy_gc(conn: &xcb::Connection, gc: x::Gcontext) -> xcb::Result<()> {
|
||||
conn.send_and_check_request(&x::FreeGc {
|
||||
gc,
|
||||
|
Loading…
Reference in New Issue
Block a user