autocommit 2022-03-24 18:27:42 CET
This commit is contained in:
parent
b3a27f889a
commit
3b1b843821
17 changed files with 388 additions and 212 deletions
|
|
@ -1,9 +1,9 @@
|
|||
use jay_config::embedded::grab_input_device;
|
||||
use jay_config::keyboard::mods::{Modifiers, ALT, CTRL, SHIFT};
|
||||
use jay_config::keyboard::syms::{
|
||||
SYM_Super_L, SYM_b, SYM_comma, SYM_d, SYM_f, SYM_h, SYM_j, SYM_k, SYM_l, SYM_p, SYM_period,
|
||||
SYM_q, SYM_r, SYM_t, SYM_v, SYM_y, SYM_F1, SYM_F10, SYM_F11, SYM_F12, SYM_F2, SYM_F3, SYM_F4,
|
||||
SYM_F5, SYM_F6, SYM_F7, SYM_F8, SYM_F9,
|
||||
SYM_Super_L, SYM_b, SYM_comma, SYM_d, SYM_f, SYM_h, SYM_j, SYM_k, SYM_l, SYM_m, SYM_p,
|
||||
SYM_period, SYM_q, SYM_r, SYM_t, SYM_v, SYM_y, SYM_F1, SYM_F10, SYM_F11, SYM_F12, SYM_F2,
|
||||
SYM_F3, SYM_F4, SYM_F5, SYM_F6, SYM_F7, SYM_F8, SYM_F9,
|
||||
};
|
||||
use jay_config::theme::{get_title_height, set_title_color, set_title_height, Color};
|
||||
use jay_config::Axis::{Horizontal, Vertical};
|
||||
|
|
@ -55,6 +55,10 @@ fn configure_seat(s: Seat) {
|
|||
s.set_split(s.split().other());
|
||||
});
|
||||
|
||||
s.bind(MOD | SYM_m, move || {
|
||||
s.set_mono(!s.mono());
|
||||
});
|
||||
|
||||
s.bind(MOD | SYM_f, move || {
|
||||
s.focus_parent();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -185,6 +185,17 @@ impl Client {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn mono(&self, seat: Seat) -> bool {
|
||||
let res = self.with_response(|| self.send(&ClientMessage::GetMono { seat }));
|
||||
match res {
|
||||
Response::GetMono { mono } => mono,
|
||||
_ => {
|
||||
log::error!("Server did not send a response to a get_mono request");
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn split(&self, seat: Seat) -> Axis {
|
||||
let res = self.with_response(|| self.send(&ClientMessage::GetSplit { seat }));
|
||||
match res {
|
||||
|
|
@ -246,6 +257,10 @@ impl Client {
|
|||
self.send(&ClientMessage::SetBorderWidth { width })
|
||||
}
|
||||
|
||||
pub fn set_mono(&self, seat: Seat, mono: bool) {
|
||||
self.send(&ClientMessage::SetMono { seat, mono });
|
||||
}
|
||||
|
||||
pub fn set_split(&self, seat: Seat, axis: Axis) {
|
||||
self.send(&ClientMessage::SetSplit { seat, axis });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,6 +65,13 @@ pub enum ClientMessage<'a> {
|
|||
seat: Seat,
|
||||
axis: Axis,
|
||||
},
|
||||
GetMono {
|
||||
seat: Seat,
|
||||
},
|
||||
SetMono {
|
||||
seat: Seat,
|
||||
mono: bool,
|
||||
},
|
||||
RemoveSeat {
|
||||
seat: Seat,
|
||||
},
|
||||
|
|
@ -136,6 +143,7 @@ pub enum Response {
|
|||
None,
|
||||
GetSeats { seats: Vec<Seat> },
|
||||
GetSplit { axis: Axis },
|
||||
GetMono { mono: bool },
|
||||
GetRepeatRate { rate: i32, delay: i32 },
|
||||
ParseKeymap { keymap: Keymap },
|
||||
CreateSeat { seat: Seat },
|
||||
|
|
|
|||
|
|
@ -104,6 +104,16 @@ impl Seat {
|
|||
get!().seat_set_repeat_rate(self, rate, delay)
|
||||
}
|
||||
|
||||
pub fn mono(self) -> bool {
|
||||
let mut res = false;
|
||||
(|| res = get!().mono(self))();
|
||||
res
|
||||
}
|
||||
|
||||
pub fn set_mono(self, mono: bool) {
|
||||
get!().set_mono(self, mono)
|
||||
}
|
||||
|
||||
pub fn split(self) -> Axis {
|
||||
let mut res = Axis::Horizontal;
|
||||
(|| res = get!().split(self))();
|
||||
|
|
|
|||
|
|
@ -204,6 +204,22 @@ impl ConfigProxyHandler {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_get_mono(&self, seat: Seat) -> Result<(), GetMonoError> {
|
||||
let seat = self.get_seat(seat)?;
|
||||
self.send(&ServerMessage::Response {
|
||||
response: Response::GetMono {
|
||||
mono: seat.get_mono().unwrap_or(false).into(),
|
||||
},
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_set_mono(&self, seat: Seat, mono: bool) -> Result<(), SetMonoError> {
|
||||
let seat = self.get_seat(seat)?;
|
||||
seat.set_mono(mono);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_get_split(&self, seat: Seat) -> Result<(), GetSplitError> {
|
||||
let seat = self.get_seat(seat)?;
|
||||
self.send(&ServerMessage::Response {
|
||||
|
|
@ -450,6 +466,8 @@ impl ConfigProxyHandler {
|
|||
self.handle_set_repeat_rate(seat, rate, delay)?
|
||||
}
|
||||
ClientMessage::SetSeat { device, seat } => self.handle_set_seat(device, seat)?,
|
||||
ClientMessage::GetMono { seat } => self.handle_get_mono(seat)?,
|
||||
ClientMessage::SetMono { seat, mono } => self.handle_set_mono(seat, mono)?,
|
||||
ClientMessage::GetSplit { seat } => self.handle_get_split(seat)?,
|
||||
ClientMessage::SetSplit { seat, axis } => self.handle_set_split(seat, axis)?,
|
||||
ClientMessage::AddShortcut { seat, mods, sym } => {
|
||||
|
|
@ -505,6 +523,10 @@ enum CphError {
|
|||
FocusError(#[from] FocusError),
|
||||
#[error("Could not process a `move` request")]
|
||||
MoveError(#[from] MoveError),
|
||||
#[error("Could not process a `set_mono` request")]
|
||||
SetMonoError(#[from] SetMonoError),
|
||||
#[error("Could not process a `get_mono` request")]
|
||||
GetMonoError(#[from] GetMonoError),
|
||||
#[error("Could not process a `set_split` request")]
|
||||
SetSplitError(#[from] SetSplitError),
|
||||
#[error("Could not process a `get_split` request")]
|
||||
|
|
@ -601,6 +623,20 @@ enum MoveError {
|
|||
}
|
||||
efrom!(MoveError, CphError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
enum SetMonoError {
|
||||
#[error(transparent)]
|
||||
CphError(#[from] Box<CphError>),
|
||||
}
|
||||
efrom!(SetMonoError, CphError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
enum GetMonoError {
|
||||
#[error(transparent)]
|
||||
CphError(#[from] Box<CphError>),
|
||||
}
|
||||
efrom!(GetMonoError, CphError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
enum SetSplitError {
|
||||
#[error(transparent)]
|
||||
|
|
|
|||
|
|
@ -204,10 +204,18 @@ impl WlSeatGlobal {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_mono(&self) -> Option<bool> {
|
||||
self.keyboard_node.get().get_parent_mono()
|
||||
}
|
||||
|
||||
pub fn get_split(&self) -> Option<ContainerSplit> {
|
||||
self.keyboard_node.get().get_parent_split()
|
||||
}
|
||||
|
||||
pub fn set_mono(&self, mono: bool) {
|
||||
self.keyboard_node.get().set_parent_mono(mono)
|
||||
}
|
||||
|
||||
pub fn set_split(&self, axis: ContainerSplit) {
|
||||
self.keyboard_node.get().set_parent_split(axis)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -641,10 +641,18 @@ impl Node for WlSurface {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_parent_mono(&self) -> Option<bool> {
|
||||
self.xdg.get().and_then(|x| x.get_mono())
|
||||
}
|
||||
|
||||
fn get_parent_split(&self) -> Option<ContainerSplit> {
|
||||
self.xdg.get().and_then(|x| x.get_split())
|
||||
}
|
||||
|
||||
fn set_parent_mono(&self, mono: bool) {
|
||||
self.xdg.get().map(|x| x.set_mono(mono));
|
||||
}
|
||||
|
||||
fn set_parent_split(&self, split: ContainerSplit) {
|
||||
self.xdg.get().map(|x| x.set_split(split));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,10 +83,18 @@ pub trait XdgSurfaceExt: Debug {
|
|||
let _ = seat;
|
||||
}
|
||||
|
||||
fn get_mono(&self) -> Option<bool> {
|
||||
None
|
||||
}
|
||||
|
||||
fn get_split(&self) -> Option<ContainerSplit> {
|
||||
None
|
||||
}
|
||||
|
||||
fn set_mono(&self, mono: bool) {
|
||||
let _ = mono;
|
||||
}
|
||||
|
||||
fn set_split(&self, split: ContainerSplit) {
|
||||
let _ = split;
|
||||
}
|
||||
|
|
@ -166,10 +174,18 @@ impl XdgSurface {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_mono(&self) -> Option<bool> {
|
||||
self.ext.get().and_then(|e| e.get_mono())
|
||||
}
|
||||
|
||||
pub fn get_split(&self) -> Option<ContainerSplit> {
|
||||
self.ext.get().and_then(|e| e.get_split())
|
||||
}
|
||||
|
||||
pub fn set_mono(&self, mono: bool) {
|
||||
self.ext.get().map(|e| e.set_mono(mono));
|
||||
}
|
||||
|
||||
pub fn set_split(&self, split: ContainerSplit) {
|
||||
self.ext.get().map(|e| e.set_split(split));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -327,7 +327,7 @@ impl XdgToplevel {
|
|||
_ => return,
|
||||
};
|
||||
let extents = self.xdg.extents.get();
|
||||
parent.child_active_changed(self, self.active_surfaces.get() > 0);
|
||||
parent.clone().child_active_changed(self, self.active_surfaces.get() > 0);
|
||||
parent.child_size_changed(self, extents.width(), extents.height());
|
||||
parent.child_title_changed(self, self.title.borrow_mut().deref());
|
||||
}
|
||||
|
|
@ -503,10 +503,23 @@ impl XdgSurfaceExt for XdgToplevel {
|
|||
Self::toggle_floating(&self);
|
||||
}
|
||||
|
||||
fn get_mono(&self) -> Option<bool> {
|
||||
self.parent_node.get().and_then(|p| p.get_mono())
|
||||
}
|
||||
|
||||
fn get_split(&self) -> Option<ContainerSplit> {
|
||||
self.parent_node.get().and_then(|p| p.get_split())
|
||||
}
|
||||
|
||||
fn set_mono(&self, mono: bool) {
|
||||
let node = if mono {
|
||||
Some(self as &dyn Node)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
self.parent_node.get().map(move |p| p.set_mono(node));
|
||||
}
|
||||
|
||||
fn set_split(&self, split: ContainerSplit) {
|
||||
self.parent_node.get().map(|p| p.set_split(split));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ use crate::render::RenderError;
|
|||
use crate::sighand::SighandError;
|
||||
use crate::state::State;
|
||||
use crate::tree::{
|
||||
container_layout, container_titles, float_layout, float_titles, DisplayNode, NodeIds,
|
||||
container_layout, container_render_data, float_layout, float_titles, DisplayNode, NodeIds,
|
||||
};
|
||||
use crate::udev::Udev;
|
||||
use crate::utils::clonecell::CloneCell;
|
||||
|
|
@ -176,7 +176,7 @@ fn main_() -> Result<(), MainError> {
|
|||
input_device_handlers: Default::default(),
|
||||
theme: Default::default(),
|
||||
pending_container_layout: Default::default(),
|
||||
pending_container_titles: Default::default(),
|
||||
pending_container_render_data: Default::default(),
|
||||
pending_float_layout: Default::default(),
|
||||
pending_float_titles: Default::default(),
|
||||
dbus: Dbus::new(&engine, &run_toplevel),
|
||||
|
|
@ -189,7 +189,7 @@ fn main_() -> Result<(), MainError> {
|
|||
let _slow_client_handler = engine.spawn(tasks::handle_slow_clients(state.clone()));
|
||||
let _container_do_layout = engine.spawn2(Phase::Layout, container_layout(state.clone()));
|
||||
let _container_render_titles =
|
||||
engine.spawn2(Phase::PostLayout, container_titles(state.clone()));
|
||||
engine.spawn2(Phase::PostLayout, container_render_data(state.clone()));
|
||||
let _float_do_layout = engine.spawn2(Phase::Layout, float_layout(state.clone()));
|
||||
let _float_render_titles = engine.spawn2(Phase::PostLayout, float_titles(state.clone()));
|
||||
let socket_path = Acceptor::install(&state)?;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use crate::render::gl::sys::{
|
|||
};
|
||||
use crate::render::renderer::context::RenderContext;
|
||||
use crate::render::renderer::renderer::Renderer;
|
||||
use crate::render::sys::{glBlendFunc, GL_ONE, GL_ONE_MINUS_SRC_ALPHA};
|
||||
use crate::render::sys::{glBlendFunc, GL_ONE, GL_ONE_MINUS_SRC_ALPHA, glFlush};
|
||||
use crate::tree::Node;
|
||||
use crate::State;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
|
|
@ -74,6 +74,9 @@ impl Framebuffer {
|
|||
}
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
glFlush();
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,24 +16,11 @@ use crate::render::sys::{glDisable, glEnable, GL_BLEND};
|
|||
use crate::render::Texture;
|
||||
use crate::theme::Color;
|
||||
use crate::tree::{
|
||||
ContainerFocus, ContainerNode, ContainerSplit, FloatNode, Node, OutputNode, WorkspaceNode,
|
||||
ContainerNode, FloatNode, Node, OutputNode, WorkspaceNode,
|
||||
};
|
||||
use crate::State;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use std::slice;
|
||||
|
||||
const NON_COLOR: Color = Color::from_rgbaf(0.2, 0.2, 0.2, 1.0);
|
||||
const CHILD_COLOR: Color = Color::from_rgbaf(0.8, 0.8, 0.8, 1.0);
|
||||
const YES_COLOR: Color = Color::from_rgbaf(0.0, 0.0, 1.0, 1.0);
|
||||
|
||||
fn focus_color(focus: ContainerFocus) -> Color {
|
||||
match focus {
|
||||
ContainerFocus::None => NON_COLOR,
|
||||
ContainerFocus::Child => CHILD_COLOR,
|
||||
ContainerFocus::Yes => YES_COLOR,
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Renderer<'a> {
|
||||
pub(super) ctx: &'a Rc<RenderContext>,
|
||||
|
|
@ -82,16 +69,21 @@ impl Renderer<'_> {
|
|||
2.0 * (y as f32 / self.fb.height as f32) - 1.0
|
||||
}
|
||||
|
||||
|
||||
fn fill_boxes(&self, boxes: &[Rect], color: &Color) {
|
||||
self.fill_boxes2(boxes, color, 0, 0);
|
||||
}
|
||||
|
||||
fn fill_boxes2(&self, boxes: &[Rect], color: &Color, dx: i32, dy: i32) {
|
||||
if boxes.is_empty() {
|
||||
return;
|
||||
}
|
||||
let mut pos = Vec::with_capacity(boxes.len() * 12);
|
||||
for bx in boxes {
|
||||
let x1 = self.x_to_f(bx.x1());
|
||||
let y1 = self.y_to_f(bx.y1());
|
||||
let x2 = self.x_to_f(bx.x2());
|
||||
let y2 = self.y_to_f(bx.y2());
|
||||
let x1 = self.x_to_f(bx.x1() + dx);
|
||||
let y1 = self.y_to_f(bx.y1() + dy);
|
||||
let x2 = self.x_to_f(bx.x2() + dx);
|
||||
let y2 = self.y_to_f(bx.y2() + dy);
|
||||
pos.extend_from_slice(&[
|
||||
// triangle 1
|
||||
x2, y1, // top right
|
||||
|
|
@ -121,128 +113,35 @@ impl Renderer<'_> {
|
|||
}
|
||||
|
||||
pub fn render_container(&mut self, container: &ContainerNode, x: i32, y: i32) {
|
||||
let border_width = self.state.theme.border_width.get();
|
||||
let title_height = self.state.theme.title_height.get();
|
||||
let cwidth = container.width.get();
|
||||
let cheight = container.height.get();
|
||||
let num_children = container.num_children();
|
||||
let title_rect = Rect::new_sized(x, y, container.width.get(), title_height).unwrap();
|
||||
let underline_rect =
|
||||
Rect::new_sized(x, y + title_height, container.width.get(), 1).unwrap();
|
||||
let mut titles = vec![];
|
||||
if let Some(child) = container.mono_child.get() {
|
||||
let space_per_child = cwidth / num_children as i32;
|
||||
let mut rem = cwidth % num_children as i32;
|
||||
let mut pos = x;
|
||||
let color = focus_color(ContainerFocus::None);
|
||||
self.fill_boxes(slice::from_ref(&title_rect), &color);
|
||||
{
|
||||
let rd = container.render_data.borrow_mut();
|
||||
let c = self.state.theme.title_color.get();
|
||||
self.fill_boxes2(&rd.title_rects, &c, x, y);
|
||||
let c = self.state.theme.active_title_color.get();
|
||||
self.fill_boxes2(&rd.active_title_rects, &c, x, y);
|
||||
let c = self.state.theme.underline_color.get();
|
||||
self.fill_boxes2(&rd.underline_rects, &c, x, y);
|
||||
let c = self.state.theme.border_color.get();
|
||||
self.fill_boxes(slice::from_ref(&underline_rect), &c);
|
||||
for child in container.children.iter() {
|
||||
let focus = child.focus.get();
|
||||
let color = focus_color(focus);
|
||||
let mut width = space_per_child;
|
||||
if rem > 0 {
|
||||
rem -= 1;
|
||||
width += 1;
|
||||
}
|
||||
if let Some(title) = child.title_texture.get() {
|
||||
titles.push((pos, 0, title));
|
||||
}
|
||||
if focus != ContainerFocus::None {
|
||||
let rect = Rect::new_sized(pos, y, width, title_height).unwrap();
|
||||
self.fill_boxes(slice::from_ref(&rect), &color);
|
||||
}
|
||||
pos += width as i32;
|
||||
self.fill_boxes2(&rd.border_rects, &c, x, y);
|
||||
for title in &rd.titles {
|
||||
self.render_texture(&title.tex, x + title.x, y + title.y, ARGB8888);
|
||||
}
|
||||
}
|
||||
if let Some(child) = container.mono_child.get() {
|
||||
unsafe {
|
||||
with_scissor(&container.mono_body.get(), || {
|
||||
let body = container.mono_body.get().move_(x, y);
|
||||
with_scissor(&body, || {
|
||||
let content = container.mono_content.get();
|
||||
child.node.render(self, x + content.x1(), y + content.y1());
|
||||
});
|
||||
}
|
||||
} else {
|
||||
let split = container.split.get();
|
||||
let num_title_rects = if split == ContainerSplit::Horizontal {
|
||||
1
|
||||
} else {
|
||||
num_children
|
||||
};
|
||||
let mut title_rects = Vec::with_capacity(num_title_rects);
|
||||
let mut underline_rects = Vec::with_capacity(num_title_rects);
|
||||
let mut border_rects = Vec::with_capacity(num_children - 1);
|
||||
let mut active_rects = Vec::new();
|
||||
title_rects.push(title_rect);
|
||||
underline_rects.push(underline_rect);
|
||||
for (i, child) in container.children.iter().enumerate() {
|
||||
let body = child.body.get();
|
||||
if let Some(title) = child.title_texture.get() {
|
||||
titles.push((body.x1(), body.y1() - title_height - 1, title));
|
||||
}
|
||||
if child.active.get() {
|
||||
active_rects.push(
|
||||
Rect::new_sized(
|
||||
x + body.x1(),
|
||||
y + body.y1() - title_height - 1,
|
||||
body.width(),
|
||||
title_height,
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
if i + 1 < num_children {
|
||||
let border_rect = if split == ContainerSplit::Horizontal {
|
||||
Rect::new_sized(
|
||||
x + body.x2(),
|
||||
y + body.y1() - title_height - 1,
|
||||
border_width,
|
||||
container.height.get(),
|
||||
)
|
||||
.unwrap()
|
||||
} else {
|
||||
title_rects.push(
|
||||
Rect::new_sized(
|
||||
x,
|
||||
y + body.y2() + border_width,
|
||||
container.width.get(),
|
||||
title_height,
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
underline_rects.push(
|
||||
Rect::new_sized(
|
||||
x,
|
||||
y + body.y2() + border_width + title_height,
|
||||
container.width.get(),
|
||||
1,
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
Rect::new_sized(x, y + body.y2(), container.width.get(), border_width)
|
||||
.unwrap()
|
||||
};
|
||||
border_rects.push(border_rect);
|
||||
}
|
||||
}
|
||||
{
|
||||
let c = self.state.theme.title_color.get();
|
||||
self.fill_boxes(&title_rects, &c);
|
||||
let c = self.state.theme.active_title_color.get();
|
||||
self.fill_boxes(&active_rects, &c);
|
||||
let c = self.state.theme.underline_color.get();
|
||||
self.fill_boxes(&underline_rects, &c);
|
||||
let c = self.state.theme.border_color.get();
|
||||
self.fill_boxes(&border_rects, &c);
|
||||
for (tx, ty, tex) in titles {
|
||||
self.render_texture(&tex, x + tx, y + ty, ARGB8888);
|
||||
}
|
||||
}
|
||||
for child in container.children.iter() {
|
||||
let body = child.body.get();
|
||||
if body.x1() >= cwidth || body.y1() >= cheight {
|
||||
if body.x1() >= container.width.get() || body.y1() >= container.height.get() {
|
||||
break;
|
||||
}
|
||||
let body = body.move_(container.abs_x1.get(), container.abs_y1.get());
|
||||
let body = body.move_(x, y);
|
||||
unsafe {
|
||||
with_scissor(&body, || {
|
||||
let content = child.content.get();
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ pub struct State {
|
|||
pub config: CloneCell<Option<Rc<ConfigProxy>>>,
|
||||
pub theme: Theme,
|
||||
pub pending_container_layout: AsyncQueue<Rc<ContainerNode>>,
|
||||
pub pending_container_titles: AsyncQueue<Rc<ContainerNode>>,
|
||||
pub pending_container_render_data: AsyncQueue<Rc<ContainerNode>>,
|
||||
pub pending_float_layout: AsyncQueue<Rc<FloatNode>>,
|
||||
pub pending_float_titles: AsyncQueue<Rc<FloatNode>>,
|
||||
pub dbus: Dbus,
|
||||
|
|
|
|||
|
|
@ -30,10 +30,6 @@ impl Color {
|
|||
a: to_f32(a),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn from_rgbaf(r: f32, g: f32, b: f32, a: f32) -> Self {
|
||||
Self { r, g, b, a }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<jay_config::theme::Color> for Color {
|
||||
|
|
|
|||
18
src/tree.rs
18
src/tree.rs
|
|
@ -84,18 +84,34 @@ pub trait Node {
|
|||
let _ = title;
|
||||
}
|
||||
|
||||
fn get_parent_mono(&self) -> Option<bool> {
|
||||
None
|
||||
}
|
||||
|
||||
fn get_parent_split(&self) -> Option<ContainerSplit> {
|
||||
None
|
||||
}
|
||||
|
||||
fn set_parent_mono(&self, mono: bool) {
|
||||
let _ = mono;
|
||||
}
|
||||
|
||||
fn set_parent_split(&self, split: ContainerSplit) {
|
||||
let _ = split;
|
||||
}
|
||||
|
||||
fn get_mono(&self) -> Option<bool> {
|
||||
None
|
||||
}
|
||||
|
||||
fn get_split(&self) -> Option<ContainerSplit> {
|
||||
None
|
||||
}
|
||||
|
||||
fn set_mono(self: Rc<Self>, child: Option<&dyn Node>) {
|
||||
let _ = child;
|
||||
}
|
||||
|
||||
fn set_split(self: Rc<Self>, split: ContainerSplit) {
|
||||
let _ = split;
|
||||
}
|
||||
|
|
@ -209,7 +225,7 @@ pub trait Node {
|
|||
let _ = (child, width, height);
|
||||
}
|
||||
|
||||
fn child_active_changed(&self, child: &dyn Node, active: bool) {
|
||||
fn child_active_changed(self: Rc<Self>, child: &dyn Node, active: bool) {
|
||||
let _ = (child, active);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,6 +54,21 @@ pub enum ContainerFocus {
|
|||
|
||||
tree_id!(ContainerNodeId);
|
||||
|
||||
pub struct ContainerTitle {
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
pub tex: Rc<Texture>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ContainerRenderData {
|
||||
pub title_rects: Vec<Rect>,
|
||||
pub active_title_rects: Vec<Rect>,
|
||||
pub border_rects: Vec<Rect>,
|
||||
pub underline_rects: Vec<Rect>,
|
||||
pub titles: Vec<ContainerTitle>,
|
||||
}
|
||||
|
||||
pub struct ContainerNode {
|
||||
pub id: ContainerNodeId,
|
||||
pub parent: CloneCell<Rc<dyn Node>>,
|
||||
|
|
@ -71,7 +86,7 @@ pub struct ContainerNode {
|
|||
pub content_height: Cell<i32>,
|
||||
pub sum_factors: Cell<f64>,
|
||||
layout_scheduled: Cell<bool>,
|
||||
render_titles_scheduled: Cell<bool>,
|
||||
compute_render_data_scheduled: Cell<bool>,
|
||||
num_children: NumCell<usize>,
|
||||
pub children: LinkedList<ContainerChild>,
|
||||
child_nodes: RefCell<AHashMap<NodeId, LinkedNode<ContainerChild>>>,
|
||||
|
|
@ -79,6 +94,7 @@ pub struct ContainerNode {
|
|||
workspace: CloneCell<Rc<WorkspaceNode>>,
|
||||
seats: RefCell<AHashMap<SeatId, SeatState>>,
|
||||
state: Rc<State>,
|
||||
pub render_data: RefCell<ContainerRenderData>,
|
||||
}
|
||||
|
||||
impl Debug for ContainerNode {
|
||||
|
|
@ -94,9 +110,7 @@ pub struct ContainerChild {
|
|||
pub body: Cell<Rect>,
|
||||
pub content: Cell<Rect>,
|
||||
factor: Cell<f64>,
|
||||
pub focus: Cell<ContainerFocus>,
|
||||
title: RefCell<String>,
|
||||
pub title_texture: CloneCell<Option<Rc<Texture>>>,
|
||||
}
|
||||
|
||||
struct SeatState {
|
||||
|
|
@ -143,9 +157,7 @@ impl ContainerNode {
|
|||
body: Cell::new(Default::default()),
|
||||
content: Cell::new(Default::default()),
|
||||
factor: Cell::new(1.0),
|
||||
focus: Cell::new(ContainerFocus::None),
|
||||
title: Default::default(),
|
||||
title_texture: Default::default(),
|
||||
}),
|
||||
);
|
||||
let slf = Rc::new(Self {
|
||||
|
|
@ -165,7 +177,7 @@ impl ContainerNode {
|
|||
content_height: Cell::new(0),
|
||||
sum_factors: Cell::new(1.0),
|
||||
layout_scheduled: Cell::new(false),
|
||||
render_titles_scheduled: Cell::new(false),
|
||||
compute_render_data_scheduled: Cell::new(false),
|
||||
num_children: NumCell::new(1),
|
||||
children,
|
||||
child_nodes: RefCell::new(child_nodes),
|
||||
|
|
@ -173,15 +185,12 @@ impl ContainerNode {
|
|||
workspace: CloneCell::new(workspace.clone()),
|
||||
seats: RefCell::new(Default::default()),
|
||||
state: state.clone(),
|
||||
render_data: Default::default(),
|
||||
});
|
||||
child.set_parent(slf.clone());
|
||||
slf
|
||||
}
|
||||
|
||||
pub fn num_children(&self) -> usize {
|
||||
self.num_children.get()
|
||||
}
|
||||
|
||||
pub fn prepend_child(self: &Rc<Self>, new: Rc<dyn Node>) {
|
||||
if let Some(child) = self.children.first() {
|
||||
self.add_child_before_(&child, new);
|
||||
|
|
@ -248,9 +257,7 @@ impl ContainerNode {
|
|||
body: Default::default(),
|
||||
content: Default::default(),
|
||||
factor: Cell::new(0.0),
|
||||
focus: Cell::new(ContainerFocus::None),
|
||||
title: Default::default(),
|
||||
title_texture: Default::default(),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
|
@ -287,7 +294,7 @@ impl ContainerNode {
|
|||
}
|
||||
|
||||
pub fn on_colors_changed(self: &Rc<Self>) {
|
||||
self.schedule_render_titles();
|
||||
self.schedule_compute_render_data();
|
||||
}
|
||||
|
||||
fn schedule_layout(self: &Rc<Self>) {
|
||||
|
|
@ -297,6 +304,23 @@ impl ContainerNode {
|
|||
}
|
||||
|
||||
fn perform_layout(self: &Rc<Self>) {
|
||||
self.layout_scheduled.set(false);
|
||||
if let Some(child) = self.mono_child.get() {
|
||||
self.perform_mono_layout(&child);
|
||||
} else {
|
||||
self.perform_split_layout();
|
||||
}
|
||||
self.schedule_compute_render_data();
|
||||
}
|
||||
|
||||
fn perform_mono_layout(self: &Rc<Self>, child: &ContainerChild) {
|
||||
let mb = self.mono_body.get();
|
||||
child.node.clone().change_extents(&mb.move_(self.abs_x1.get(), self.abs_y1.get()));
|
||||
self.mono_content
|
||||
.set(child.content.get().at_point(mb.x1(), mb.y1()));
|
||||
}
|
||||
|
||||
fn perform_split_layout(self: &Rc<Self>) {
|
||||
let sum_factors = self.sum_factors.get();
|
||||
let border_width = self.state.theme.border_width.get();
|
||||
let title_height = self.state.theme.title_height.get();
|
||||
|
|
@ -363,13 +387,11 @@ impl ContainerNode {
|
|||
}
|
||||
}
|
||||
self.sum_factors.set(1.0);
|
||||
self.layout_scheduled.set(false);
|
||||
for child in self.children.iter() {
|
||||
let body = child.body.get().move_(self.abs_x1.get(), self.abs_y1.get());
|
||||
child.node.clone().change_extents(&body);
|
||||
child.position_content();
|
||||
}
|
||||
self.schedule_render_titles();
|
||||
}
|
||||
|
||||
fn update_content_size(&self) {
|
||||
|
|
@ -393,6 +415,15 @@ impl ContainerNode {
|
|||
self.content_width.set(self.width.get());
|
||||
}
|
||||
}
|
||||
self.mono_body.set(
|
||||
Rect::new_sized(
|
||||
0,
|
||||
title_height + 1,
|
||||
self.width.get(),
|
||||
self.height.get().sub(title_height + 1).max(0),
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
fn pointer_move(self: &Rc<Self>, seat: &Rc<WlSeatGlobal>, mut x: i32, mut y: i32) {
|
||||
|
|
@ -482,55 +513,122 @@ impl ContainerNode {
|
|||
}
|
||||
|
||||
fn update_title(self: &Rc<Self>) {
|
||||
let split = match self.split.get() {
|
||||
ContainerSplit::Horizontal => "H",
|
||||
ContainerSplit::Vertical => "V",
|
||||
};
|
||||
let mut title = self.title.borrow_mut();
|
||||
title.clear();
|
||||
title.push_str(split);
|
||||
title.push_str("[");
|
||||
for (i, c) in self.children.iter().enumerate() {
|
||||
if i > 0 {
|
||||
title.push_str(", ");
|
||||
if let Some(mc) = self.mono_child.get() {
|
||||
title.push_str("M[");
|
||||
title.push_str(mc.title.borrow_mut().deref());
|
||||
title.push_str("]");
|
||||
} else {
|
||||
let split = match self.split.get() {
|
||||
ContainerSplit::Horizontal => "H",
|
||||
ContainerSplit::Vertical => "V",
|
||||
};
|
||||
title.push_str(split);
|
||||
title.push_str("[");
|
||||
for (i, c) in self.children.iter().enumerate() {
|
||||
if i > 0 {
|
||||
title.push_str(", ");
|
||||
}
|
||||
title.push_str(c.title.borrow_mut().deref());
|
||||
}
|
||||
title.push_str(c.title.borrow_mut().deref());
|
||||
title.push_str("]");
|
||||
}
|
||||
title.push_str("]");
|
||||
self.parent.get().child_title_changed(&**self, &title);
|
||||
self.schedule_render_titles();
|
||||
}
|
||||
|
||||
fn schedule_render_titles(self: &Rc<Self>) {
|
||||
if !self.render_titles_scheduled.replace(true) {
|
||||
self.state.pending_container_titles.push(self.clone());
|
||||
fn schedule_compute_render_data(self: &Rc<Self>) {
|
||||
if !self.compute_render_data_scheduled.replace(true) {
|
||||
self.state.pending_container_render_data.push(self.clone());
|
||||
}
|
||||
}
|
||||
|
||||
fn render_titles(&self) {
|
||||
self.render_titles_scheduled.set(false);
|
||||
fn compute_render_data(&self) {
|
||||
self.compute_render_data_scheduled.set(false);
|
||||
let mut rd = self.render_data.borrow_mut();
|
||||
let theme = &self.state.theme;
|
||||
let th = theme.title_height.get();
|
||||
let bw = theme.border_width.get();
|
||||
let font = theme.font.borrow_mut();
|
||||
for c in self.children.iter() {
|
||||
c.title_texture.set(None);
|
||||
let title = c.title.borrow_mut();
|
||||
let body = c.body.get();
|
||||
if title.is_empty() || th == 0 || body.width() == 0 {
|
||||
continue;
|
||||
}
|
||||
let ctx = match self.state.render_ctx.get() {
|
||||
Some(c) => c,
|
||||
_ => continue,
|
||||
};
|
||||
let texture = match text::render(&ctx, body.width(), th, &font, &title, Color::GREY) {
|
||||
Ok(t) => t,
|
||||
Err(e) => {
|
||||
log::error!("Could not render title {}: {}", title, ErrorFmt(e));
|
||||
continue;
|
||||
let cwidth = self.width.get();
|
||||
let cheight = self.height.get();
|
||||
let num_children = self.num_children.get() as i32;
|
||||
let ctx = self.state.render_ctx.get();
|
||||
rd.titles.clear();
|
||||
rd.title_rects.clear();
|
||||
rd.active_title_rects.clear();
|
||||
rd.border_rects.clear();
|
||||
rd.underline_rects.clear();
|
||||
if self.mono_child.get().is_some() {
|
||||
let content_width = self.width.get().sub(bw * (num_children - 1)).max(0);
|
||||
let space_per_child = content_width / num_children;
|
||||
let mut rem = content_width % num_children;
|
||||
let mut pos = 0;
|
||||
for (i, c) in self.children.iter().enumerate() {
|
||||
if i > 0 {
|
||||
rd.border_rects.push(Rect::new_sized(pos - bw, 0, bw, th).unwrap());
|
||||
}
|
||||
};
|
||||
c.title_texture.set(Some(texture));
|
||||
let mut width = space_per_child;
|
||||
if rem > 0 {
|
||||
rem -= 1;
|
||||
width += 1;
|
||||
}
|
||||
let rect = Rect::new_sized(pos, 0, width, th).unwrap();
|
||||
if c.active.get() {
|
||||
rd.active_title_rects.push(rect);
|
||||
} else {
|
||||
rd.title_rects.push(rect);
|
||||
}
|
||||
if let Some(ctx) = &ctx {
|
||||
let title = c.title.borrow_mut();
|
||||
match text::render(&ctx, width, th, &font, &title, Color::GREY) {
|
||||
Ok(t) => rd.titles.push(ContainerTitle {
|
||||
x: pos,
|
||||
y: 0,
|
||||
tex: t,
|
||||
}),
|
||||
Err(e) => {
|
||||
log::error!("Could not render title {}: {}", title, ErrorFmt(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
pos += width + bw;
|
||||
}
|
||||
rd.underline_rects.push(Rect::new_sized(0, th, cwidth, 1).unwrap());
|
||||
} else {
|
||||
let split = self.split.get();
|
||||
for (i, c) in self.children.iter().enumerate() {
|
||||
let body = c.body.get();
|
||||
if i > 0 {
|
||||
let rect = if split == ContainerSplit::Horizontal {
|
||||
Rect::new_sized(body.x1() - bw, 0, bw, cheight).unwrap()
|
||||
} else {
|
||||
Rect::new_sized(0, body.y1() - th - 1 - bw, cwidth, bw).unwrap()
|
||||
};
|
||||
rd.border_rects.push(rect);
|
||||
}
|
||||
let rect = Rect::new_sized(body.x1(), body.y1() - th - 1, body.width(), th).unwrap();
|
||||
if c.active.get() {
|
||||
rd.active_title_rects.push(rect);
|
||||
} else {
|
||||
rd.title_rects.push(rect);
|
||||
}
|
||||
let rect = Rect::new_sized(body.x1(), body.y1() - 1, body.width(), 1).unwrap();
|
||||
rd.underline_rects.push(rect);
|
||||
if let Some(ctx) = &ctx {
|
||||
let title = c.title.borrow_mut();
|
||||
match text::render(&ctx, body.width(), th, &font, &title, Color::GREY) {
|
||||
Ok(t) => rd.titles.push(ContainerTitle {
|
||||
x: body.x1(),
|
||||
y: body.y1() - th - 1,
|
||||
tex: t,
|
||||
}),
|
||||
Err(e) => {
|
||||
log::error!("Could not render title {}: {}", title, ErrorFmt(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -555,11 +653,11 @@ pub async fn container_layout(state: Rc<State>) {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn container_titles(state: Rc<State>) {
|
||||
pub async fn container_render_data(state: Rc<State>) {
|
||||
loop {
|
||||
let container = state.pending_container_titles.pop().await;
|
||||
if container.render_titles_scheduled.get() {
|
||||
container.render_titles();
|
||||
let container = state.pending_container_render_data.pop().await;
|
||||
if container.compute_render_data_scheduled.get() {
|
||||
container.compute_render_data();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -617,12 +715,33 @@ impl Node for ContainerNode {
|
|||
ct.push_str(title);
|
||||
}
|
||||
self.update_title();
|
||||
self.schedule_compute_render_data();
|
||||
}
|
||||
|
||||
fn get_mono(&self) -> Option<bool> {
|
||||
Some(self.mono_child.get().is_some())
|
||||
}
|
||||
|
||||
fn get_split(&self) -> Option<ContainerSplit> {
|
||||
Some(self.split.get())
|
||||
}
|
||||
|
||||
fn set_mono(self: Rc<Self>, child: Option<&dyn Node>) {
|
||||
if self.mono_child.get().is_some() != child.is_some() {
|
||||
let children = self.child_nodes.borrow_mut();
|
||||
let child = match child {
|
||||
Some(c) => match children.get(&c.id()) {
|
||||
Some(c) => Some(c.to_ref()),
|
||||
_ => return,
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
self.mono_child.set(child);
|
||||
self.schedule_layout();
|
||||
self.update_title();
|
||||
}
|
||||
}
|
||||
|
||||
fn set_split(self: Rc<Self>, split: ContainerSplit) {
|
||||
if self.split.replace(split) != split {
|
||||
self.update_content_size();
|
||||
|
|
@ -636,11 +755,15 @@ impl Node for ContainerNode {
|
|||
}
|
||||
|
||||
fn do_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, direction: Direction) {
|
||||
let node = match direction {
|
||||
Direction::Left => self.children.last(),
|
||||
Direction::Down => self.children.first(),
|
||||
Direction::Up => self.children.last(),
|
||||
Direction::Right => self.children.first(),
|
||||
let node = if let Some(cn) = self.mono_child.get() {
|
||||
Some(cn)
|
||||
} else {
|
||||
match direction {
|
||||
Direction::Left => self.children.last(),
|
||||
Direction::Down => self.children.first(),
|
||||
Direction::Up => self.children.last(),
|
||||
Direction::Right => self.children.first(),
|
||||
}
|
||||
};
|
||||
if let Some(node) = node {
|
||||
node.node.clone().do_focus(seat, direction);
|
||||
|
|
@ -671,9 +794,14 @@ impl Node for ContainerNode {
|
|||
Some(c) => c.to_ref(),
|
||||
_ => return,
|
||||
};
|
||||
let in_line = match self.split.get() {
|
||||
ContainerSplit::Horizontal => matches!(direction, Direction::Left | Direction::Right),
|
||||
ContainerSplit::Vertical => matches!(direction, Direction::Up | Direction::Down),
|
||||
let mc = self.mono_child.get();
|
||||
let in_line = if mc.is_some() {
|
||||
matches!(direction, Direction::Left | Direction::Right)
|
||||
} else {
|
||||
match self.split.get() {
|
||||
ContainerSplit::Horizontal => matches!(direction, Direction::Left | Direction::Right),
|
||||
ContainerSplit::Vertical => matches!(direction, Direction::Up | Direction::Down),
|
||||
}
|
||||
};
|
||||
if !in_line {
|
||||
self.parent
|
||||
|
|
@ -700,6 +828,12 @@ impl Node for ContainerNode {
|
|||
return;
|
||||
}
|
||||
};
|
||||
if mc.is_some() {
|
||||
self.mono_child.set(Some(sibling.clone()));
|
||||
let body = self.mono_body.get();
|
||||
self.mono_content.set(sibling.content.get().at_point(body.x1(), body.y1()));
|
||||
sibling.node.clone().change_extents(&body.move_(self.abs_x1.get(), self.abs_y1.get()));
|
||||
}
|
||||
sibling.node.clone().do_focus(seat, direction);
|
||||
}
|
||||
//
|
||||
|
|
@ -902,9 +1036,7 @@ impl Node for ContainerNode {
|
|||
body: Cell::new(node.body.get()),
|
||||
content: Cell::new(node.content.get()),
|
||||
factor: Cell::new(node.factor.get()),
|
||||
focus: Cell::new(node.focus.get()),
|
||||
title: Default::default(),
|
||||
title_texture: Default::default(),
|
||||
});
|
||||
let body = link.body.get();
|
||||
drop(node);
|
||||
|
|
@ -954,15 +1086,22 @@ impl Node for ContainerNode {
|
|||
let rect = Rect::new(0, 0, width, height).unwrap();
|
||||
node.content.set(rect);
|
||||
node.position_content();
|
||||
if let Some(mono) = self.mono_child.get() {
|
||||
if mono.node.id() == node.node.id() {
|
||||
let body = self.mono_body.get();
|
||||
self.mono_content.set(rect.at_point(body.x1(), body.y1()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn child_active_changed(&self, child: &dyn Node, active: bool) {
|
||||
fn child_active_changed(self: Rc<Self>, child: &dyn Node, active: bool) {
|
||||
let node = match self.child_nodes.borrow_mut().get(&child.id()) {
|
||||
Some(l) => l.to_ref(),
|
||||
None => return,
|
||||
};
|
||||
node.active.set(active);
|
||||
self.schedule_compute_render_data();
|
||||
}
|
||||
|
||||
fn pointer_enter(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) {
|
||||
|
|
@ -1027,9 +1166,14 @@ impl Node for ContainerNode {
|
|||
.get()
|
||||
.child_size_changed(&*self, rect.width(), rect.height());
|
||||
} else {
|
||||
for child in self.children.iter() {
|
||||
let body = child.body.get().move_(self.abs_x1.get(), self.abs_y1.get());
|
||||
child.node.clone().change_extents(&body);
|
||||
if let Some(c) = self.mono_child.get() {
|
||||
let body = self.mono_body.get().move_(self.abs_x1.get(), self.abs_y1.get());
|
||||
c.node.clone().change_extents(&body);
|
||||
} else {
|
||||
for child in self.children.iter() {
|
||||
let body = child.body.get().move_(self.abs_x1.get(), self.abs_y1.get());
|
||||
child.node.clone().change_extents(&body);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1043,7 +1187,7 @@ impl Node for ContainerNode {
|
|||
|
||||
fn set_parent(self: Rc<Self>, parent: Rc<dyn Node>) {
|
||||
self.parent.set(parent.clone());
|
||||
parent.child_active_changed(&*self, self.active.get());
|
||||
parent.clone().child_active_changed(&*self, self.active.get());
|
||||
parent.child_size_changed(&*self, self.width.get(), self.height.get());
|
||||
parent
|
||||
.clone()
|
||||
|
|
|
|||
|
|
@ -437,7 +437,7 @@ impl Node for FloatNode {
|
|||
self.workspace_link.set(None);
|
||||
}
|
||||
|
||||
fn child_active_changed(&self, _child: &dyn Node, active: bool) {
|
||||
fn child_active_changed(self: Rc<Self>, _child: &dyn Node, active: bool) {
|
||||
self.active.set(active);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue