|
@@ -1,71 +1,62 @@
|
|
|
use ui;
|
|
|
-use ui::panel;
|
|
|
use ui::x11;
|
|
|
use xcb;
|
|
|
|
|
|
-use std::rc::Weak;
|
|
|
+use std::sync::Arc;
|
|
|
|
|
|
const CLIENT_MESSAGE: u8 = xcb::CLIENT_MESSAGE | 0x80; // 0x80 flag for client messages
|
|
|
|
|
|
pub struct Tray {
|
|
|
- panel: Weak<panel::Panel>,
|
|
|
+ conn: Arc<x11::Connection>,
|
|
|
+ window: xcb::Window,
|
|
|
+ panel_width: u32,
|
|
|
children: Vec<xcb::Window>,
|
|
|
- timestamp: xcb::Timestamp
|
|
|
-}
|
|
|
-
|
|
|
-// I'M SO SORRY
|
|
|
-macro_rules! refs {
|
|
|
- ( $slf:ident, $panel:ident, $conn:ident ) => {
|
|
|
- let $panel = $slf.panel.upgrade().unwrap();
|
|
|
- let $conn = &$panel.conn;
|
|
|
- }
|
|
|
+ timestamp: xcb::Timestamp,
|
|
|
}
|
|
|
|
|
|
impl Tray {
|
|
|
- pub fn new(panel: Weak<panel::Panel>) -> Tray {
|
|
|
+ pub fn new(conn: Arc<x11::Connection>, window: xcb::Window, width: u32) -> Tray {
|
|
|
Tray {
|
|
|
- panel: panel,
|
|
|
+ conn: conn,
|
|
|
+ window: window,
|
|
|
+ panel_width: width,
|
|
|
children: vec![],
|
|
|
timestamp: 0
|
|
|
}
|
|
|
}
|
|
|
|
|
|
pub fn take_selection(&mut self, timestamp: xcb::Timestamp) -> bool {
|
|
|
- refs!(self, panel, conn);
|
|
|
- let window = panel.window;
|
|
|
- let selection = conn.atom(x11::_NET_SYSTEM_TRAY_S0);
|
|
|
- xcb::set_selection_owner(conn, window, selection, timestamp);
|
|
|
- let owner = xcb::get_selection_owner(conn, selection).get_reply().unwrap().owner();
|
|
|
- let ok = owner == window;
|
|
|
+ let selection = self.conn.atom(x11::_NET_SYSTEM_TRAY_S0);
|
|
|
+ xcb::set_selection_owner(&self.conn, self.window, selection, timestamp);
|
|
|
+ let owner = xcb::get_selection_owner(&self.conn, selection).get_reply().unwrap().owner();
|
|
|
+ let ok = owner == self.window;
|
|
|
if ok {
|
|
|
self.timestamp = timestamp;
|
|
|
- let screen = conn.default_screen();
|
|
|
+ let screen = self.conn.default_screen();
|
|
|
|
|
|
let client_event = xcb::ClientMessageEvent::new(
|
|
|
32, // 32 bits (refers to data)
|
|
|
screen.root,
|
|
|
- conn.atom(x11::MANAGER),
|
|
|
- xcb::ClientMessageData::from_data32([timestamp, selection, window, 0, 0])
|
|
|
+ self.conn.atom(x11::MANAGER),
|
|
|
+ xcb::ClientMessageData::from_data32([timestamp, selection, self.window, 0, 0])
|
|
|
);
|
|
|
- xcb::send_event(conn, false, screen.root, xcb::EVENT_MASK_STRUCTURE_NOTIFY, &client_event);
|
|
|
- conn.flush();
|
|
|
+ xcb::send_event(&self.conn, false, screen.root, xcb::EVENT_MASK_STRUCTURE_NOTIFY, &client_event);
|
|
|
+ self.conn.flush();
|
|
|
}
|
|
|
ok
|
|
|
}
|
|
|
|
|
|
fn x_pos(&self, index: usize) -> u32 {
|
|
|
- refs!(self, panel, _conn);
|
|
|
- let panel_width = panel.width as u32;
|
|
|
let tray_width = (index + 1) as u32 * ui::SIZE as u32;
|
|
|
- panel_width - tray_width
|
|
|
+ self.panel_width - tray_width
|
|
|
}
|
|
|
|
|
|
pub fn adopt(&mut self, window: xcb::Window) {
|
|
|
- refs!(self, panel, conn);
|
|
|
+ let conn = &self.conn;
|
|
|
xcb::change_window_attributes(conn, window, &[
|
|
|
(xcb::CW_EVENT_MASK, xcb::EVENT_MASK_STRUCTURE_NOTIFY)
|
|
|
]);
|
|
|
- xcb::reparent_window(conn, window, panel.window, self.x_pos(self.children.len()) as i16, 0);
|
|
|
+ xcb::reparent_window(conn, window, self.window, self.x_pos(self.children.len()) as i16, 0);
|
|
|
xcb::map_window(conn, window);
|
|
|
self.force_size(window, None);
|
|
|
conn.flush();
|
|
@@ -79,7 +70,7 @@ impl Tray {
|
|
|
}
|
|
|
|
|
|
pub fn force_size(&self, window: xcb::Window, dimensions: Option<(u16, u16)>) {
|
|
|
- refs!(self, panel, conn);
|
|
|
+ let conn = &self.conn;
|
|
|
let dimensions = dimensions.unwrap_or_else(|| {
|
|
|
let geometry = xcb::get_geometry(conn, window).get_reply().unwrap();
|
|
|
(geometry.width(), geometry.height())
|
|
@@ -94,7 +85,7 @@ impl Tray {
|
|
|
}
|
|
|
|
|
|
pub fn reposition(&self) {
|
|
|
- refs!(self, panel, conn);
|
|
|
+ let conn = &self.conn;
|
|
|
for (index, child) in self.children.iter().enumerate() {
|
|
|
let window = *child;
|
|
|
xcb::configure_window(conn, window, &[
|
|
@@ -105,7 +96,7 @@ impl Tray {
|
|
|
}
|
|
|
|
|
|
pub fn finish(&mut self) {
|
|
|
- refs!(self, panel, conn);
|
|
|
+ let conn = &self.conn;
|
|
|
let screen = conn.default_screen();
|
|
|
|
|
|
for child in self.children.iter() {
|
|
@@ -116,16 +107,15 @@ impl Tray {
|
|
|
xcb::unmap_window(conn, window);
|
|
|
xcb::reparent_window(conn, window, screen.root, 0, 0);
|
|
|
}
|
|
|
- xcb::change_window_attributes(conn, panel.window, &[
|
|
|
+ xcb::change_window_attributes(conn, self.window, &[
|
|
|
(xcb::CW_EVENT_MASK, xcb::EVENT_MASK_STRUCTURE_NOTIFY)
|
|
|
]);
|
|
|
xcb::set_selection_owner(conn, xcb::NONE, conn.atom(x11::_NET_SYSTEM_TRAY_S0), self.timestamp);
|
|
|
conn.flush();
|
|
|
}
|
|
|
|
|
|
- pub fn handle_event(&mut self, event: &xcb::GenericEvent) -> bool {
|
|
|
- refs!(self, panel, conn);
|
|
|
- if panel.is_finishing() {
|
|
|
+ pub fn handle_event(&mut self, event: &xcb::GenericEvent, is_finishing: bool) -> bool {
|
|
|
+ if is_finishing {
|
|
|
return false
|
|
|
}
|
|
|
match event.response_type() {
|
|
@@ -138,7 +128,7 @@ impl Tray {
|
|
|
},
|
|
|
CLIENT_MESSAGE => {
|
|
|
let event: &xcb::ClientMessageEvent = xcb::cast_event(&event);
|
|
|
- if event.type_() == conn.atom(x11::_NET_SYSTEM_TRAY_OPCODE) {
|
|
|
+ if event.type_() == self.conn.atom(x11::_NET_SYSTEM_TRAY_OPCODE) {
|
|
|
let data = event.data().data32();
|
|
|
let opcode = data[1];
|
|
|
let window = data[2];
|
|
@@ -149,7 +139,7 @@ impl Tray {
|
|
|
},
|
|
|
xcb::REPARENT_NOTIFY => {
|
|
|
let event: &xcb::ReparentNotifyEvent = xcb::cast_event(&event);
|
|
|
- if event.parent() != panel.window {
|
|
|
+ if event.parent() != self.window {
|
|
|
self.forget(event.window());
|
|
|
}
|
|
|
},
|
|
@@ -160,7 +150,7 @@ impl Tray {
|
|
|
xcb::CONFIGURE_NOTIFY => {
|
|
|
let event: &xcb::ConfigureNotifyEvent = xcb::cast_event(&event);
|
|
|
let window = event.window();
|
|
|
- if window != panel.window {
|
|
|
+ if window != self.window {
|
|
|
self.force_size(window, Some((event.width(), event.height())));
|
|
|
}
|
|
|
},
|