summaryrefslogtreecommitdiff
path: root/src/systray.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/systray.rs')
-rw-r--r--src/systray.rs90
1 files changed, 84 insertions, 6 deletions
diff --git a/src/systray.rs b/src/systray.rs
index 3370c73..b06f08d 100644
--- a/src/systray.rs
+++ b/src/systray.rs
@@ -20,7 +20,7 @@ struct SystrayAtoms {
manager: x11::xlib::Atom,
}
-fn intern_xatom(name: &str, disp: *mut x11::xlib::Display) -> x11::xlib::Atom {
+pub fn intern_xatom(name: &str, disp: *mut x11::xlib::Display) -> x11::xlib::Atom {
gdk::error_trap_push();
let atom = unsafe {
use std::ffi::CString;
@@ -171,8 +171,22 @@ impl SystrayInner {
}
fn create_dock(&self, xid: gtk::xlib::Window) {
+ let mut attrs: x11::xlib::XSetWindowAttributes =
+ unsafe { std::mem::MaybeUninit::zeroed().assume_init() };
+ attrs.background_pixmap = x11::xlib::ParentRelative as x11::xlib::Pixmap;
+ attrs.event_mask = x11::xlib::PropertyChangeMask | x11::xlib::StructureNotifyMask;
+ unsafe {
+ x11::xlib::XChangeWindowAttributes(
+ self.display.unwrap(),
+ xid as x11::xlib::Window,
+ x11::xlib::CWBackPixmap | x11::xlib::CWEventMask,
+ &mut attrs as *mut _,
+ );
+ x11::xlib::XAddToSaveSet(self.display.unwrap(), xid as x11::xlib::Window);
+ }
let client = client::TrayClient::new(self.display.unwrap(), xid);
self.tray_widget.pack_start(&client, false, false, 0);
+ self.tray_widget.show_all();
client.begin_embed()
}
@@ -295,7 +309,7 @@ mod client {
.get()
.expect("Conformity expected in Object::set_property")
.expect("Expected window to be provided");
- println!("Replacing socket with {:?}", window);
+ println!("Replacing window ID with 0x{:X}", window);
self.window.replace(window);
}
_ => unimplemented!(),
@@ -314,6 +328,8 @@ mod client {
self.parent_constructed(obj);
let self_ = obj.downcast_ref::<TrayClient>().expect("Not a TrayClient");
self_.add(&self.socket);
+ let styles = self_.get_style_context();
+ styles.add_class("tray-client");
}
}
@@ -342,16 +358,45 @@ mod client {
}
self.parent_size_allocate(widget, allocation);
if (moved || resized) && widget.get_mapped() {
- // TODO: Send an expose event to the mapped client somehow?
+ self.force_redraw();
+ }
+ }
+
+ fn realize(&self, widget: &gtk::Widget) {
+ self.parent_realize(widget);
+ widget.show_all();
+ let sock_window = self.socket.get_window().expect("No window?");
+ let bin_window = sock_window.get_parent().expect("No parent?");
+ println!(
+ "{:?} == {:?}",
+ sock_window.get_visual(),
+ bin_window.get_visual()
+ );
+ if *self.has_alpha.borrow() {
+ todo!("Write the has_alpha stuff")
+ } else if sock_window.get_visual() == bin_window.get_visual() {
+ // We're doing parent-relative backgroundery
+ println!("Parent relative background mode");
+ self.parent_relative.replace(true);
+ sock_window.set_background_pattern(None);
+ } else {
+ println!("Ugly-ass mode");
}
+ sock_window.set_composited(*self.has_alpha.borrow());
+ self.socket
+ .set_app_paintable(*self.has_alpha.borrow() || *self.parent_relative.borrow());
+ //self.socket.set_double_buffered(!*self.parent_relative.borrow());
}
fn draw(&self, widget: &gtk::Widget, context: &cairo::Context) -> glib::signal::Inhibit {
+ self.parent_draw(widget, context);
if *self.has_alpha.borrow() {
+ println!("Alpha render");
context.set_source_rgba(0.0, 0.0, 0.0, 0.0);
context.set_operator(cairo::Operator::Source);
context.paint();
- } else {
+ } else if *self.parent_relative.borrow() {
+ println!("Render, parent relative");
if let Some(clip) = context.get_clip_rectangle() {
let target = context.get_group_target();
target.flush();
@@ -400,6 +445,8 @@ mod client {
)
}
}
+ } else {
+ println!("Dodgy ass mess");
}
glib::signal::Inhibit(false)
}
@@ -482,6 +529,38 @@ mod client {
);
println!("Has alpha: {}", self.has_alpha.borrow());
}
+
+ fn force_redraw(&self) {
+ if self.socket.get_mapped() && *self.parent_relative.borrow() {
+ println!("Mapped and parent relative, force redraw");
+ let alloc = self.socket.get_allocation();
+ let xeev = x11::xlib::XExposeEvent {
+ type_: x11::xlib::Expose,
+ window: *self.window.borrow() as u64,
+ x: 0,
+ y: 0,
+ width: alloc.width,
+ height: alloc.height,
+ count: 0,
+ // Spare bits
+ serial: 0,
+ display: std::ptr::null_mut(),
+ send_event: 0,
+ };
+ gdk::error_trap_push();
+ unsafe {
+ let mut event: x11::xlib::XEvent = xeev.into();
+ x11::xlib::XSendEvent(
+ *self.display.borrow(),
+ *self.window.borrow() as u64,
+ 0,
+ x11::xlib::ExposureMask,
+ &mut event as *mut _,
+ );
+ }
+ gdk::error_trap_pop_ignored();
+ }
+ }
}
glib_wrapper! {
@@ -505,13 +584,12 @@ mod client {
.expect("TrayClient is not of expected type");
let priv_ = TrayClientPrivate::from_instance(&ret);
priv_.display.replace(display);
+ priv_.learn_about_window();
ret
}
pub fn begin_embed(&self) {
let priv_ = TrayClientPrivate::from_instance(self);
- priv_.learn_about_window();
- self.show_all();
priv_.socket.add_id(*priv_.window.borrow());
}
}