text: re-use textures if possible
This commit is contained in:
parent
bf90204db6
commit
a04870388f
10 changed files with 153 additions and 45 deletions
|
|
@ -410,6 +410,7 @@ fn create_dummy_output(state: &Rc<State>) {
|
||||||
desired_output: CloneCell::new(dummy_output.global.output_id.clone()),
|
desired_output: CloneCell::new(dummy_output.global.output_id.clone()),
|
||||||
jay_workspaces: Default::default(),
|
jay_workspaces: Default::default(),
|
||||||
capture: Cell::new(false),
|
capture: Cell::new(false),
|
||||||
|
title_texture: Cell::new(None),
|
||||||
});
|
});
|
||||||
dummy_workspace.output_link.set(Some(
|
dummy_workspace.output_link.set(Some(
|
||||||
dummy_output.workspaces.add_last(dummy_workspace.clone()),
|
dummy_output.workspaces.add_last(dummy_workspace.clone()),
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@ use {
|
||||||
cursor::KnownCursor,
|
cursor::KnownCursor,
|
||||||
fixed::Fixed,
|
fixed::Fixed,
|
||||||
format::ARGB8888,
|
format::ARGB8888,
|
||||||
gfx_api::{GfxContext, GfxFramebuffer, GfxTexture},
|
gfx_api::{GfxContext, GfxFramebuffer},
|
||||||
ifs::zwlr_layer_shell_v1::OVERLAY,
|
ifs::zwlr_layer_shell_v1::OVERLAY,
|
||||||
portal::ptl_display::{PortalDisplay, PortalOutput, PortalSeat},
|
portal::ptl_display::{PortalDisplay, PortalOutput, PortalSeat},
|
||||||
renderer::renderer_base::RendererBase,
|
renderer::renderer_base::RendererBase,
|
||||||
scale::Scale,
|
scale::Scale,
|
||||||
text::{self, TextMeasurement},
|
text::{self, TextMeasurement, TextTexture},
|
||||||
theme::Color,
|
theme::Color,
|
||||||
utils::{
|
utils::{
|
||||||
asyncevent::AsyncEvent, clonecell::CloneCell, copyhashmap::CopyHashMap,
|
asyncevent::AsyncEvent, clonecell::CloneCell, copyhashmap::CopyHashMap,
|
||||||
|
|
@ -118,7 +118,7 @@ pub struct Button {
|
||||||
pub bg_hover_color: Cell<Color>,
|
pub bg_hover_color: Cell<Color>,
|
||||||
pub text: RefCell<String>,
|
pub text: RefCell<String>,
|
||||||
pub font: RefCell<Cow<'static, str>>,
|
pub font: RefCell<Cow<'static, str>>,
|
||||||
pub tex: CloneCell<Option<Rc<dyn GfxTexture>>>,
|
pub tex: CloneCell<Option<TextTexture>>,
|
||||||
pub owner: CloneCell<Option<Rc<dyn ButtonOwner>>>,
|
pub owner: CloneCell<Option<Rc<dyn ButtonOwner>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -162,10 +162,12 @@ impl GuiElement for Button {
|
||||||
_max_width: f32,
|
_max_width: f32,
|
||||||
_max_height: f32,
|
_max_height: f32,
|
||||||
) -> (f32, f32) {
|
) -> (f32, f32) {
|
||||||
|
let old_tex = self.tex.take();
|
||||||
let font = self.font.borrow_mut();
|
let font = self.font.borrow_mut();
|
||||||
let text = self.text.borrow_mut();
|
let text = self.text.borrow_mut();
|
||||||
let tex = text::render_fitting2(
|
let tex = text::render_fitting2(
|
||||||
ctx,
|
ctx,
|
||||||
|
old_tex,
|
||||||
None,
|
None,
|
||||||
&font,
|
&font,
|
||||||
&text,
|
&text,
|
||||||
|
|
@ -213,7 +215,7 @@ impl GuiElement for Button {
|
||||||
if let Some(tex) = self.tex.get() {
|
if let Some(tex) = self.tex.get() {
|
||||||
let (tx, ty) = r.scale_point_f(x1 + self.tex_off_x.get(), y1 + self.tex_off_y.get());
|
let (tx, ty) = r.scale_point_f(x1 + self.tex_off_x.get(), y1 + self.tex_off_y.get());
|
||||||
r.render_texture(
|
r.render_texture(
|
||||||
&tex,
|
&tex.texture,
|
||||||
tx.round() as _,
|
tx.round() as _,
|
||||||
ty.round() as _,
|
ty.round() as _,
|
||||||
ARGB8888,
|
ARGB8888,
|
||||||
|
|
@ -260,7 +262,7 @@ pub struct Label {
|
||||||
pub data: GuiElementData,
|
pub data: GuiElementData,
|
||||||
pub font: RefCell<Cow<'static, str>>,
|
pub font: RefCell<Cow<'static, str>>,
|
||||||
pub text: RefCell<String>,
|
pub text: RefCell<String>,
|
||||||
pub tex: CloneCell<Option<Rc<dyn GfxTexture>>>,
|
pub tex: CloneCell<Option<TextTexture>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Label {
|
impl Default for Label {
|
||||||
|
|
@ -286,10 +288,12 @@ impl GuiElement for Label {
|
||||||
_max_width: f32,
|
_max_width: f32,
|
||||||
_max_height: f32,
|
_max_height: f32,
|
||||||
) -> (f32, f32) {
|
) -> (f32, f32) {
|
||||||
|
let old_tex = self.tex.take();
|
||||||
let text = self.text.borrow_mut();
|
let text = self.text.borrow_mut();
|
||||||
let font = self.font.borrow_mut();
|
let font = self.font.borrow_mut();
|
||||||
let tex = text::render_fitting2(
|
let tex = text::render_fitting2(
|
||||||
ctx,
|
ctx,
|
||||||
|
old_tex,
|
||||||
None,
|
None,
|
||||||
&font,
|
&font,
|
||||||
&text,
|
&text,
|
||||||
|
|
@ -300,7 +304,7 @@ impl GuiElement for Label {
|
||||||
)
|
)
|
||||||
.ok();
|
.ok();
|
||||||
let (tex, width, height) = match tex {
|
let (tex, width, height) = match tex {
|
||||||
Some((t, _)) => (Some(t.clone()), t.width(), t.height()),
|
Some((t, _)) => (Some(t.clone()), t.texture.width(), t.texture.height()),
|
||||||
_ => (None, 0, 0),
|
_ => (None, 0, 0),
|
||||||
};
|
};
|
||||||
self.tex.set(tex);
|
self.tex.set(tex);
|
||||||
|
|
@ -311,7 +315,7 @@ impl GuiElement for Label {
|
||||||
if let Some(tex) = self.tex.get() {
|
if let Some(tex) = self.tex.get() {
|
||||||
let (tx, ty) = r.scale_point_f(x, y);
|
let (tx, ty) = r.scale_point_f(x, y);
|
||||||
r.render_texture(
|
r.render_texture(
|
||||||
&tex,
|
&tex.texture,
|
||||||
tx.round() as _,
|
tx.round() as _,
|
||||||
ty.round() as _,
|
ty.round() as _,
|
||||||
ARGB8888,
|
ARGB8888,
|
||||||
|
|
|
||||||
|
|
@ -155,7 +155,7 @@ impl Renderer<'_> {
|
||||||
if let Some(status) = &rd.status {
|
if let Some(status) = &rd.status {
|
||||||
let (x, y) = self.base.scale_point(x + status.tex_x, y + status.tex_y);
|
let (x, y) = self.base.scale_point(x + status.tex_x, y + status.tex_y);
|
||||||
self.base.render_texture(
|
self.base.render_texture(
|
||||||
&status.tex,
|
&status.tex.texture,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
ARGB8888,
|
ARGB8888,
|
||||||
|
|
@ -197,10 +197,10 @@ impl Renderer<'_> {
|
||||||
&Color::from_rgba_straight(20, 20, 20, 255),
|
&Color::from_rgba_straight(20, 20, 20, 255),
|
||||||
);
|
);
|
||||||
if let Some(tex) = placeholder.textures.get(&self.base.scale) {
|
if let Some(tex) = placeholder.textures.get(&self.base.scale) {
|
||||||
let x = x + (pos.width() - tex.width()) / 2;
|
let x = x + (pos.width() - tex.texture.width()) / 2;
|
||||||
let y = y + (pos.height() - tex.height()) / 2;
|
let y = y + (pos.height() - tex.texture.height()) / 2;
|
||||||
self.base.render_texture(
|
self.base.render_texture(
|
||||||
&tex,
|
&tex.texture,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
ARGB8888,
|
ARGB8888,
|
||||||
|
|
@ -237,7 +237,7 @@ impl Renderer<'_> {
|
||||||
for title in titles {
|
for title in titles {
|
||||||
let (x, y) = self.base.scale_point(x + title.x, y + title.y);
|
let (x, y) = self.base.scale_point(x + title.x, y + title.y);
|
||||||
self.base.render_texture(
|
self.base.render_texture(
|
||||||
&title.tex,
|
&title.tex.texture,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
ARGB8888,
|
ARGB8888,
|
||||||
|
|
@ -439,7 +439,7 @@ impl Renderer<'_> {
|
||||||
if let Some(title) = floating.title_textures.get(&self.base.scale) {
|
if let Some(title) = floating.title_textures.get(&self.base.scale) {
|
||||||
let (x, y) = self.base.scale_point(x + bw, y + bw);
|
let (x, y) = self.base.scale_point(x + bw, y + bw);
|
||||||
self.base.render_texture(
|
self.base.render_texture(
|
||||||
&title,
|
&title.texture,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
ARGB8888,
|
ARGB8888,
|
||||||
|
|
|
||||||
|
|
@ -237,6 +237,7 @@ impl DrmDevData {
|
||||||
struct UpdateTextTexturesVisitor;
|
struct UpdateTextTexturesVisitor;
|
||||||
impl NodeVisitorBase for UpdateTextTexturesVisitor {
|
impl NodeVisitorBase for UpdateTextTexturesVisitor {
|
||||||
fn visit_container(&mut self, node: &Rc<ContainerNode>) {
|
fn visit_container(&mut self, node: &Rc<ContainerNode>) {
|
||||||
|
node.children.iter().for_each(|c| c.title_tex.clear());
|
||||||
node.schedule_compute_render_data();
|
node.schedule_compute_render_data();
|
||||||
node.node_visit_children(self);
|
node.node_visit_children(self);
|
||||||
}
|
}
|
||||||
|
|
@ -245,10 +246,12 @@ impl NodeVisitorBase for UpdateTextTexturesVisitor {
|
||||||
node.node_visit_children(self);
|
node.node_visit_children(self);
|
||||||
}
|
}
|
||||||
fn visit_float(&mut self, node: &Rc<FloatNode>) {
|
fn visit_float(&mut self, node: &Rc<FloatNode>) {
|
||||||
|
node.title_textures.clear();
|
||||||
node.schedule_render_titles();
|
node.schedule_render_titles();
|
||||||
node.node_visit_children(self);
|
node.node_visit_children(self);
|
||||||
}
|
}
|
||||||
fn visit_placeholder(&mut self, node: &Rc<PlaceholderNode>) {
|
fn visit_placeholder(&mut self, node: &Rc<PlaceholderNode>) {
|
||||||
|
node.textures.clear();
|
||||||
node.update_texture();
|
node.update_texture();
|
||||||
node.node_visit_children(self);
|
node.node_visit_children(self);
|
||||||
}
|
}
|
||||||
|
|
@ -339,6 +342,11 @@ impl State {
|
||||||
impl NodeVisitorBase for Walker {
|
impl NodeVisitorBase for Walker {
|
||||||
fn visit_container(&mut self, node: &Rc<ContainerNode>) {
|
fn visit_container(&mut self, node: &Rc<ContainerNode>) {
|
||||||
node.render_data.borrow_mut().titles.clear();
|
node.render_data.borrow_mut().titles.clear();
|
||||||
|
node.children.iter().for_each(|c| c.title_tex.clear());
|
||||||
|
node.node_visit_children(self);
|
||||||
|
}
|
||||||
|
fn visit_workspace(&mut self, node: &Rc<WorkspaceNode>) {
|
||||||
|
node.title_texture.set(None);
|
||||||
node.node_visit_children(self);
|
node.node_visit_children(self);
|
||||||
}
|
}
|
||||||
fn visit_output(&mut self, node: &Rc<OutputNode>) {
|
fn visit_output(&mut self, node: &Rc<OutputNode>) {
|
||||||
|
|
|
||||||
88
src/text.rs
88
src/text.rs
|
|
@ -11,8 +11,13 @@ use {
|
||||||
},
|
},
|
||||||
rect::Rect,
|
rect::Rect,
|
||||||
theme::Color,
|
theme::Color,
|
||||||
|
utils::clonecell::UnsafeCellCloneSafe,
|
||||||
|
},
|
||||||
|
std::{
|
||||||
|
borrow::Cow,
|
||||||
|
ops::{Deref, Neg},
|
||||||
|
rc::Rc,
|
||||||
},
|
},
|
||||||
std::{ops::Neg, rc::Rc},
|
|
||||||
thiserror::Error,
|
thiserror::Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -32,6 +37,47 @@ pub enum TextError {
|
||||||
ImageData(#[source] PangoError),
|
ImageData(#[source] PangoError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
struct Config<'a> {
|
||||||
|
x: i32,
|
||||||
|
y: Option<i32>,
|
||||||
|
width: i32,
|
||||||
|
height: i32,
|
||||||
|
padding: i32,
|
||||||
|
font: Cow<'a, str>,
|
||||||
|
text: Cow<'a, str>,
|
||||||
|
color: Color,
|
||||||
|
ellipsize: bool,
|
||||||
|
markup: bool,
|
||||||
|
scale: Option<f64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Config<'a> {
|
||||||
|
fn to_static(self) -> Config<'static> {
|
||||||
|
Config {
|
||||||
|
x: self.x,
|
||||||
|
y: self.y,
|
||||||
|
width: self.width,
|
||||||
|
height: self.height,
|
||||||
|
padding: self.padding,
|
||||||
|
font: Cow::Owned(self.font.into_owned()),
|
||||||
|
text: Cow::Owned(self.text.into_owned()),
|
||||||
|
color: self.color,
|
||||||
|
ellipsize: self.ellipsize,
|
||||||
|
markup: self.markup,
|
||||||
|
scale: self.scale,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct TextTexture {
|
||||||
|
config: Rc<Config<'static>>,
|
||||||
|
pub texture: Rc<dyn GfxTexture>,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl UnsafeCellCloneSafe for TextTexture {}
|
||||||
|
|
||||||
struct Data {
|
struct Data {
|
||||||
image: Rc<CairoImageSurface>,
|
image: Rc<CairoImageSurface>,
|
||||||
cctx: Rc<CairoContext>,
|
cctx: Rc<CairoContext>,
|
||||||
|
|
@ -95,20 +141,22 @@ pub fn measure(
|
||||||
|
|
||||||
pub fn render(
|
pub fn render(
|
||||||
ctx: &Rc<dyn GfxContext>,
|
ctx: &Rc<dyn GfxContext>,
|
||||||
|
old: Option<TextTexture>,
|
||||||
width: i32,
|
width: i32,
|
||||||
height: i32,
|
height: i32,
|
||||||
font: &str,
|
font: &str,
|
||||||
text: &str,
|
text: &str,
|
||||||
color: Color,
|
color: Color,
|
||||||
scale: Option<f64>,
|
scale: Option<f64>,
|
||||||
) -> Result<Rc<dyn GfxTexture>, TextError> {
|
) -> Result<TextTexture, TextError> {
|
||||||
render2(
|
render2(
|
||||||
ctx, 1, None, width, height, 1, font, text, color, true, false, scale,
|
ctx, old, 1, None, width, height, 1, font, text, color, true, false, scale,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render2(
|
fn render2(
|
||||||
ctx: &Rc<dyn GfxContext>,
|
ctx: &Rc<dyn GfxContext>,
|
||||||
|
old: Option<TextTexture>,
|
||||||
x: i32,
|
x: i32,
|
||||||
y: Option<i32>,
|
y: Option<i32>,
|
||||||
width: i32,
|
width: i32,
|
||||||
|
|
@ -120,7 +168,25 @@ fn render2(
|
||||||
ellipsize: bool,
|
ellipsize: bool,
|
||||||
markup: bool,
|
markup: bool,
|
||||||
scale: Option<f64>,
|
scale: Option<f64>,
|
||||||
) -> Result<Rc<dyn GfxTexture>, TextError> {
|
) -> Result<TextTexture, TextError> {
|
||||||
|
let config = Config {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
padding,
|
||||||
|
font: Cow::Borrowed(font),
|
||||||
|
text: Cow::Borrowed(text),
|
||||||
|
color,
|
||||||
|
ellipsize,
|
||||||
|
markup,
|
||||||
|
scale,
|
||||||
|
};
|
||||||
|
if let Some(old2) = &old {
|
||||||
|
if old2.config.deref() == &config {
|
||||||
|
return Ok(old.unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
let data = create_data(font, width, height, scale)?;
|
let data = create_data(font, width, height, scale)?;
|
||||||
if ellipsize {
|
if ellipsize {
|
||||||
data.layout
|
data.layout
|
||||||
|
|
@ -148,21 +214,25 @@ fn render2(
|
||||||
.clone()
|
.clone()
|
||||||
.shmem_texture(bytes, ARGB8888, width, height, data.image.stride())
|
.shmem_texture(bytes, ARGB8888, width, height, data.image.stride())
|
||||||
{
|
{
|
||||||
Ok(t) => Ok(t),
|
Ok(t) => Ok(TextTexture {
|
||||||
|
config: Rc::new(config.to_static()),
|
||||||
|
texture: t,
|
||||||
|
}),
|
||||||
Err(e) => Err(TextError::RenderError(e)),
|
Err(e) => Err(TextError::RenderError(e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_fitting(
|
pub fn render_fitting(
|
||||||
ctx: &Rc<dyn GfxContext>,
|
ctx: &Rc<dyn GfxContext>,
|
||||||
|
old: Option<TextTexture>,
|
||||||
height: Option<i32>,
|
height: Option<i32>,
|
||||||
font: &str,
|
font: &str,
|
||||||
text: &str,
|
text: &str,
|
||||||
color: Color,
|
color: Color,
|
||||||
markup: bool,
|
markup: bool,
|
||||||
scale: Option<f64>,
|
scale: Option<f64>,
|
||||||
) -> Result<Rc<dyn GfxTexture>, TextError> {
|
) -> Result<TextTexture, TextError> {
|
||||||
render_fitting2(ctx, height, font, text, color, markup, scale, false).map(|(a, _)| a)
|
render_fitting2(ctx, old, height, font, text, color, markup, scale, false).map(|(a, _)| a)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Default)]
|
#[derive(Debug, Copy, Clone, Default)]
|
||||||
|
|
@ -174,6 +244,7 @@ pub struct TextMeasurement {
|
||||||
|
|
||||||
pub fn render_fitting2(
|
pub fn render_fitting2(
|
||||||
ctx: &Rc<dyn GfxContext>,
|
ctx: &Rc<dyn GfxContext>,
|
||||||
|
old: Option<TextTexture>,
|
||||||
height: Option<i32>,
|
height: Option<i32>,
|
||||||
font: &str,
|
font: &str,
|
||||||
text: &str,
|
text: &str,
|
||||||
|
|
@ -181,7 +252,7 @@ pub fn render_fitting2(
|
||||||
markup: bool,
|
markup: bool,
|
||||||
scale: Option<f64>,
|
scale: Option<f64>,
|
||||||
include_measurements: bool,
|
include_measurements: bool,
|
||||||
) -> Result<(Rc<dyn GfxTexture>, TextMeasurement), TextError> {
|
) -> Result<(TextTexture, TextMeasurement), TextError> {
|
||||||
let measurement = measure(font, text, markup, scale, include_measurements)?;
|
let measurement = measure(font, text, markup, scale, include_measurements)?;
|
||||||
let y = match height {
|
let y = match height {
|
||||||
Some(_) => None,
|
Some(_) => None,
|
||||||
|
|
@ -189,6 +260,7 @@ pub fn render_fitting2(
|
||||||
};
|
};
|
||||||
let res = render2(
|
let res = render2(
|
||||||
ctx,
|
ctx,
|
||||||
|
old,
|
||||||
measurement.ink_rect.x1().neg(),
|
measurement.ink_rect.x1().neg(),
|
||||||
y,
|
y,
|
||||||
measurement.ink_rect.width(),
|
measurement.ink_rect.width(),
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ use {
|
||||||
backend::KeyState,
|
backend::KeyState,
|
||||||
cursor::KnownCursor,
|
cursor::KnownCursor,
|
||||||
fixed::Fixed,
|
fixed::Fixed,
|
||||||
gfx_api::GfxTexture,
|
|
||||||
ifs::wl_seat::{
|
ifs::wl_seat::{
|
||||||
collect_kb_foci, collect_kb_foci2, wl_pointer::PendingScroll, NodeSeatState, SeatId,
|
collect_kb_foci, collect_kb_foci2, wl_pointer::PendingScroll, NodeSeatState, SeatId,
|
||||||
WlSeatGlobal, BTN_LEFT,
|
WlSeatGlobal, BTN_LEFT,
|
||||||
|
|
@ -12,7 +11,7 @@ use {
|
||||||
renderer::Renderer,
|
renderer::Renderer,
|
||||||
scale::Scale,
|
scale::Scale,
|
||||||
state::State,
|
state::State,
|
||||||
text,
|
text::{self, TextTexture},
|
||||||
tree::{
|
tree::{
|
||||||
walker::NodeVisitor, ContainingNode, Direction, FindTreeResult, FoundNode, Node,
|
walker::NodeVisitor, ContainingNode, Direction, FindTreeResult, FoundNode, Node,
|
||||||
NodeId, ToplevelData, ToplevelNode, WorkspaceNode,
|
NodeId, ToplevelData, ToplevelNode, WorkspaceNode,
|
||||||
|
|
@ -24,7 +23,7 @@ use {
|
||||||
numcell::NumCell,
|
numcell::NumCell,
|
||||||
rc_eq::rc_eq,
|
rc_eq::rc_eq,
|
||||||
scroller::Scroller,
|
scroller::Scroller,
|
||||||
smallmap::SmallMapMut,
|
smallmap::{SmallMap, SmallMapMut},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ahash::AHashMap,
|
ahash::AHashMap,
|
||||||
|
|
@ -77,7 +76,7 @@ tree_id!(ContainerNodeId);
|
||||||
pub struct ContainerTitle {
|
pub struct ContainerTitle {
|
||||||
pub x: i32,
|
pub x: i32,
|
||||||
pub y: i32,
|
pub y: i32,
|
||||||
pub tex: Rc<dyn GfxTexture>,
|
pub tex: TextTexture,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -128,6 +127,7 @@ pub struct ContainerChild {
|
||||||
pub node: Rc<dyn ToplevelNode>,
|
pub node: Rc<dyn ToplevelNode>,
|
||||||
pub active: Cell<bool>,
|
pub active: Cell<bool>,
|
||||||
title: RefCell<String>,
|
title: RefCell<String>,
|
||||||
|
pub title_tex: SmallMap<Scale, TextTexture, 2>,
|
||||||
pub title_rect: Cell<Rect>,
|
pub title_rect: Cell<Rect>,
|
||||||
focus_history: Cell<Option<LinkedNode<NodeRef<ContainerChild>>>>,
|
focus_history: Cell<Option<LinkedNode<NodeRef<ContainerChild>>>>,
|
||||||
|
|
||||||
|
|
@ -182,6 +182,7 @@ impl ContainerNode {
|
||||||
content: Default::default(),
|
content: Default::default(),
|
||||||
factor: Cell::new(1.0),
|
factor: Cell::new(1.0),
|
||||||
title: Default::default(),
|
title: Default::default(),
|
||||||
|
title_tex: Default::default(),
|
||||||
title_rect: Default::default(),
|
title_rect: Default::default(),
|
||||||
focus_history: Default::default(),
|
focus_history: Default::default(),
|
||||||
}),
|
}),
|
||||||
|
|
@ -289,6 +290,7 @@ impl ContainerNode {
|
||||||
content: Default::default(),
|
content: Default::default(),
|
||||||
factor: Default::default(),
|
factor: Default::default(),
|
||||||
title: Default::default(),
|
title: Default::default(),
|
||||||
|
title_tex: Default::default(),
|
||||||
title_rect: Default::default(),
|
title_rect: Default::default(),
|
||||||
focus_history: Default::default(),
|
focus_history: Default::default(),
|
||||||
});
|
});
|
||||||
|
|
@ -678,6 +680,7 @@ impl ContainerNode {
|
||||||
}
|
}
|
||||||
let title = child.title.borrow_mut();
|
let title = child.title.borrow_mut();
|
||||||
for (scale, _) in scales.iter() {
|
for (scale, _) in scales.iter() {
|
||||||
|
let old_tex = child.title_tex.remove(scale);
|
||||||
let titles = rd.titles.get_or_default_mut(*scale);
|
let titles = rd.titles.get_or_default_mut(*scale);
|
||||||
'render_title: {
|
'render_title: {
|
||||||
let mut th = th;
|
let mut th = th;
|
||||||
|
|
@ -693,12 +696,24 @@ impl ContainerNode {
|
||||||
break 'render_title;
|
break 'render_title;
|
||||||
}
|
}
|
||||||
if let Some(ctx) = &ctx {
|
if let Some(ctx) = &ctx {
|
||||||
match text::render(ctx, width, th, &font, title.deref(), color, scalef) {
|
match text::render(
|
||||||
Ok(t) => titles.push(ContainerTitle {
|
ctx,
|
||||||
x: rect.x1(),
|
old_tex,
|
||||||
y: rect.y1(),
|
width,
|
||||||
tex: t,
|
th,
|
||||||
}),
|
&font,
|
||||||
|
title.deref(),
|
||||||
|
color,
|
||||||
|
scalef,
|
||||||
|
) {
|
||||||
|
Ok(t) => {
|
||||||
|
child.title_tex.insert(*scale, t.clone());
|
||||||
|
titles.push(ContainerTitle {
|
||||||
|
x: rect.x1(),
|
||||||
|
y: rect.y1(),
|
||||||
|
tex: t,
|
||||||
|
})
|
||||||
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("Could not render title {}: {}", title, ErrorFmt(e));
|
log::error!("Could not render title {}: {}", title, ErrorFmt(e));
|
||||||
}
|
}
|
||||||
|
|
@ -1268,6 +1283,7 @@ impl ContainingNode for ContainerNode {
|
||||||
content: Default::default(),
|
content: Default::default(),
|
||||||
factor: Cell::new(node.factor.get()),
|
factor: Cell::new(node.factor.get()),
|
||||||
title: Default::default(),
|
title: Default::default(),
|
||||||
|
title_tex: Default::default(),
|
||||||
title_rect: Cell::new(node.title_rect.get()),
|
title_rect: Cell::new(node.title_rect.get()),
|
||||||
focus_history: Cell::new(None),
|
focus_history: Cell::new(None),
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,12 @@ use {
|
||||||
backend::KeyState,
|
backend::KeyState,
|
||||||
cursor::KnownCursor,
|
cursor::KnownCursor,
|
||||||
fixed::Fixed,
|
fixed::Fixed,
|
||||||
gfx_api::GfxTexture,
|
|
||||||
ifs::wl_seat::{NodeSeatState, SeatId, WlSeatGlobal, BTN_LEFT},
|
ifs::wl_seat::{NodeSeatState, SeatId, WlSeatGlobal, BTN_LEFT},
|
||||||
rect::Rect,
|
rect::Rect,
|
||||||
renderer::Renderer,
|
renderer::Renderer,
|
||||||
scale::Scale,
|
scale::Scale,
|
||||||
state::State,
|
state::State,
|
||||||
text,
|
text::{self, TextTexture},
|
||||||
tree::{
|
tree::{
|
||||||
walker::NodeVisitor, ContainingNode, FindTreeResult, FoundNode, Node, NodeId,
|
walker::NodeVisitor, ContainingNode, FindTreeResult, FoundNode, Node, NodeId,
|
||||||
StackedNode, ToplevelNode, WorkspaceNode,
|
StackedNode, ToplevelNode, WorkspaceNode,
|
||||||
|
|
@ -44,7 +43,7 @@ pub struct FloatNode {
|
||||||
pub layout_scheduled: Cell<bool>,
|
pub layout_scheduled: Cell<bool>,
|
||||||
pub render_titles_scheduled: Cell<bool>,
|
pub render_titles_scheduled: Cell<bool>,
|
||||||
pub title: RefCell<String>,
|
pub title: RefCell<String>,
|
||||||
pub title_textures: CopyHashMap<Scale, Rc<dyn GfxTexture>>,
|
pub title_textures: CopyHashMap<Scale, TextTexture>,
|
||||||
seats: RefCell<AHashMap<SeatId, SeatState>>,
|
seats: RefCell<AHashMap<SeatId, SeatState>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -179,7 +178,6 @@ impl FloatNode {
|
||||||
let bw = theme.sizes.border_width.get();
|
let bw = theme.sizes.border_width.get();
|
||||||
let font = theme.font.borrow_mut();
|
let font = theme.font.borrow_mut();
|
||||||
let title = self.title.borrow_mut();
|
let title = self.title.borrow_mut();
|
||||||
self.title_textures.clear();
|
|
||||||
let pos = self.position.get();
|
let pos = self.position.get();
|
||||||
if pos.width() <= 2 * bw || title.is_empty() {
|
if pos.width() <= 2 * bw || title.is_empty() {
|
||||||
return;
|
return;
|
||||||
|
|
@ -190,6 +188,7 @@ impl FloatNode {
|
||||||
};
|
};
|
||||||
let scales = self.state.scales.lock();
|
let scales = self.state.scales.lock();
|
||||||
for (scale, _) in scales.iter() {
|
for (scale, _) in scales.iter() {
|
||||||
|
let old_tex = self.title_textures.remove(scale);
|
||||||
let mut th = th;
|
let mut th = th;
|
||||||
let mut scalef = None;
|
let mut scalef = None;
|
||||||
let mut width = pos.width() - 2 * bw;
|
let mut width = pos.width() - 2 * bw;
|
||||||
|
|
@ -202,7 +201,7 @@ impl FloatNode {
|
||||||
if th == 0 || width == 0 {
|
if th == 0 || width == 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let texture = match text::render(&ctx, width, th, &font, &title, tc, scalef) {
|
let texture = match text::render(&ctx, old_tex, width, th, &font, &title, tc, scalef) {
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("Could not render title {}: {}", title, ErrorFmt(e));
|
log::error!("Could not render title {}: {}", title, ErrorFmt(e));
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ use {
|
||||||
renderer::Renderer,
|
renderer::Renderer,
|
||||||
scale::Scale,
|
scale::Scale,
|
||||||
state::State,
|
state::State,
|
||||||
text,
|
text::{self, TextTexture},
|
||||||
tree::{
|
tree::{
|
||||||
walker::NodeVisitor, Direction, FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode,
|
walker::NodeVisitor, Direction, FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode,
|
||||||
},
|
},
|
||||||
|
|
@ -165,6 +165,7 @@ impl OutputNode {
|
||||||
let output_width = self.global.pos.get().width();
|
let output_width = self.global.pos.get().width();
|
||||||
rd.underline = Rect::new_sized(0, th, output_width, 1).unwrap();
|
rd.underline = Rect::new_sized(0, th, output_width, 1).unwrap();
|
||||||
for ws in self.workspaces.iter() {
|
for ws in self.workspaces.iter() {
|
||||||
|
let old_tex = ws.title_texture.take();
|
||||||
let mut title_width = th;
|
let mut title_width = th;
|
||||||
'create_texture: {
|
'create_texture: {
|
||||||
if let Some(ctx) = self.state.render_ctx.get() {
|
if let Some(ctx) = self.state.render_ctx.get() {
|
||||||
|
|
@ -177,6 +178,7 @@ impl OutputNode {
|
||||||
};
|
};
|
||||||
let title = match text::render_fitting(
|
let title = match text::render_fitting(
|
||||||
&ctx,
|
&ctx,
|
||||||
|
old_tex,
|
||||||
Some(texture_height),
|
Some(texture_height),
|
||||||
&font,
|
&font,
|
||||||
&ws.name,
|
&ws.name,
|
||||||
|
|
@ -190,8 +192,9 @@ impl OutputNode {
|
||||||
break 'create_texture;
|
break 'create_texture;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
ws.title_texture.set(Some(title.clone()));
|
||||||
let mut x = pos + 1;
|
let mut x = pos + 1;
|
||||||
let mut width = title.width();
|
let mut width = title.texture.width();
|
||||||
if let Some(scale) = scale {
|
if let Some(scale) = scale {
|
||||||
width = (width as f64 / scale).round() as _;
|
width = (width as f64 / scale).round() as _;
|
||||||
}
|
}
|
||||||
|
|
@ -205,7 +208,7 @@ impl OutputNode {
|
||||||
x2: pos + title_width,
|
x2: pos + title_width,
|
||||||
tex_x: x,
|
tex_x: x,
|
||||||
tex_y: 0,
|
tex_y: 0,
|
||||||
tex: title,
|
tex: title.texture,
|
||||||
ws: ws.deref().clone(),
|
ws: ws.deref().clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -224,6 +227,7 @@ impl OutputNode {
|
||||||
pos += title_width;
|
pos += title_width;
|
||||||
}
|
}
|
||||||
'set_status: {
|
'set_status: {
|
||||||
|
let old_tex = rd.status.take().map(|s| s.tex);
|
||||||
let ctx = match self.state.render_ctx.get() {
|
let ctx = match self.state.render_ctx.get() {
|
||||||
Some(ctx) => ctx,
|
Some(ctx) => ctx,
|
||||||
_ => break 'set_status,
|
_ => break 'set_status,
|
||||||
|
|
@ -235,6 +239,7 @@ impl OutputNode {
|
||||||
let tc = self.state.theme.colors.bar_text.get();
|
let tc = self.state.theme.colors.bar_text.get();
|
||||||
let title = match text::render_fitting(
|
let title = match text::render_fitting(
|
||||||
&ctx,
|
&ctx,
|
||||||
|
old_tex,
|
||||||
Some(texture_height),
|
Some(texture_height),
|
||||||
&font,
|
&font,
|
||||||
&status,
|
&status,
|
||||||
|
|
@ -248,7 +253,7 @@ impl OutputNode {
|
||||||
break 'set_status;
|
break 'set_status;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut width = title.width();
|
let mut width = title.texture.width();
|
||||||
if let Some(scale) = scale {
|
if let Some(scale) = scale {
|
||||||
width = (width as f64 / scale).round() as _;
|
width = (width as f64 / scale).round() as _;
|
||||||
}
|
}
|
||||||
|
|
@ -324,6 +329,7 @@ impl OutputNode {
|
||||||
desired_output: CloneCell::new(self.global.output_id.clone()),
|
desired_output: CloneCell::new(self.global.output_id.clone()),
|
||||||
jay_workspaces: Default::default(),
|
jay_workspaces: Default::default(),
|
||||||
capture: self.state.default_workspace_capture.clone(),
|
capture: self.state.default_workspace_capture.clone(),
|
||||||
|
title_texture: Default::default(),
|
||||||
});
|
});
|
||||||
ws.output_link
|
ws.output_link
|
||||||
.set(Some(self.workspaces.add_last(ws.clone())));
|
.set(Some(self.workspaces.add_last(ws.clone())));
|
||||||
|
|
@ -473,7 +479,7 @@ pub struct OutputTitle {
|
||||||
pub struct OutputStatus {
|
pub struct OutputStatus {
|
||||||
pub tex_x: i32,
|
pub tex_x: i32,
|
||||||
pub tex_y: i32,
|
pub tex_y: i32,
|
||||||
pub tex: Rc<dyn GfxTexture>,
|
pub tex: TextTexture,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,12 @@ use {
|
||||||
client::Client,
|
client::Client,
|
||||||
cursor::KnownCursor,
|
cursor::KnownCursor,
|
||||||
fixed::Fixed,
|
fixed::Fixed,
|
||||||
gfx_api::GfxTexture,
|
|
||||||
ifs::wl_seat::{NodeSeatState, WlSeatGlobal},
|
ifs::wl_seat::{NodeSeatState, WlSeatGlobal},
|
||||||
rect::Rect,
|
rect::Rect,
|
||||||
renderer::Renderer,
|
renderer::Renderer,
|
||||||
scale::Scale,
|
scale::Scale,
|
||||||
state::State,
|
state::State,
|
||||||
text,
|
text::{self, TextTexture},
|
||||||
tree::{
|
tree::{
|
||||||
Direction, FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, ToplevelData,
|
Direction, FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, ToplevelData,
|
||||||
ToplevelNode,
|
ToplevelNode,
|
||||||
|
|
@ -25,7 +24,7 @@ pub struct PlaceholderNode {
|
||||||
id: PlaceholderNodeId,
|
id: PlaceholderNodeId,
|
||||||
toplevel: ToplevelData,
|
toplevel: ToplevelData,
|
||||||
destroyed: Cell<bool>,
|
destroyed: Cell<bool>,
|
||||||
pub textures: SmallMap<Scale, Rc<dyn GfxTexture>, 2>,
|
pub textures: SmallMap<Scale, TextTexture, 2>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PlaceholderNode {
|
impl PlaceholderNode {
|
||||||
|
|
@ -47,11 +46,11 @@ impl PlaceholderNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_texture(&self) {
|
pub fn update_texture(&self) {
|
||||||
self.textures.clear();
|
|
||||||
if let Some(ctx) = self.toplevel.state.render_ctx.get() {
|
if let Some(ctx) = self.toplevel.state.render_ctx.get() {
|
||||||
let scales = self.toplevel.state.scales.lock();
|
let scales = self.toplevel.state.scales.lock();
|
||||||
let rect = self.toplevel.pos.get();
|
let rect = self.toplevel.pos.get();
|
||||||
for (scale, _) in scales.iter() {
|
for (scale, _) in scales.iter() {
|
||||||
|
let old_tex = self.textures.remove(scale);
|
||||||
let mut width = rect.width();
|
let mut width = rect.width();
|
||||||
let mut height = rect.height();
|
let mut height = rect.height();
|
||||||
if *scale != 1 {
|
if *scale != 1 {
|
||||||
|
|
@ -63,6 +62,7 @@ impl PlaceholderNode {
|
||||||
let font = format!("monospace {}", width / 10);
|
let font = format!("monospace {}", width / 10);
|
||||||
match text::render_fitting(
|
match text::render_fitting(
|
||||||
&ctx,
|
&ctx,
|
||||||
|
old_tex,
|
||||||
Some(height),
|
Some(height),
|
||||||
&font,
|
&font,
|
||||||
"Fullscreen",
|
"Fullscreen",
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ use {
|
||||||
},
|
},
|
||||||
rect::Rect,
|
rect::Rect,
|
||||||
renderer::Renderer,
|
renderer::Renderer,
|
||||||
|
text::TextTexture,
|
||||||
tree::{
|
tree::{
|
||||||
container::ContainerNode, walker::NodeVisitor, ContainingNode, Direction,
|
container::ContainerNode, walker::NodeVisitor, ContainingNode, Direction,
|
||||||
FindTreeResult, FoundNode, Node, NodeId, NodeVisitorBase, OutputNode, StackedNode,
|
FindTreeResult, FoundNode, Node, NodeId, NodeVisitorBase, OutputNode, StackedNode,
|
||||||
|
|
@ -43,6 +44,7 @@ pub struct WorkspaceNode {
|
||||||
pub desired_output: CloneCell<Rc<OutputId>>,
|
pub desired_output: CloneCell<Rc<OutputId>>,
|
||||||
pub jay_workspaces: CopyHashMap<(ClientId, JayWorkspaceId), Rc<JayWorkspace>>,
|
pub jay_workspaces: CopyHashMap<(ClientId, JayWorkspaceId), Rc<JayWorkspace>>,
|
||||||
pub capture: Cell<bool>,
|
pub capture: Cell<bool>,
|
||||||
|
pub title_texture: Cell<Option<TextTexture>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WorkspaceNode {
|
impl WorkspaceNode {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue