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 log::{debug, warn};
|
||||||
use std::{cmp, cell::RefCell};
|
use std::cmp;
|
||||||
use xcb::{x, randr, xfixes, Xid};
|
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_ATOM_NAME: &[u8] = b"Backlight";
|
||||||
const BACKLIGHT_FALLBACK_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 output: randr::Output,
|
||||||
pub blanker_window: x::Window,
|
pub blanker_window: x::Window,
|
||||||
pub unlock_window: x::Window,
|
pub unlock_window: x::Window,
|
||||||
|
pub blank_cursor: x::Cursor,
|
||||||
pub x: i16,
|
pub x: i16,
|
||||||
pub y: i16,
|
pub y: i16,
|
||||||
pub width: u16,
|
pub width: u16,
|
||||||
pub height: u16,
|
pub height: u16,
|
||||||
// RefCell used here to avoid requiring '&mut self' on blank/unblank
|
|
||||||
cursor_hidden: RefCell<u32>,
|
|
||||||
backlight_control: Option<BacklightControl>,
|
backlight_control: Option<BacklightControl>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,6 +51,7 @@ impl Monitor {
|
|||||||
let reply = conn.wait_for_reply(cookie)?;
|
let reply = conn.wait_for_reply(cookie)?;
|
||||||
|
|
||||||
let (blanker_window, unlock_window) = create_windows(conn, &screen, &reply)?;
|
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();
|
let black_gc: x::Gcontext = conn.generate_id();
|
||||||
conn.send_and_check_request(&x::CreateGc {
|
conn.send_and_check_request(&x::CreateGc {
|
||||||
@ -74,11 +74,11 @@ impl Monitor {
|
|||||||
output: *output,
|
output: *output,
|
||||||
blanker_window,
|
blanker_window,
|
||||||
unlock_window,
|
unlock_window,
|
||||||
|
blank_cursor,
|
||||||
x: reply.x(),
|
x: reply.x(),
|
||||||
y: reply.y(),
|
y: reply.y(),
|
||||||
width: reply.width(),
|
width: reply.width(),
|
||||||
height: reply.height(),
|
height: reply.height(),
|
||||||
cursor_hidden: RefCell::new(0),
|
|
||||||
backlight_control: backlight_control.ok().flatten(),
|
backlight_control: backlight_control.ok().flatten(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -196,25 +196,24 @@ impl Monitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn show_cursor(&self, conn: &xcb::Connection) {
|
pub fn show_cursor(&self, conn: &xcb::Connection) {
|
||||||
let ok = self.cursor_hidden.try_borrow().map(|ch| *ch > 0).unwrap_or(true);
|
if let Err(err) = conn.send_and_check_request(&x::ChangeWindowAttributes {
|
||||||
if ok {
|
window: self.blanker_window,
|
||||||
if let Err(err) = conn.send_and_check_request(&xfixes::ShowCursor {
|
value_list: &[
|
||||||
window: self.blanker_window,
|
x::Cw::Cursor(x::CURSOR_NONE),
|
||||||
}) {
|
],
|
||||||
warn!("Failed to show cursor: {}", err);
|
}) {
|
||||||
} else {
|
warn!("Failed to show cursor: {}", err);
|
||||||
let _ = self.cursor_hidden.try_borrow_mut().map(|mut ch| *ch -= 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hide_cursor(&self, conn: &xcb::Connection) {
|
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,
|
window: self.blanker_window,
|
||||||
|
value_list: &[
|
||||||
|
x::Cw::Cursor(self.blank_cursor),
|
||||||
|
],
|
||||||
}) {
|
}) {
|
||||||
warn!("Failed to hide cursor: {}", err);
|
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))
|
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>> {
|
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] {
|
for prop_name in [BACKLIGHT_ATOM_NAME, BACKLIGHT_FALLBACK_ATOM_NAME] {
|
||||||
let property = create_atom(conn, prop_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())
|
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<()> {
|
pub fn destroy_gc(conn: &xcb::Connection, gc: x::Gcontext) -> xcb::Result<()> {
|
||||||
conn.send_and_check_request(&x::FreeGc {
|
conn.send_and_check_request(&x::FreeGc {
|
||||||
gc,
|
gc,
|
||||||
|
Loading…
Reference in New Issue
Block a user