Implement Kitty graphics protocol for background image rendering
- Added `kitty_gfx` module to handle loading, scaling, and displaying background images using the Kitty graphics protocol. - Integrated background image handling into the main application loop, allowing dynamic updates based on configuration. - Enhanced terminal rendering to support transparent backgrounds when a Kitty image is active. - Updated IPC server to manage client connections and messages, including handling background image settings. - Modified `PtyTerminal` to accept additional environment variables during shell spawning. - Improved rendering logic to support popup dialogs and terminal background color customization.
This commit is contained in:
112
src/server.rs
Normal file
112
src/server.rs
Normal file
@@ -0,0 +1,112 @@
|
||||
use crate::ipc::{self, ClientMessage, ClientRole, ServerMessage};
|
||||
use std::io::{BufReader, BufWriter};
|
||||
use std::os::unix::net::{UnixListener, UnixStream};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::mpsc;
|
||||
use std::thread;
|
||||
|
||||
static NEXT_CLIENT_ID: AtomicUsize = AtomicUsize::new(1);
|
||||
|
||||
pub enum IpcEvent {
|
||||
ClientConnected {
|
||||
client_id: usize,
|
||||
role: ClientRole,
|
||||
width: u16,
|
||||
height: u16,
|
||||
tx: mpsc::SyncSender<ServerMessage>,
|
||||
},
|
||||
ClientDisconnected {
|
||||
client_id: usize,
|
||||
},
|
||||
Message {
|
||||
client_id: usize,
|
||||
msg: ClientMessage,
|
||||
},
|
||||
}
|
||||
|
||||
pub fn start(socket_path: &str, event_tx: mpsc::Sender<IpcEvent>) {
|
||||
let _ = std::fs::remove_file(socket_path);
|
||||
let listener = match UnixListener::bind(socket_path) {
|
||||
Ok(l) => l,
|
||||
Err(e) => {
|
||||
eprintln!("Kunde inte binda Unix socket {}: {}", socket_path, e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let socket_path = socket_path.to_string();
|
||||
thread::spawn(move || {
|
||||
for stream in listener.incoming() {
|
||||
match stream {
|
||||
Ok(stream) => {
|
||||
let client_id = NEXT_CLIENT_ID.fetch_add(1, Ordering::SeqCst);
|
||||
let event_tx = event_tx.clone();
|
||||
let sp = socket_path.clone();
|
||||
thread::spawn(move || {
|
||||
handle_client(client_id, stream, event_tx, sp);
|
||||
});
|
||||
}
|
||||
Err(_) => break,
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn handle_client(
|
||||
client_id: usize,
|
||||
stream: UnixStream,
|
||||
event_tx: mpsc::Sender<IpcEvent>,
|
||||
socket_path: String,
|
||||
) {
|
||||
let stream_write = match stream.try_clone() {
|
||||
Ok(s) => s,
|
||||
Err(_) => return,
|
||||
};
|
||||
let mut reader = BufReader::new(stream);
|
||||
let (tx, rx) = mpsc::sync_channel::<ServerMessage>(64);
|
||||
|
||||
// Writer thread
|
||||
thread::spawn(move || {
|
||||
let mut writer = BufWriter::new(stream_write);
|
||||
for msg in rx {
|
||||
if ipc::write_message(&mut writer, &msg).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Read Hello
|
||||
let hello: ClientMessage = match ipc::read_message(&mut reader) {
|
||||
Ok(m) => m,
|
||||
Err(_) => return,
|
||||
};
|
||||
let (role, width, height) = match &hello {
|
||||
ClientMessage::Hello { role, width, height, .. } => (role.clone(), *width, *height),
|
||||
_ => return,
|
||||
};
|
||||
|
||||
let _ = tx.send(ServerMessage::HelloOk {
|
||||
version: ipc::VERSION.to_string(),
|
||||
socket_path: socket_path.clone(),
|
||||
});
|
||||
|
||||
let _ = event_tx.send(IpcEvent::ClientConnected {
|
||||
client_id,
|
||||
role,
|
||||
width,
|
||||
height,
|
||||
tx: tx.clone(),
|
||||
});
|
||||
|
||||
loop {
|
||||
match ipc::read_message::<_, ClientMessage>(&mut reader) {
|
||||
Ok(msg) => {
|
||||
if event_tx.send(IpcEvent::Message { client_id, msg }).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(_) => break,
|
||||
}
|
||||
}
|
||||
|
||||
let _ = event_tx.send(IpcEvent::ClientDisconnected { client_id });
|
||||
}
|
||||
Reference in New Issue
Block a user