Refactor slightly
This commit is contained in:
@@ -4,6 +4,10 @@ use crate::draw;
|
||||
use fontconfig::Fontconfig as FontConfig;
|
||||
use rusttype::Font;
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
mem,
|
||||
rc::Rc,
|
||||
thread,
|
||||
collections::HashMap,
|
||||
fs::File,
|
||||
hash,
|
||||
@@ -11,6 +15,7 @@ use std::{
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
|
||||
/// FontRef is used to store Fonts on widgets.
|
||||
pub type FontRef<'a> = &'a rusttype::Font<'a>;
|
||||
|
||||
@@ -126,3 +131,31 @@ impl FontMap {
|
||||
.expect("no font at specified size")
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MaybeFontMap {
|
||||
Waiting(thread::JoinHandle<FontMap>),
|
||||
Ready(Rc<RefCell<FontMap>>),
|
||||
Invalid,
|
||||
}
|
||||
|
||||
impl MaybeFontMap {
|
||||
pub fn unwrap(&self) -> Rc<RefCell<FontMap>> {
|
||||
match self {
|
||||
MaybeFontMap::Ready(f) => f.clone(),
|
||||
_ => panic!("fontmap not yet ready"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve(&mut self) {
|
||||
if matches!(self, MaybeFontMap::Waiting(_)) {
|
||||
let s = mem::replace(self, MaybeFontMap::Invalid);
|
||||
match s {
|
||||
MaybeFontMap::Waiting(handle) => {
|
||||
*self = MaybeFontMap::Ready(Rc::new(RefCell::new(handle.join().unwrap())));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+13
-435
@@ -5,19 +5,9 @@ mod fonts;
|
||||
mod keyboard;
|
||||
mod utils;
|
||||
mod widgets;
|
||||
mod state;
|
||||
|
||||
use wayland_client::{
|
||||
protocol::{
|
||||
wl_buffer, wl_compositor, wl_keyboard, wl_registry, wl_seat, wl_shm, wl_shm_pool,
|
||||
wl_surface,
|
||||
},
|
||||
Connection, Dispatch, QueueHandle, WEnum, WaylandSource,
|
||||
};
|
||||
|
||||
use wayland_protocols::xdg::{
|
||||
activation::v1::client::{xdg_activation_token_v1, xdg_activation_v1},
|
||||
shell::client::{xdg_surface, xdg_toplevel, xdg_wm_base},
|
||||
};
|
||||
use wayland_client::{Connection, QueueHandle, WaylandSource,};
|
||||
|
||||
use calloop::{
|
||||
timer::{TimeoutAction, Timer},
|
||||
@@ -27,84 +17,14 @@ use chrono::{Duration, Local, Timelike};
|
||||
|
||||
use buffer::{BufferManager, BufferView};
|
||||
use color::Color;
|
||||
use fonts::FontMap;
|
||||
use fonts::{MaybeFontMap, FontMap};
|
||||
use keyboard::Keyboard;
|
||||
use widgets::{
|
||||
Backlight, Battery, Clock, Date, Geometry, HorizontalLayout, IndexedLayout, Interface, Layout,
|
||||
Line, Margin, VerticalLayout, Widget, WidgetUpdater,
|
||||
Backlight, Battery, Clock, Date, Geometry, Interface, Line, WidgetUpdater,
|
||||
};
|
||||
use state::State;
|
||||
|
||||
use std::{cell::RefCell, env, mem, process::exit, rc::Rc, thread};
|
||||
|
||||
enum MaybeFontMap {
|
||||
Waiting(thread::JoinHandle<FontMap>),
|
||||
Ready(Rc<RefCell<FontMap>>),
|
||||
Invalid,
|
||||
}
|
||||
|
||||
impl MaybeFontMap {
|
||||
fn unwrap(&self) -> Rc<RefCell<FontMap>> {
|
||||
match self {
|
||||
MaybeFontMap::Ready(f) => f.clone(),
|
||||
_ => panic!("fontmap not yet ready"),
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve(&mut self) {
|
||||
if matches!(self, MaybeFontMap::Waiting(_)) {
|
||||
let s = mem::replace(self, MaybeFontMap::Invalid);
|
||||
match s {
|
||||
MaybeFontMap::Waiting(handle) => {
|
||||
*self = MaybeFontMap::Ready(Rc::new(RefCell::new(handle.join().unwrap())));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct State {
|
||||
running: bool,
|
||||
dirty: bool,
|
||||
activated: bool,
|
||||
base_surface: Option<wl_surface::WlSurface>,
|
||||
wm_base: Option<xdg_wm_base::XdgWmBase>,
|
||||
xdg_surface: Option<(xdg_surface::XdgSurface, xdg_toplevel::XdgToplevel)>,
|
||||
wl_shm: Option<wl_shm::WlShm>,
|
||||
xdg_activation: Option<xdg_activation_v1::XdgActivationV1>,
|
||||
configured: bool,
|
||||
dimensions: (i32, i32),
|
||||
bufmgr: BufferManager,
|
||||
widgets: Vec<Box<dyn Widget>>,
|
||||
keyboard: Keyboard,
|
||||
fonts: MaybeFontMap,
|
||||
}
|
||||
|
||||
impl State {
|
||||
fn add_buffer(&mut self, qh: &QueueHandle<Self>) {
|
||||
self.bufmgr.add_buffer(
|
||||
self.wl_shm.as_ref().expect("missing wl_shm"),
|
||||
self.dimensions,
|
||||
qh,
|
||||
);
|
||||
}
|
||||
|
||||
fn activate(&mut self, qh: &QueueHandle<Self>) {
|
||||
let key = match env::var("XDG_ACTIVATION_TOKEN") {
|
||||
Ok(token) => token,
|
||||
Err(_) => return,
|
||||
};
|
||||
match (&self.base_surface, &self.xdg_activation) {
|
||||
(Some(surface), Some(activation)) => {
|
||||
activation.activate(key, surface);
|
||||
let activation_token = activation.get_activation_token(qh, ());
|
||||
activation_token.commit();
|
||||
env::remove_var("XDG_ACTIVATION_TOKEN");
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
use std::thread;
|
||||
|
||||
impl WidgetUpdater for State {
|
||||
fn geometry_update(
|
||||
@@ -121,8 +41,8 @@ fn main() {
|
||||
let font_thread = thread::spawn(move || {
|
||||
let mut fm = FontMap::new();
|
||||
// Hard-coding font paths make things a lot faster
|
||||
fm.queue_font_path("sans", "/usr/share/fonts/noto/NotoSans-Regular.ttf", 96.);
|
||||
fm.queue_font_path("sans", "/usr/share/fonts/noto/NotoSans-Regular.ttf", 40.);
|
||||
fm.queue_font_path("sans", "/usr/share/fonts/noto/NotoSans-Regular.ttf", 128.);
|
||||
fm.queue_font_path("sans", "/usr/share/fonts/noto/NotoSans-Regular.ttf", 48.);
|
||||
fm.queue_font_path("sans", "/usr/share/fonts/noto/NotoSans-Regular.ttf", 24.);
|
||||
fm.queue_font_path(
|
||||
"monospace",
|
||||
@@ -146,12 +66,12 @@ fn main() {
|
||||
|
||||
let (ping_sender, ping_source) = calloop::ping::make_ping().unwrap();
|
||||
|
||||
let clock = Box::new(Clock::new());
|
||||
let date = Box::new(Date::new());
|
||||
let clock = Box::new(Clock::new("sans", 128.));
|
||||
let date = Box::new(Date::new("sans", 48.));
|
||||
let line = Box::new(Line::new());
|
||||
let launcher = Box::new(Interface::new());
|
||||
let battery = Box::new(Battery::new(ping_sender));
|
||||
let backlight = Box::new(Backlight::new("intel_backlight"));
|
||||
let launcher = Box::new(Interface::new("monospace", 32.));
|
||||
let battery = Box::new(Battery::new(ping_sender, "sans", 24.));
|
||||
let backlight = Box::new(Backlight::new("intel_backlight", "sans", 24.));
|
||||
|
||||
let mut event_loop: EventLoop<State> =
|
||||
EventLoop::try_new().expect("Failed to initialize the event loop!");
|
||||
@@ -288,345 +208,3 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<wl_registry::WlRegistry, ()> for State {
|
||||
fn event(
|
||||
state: &mut Self,
|
||||
registry: &wl_registry::WlRegistry,
|
||||
event: wl_registry::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
qh: &QueueHandle<Self>,
|
||||
) {
|
||||
if let wl_registry::Event::Global {
|
||||
name, interface, ..
|
||||
} = event
|
||||
{
|
||||
match &interface[..] {
|
||||
"wl_compositor" => {
|
||||
let compositor =
|
||||
registry.bind::<wl_compositor::WlCompositor, _, _>(name, 4, qh, ());
|
||||
let surface = compositor.create_surface(qh, ());
|
||||
state.base_surface = Some(surface);
|
||||
state.activate(qh);
|
||||
|
||||
if state.wm_base.is_some() && state.xdg_surface.is_none() {
|
||||
state.init_xdg_surface(qh);
|
||||
}
|
||||
}
|
||||
"wl_shm" => {
|
||||
state.wl_shm = Some(registry.bind::<wl_shm::WlShm, _, _>(name, 1, qh, ()));
|
||||
}
|
||||
"wl_seat" => {
|
||||
registry.bind::<wl_seat::WlSeat, _, _>(name, 1, qh, ());
|
||||
}
|
||||
"xdg_wm_base" => {
|
||||
let wm_base = registry.bind::<xdg_wm_base::XdgWmBase, _, _>(name, 1, qh, ());
|
||||
state.wm_base = Some(wm_base);
|
||||
|
||||
if state.base_surface.is_some() && state.xdg_surface.is_none() {
|
||||
state.init_xdg_surface(qh);
|
||||
}
|
||||
}
|
||||
"xdg_activation_v1" => {
|
||||
state.xdg_activation = Some(
|
||||
registry.bind::<xdg_activation_v1::XdgActivationV1, _, _>(name, 1, qh, ()),
|
||||
);
|
||||
state.activate(qh);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<wl_compositor::WlCompositor, ()> for State {
|
||||
fn event(
|
||||
_: &mut Self,
|
||||
_: &wl_compositor::WlCompositor,
|
||||
_: wl_compositor::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<wl_surface::WlSurface, ()> for State {
|
||||
fn event(
|
||||
_: &mut Self,
|
||||
_: &wl_surface::WlSurface,
|
||||
_: wl_surface::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<wl_shm::WlShm, ()> for State {
|
||||
fn event(
|
||||
_: &mut Self,
|
||||
_: &wl_shm::WlShm,
|
||||
_: wl_shm::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<wl_shm_pool::WlShmPool, ()> for State {
|
||||
fn event(
|
||||
_: &mut Self,
|
||||
_: &wl_shm_pool::WlShmPool,
|
||||
_: wl_shm_pool::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<wl_buffer::WlBuffer, ()> for State {
|
||||
fn event(
|
||||
state: &mut Self,
|
||||
buffer: &wl_buffer::WlBuffer,
|
||||
_: wl_buffer::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
for buf in state.bufmgr.buffers.iter_mut() {
|
||||
if &buf.buffer == buffer {
|
||||
buf.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
fn init_xdg_surface(&mut self, qh: &QueueHandle<State>) {
|
||||
let wm_base = self.wm_base.as_ref().unwrap();
|
||||
let base_surface = self.base_surface.as_ref().unwrap();
|
||||
|
||||
let xdg_surface = wm_base.get_xdg_surface(base_surface, qh, ());
|
||||
let toplevel = xdg_surface.get_toplevel(qh, ());
|
||||
toplevel.set_title("wldash".into());
|
||||
|
||||
base_surface.commit();
|
||||
|
||||
self.xdg_surface = Some((xdg_surface, toplevel));
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<xdg_wm_base::XdgWmBase, ()> for State {
|
||||
fn event(
|
||||
_: &mut Self,
|
||||
wm_base: &xdg_wm_base::XdgWmBase,
|
||||
event: xdg_wm_base::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
if let xdg_wm_base::Event::Ping { serial } = event {
|
||||
wm_base.pong(serial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<xdg_surface::XdgSurface, ()> for State {
|
||||
fn event(
|
||||
state: &mut Self,
|
||||
xdg_surface: &xdg_surface::XdgSurface,
|
||||
event: xdg_surface::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
if let xdg_surface::Event::Configure { serial, .. } = event {
|
||||
xdg_surface.ack_configure(serial);
|
||||
state.configured = true;
|
||||
state.dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<xdg_toplevel::XdgToplevel, ()> for State {
|
||||
fn event(
|
||||
state: &mut Self,
|
||||
_: &xdg_toplevel::XdgToplevel,
|
||||
event: xdg_toplevel::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
match event {
|
||||
xdg_toplevel::Event::Configure {
|
||||
width,
|
||||
height,
|
||||
states,
|
||||
..
|
||||
} => {
|
||||
if (width, height) == (0, 0) {
|
||||
return;
|
||||
}
|
||||
let activated = states
|
||||
.iter()
|
||||
.find(|&st| *st as u32 == xdg_toplevel::State::Activated as u32)
|
||||
.is_some();
|
||||
|
||||
if activated {
|
||||
state.activated = true;
|
||||
} else if state.activated && !activated {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if state.dimensions != (width, height) {
|
||||
state.bufmgr.clear_buffers();
|
||||
state.dimensions = (width, height);
|
||||
let mut layout = VerticalLayout {
|
||||
widgets: vec![
|
||||
Box::new(HorizontalLayout {
|
||||
widgets: vec![
|
||||
Box::new(IndexedLayout { widget_idx: 0 }),
|
||||
Box::new(Margin {
|
||||
widget: Box::new(IndexedLayout { widget_idx: 1 }),
|
||||
margin: (16, 8, 0, 0),
|
||||
}),
|
||||
Box::new(VerticalLayout {
|
||||
widgets: vec![
|
||||
Box::new(Margin {
|
||||
widget: Box::new(IndexedLayout { widget_idx: 2 }),
|
||||
margin: (16, 8, 8, 0),
|
||||
}),
|
||||
Box::new(Margin {
|
||||
widget: Box::new(IndexedLayout { widget_idx: 3 }),
|
||||
margin: (16, 8, 8, 0),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
}),
|
||||
Box::new(IndexedLayout { widget_idx: 4 }),
|
||||
Box::new(IndexedLayout { widget_idx: 5 }),
|
||||
],
|
||||
};
|
||||
|
||||
state.fonts.resolve();
|
||||
let fonts = state.fonts.unwrap();
|
||||
layout.geometry_update(
|
||||
&mut fonts.borrow_mut(),
|
||||
&Geometry {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: width as u32,
|
||||
height: height as u32,
|
||||
},
|
||||
state,
|
||||
);
|
||||
}
|
||||
}
|
||||
xdg_toplevel::Event::Close => {
|
||||
state.running = false;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<wl_seat::WlSeat, ()> for State {
|
||||
fn event(
|
||||
_: &mut Self,
|
||||
seat: &wl_seat::WlSeat,
|
||||
event: wl_seat::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
qh: &QueueHandle<Self>,
|
||||
) {
|
||||
if let wl_seat::Event::Capabilities {
|
||||
capabilities: WEnum::Value(capabilities),
|
||||
} = event
|
||||
{
|
||||
if capabilities.contains(wl_seat::Capability::Keyboard) {
|
||||
seat.get_keyboard(qh, ());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<wl_keyboard::WlKeyboard, ()> for State {
|
||||
fn event(
|
||||
state: &mut Self,
|
||||
_: &wl_keyboard::WlKeyboard,
|
||||
event: wl_keyboard::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
match event {
|
||||
wl_keyboard::Event::Key {
|
||||
serial,
|
||||
time,
|
||||
key,
|
||||
state: kbstate,
|
||||
} => {
|
||||
if key == 1 {
|
||||
state.running = false;
|
||||
return;
|
||||
}
|
||||
let k = state.keyboard.key(serial, time, key, kbstate);
|
||||
for widget in state.widgets.iter_mut() {
|
||||
widget.keyboard_input(&k);
|
||||
}
|
||||
state.dirty = true;
|
||||
}
|
||||
wl_keyboard::Event::Modifiers {
|
||||
mods_depressed,
|
||||
mods_latched,
|
||||
mods_locked,
|
||||
group,
|
||||
..
|
||||
} => {
|
||||
state
|
||||
.keyboard
|
||||
.modifiers(mods_depressed, mods_latched, mods_locked, group);
|
||||
}
|
||||
wl_keyboard::Event::Keymap { format, fd, size } => {
|
||||
state.keyboard.keymap(format, fd, size);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<xdg_activation_v1::XdgActivationV1, ()> for State {
|
||||
fn event(
|
||||
_: &mut Self,
|
||||
_: &xdg_activation_v1::XdgActivationV1,
|
||||
_: xdg_activation_v1::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<xdg_activation_token_v1::XdgActivationTokenV1, ()> for State {
|
||||
fn event(
|
||||
state: &mut Self,
|
||||
_: &xdg_activation_token_v1::XdgActivationTokenV1,
|
||||
event: xdg_activation_token_v1::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
match event {
|
||||
xdg_activation_token_v1::Event::Done { token } => {
|
||||
for widget in state.widgets.iter_mut() {
|
||||
widget.token_update(&token);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+412
@@ -0,0 +1,412 @@
|
||||
use std::{
|
||||
env,
|
||||
process::exit,
|
||||
};
|
||||
|
||||
use wayland_client::{
|
||||
protocol::{
|
||||
wl_buffer, wl_compositor, wl_keyboard, wl_registry, wl_seat, wl_shm, wl_shm_pool,
|
||||
wl_surface,
|
||||
},
|
||||
Connection, Dispatch, QueueHandle, WEnum,
|
||||
};
|
||||
|
||||
use wayland_protocols::xdg::{
|
||||
activation::v1::client::{xdg_activation_token_v1, xdg_activation_v1},
|
||||
shell::client::{xdg_surface, xdg_toplevel, xdg_wm_base},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
buffer::BufferManager,
|
||||
fonts::MaybeFontMap,
|
||||
keyboard::Keyboard,
|
||||
widgets::{
|
||||
Geometry, HorizontalLayout, IndexedLayout, Layout, Margin, VerticalLayout, Widget,
|
||||
},
|
||||
};
|
||||
|
||||
pub struct State {
|
||||
pub running: bool,
|
||||
pub dirty: bool,
|
||||
pub activated: bool,
|
||||
pub base_surface: Option<wl_surface::WlSurface>,
|
||||
pub wm_base: Option<xdg_wm_base::XdgWmBase>,
|
||||
pub xdg_surface: Option<(xdg_surface::XdgSurface, xdg_toplevel::XdgToplevel)>,
|
||||
pub wl_shm: Option<wl_shm::WlShm>,
|
||||
pub xdg_activation: Option<xdg_activation_v1::XdgActivationV1>,
|
||||
pub configured: bool,
|
||||
pub dimensions: (i32, i32),
|
||||
pub bufmgr: BufferManager,
|
||||
pub widgets: Vec<Box<dyn Widget>>,
|
||||
pub keyboard: Keyboard,
|
||||
pub fonts: MaybeFontMap,
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn add_buffer(&mut self, qh: &QueueHandle<Self>) {
|
||||
self.bufmgr.add_buffer(
|
||||
self.wl_shm.as_ref().expect("missing wl_shm"),
|
||||
self.dimensions,
|
||||
qh,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn activate(&mut self, qh: &QueueHandle<Self>) {
|
||||
let key = match env::var("XDG_ACTIVATION_TOKEN") {
|
||||
Ok(token) => token,
|
||||
Err(_) => return,
|
||||
};
|
||||
match (&self.base_surface, &self.xdg_activation) {
|
||||
(Some(surface), Some(activation)) => {
|
||||
activation.activate(key, surface);
|
||||
let activation_token = activation.get_activation_token(qh, ());
|
||||
activation_token.commit();
|
||||
env::remove_var("XDG_ACTIVATION_TOKEN");
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<wl_registry::WlRegistry, ()> for State {
|
||||
fn event(
|
||||
state: &mut Self,
|
||||
registry: &wl_registry::WlRegistry,
|
||||
event: wl_registry::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
qh: &QueueHandle<Self>,
|
||||
) {
|
||||
if let wl_registry::Event::Global {
|
||||
name, interface, ..
|
||||
} = event
|
||||
{
|
||||
match &interface[..] {
|
||||
"wl_compositor" => {
|
||||
let compositor =
|
||||
registry.bind::<wl_compositor::WlCompositor, _, _>(name, 4, qh, ());
|
||||
let surface = compositor.create_surface(qh, ());
|
||||
state.base_surface = Some(surface);
|
||||
state.activate(qh);
|
||||
|
||||
if state.wm_base.is_some() && state.xdg_surface.is_none() {
|
||||
state.init_xdg_surface(qh);
|
||||
}
|
||||
}
|
||||
"wl_shm" => {
|
||||
state.wl_shm = Some(registry.bind::<wl_shm::WlShm, _, _>(name, 1, qh, ()));
|
||||
}
|
||||
"wl_seat" => {
|
||||
registry.bind::<wl_seat::WlSeat, _, _>(name, 1, qh, ());
|
||||
}
|
||||
"xdg_wm_base" => {
|
||||
let wm_base = registry.bind::<xdg_wm_base::XdgWmBase, _, _>(name, 1, qh, ());
|
||||
state.wm_base = Some(wm_base);
|
||||
|
||||
if state.base_surface.is_some() && state.xdg_surface.is_none() {
|
||||
state.init_xdg_surface(qh);
|
||||
}
|
||||
}
|
||||
"xdg_activation_v1" => {
|
||||
state.xdg_activation = Some(
|
||||
registry.bind::<xdg_activation_v1::XdgActivationV1, _, _>(name, 1, qh, ()),
|
||||
);
|
||||
state.activate(qh);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<wl_compositor::WlCompositor, ()> for State {
|
||||
fn event(
|
||||
_: &mut Self,
|
||||
_: &wl_compositor::WlCompositor,
|
||||
_: wl_compositor::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<wl_surface::WlSurface, ()> for State {
|
||||
fn event(
|
||||
_: &mut Self,
|
||||
_: &wl_surface::WlSurface,
|
||||
_: wl_surface::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<wl_shm::WlShm, ()> for State {
|
||||
fn event(
|
||||
_: &mut Self,
|
||||
_: &wl_shm::WlShm,
|
||||
_: wl_shm::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<wl_shm_pool::WlShmPool, ()> for State {
|
||||
fn event(
|
||||
_: &mut Self,
|
||||
_: &wl_shm_pool::WlShmPool,
|
||||
_: wl_shm_pool::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<wl_buffer::WlBuffer, ()> for State {
|
||||
fn event(
|
||||
state: &mut Self,
|
||||
buffer: &wl_buffer::WlBuffer,
|
||||
_: wl_buffer::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
for buf in state.bufmgr.buffers.iter_mut() {
|
||||
if &buf.buffer == buffer {
|
||||
buf.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
fn init_xdg_surface(&mut self, qh: &QueueHandle<State>) {
|
||||
let wm_base = self.wm_base.as_ref().unwrap();
|
||||
let base_surface = self.base_surface.as_ref().unwrap();
|
||||
|
||||
let xdg_surface = wm_base.get_xdg_surface(base_surface, qh, ());
|
||||
let toplevel = xdg_surface.get_toplevel(qh, ());
|
||||
toplevel.set_title("wldash".into());
|
||||
|
||||
base_surface.commit();
|
||||
|
||||
self.xdg_surface = Some((xdg_surface, toplevel));
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<xdg_wm_base::XdgWmBase, ()> for State {
|
||||
fn event(
|
||||
_: &mut Self,
|
||||
wm_base: &xdg_wm_base::XdgWmBase,
|
||||
event: xdg_wm_base::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
if let xdg_wm_base::Event::Ping { serial } = event {
|
||||
wm_base.pong(serial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<xdg_surface::XdgSurface, ()> for State {
|
||||
fn event(
|
||||
state: &mut Self,
|
||||
xdg_surface: &xdg_surface::XdgSurface,
|
||||
event: xdg_surface::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
if let xdg_surface::Event::Configure { serial, .. } = event {
|
||||
xdg_surface.ack_configure(serial);
|
||||
state.configured = true;
|
||||
state.dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<xdg_toplevel::XdgToplevel, ()> for State {
|
||||
fn event(
|
||||
state: &mut Self,
|
||||
_: &xdg_toplevel::XdgToplevel,
|
||||
event: xdg_toplevel::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
match event {
|
||||
xdg_toplevel::Event::Configure {
|
||||
width,
|
||||
height,
|
||||
states,
|
||||
..
|
||||
} => {
|
||||
if (width, height) == (0, 0) {
|
||||
return;
|
||||
}
|
||||
let activated = states
|
||||
.iter()
|
||||
.find(|&st| *st as u32 == xdg_toplevel::State::Activated as u32)
|
||||
.is_some();
|
||||
|
||||
if activated {
|
||||
state.activated = true;
|
||||
} else if state.activated && !activated {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if state.dimensions != (width, height) {
|
||||
state.bufmgr.clear_buffers();
|
||||
state.dimensions = (width, height);
|
||||
let mut layout = VerticalLayout {
|
||||
widgets: vec![
|
||||
Box::new(HorizontalLayout {
|
||||
widgets: vec![
|
||||
Box::new(IndexedLayout { widget_idx: 0 }),
|
||||
Box::new(Margin {
|
||||
widget: Box::new(IndexedLayout { widget_idx: 1 }),
|
||||
margin: (16, 8, 0, 0),
|
||||
}),
|
||||
Box::new(VerticalLayout {
|
||||
widgets: vec![
|
||||
Box::new(Margin {
|
||||
widget: Box::new(IndexedLayout { widget_idx: 2 }),
|
||||
margin: (16, 8, 8, 0),
|
||||
}),
|
||||
Box::new(Margin {
|
||||
widget: Box::new(IndexedLayout { widget_idx: 3 }),
|
||||
margin: (16, 8, 8, 0),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
}),
|
||||
Box::new(IndexedLayout { widget_idx: 4 }),
|
||||
Box::new(IndexedLayout { widget_idx: 5 }),
|
||||
],
|
||||
};
|
||||
|
||||
state.fonts.resolve();
|
||||
let fonts = state.fonts.unwrap();
|
||||
layout.geometry_update(
|
||||
&mut fonts.borrow_mut(),
|
||||
&Geometry {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: width as u32,
|
||||
height: height as u32,
|
||||
},
|
||||
state,
|
||||
);
|
||||
}
|
||||
}
|
||||
xdg_toplevel::Event::Close => {
|
||||
state.running = false;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<wl_seat::WlSeat, ()> for State {
|
||||
fn event(
|
||||
_: &mut Self,
|
||||
seat: &wl_seat::WlSeat,
|
||||
event: wl_seat::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
qh: &QueueHandle<Self>,
|
||||
) {
|
||||
if let wl_seat::Event::Capabilities {
|
||||
capabilities: WEnum::Value(capabilities),
|
||||
} = event
|
||||
{
|
||||
if capabilities.contains(wl_seat::Capability::Keyboard) {
|
||||
seat.get_keyboard(qh, ());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<wl_keyboard::WlKeyboard, ()> for State {
|
||||
fn event(
|
||||
state: &mut Self,
|
||||
_: &wl_keyboard::WlKeyboard,
|
||||
event: wl_keyboard::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
match event {
|
||||
wl_keyboard::Event::Key {
|
||||
serial,
|
||||
time,
|
||||
key,
|
||||
state: kbstate,
|
||||
} => {
|
||||
if key == 1 {
|
||||
state.running = false;
|
||||
return;
|
||||
}
|
||||
let k = state.keyboard.key(serial, time, key, kbstate);
|
||||
for widget in state.widgets.iter_mut() {
|
||||
widget.keyboard_input(&k);
|
||||
}
|
||||
state.dirty = true;
|
||||
}
|
||||
wl_keyboard::Event::Modifiers {
|
||||
mods_depressed,
|
||||
mods_latched,
|
||||
mods_locked,
|
||||
group,
|
||||
..
|
||||
} => {
|
||||
state
|
||||
.keyboard
|
||||
.modifiers(mods_depressed, mods_latched, mods_locked, group);
|
||||
}
|
||||
wl_keyboard::Event::Keymap { format, fd, size } => {
|
||||
state.keyboard.keymap(format, fd, size);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<xdg_activation_v1::XdgActivationV1, ()> for State {
|
||||
fn event(
|
||||
_: &mut Self,
|
||||
_: &xdg_activation_v1::XdgActivationV1,
|
||||
_: xdg_activation_v1::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<xdg_activation_token_v1::XdgActivationTokenV1, ()> for State {
|
||||
fn event(
|
||||
state: &mut Self,
|
||||
_: &xdg_activation_token_v1::XdgActivationTokenV1,
|
||||
event: xdg_activation_token_v1::Event,
|
||||
_: &(),
|
||||
_: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
) {
|
||||
match event {
|
||||
xdg_activation_token_v1::Event::Done { token } => {
|
||||
for widget in state.widgets.iter_mut() {
|
||||
widget.token_update(&token);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ impl Backlight {
|
||||
self.max = read_file_as_u64(self.device_path.join("max_brightness").as_path()).unwrap();
|
||||
}
|
||||
|
||||
pub fn new(path: &str) -> BarWidget {
|
||||
pub fn new(path: &str, font: &'static str, size: f32) -> BarWidget {
|
||||
let mut dev = Backlight {
|
||||
device_path: Path::new("/sys/class/backlight").to_path_buf().join(path),
|
||||
cur: 0,
|
||||
@@ -38,7 +38,7 @@ impl Backlight {
|
||||
};
|
||||
|
||||
dev.update();
|
||||
BarWidget::new(Box::new(dev))
|
||||
BarWidget::new(Box::new(dev), font, size)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,9 +8,6 @@ use crate::{
|
||||
widgets::{Geometry, Widget},
|
||||
};
|
||||
|
||||
const BAR_FONT: &str = "sans";
|
||||
const BAR_SIZE: f32 = 24.;
|
||||
|
||||
pub trait BarWidgetImpl {
|
||||
fn get_dirty(&self) -> bool;
|
||||
fn set_dirty(&mut self, dirty: bool);
|
||||
@@ -20,15 +17,17 @@ pub trait BarWidgetImpl {
|
||||
}
|
||||
|
||||
pub struct BarWidget {
|
||||
font: &'static str,
|
||||
size: f32,
|
||||
geometry: Geometry,
|
||||
inner_widget: Box<dyn BarWidgetImpl>,
|
||||
}
|
||||
|
||||
impl BarWidget {
|
||||
pub fn new(inner_widget: Box<dyn BarWidgetImpl>) -> BarWidget {
|
||||
pub fn new(inner_widget: Box<dyn BarWidgetImpl>, font: &'static str, size: f32) -> BarWidget {
|
||||
BarWidget {
|
||||
geometry: Default::default(),
|
||||
inner_widget,
|
||||
inner_widget, font, size,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,13 +46,13 @@ impl Widget for BarWidget {
|
||||
}
|
||||
|
||||
fn draw(&mut self, fonts: &mut FontMap, view: &mut BufferView) -> Geometry {
|
||||
let font = fonts.get_font(BAR_FONT, BAR_SIZE);
|
||||
let font = fonts.get_font(self.font, self.size);
|
||||
let fg = Color::new(1., 1., 1., 1.);
|
||||
let bg = Color::new(0., 0., 0., 1.);
|
||||
|
||||
font.auto_draw_text(view, &bg, &fg, self.inner_widget.name())
|
||||
.unwrap();
|
||||
let size = BAR_SIZE.ceil() as u32;
|
||||
let size = self.size.ceil() as u32;
|
||||
let bar_offset = 4 * size;
|
||||
let val = self.inner_widget.value();
|
||||
|
||||
@@ -86,7 +85,7 @@ impl Widget for BarWidget {
|
||||
x: x,
|
||||
y: geometry.y,
|
||||
width: w,
|
||||
height: BAR_SIZE.ceil() as u32,
|
||||
height: self.size.ceil() as u32,
|
||||
};
|
||||
self.geometry
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ pub struct Battery {
|
||||
}
|
||||
|
||||
impl Battery {
|
||||
pub fn new(ping: Ping) -> BarWidget {
|
||||
pub fn new(ping: Ping, font: &'static str, size: f32) -> BarWidget {
|
||||
let battery = Battery {
|
||||
inner: Arc::new(Mutex::new(InnerBattery {
|
||||
value: 0.,
|
||||
@@ -120,7 +120,7 @@ impl Battery {
|
||||
dirty: false,
|
||||
};
|
||||
start_monitor(battery.inner.clone(), ping);
|
||||
BarWidget::new(Box::new(battery))
|
||||
BarWidget::new(Box::new(battery), font, size)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,10 +9,9 @@ use crate::{
|
||||
|
||||
use chrono::{Local, Timelike};
|
||||
|
||||
const CLOCK_FONT: &str = "sans";
|
||||
const CLOCK_SIZE: f32 = 96.;
|
||||
|
||||
pub struct Clock {
|
||||
font: &'static str,
|
||||
size: f32,
|
||||
dirty: bool,
|
||||
geometry: Geometry,
|
||||
digit_width: u32,
|
||||
@@ -20,8 +19,9 @@ pub struct Clock {
|
||||
}
|
||||
|
||||
impl<'a> Clock {
|
||||
pub fn new() -> Clock {
|
||||
pub fn new(font: &'static str, size: f32) -> Clock {
|
||||
Clock {
|
||||
font, size,
|
||||
dirty: true,
|
||||
geometry: Default::default(),
|
||||
digit_width: 0,
|
||||
@@ -49,7 +49,7 @@ impl<'a> Widget for Clock {
|
||||
|
||||
let digit = self.digit_width;
|
||||
let colon = self.colon_width;
|
||||
let font = fonts.get_font(CLOCK_FONT, CLOCK_SIZE);
|
||||
let font = fonts.get_font(self.font, self.size);
|
||||
font.draw_text_fixed_width(
|
||||
view,
|
||||
&bg,
|
||||
@@ -62,14 +62,14 @@ impl<'a> Widget for Clock {
|
||||
}
|
||||
|
||||
fn geometry_update(&mut self, fonts: &mut FontMap, geometry: &Geometry) -> Geometry {
|
||||
let font = fonts.get_font(CLOCK_FONT, CLOCK_SIZE);
|
||||
let font = fonts.get_font(self.font, self.size);
|
||||
self.digit_width = font.auto_widest("0123456789").unwrap();
|
||||
self.colon_width = font.auto_widest(":").unwrap();
|
||||
self.geometry = Geometry {
|
||||
x: geometry.x,
|
||||
y: geometry.y,
|
||||
width: self.digit_width * 4 + self.colon_width,
|
||||
height: CLOCK_SIZE.ceil() as u32,
|
||||
height: self.size.ceil() as u32,
|
||||
};
|
||||
self.geometry
|
||||
}
|
||||
|
||||
+8
-7
@@ -9,17 +9,17 @@ use crate::{
|
||||
|
||||
use chrono::{Datelike, Local};
|
||||
|
||||
const DATE_FONT: &str = "sans";
|
||||
const DATE_SIZE: f32 = 40.;
|
||||
|
||||
pub struct Date {
|
||||
font: &'static str,
|
||||
size: f32,
|
||||
dirty: bool,
|
||||
geometry: Geometry,
|
||||
}
|
||||
|
||||
impl Date {
|
||||
pub fn new() -> Date {
|
||||
pub fn new(font: &'static str, size: f32) -> Date {
|
||||
Date {
|
||||
font, size,
|
||||
dirty: true,
|
||||
geometry: Default::default(),
|
||||
}
|
||||
@@ -43,7 +43,7 @@ impl<'a> Widget for Date {
|
||||
let fg = Color::new(1., 1., 1., 1.);
|
||||
let bg = Color::new(0., 0., 0., 1.);
|
||||
let mut date_line = view.offset((0, 8)).unwrap();
|
||||
let font = fonts.get_font(DATE_FONT, DATE_SIZE);
|
||||
let font = fonts.get_font(self.font, self.size);
|
||||
font.auto_draw_text(
|
||||
&mut date_line,
|
||||
&bg,
|
||||
@@ -61,11 +61,12 @@ impl<'a> Widget for Date {
|
||||
}
|
||||
|
||||
fn geometry_update(&mut self, _fonts: &mut FontMap, geometry: &Geometry) -> Geometry {
|
||||
let width = (3. + 2. + 2. + 2. + 4.) * self.size / 2.;
|
||||
self.geometry = Geometry {
|
||||
x: geometry.x,
|
||||
y: geometry.y,
|
||||
width: 256,
|
||||
height: DATE_SIZE.ceil() as u32,
|
||||
width: width.ceil() as u32,
|
||||
height: self.size.ceil() as u32,
|
||||
};
|
||||
self.geometry
|
||||
}
|
||||
|
||||
+29
-32
@@ -1,7 +1,11 @@
|
||||
use std::cmp::{min, Ordering};
|
||||
use std::collections::HashMap;
|
||||
use std::default::Default;
|
||||
use std::process::{exit, Command};
|
||||
use std::{
|
||||
cmp::{min, max, Ordering},
|
||||
collections::HashMap,
|
||||
default::Default,
|
||||
process::{exit, Command},
|
||||
sync::{Arc, Mutex},
|
||||
thread,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
buffer::BufferView,
|
||||
@@ -17,12 +21,6 @@ use fuzzy_matcher::FuzzyMatcher;
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
use wayland_client::{protocol::wl_keyboard, WEnum};
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::thread;
|
||||
|
||||
const LAUNCHER_FONT: &str = "monospace";
|
||||
const LAUNCHER_SIZE: f32 = 32.;
|
||||
|
||||
struct Matcher {
|
||||
matches: HashMap<Desktop, i64>,
|
||||
}
|
||||
@@ -284,7 +282,7 @@ impl InterfaceWidget for Launcher {
|
||||
let fg = Color::new(1., 1., 1., 1.);
|
||||
let bg = Color::new(0., 0., 0., 1.);
|
||||
|
||||
let line_height = LAUNCHER_SIZE.ceil() as u32;
|
||||
let line_height = intf.size.ceil() as u32;
|
||||
|
||||
// Draw line
|
||||
let mut prompt_offset = intf.geometry.height - line_height;
|
||||
@@ -292,9 +290,8 @@ impl InterfaceWidget for Launcher {
|
||||
let mut prompt_border = prompt_line.limit((intf.geometry.width, 1)).unwrap();
|
||||
prompt_border.memset(&fg);
|
||||
|
||||
// Draw prompt
|
||||
let font = fonts.get_font(LAUNCHER_FONT, LAUNCHER_SIZE);
|
||||
font.auto_draw_text_with_cursor(
|
||||
let font = fonts.get_font(intf.font, intf.size);
|
||||
let mut x_max = font.auto_draw_text_with_cursor(
|
||||
&mut prompt_line,
|
||||
&bg,
|
||||
&fg,
|
||||
@@ -303,7 +300,6 @@ impl InterfaceWidget for Launcher {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let font = fonts.get_font(LAUNCHER_FONT, LAUNCHER_SIZE);
|
||||
font.auto_draw_text(&mut prompt_line, &bg, &fg, ">")
|
||||
.unwrap();
|
||||
|
||||
@@ -332,11 +328,11 @@ impl InterfaceWidget for Launcher {
|
||||
colors.push(Color::new(0.75, 0.75, 0.75, 1.0));
|
||||
}
|
||||
}
|
||||
font.auto_draw_text_individual_colors(&mut line, &bg, &colors, &m.name)
|
||||
.unwrap();
|
||||
x_max = max(x_max, font.auto_draw_text_individual_colors(&mut line, &bg, &colors, &m.name)
|
||||
.unwrap());
|
||||
} else {
|
||||
font.auto_draw_text(&mut line, &bg, &dimfg, &m.name)
|
||||
.unwrap();
|
||||
x_max = max(x_max, font.auto_draw_text(&mut line, &bg, &dimfg, &m.name)
|
||||
.unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,7 +343,7 @@ impl InterfaceWidget for Launcher {
|
||||
Geometry {
|
||||
x: intf.geometry.x,
|
||||
y: intf.geometry.y + intf.geometry.height - content_height,
|
||||
width: intf.geometry.width,
|
||||
width: x_max.0+1,
|
||||
height: content_height,
|
||||
}
|
||||
}
|
||||
@@ -380,7 +376,7 @@ impl InterfaceWidget for Shell {
|
||||
let fg = Color::new(1., 1., 1., 1.);
|
||||
let bg = Color::new(0., 0., 0., 1.);
|
||||
|
||||
let line_height = LAUNCHER_SIZE.ceil() as u32;
|
||||
let line_height = intf.size.ceil() as u32;
|
||||
|
||||
// Draw line
|
||||
let prompt_offset = intf.geometry.height - line_height;
|
||||
@@ -389,8 +385,8 @@ impl InterfaceWidget for Shell {
|
||||
prompt_border.memset(&fg);
|
||||
|
||||
// Draw prompt
|
||||
let font = fonts.get_font(LAUNCHER_FONT, LAUNCHER_SIZE);
|
||||
font.auto_draw_text_with_cursor(
|
||||
let font = fonts.get_font(intf.font, intf.size);
|
||||
let x_max = font.auto_draw_text_with_cursor(
|
||||
&mut prompt_line,
|
||||
&bg,
|
||||
&fg,
|
||||
@@ -398,14 +394,13 @@ impl InterfaceWidget for Shell {
|
||||
intf.prompt.cursor + 3,
|
||||
)
|
||||
.unwrap();
|
||||
let font = fonts.get_font(LAUNCHER_FONT, LAUNCHER_SIZE);
|
||||
font.auto_draw_text(&mut prompt_line, &bg, &Color::new(1., 0.75, 0.5, 1.), "!")
|
||||
.unwrap();
|
||||
|
||||
Geometry {
|
||||
x: intf.geometry.x,
|
||||
y: intf.geometry.y + intf.geometry.height - line_height,
|
||||
width: intf.geometry.width,
|
||||
width: x_max.0 + 1,
|
||||
height: line_height,
|
||||
}
|
||||
}
|
||||
@@ -443,16 +438,16 @@ impl InterfaceWidget for Calc {
|
||||
let fg = Color::new(1., 1., 1., 1.);
|
||||
let bg = Color::new(0., 0., 0., 1.);
|
||||
|
||||
let line_height = LAUNCHER_SIZE.ceil() as u32;
|
||||
let line_height = intf.size.ceil() as u32;
|
||||
|
||||
// Draw line
|
||||
let mut prompt_offset = intf.geometry.height - (LAUNCHER_SIZE.ceil() as u32);
|
||||
let mut prompt_offset = intf.geometry.height - (line_height);
|
||||
let mut prompt_line = view.offset((0, prompt_offset)).unwrap();
|
||||
let mut prompt_border = prompt_line.limit((intf.geometry.width, 1)).unwrap();
|
||||
prompt_border.memset(&fg);
|
||||
|
||||
// Draw prompt
|
||||
let font = fonts.get_font(LAUNCHER_FONT, LAUNCHER_SIZE);
|
||||
let font = fonts.get_font(intf.font, intf.size);
|
||||
let res_off = font
|
||||
.auto_draw_text_with_cursor(
|
||||
&mut prompt_line,
|
||||
@@ -463,7 +458,6 @@ impl InterfaceWidget for Calc {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let font = fonts.get_font(LAUNCHER_FONT, LAUNCHER_SIZE);
|
||||
font.auto_draw_text(&mut prompt_line, &bg, &Color::new(1., 0.75, 0.5, 1.), "=")
|
||||
.unwrap();
|
||||
|
||||
@@ -476,10 +470,10 @@ impl InterfaceWidget for Calc {
|
||||
|
||||
for m in self.old.iter().rev() {
|
||||
let dimfg = Color::new(0.5, 0.5, 0.5, 1.0);
|
||||
if prompt_offset < LAUNCHER_SIZE.ceil() as u32 {
|
||||
if prompt_offset < line_height {
|
||||
break;
|
||||
}
|
||||
prompt_offset -= LAUNCHER_SIZE.ceil() as u32;
|
||||
prompt_offset -= line_height;
|
||||
let mut result_line = view.offset((0, prompt_offset)).unwrap();
|
||||
font.auto_draw_text(&mut result_line, &bg, &dimfg, &m)
|
||||
.unwrap();
|
||||
@@ -499,6 +493,8 @@ impl InterfaceWidget for Calc {
|
||||
}
|
||||
|
||||
struct InnerInterface {
|
||||
font: &'static str,
|
||||
size: f32,
|
||||
dirty: bool,
|
||||
geometry: Geometry,
|
||||
selection: usize,
|
||||
@@ -513,7 +509,7 @@ pub struct Interface {
|
||||
}
|
||||
|
||||
impl Interface {
|
||||
pub fn new() -> Interface {
|
||||
pub fn new(font: &'static str, size: f32) -> Interface {
|
||||
Interface {
|
||||
launcher: Launcher::new(),
|
||||
shell: Shell {},
|
||||
@@ -522,6 +518,7 @@ impl Interface {
|
||||
result: None,
|
||||
},
|
||||
inner: InnerInterface {
|
||||
font, size,
|
||||
dirty: false,
|
||||
geometry: Default::default(),
|
||||
selection: 0,
|
||||
|
||||
Reference in New Issue
Block a user