|
@@ -4,18 +4,23 @@ use xcb;
|
|
|
use ui::ext;
|
|
|
use ui::ext::ConnectionExt;
|
|
|
use ui::font;
|
|
|
+use ui::widget;
|
|
|
use ui::widget::Widget;
|
|
|
use ui::x11;
|
|
|
|
|
|
+use std::rc::Rc;
|
|
|
use std::sync::Arc;
|
|
|
+use std::iter;
|
|
|
+use std::slice;
|
|
|
|
|
|
pub struct Panel {
|
|
|
pub conn: Arc<x11::Connection>,
|
|
|
pub window: xcb::Window,
|
|
|
pub width: u16,
|
|
|
pub tx: chan::Sender<()>,
|
|
|
+ left_widgets: Vec<Box<Widget>>,
|
|
|
right_widgets: Vec<Box<Widget>>,
|
|
|
- fonts: font::FontLoader,
|
|
|
+ fonts: Rc<font::FontLoader>,
|
|
|
picture: xcb::render::Picture,
|
|
|
finishing: bool
|
|
|
}
|
|
@@ -26,41 +31,37 @@ impl Panel {
|
|
|
let window = conn.generate_id();
|
|
|
let picture = conn.generate_id();
|
|
|
|
|
|
- let val = cfg.lookup("bar.fonts").unwrap();
|
|
|
- let fonts = val.as_slice().unwrap();
|
|
|
- let fonts = fonts.iter().flat_map(|elem| elem.as_str());
|
|
|
- let mut font_loader = font::FontLoader::new(conn.clone_connection());
|
|
|
- for font in fonts {
|
|
|
- font_loader.load(font);
|
|
|
- }
|
|
|
-
|
|
|
let (tx, rx) = chan::sync(10);
|
|
|
let width = conn.default_screen().width;
|
|
|
+ let font_loader = Rc::new(font::FontLoader::from_config(conn.clone_connection(), cfg));
|
|
|
|
|
|
let panel = Panel {
|
|
|
conn: conn,
|
|
|
width: width,
|
|
|
tx: tx,
|
|
|
window: window,
|
|
|
- fonts: font_loader,
|
|
|
+ left_widgets: vec![],
|
|
|
right_widgets: vec![],
|
|
|
+ fonts: font_loader,
|
|
|
picture: picture,
|
|
|
finishing: false
|
|
|
};
|
|
|
(panel, rx)
|
|
|
}
|
|
|
|
|
|
- pub fn create(&self) {
|
|
|
- let conn = &self.conn;
|
|
|
- let screen = conn.default_screen();
|
|
|
+ pub fn create(&mut self) {
|
|
|
+ let (root, width) = {
|
|
|
+ let screen = self.conn.default_screen();
|
|
|
+ (screen.root, screen.width)
|
|
|
+ };
|
|
|
|
|
|
xcb::create_window(
|
|
|
- conn,
|
|
|
+ &self.conn,
|
|
|
xcb::COPY_FROM_PARENT as u8,
|
|
|
self.window,
|
|
|
- screen.root,
|
|
|
+ root,
|
|
|
0, 0,
|
|
|
- screen.width, 20,
|
|
|
+ width, 20,
|
|
|
0,
|
|
|
xcb::WINDOW_CLASS_INPUT_OUTPUT as u16,
|
|
|
xcb::COPY_FROM_PARENT,
|
|
@@ -70,17 +71,29 @@ impl Panel {
|
|
|
]
|
|
|
);
|
|
|
self.set_property(
|
|
|
- conn.atom(x11::_NET_WM_WINDOW_TYPE),
|
|
|
+ self.conn.atom(x11::_NET_WM_WINDOW_TYPE),
|
|
|
xcb::ATOM_ATOM,
|
|
|
32,
|
|
|
- &[conn.atom(x11::_NET_WM_WINDOW_TYPE_DOCK)]
|
|
|
+ &[self.conn.atom(x11::_NET_WM_WINDOW_TYPE_DOCK)]
|
|
|
);
|
|
|
- xcb::map_window(conn, self.window);
|
|
|
- xcb::render::create_picture(&conn, self.picture, self.window, conn.get_pict_format(ext::PictFormat::RGB24), &[
|
|
|
+ xcb::map_window(&self.conn, self.window);
|
|
|
+ xcb::render::create_picture(&self.conn, self.picture, self.window, self.conn.get_pict_format(ext::PictFormat::RGB24), &[
|
|
|
(xcb::render::CP_POLY_EDGE, xcb::render::POLY_EDGE_SMOOTH),
|
|
|
(xcb::render::CP_POLY_MODE, xcb::render::POLY_MODE_IMPRECISE)
|
|
|
]);
|
|
|
- conn.flush();
|
|
|
+ self.conn.flush();
|
|
|
+ for widget in self.widgets_iter() {
|
|
|
+ widget.init();
|
|
|
+ }
|
|
|
+ self.conn.flush();
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn make_draw_context(&self) -> widget::DrawContext {
|
|
|
+ widget::DrawContext::new(self.conn.clone_connection(), self.picture, self.fonts.clone())
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn widgets_iter(&mut self) -> iter::Chain<slice::IterMut<Box<Widget>>, slice::IterMut<Box<Widget>>>{
|
|
|
+ self.left_widgets.iter_mut().chain(self.right_widgets.iter_mut())
|
|
|
}
|
|
|
|
|
|
pub fn set_property<T>(&self, name: xcb::Atom, type_: xcb::Atom, format: u8, data: &[T]) {
|
|
@@ -96,15 +109,15 @@ impl Panel {
|
|
|
}
|
|
|
|
|
|
pub fn handle_event(&mut self, event: xcb::GenericEvent) -> bool {
|
|
|
+ let finishing = self.finishing;
|
|
|
let mut should_exit = false;
|
|
|
- for widget in self.right_widgets.iter_mut() {
|
|
|
- should_exit |= widget.handle_event(&event, self.finishing);
|
|
|
+ for widget in self.widgets_iter() {
|
|
|
+ should_exit |= widget.handle_event(&event, finishing);
|
|
|
}
|
|
|
if event.response_type() == xcb::EXPOSE {
|
|
|
self.relayout();
|
|
|
- self.draw_text("Hello 世界!");
|
|
|
}
|
|
|
- if self.finishing && event.response_type() == xcb::DESTROY_NOTIFY {
|
|
|
+ if finishing && event.response_type() == xcb::DESTROY_NOTIFY {
|
|
|
let event: &xcb::DestroyNotifyEvent = xcb::cast_event(&event);
|
|
|
if event.window() == self.window {
|
|
|
return true
|
|
@@ -113,44 +126,15 @@ impl Panel {
|
|
|
should_exit
|
|
|
}
|
|
|
|
|
|
- pub fn add_right_widget(&mut self, widget: Box<Widget>) {
|
|
|
- self.right_widgets.push(widget);
|
|
|
- }
|
|
|
-
|
|
|
- pub fn create_pen(&self, r: u16, g: u16, b: u16, a: u16) -> xcb::render::Picture {
|
|
|
- let color = xcb::render::Color::new(r, g, b, a);
|
|
|
- let format = self.conn.get_pict_format(ext::PictFormat::ARGB32);
|
|
|
- let pixmap = self.conn.generate_id();
|
|
|
- xcb::create_pixmap(&self.conn, 32, pixmap, self.window, 1, 1);
|
|
|
- let picture = self.conn.generate_id();
|
|
|
- xcb::render::create_picture(
|
|
|
- &self.conn,
|
|
|
- picture,
|
|
|
- pixmap,
|
|
|
- format,
|
|
|
- &[(xcb::render::CP_REPEAT, xcb::render::REPEAT_NORMAL)]
|
|
|
- );
|
|
|
- xcb::render::fill_rectangles(
|
|
|
- &self.conn,
|
|
|
- xcb::render::PICT_OP_OVER as u8,
|
|
|
- picture,
|
|
|
- color,
|
|
|
- &[xcb::Rectangle::new(0, 0, 1, 1)]
|
|
|
- );
|
|
|
- xcb::free_pixmap(&self.conn, pixmap);
|
|
|
- self.conn.flush();
|
|
|
- picture
|
|
|
+ pub fn add_left_widget(&mut self, widget: Box<Widget>) {
|
|
|
+ self.left_widgets.push(widget);
|
|
|
}
|
|
|
|
|
|
- pub fn draw_text(&self, name: &str) {
|
|
|
- let pen = self.create_pen(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF);
|
|
|
- let text = self.fonts.create_renderable_text(name);
|
|
|
- let baseline = 20 - self.fonts.default_offset(20);
|
|
|
- text.render(&self.conn, pen, self.picture, 0, baseline as u16);
|
|
|
- self.conn.flush();
|
|
|
+ pub fn add_right_widget(&mut self, widget: Box<Widget>) {
|
|
|
+ self.right_widgets.push(widget);
|
|
|
}
|
|
|
|
|
|
- pub fn relayout(&self) {
|
|
|
+ pub fn relayout(&mut self) {
|
|
|
let color = xcb::render::Color::new(0, 0, 0, 0xFFFF);
|
|
|
xcb::render::fill_rectangles(
|
|
|
&self.conn,
|
|
@@ -159,8 +143,13 @@ impl Panel {
|
|
|
color,
|
|
|
&[xcb::Rectangle::new(0, 0, self.width, 20)]
|
|
|
);
|
|
|
+ let mut left_pos = 0;
|
|
|
+ for widget in self.left_widgets.iter_mut() {
|
|
|
+ widget.render(left_pos);
|
|
|
+ left_pos += widget.width();
|
|
|
+ }
|
|
|
let mut right_pos = self.width;
|
|
|
- for widget in self.right_widgets.iter() {
|
|
|
+ for widget in self.right_widgets.iter_mut() {
|
|
|
right_pos -= widget.width();
|
|
|
widget.render(right_pos);
|
|
|
}
|
|
@@ -169,7 +158,7 @@ impl Panel {
|
|
|
|
|
|
pub fn finish(&mut self) {
|
|
|
self.finishing = true;
|
|
|
- for widget in self.right_widgets.iter_mut() {
|
|
|
+ for widget in self.widgets_iter() {
|
|
|
widget.finish();
|
|
|
}
|
|
|
xcb::destroy_window(&self.conn, self.window);
|