gardesk/garfield / 9dca739

Browse files

app: integrate X11 clipboard for system-wide file copy/paste

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
9dca739f7d9a5db2ddc969230416b28e58abecb9
Parents
ef80a58
Tree
6d2bc32

1 changed file

StatusFile+-
M garfield/src/app.rs 37 3
garfield/src/app.rsmodified
@@ -10,7 +10,7 @@ use garfield::ui::{AddressBar, AppPickerDialog, AppPickerResult, Breadcrumb, Con
1010
 use anyhow::Result;
1111
 use gartk_core::{InputEvent, Key, MouseButton, Point, Rect, Theme};
1212
 use gartk_render::{Renderer, TextStyle};
13
-use gartk_x11::{Connection, EventLoop, EventLoopConfig, Window, WindowConfig};
13
+use gartk_x11::{ClipboardManager, Connection, EventLoop, EventLoopConfig, Window, WindowConfig};
1414
 use std::path::PathBuf;
1515
 use std::time::Instant;
1616
 use x11rb::protocol::xproto::{ConnectionExt, ImageFormat};
@@ -98,6 +98,8 @@ pub struct App {
9898
     preview_loader: PreviewLoader,
9999
     /// Async image preview loader.
100100
     image_preview_loader: ImagePreviewLoader,
101
+    /// X11 clipboard manager for system clipboard integration.
102
+    x11_clipboard: ClipboardManager,
101103
 }
102104
 
103105
 /// State for a paste operation with conflicts.
@@ -140,6 +142,9 @@ impl App {
140142
 
141143
         window.focus()?;
142144
 
145
+        // Create X11 clipboard manager for system clipboard integration
146
+        let x11_clipboard = ClipboardManager::new(conn.clone(), window.id())?;
147
+
143148
         // Create graphics context for blitting
144149
         let gc = conn.generate_id()?;
145150
         conn.inner().create_gc(gc, window.id(), &Default::default())?;
@@ -274,6 +279,7 @@ impl App {
274279
             pending_paste: None,
275280
             preview_loader: PreviewLoader::new(),
276281
             image_preview_loader: ImagePreviewLoader::new(),
282
+            x11_clipboard,
277283
         };
278284
 
279285
         app.update_status_bar();
@@ -349,6 +355,18 @@ impl App {
349355
                         ev.request_redraw();
350356
                     }
351357
                 }
358
+                InputEvent::SelectionRequest(req) => {
359
+                    // Another application is requesting our clipboard data
360
+                    tracing::debug!("Received SelectionRequest event");
361
+                    if let Err(e) = self.x11_clipboard.handle_selection_request(&req) {
362
+                        tracing::warn!("Failed to handle selection request: {}", e);
363
+                    }
364
+                }
365
+                InputEvent::SelectionClear => {
366
+                    // We lost clipboard ownership to another application
367
+                    tracing::debug!("Received SelectionClear event");
368
+                    self.x11_clipboard.handle_selection_clear();
369
+                }
352370
                 _ => {}
353371
             }
354372
 
@@ -1493,7 +1511,15 @@ impl App {
14931511
         let paths = self.get_selected_paths();
14941512
         if !paths.is_empty() {
14951513
             let count = paths.len();
1496
-            self.clipboard.copy(paths);
1514
+
1515
+            // Update internal clipboard
1516
+            self.clipboard.copy(paths.clone());
1517
+
1518
+            // Update X11 system clipboard so other apps can paste
1519
+            if let Err(e) = self.x11_clipboard.set_files(&paths, false) {
1520
+                tracing::warn!("Failed to set X11 clipboard: {}", e);
1521
+            }
1522
+
14971523
             let msg = if count == 1 { "1 item copied".to_string() } else { format!("{} items copied", count) };
14981524
             self.status_bar.set_status_message(msg);
14991525
             self.update_status_bar();
@@ -1505,7 +1531,15 @@ impl App {
15051531
         let paths = self.get_selected_paths();
15061532
         if !paths.is_empty() {
15071533
             let count = paths.len();
1508
-            self.clipboard.cut(paths);
1534
+
1535
+            // Update internal clipboard
1536
+            self.clipboard.cut(paths.clone());
1537
+
1538
+            // Update X11 system clipboard with cut flag so other apps know to move
1539
+            if let Err(e) = self.x11_clipboard.set_files(&paths, true) {
1540
+                tracing::warn!("Failed to set X11 clipboard: {}", e);
1541
+            }
1542
+
15091543
             let msg = if count == 1 { "1 item cut".to_string() } else { format!("{} items cut", count) };
15101544
             self.status_bar.set_status_message(msg);
15111545
             self.update_status_bar();