gardesk/garclip / a982bd8

Browse files

add XFixes selection monitoring to SelectionManager

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
a982bd808a515cf8a2d442b62e69d39cfa2fed9c
Parents
dc9e47c
Tree
6f83171

1 changed file

StatusFile+-
M garclip/src/x11/selection.rs 59 1
garclip/src/x11/selection.rsmodified
@@ -1,7 +1,8 @@
11
 use std::collections::HashSet;
22
 use std::sync::Arc;
33
 
4
-use x11rb::connection::Connection;
4
+use x11rb::connection::{Connection, RequestConnection};
5
+use x11rb::protocol::xfixes::{self, ConnectionExt as XFixesExt, SelectionEventMask};
56
 use x11rb::protocol::xproto::{
67
     Atom, ConnectionExt as _, CreateWindowAux, EventMask, PropMode, Screen, Window, WindowClass,
78
 };
@@ -19,6 +20,8 @@ pub struct SelectionManager {
1920
     window: Window,
2021
     atoms: Atoms,
2122
     owned_selections: HashSet<Atom>,
23
+    /// XFixes extension event base (for identifying XFixes events)
24
+    xfixes_event_base: u8,
2225
 }
2326
 
2427
 impl SelectionManager {
@@ -26,6 +29,20 @@ impl SelectionManager {
2629
     pub fn new(conn: Arc<RustConnection>, screen_num: usize, atoms: Atoms) -> Result<Self> {
2730
         let screen = conn.setup().roots[screen_num].clone();
2831
 
32
+        // Query XFixes extension
33
+        let xfixes_info = conn.xfixes_query_version(5, 0)?.reply()?;
34
+        tracing::debug!(
35
+            "XFixes version: {}.{}",
36
+            xfixes_info.major_version,
37
+            xfixes_info.minor_version
38
+        );
39
+
40
+        // Get XFixes event base
41
+        let ext_info = conn
42
+            .extension_information(xfixes::X11_EXTENSION_NAME)?
43
+            .ok_or_else(|| crate::error::Error::Other("XFixes extension not available".into()))?;
44
+        let xfixes_event_base = ext_info.first_event;
45
+
2946
         // Create a hidden window for selection ownership
3047
         let window = conn.generate_id()?;
3148
         conn.create_window(
@@ -60,9 +77,50 @@ impl SelectionManager {
6077
             window,
6178
             atoms,
6279
             owned_selections: HashSet::new(),
80
+            xfixes_event_base,
6381
         })
6482
     }
6583
 
84
+    /// Subscribe to selection owner change notifications via XFixes
85
+    pub fn watch_selection(&self, selection: Atom) -> Result<()> {
86
+        self.conn.xfixes_select_selection_input(
87
+            self.window,
88
+            selection,
89
+            SelectionEventMask::SET_SELECTION_OWNER
90
+                | SelectionEventMask::SELECTION_WINDOW_DESTROY
91
+                | SelectionEventMask::SELECTION_CLIENT_CLOSE,
92
+        )?;
93
+        self.conn.flush()?;
94
+
95
+        tracing::debug!(
96
+            "Watching selection: {}",
97
+            self.atoms.name(&*self.conn, selection).unwrap_or_default()
98
+        );
99
+
100
+        Ok(())
101
+    }
102
+
103
+    /// Stop watching a selection
104
+    pub fn unwatch_selection(&self, selection: Atom) -> Result<()> {
105
+        self.conn.xfixes_select_selection_input(
106
+            self.window,
107
+            selection,
108
+            SelectionEventMask::from(0u32),
109
+        )?;
110
+        self.conn.flush()?;
111
+        Ok(())
112
+    }
113
+
114
+    /// Get the XFixes event base
115
+    pub fn xfixes_event_base(&self) -> u8 {
116
+        self.xfixes_event_base
117
+    }
118
+
119
+    /// Check if an event code is an XFixes SelectionNotify
120
+    pub fn is_xfixes_selection_notify(&self, event_code: u8) -> bool {
121
+        event_code == self.xfixes_event_base + xfixes::SELECTION_NOTIFY_EVENT
122
+    }
123
+
66124
     /// Get the connection
67125
     pub fn conn(&self) -> &Arc<RustConnection> {
68126
         &self.conn