|  | @@ -12,12 +12,24 @@ use std::sync::Arc;
 | 
											
												
													
														|  |  use std::iter;
 |  |  use std::iter;
 | 
											
												
													
														|  |  use std::slice;
 |  |  use std::slice;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +struct WidgetState {
 | 
											
												
													
														|  | 
 |  | +    widget: Box<Widget>,
 | 
											
												
													
														|  | 
 |  | +    position: u16,
 | 
											
												
													
														|  | 
 |  | +    width: u16
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +impl WidgetState {
 | 
											
												
													
														|  | 
 |  | +    fn contains(&self, x: u16) -> bool {
 | 
											
												
													
														|  | 
 |  | +        x >= self.position && x < self.position + self.width
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  pub struct Panel {
 |  |  pub struct Panel {
 | 
											
												
													
														|  |      pub conn: Arc<x11::Connection>,
 |  |      pub conn: Arc<x11::Connection>,
 | 
											
												
													
														|  |      pub window: xcb::Window,
 |  |      pub window: xcb::Window,
 | 
											
												
													
														|  |      pub width: u16,
 |  |      pub width: u16,
 | 
											
												
													
														|  | -    left_widgets: Vec<Box<Widget>>,
 |  | 
 | 
											
												
													
														|  | -    right_widgets: Vec<Box<Widget>>,
 |  | 
 | 
											
												
													
														|  | 
 |  | +    left_widgets: Vec<WidgetState>,
 | 
											
												
													
														|  | 
 |  | +    right_widgets: Vec<WidgetState>,
 | 
											
												
													
														|  |      fonts: Rc<font::FontLoader>,
 |  |      fonts: Rc<font::FontLoader>,
 | 
											
												
													
														|  |      picture: xcb::render::Picture,
 |  |      picture: xcb::render::Picture,
 | 
											
												
													
														|  |      finishing: bool
 |  |      finishing: bool
 | 
											
										
											
												
													
														|  | @@ -62,7 +74,7 @@ impl Panel {
 | 
											
												
													
														|  |              xcb::COPY_FROM_PARENT,
 |  |              xcb::COPY_FROM_PARENT,
 | 
											
												
													
														|  |              &[
 |  |              &[
 | 
											
												
													
														|  |                  (xcb::CW_BACK_PIXEL, 0xFF000000),
 |  |                  (xcb::CW_BACK_PIXEL, 0xFF000000),
 | 
											
												
													
														|  | -                (xcb::CW_EVENT_MASK, xcb::EVENT_MASK_EXPOSURE | xcb::EVENT_MASK_PROPERTY_CHANGE | xcb::EVENT_MASK_STRUCTURE_NOTIFY)
 |  | 
 | 
											
												
													
														|  | 
 |  | +                (xcb::CW_EVENT_MASK, xcb::EVENT_MASK_EXPOSURE | xcb::EVENT_MASK_PROPERTY_CHANGE | xcb::EVENT_MASK_STRUCTURE_NOTIFY | xcb::EVENT_MASK_BUTTON_PRESS)
 | 
											
												
													
														|  |              ]
 |  |              ]
 | 
											
												
													
														|  |          );
 |  |          );
 | 
											
												
													
														|  |          self.set_property(
 |  |          self.set_property(
 | 
											
										
											
												
													
														|  | @@ -77,8 +89,8 @@ impl Panel {
 | 
											
												
													
														|  |              (xcb::render::CP_POLY_MODE, xcb::render::POLY_MODE_IMPRECISE)
 |  |              (xcb::render::CP_POLY_MODE, xcb::render::POLY_MODE_IMPRECISE)
 | 
											
												
													
														|  |          ]);
 |  |          ]);
 | 
											
												
													
														|  |          self.conn.flush();
 |  |          self.conn.flush();
 | 
											
												
													
														|  | -        for widget in self.widgets_iter() {
 |  | 
 | 
											
												
													
														|  | -            widget.init();
 |  | 
 | 
											
												
													
														|  | 
 |  | +        for state in self.widgets_iter() {
 | 
											
												
													
														|  | 
 |  | +            state.widget.init();
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |          self.conn.flush();
 |  |          self.conn.flush();
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
										
											
												
													
														|  | @@ -87,7 +99,7 @@ impl Panel {
 | 
											
												
													
														|  |          widget::DrawContext::new(self.conn.clone_connection(), self.window, self.picture, self.fonts.clone())
 |  |          widget::DrawContext::new(self.conn.clone_connection(), self.window, self.picture, self.fonts.clone())
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    pub fn widgets_iter(&mut self) -> iter::Chain<slice::IterMut<Box<Widget>>, slice::IterMut<Box<Widget>>>{
 |  | 
 | 
											
												
													
														|  | 
 |  | +    fn widgets_iter(&mut self) -> iter::Chain<slice::IterMut<WidgetState>, slice::IterMut<WidgetState>>{
 | 
											
												
													
														|  |          self.left_widgets.iter_mut().chain(self.right_widgets.iter_mut())
 |  |          self.left_widgets.iter_mut().chain(self.right_widgets.iter_mut())
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -107,8 +119,8 @@ impl Panel {
 | 
											
												
													
														|  |          let finishing = self.finishing;
 |  |          let finishing = self.finishing;
 | 
											
												
													
														|  |          let mut should_exit = false;
 |  |          let mut should_exit = false;
 | 
											
												
													
														|  |          if !finishing {
 |  |          if !finishing {
 | 
											
												
													
														|  | -            for widget in self.widgets_iter() {
 |  | 
 | 
											
												
													
														|  | -                should_exit |= widget.handle_event(&event);
 |  | 
 | 
											
												
													
														|  | 
 |  | +            for state in self.widgets_iter() {
 | 
											
												
													
														|  | 
 |  | +                should_exit |= state.widget.handle_event(&event);
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |          match event {
 |  |          match event {
 | 
											
										
											
												
													
														|  | @@ -116,6 +128,17 @@ impl Panel {
 | 
											
												
													
														|  |                  if event.response_type() == xcb::EXPOSE {
 |  |                  if event.response_type() == xcb::EXPOSE {
 | 
											
												
													
														|  |                      self.relayout();
 |  |                      self.relayout();
 | 
											
												
													
														|  |                  };
 |  |                  };
 | 
											
												
													
														|  | 
 |  | +                if event.response_type() == xcb::BUTTON_PRESS {
 | 
											
												
													
														|  | 
 |  | +                    let event: &xcb::ButtonPressEvent = unsafe { xcb::cast_event(&event) };
 | 
											
												
													
														|  | 
 |  | +                    let x = event.root_x() as u16;
 | 
											
												
													
														|  | 
 |  | +                    for state in self.widgets_iter() {
 | 
											
												
													
														|  | 
 |  | +                        if state.contains(x) {
 | 
											
												
													
														|  | 
 |  | +                            let offset_x = x - state.position;
 | 
											
												
													
														|  | 
 |  | +                            let event = widget::Message::MousePress(offset_x);
 | 
											
												
													
														|  | 
 |  | +                            state.widget.handle_event(&event);
 | 
											
												
													
														|  | 
 |  | +                        }
 | 
											
												
													
														|  | 
 |  | +                    }
 | 
											
												
													
														|  | 
 |  | +                };
 | 
											
												
													
														|  |                  if finishing && event.response_type() == xcb::DESTROY_NOTIFY {
 |  |                  if finishing && event.response_type() == xcb::DESTROY_NOTIFY {
 | 
											
												
													
														|  |                      let event: &xcb::DestroyNotifyEvent = unsafe { xcb::cast_event(&event) };
 |  |                      let event: &xcb::DestroyNotifyEvent = unsafe { xcb::cast_event(&event) };
 | 
											
												
													
														|  |                      if event.window() == self.window {
 |  |                      if event.window() == self.window {
 | 
											
										
											
												
													
														|  | @@ -135,11 +158,19 @@ impl Panel {
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      pub fn add_left_widget(&mut self, widget: Box<Widget>) {
 |  |      pub fn add_left_widget(&mut self, widget: Box<Widget>) {
 | 
											
												
													
														|  | -        self.left_widgets.push(widget);
 |  | 
 | 
											
												
													
														|  | 
 |  | +        self.left_widgets.push(WidgetState{
 | 
											
												
													
														|  | 
 |  | +            widget: widget,
 | 
											
												
													
														|  | 
 |  | +            position: 0,
 | 
											
												
													
														|  | 
 |  | +            width: 0
 | 
											
												
													
														|  | 
 |  | +        });
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      pub fn add_right_widget(&mut self, widget: Box<Widget>) {
 |  |      pub fn add_right_widget(&mut self, widget: Box<Widget>) {
 | 
											
												
													
														|  | -        self.right_widgets.push(widget);
 |  | 
 | 
											
												
													
														|  | 
 |  | +        self.right_widgets.push(WidgetState{
 | 
											
												
													
														|  | 
 |  | +            widget: widget,
 | 
											
												
													
														|  | 
 |  | +            position: 0,
 | 
											
												
													
														|  | 
 |  | +            width: 0
 | 
											
												
													
														|  | 
 |  | +        });
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      pub fn relayout(&mut self) {
 |  |      pub fn relayout(&mut self) {
 | 
											
										
											
												
													
														|  | @@ -151,23 +182,32 @@ impl Panel {
 | 
											
												
													
														|  |              color,
 |  |              color,
 | 
											
												
													
														|  |              &[xcb::Rectangle::new(0, 0, self.width, 20)]
 |  |              &[xcb::Rectangle::new(0, 0, self.width, 20)]
 | 
											
												
													
														|  |          );
 |  |          );
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        // measure
 | 
											
												
													
														|  |          let mut left_pos = 0;
 |  |          let mut left_pos = 0;
 | 
											
												
													
														|  | -        for widget in self.left_widgets.iter_mut() {
 |  | 
 | 
											
												
													
														|  | -            widget.render(left_pos);
 |  | 
 | 
											
												
													
														|  | -            left_pos += widget.width();
 |  | 
 | 
											
												
													
														|  | 
 |  | +        for state in self.left_widgets.iter_mut() {
 | 
											
												
													
														|  | 
 |  | +            state.position = left_pos;
 | 
											
												
													
														|  | 
 |  | +            state.width = state.widget.width();
 | 
											
												
													
														|  | 
 |  | +            left_pos += state.width;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |          let mut right_pos = self.width;
 |  |          let mut right_pos = self.width;
 | 
											
												
													
														|  | -        for widget in self.right_widgets.iter_mut() {
 |  | 
 | 
											
												
													
														|  | -            right_pos -= widget.width();
 |  | 
 | 
											
												
													
														|  | -            widget.render(right_pos);
 |  | 
 | 
											
												
													
														|  | 
 |  | +        for state in self.right_widgets.iter_mut() {
 | 
											
												
													
														|  | 
 |  | +            state.width = state.widget.width();
 | 
											
												
													
														|  | 
 |  | +            right_pos -= state.width;
 | 
											
												
													
														|  | 
 |  | +            state.position = right_pos;
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        // render
 | 
											
												
													
														|  | 
 |  | +        for state in self.widgets_iter() {
 | 
											
												
													
														|  | 
 |  | +            state.widget.render(state.position);
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |          self.conn.flush();
 |  |          self.conn.flush();
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      pub fn finish(&mut self) {
 |  |      pub fn finish(&mut self) {
 | 
											
												
													
														|  |          self.finishing = true;
 |  |          self.finishing = true;
 | 
											
												
													
														|  | -        for widget in self.widgets_iter() {
 |  | 
 | 
											
												
													
														|  | -            widget.finish();
 |  | 
 | 
											
												
													
														|  | 
 |  | +        for state in self.widgets_iter() {
 | 
											
												
													
														|  | 
 |  | +            state.widget.finish();
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |          xcb::destroy_window(&self.conn, self.window);
 |  |          xcb::destroy_window(&self.conn, self.window);
 | 
											
												
													
														|  |          self.conn.flush();
 |  |          self.conn.flush();
 |