Skip to content

Commit

Permalink
Add ability to hide titlebar, and draw only the frame
Browse files Browse the repository at this point in the history
  • Loading branch information
PolyMeilex committed Jan 9, 2025
1 parent c7a13f9 commit 2cbc306
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 33 deletions.
62 changes: 47 additions & 15 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ pub struct AdwaitaFrame<State> {
title: Option<String>,
title_text: Option<TitleText>,
shadow: Shadow,

/// Draw decorations but without the titlebar
hide_titlebar: bool,
}

impl<State> AdwaitaFrame<State>
Expand All @@ -111,6 +114,7 @@ where
&base_surface,
&subcompositor,
&queue_handle,
frame_config.hide_titlebar,
));

let theme = frame_config.theme;
Expand All @@ -134,6 +138,7 @@ where
wm_capabilities: WindowManagerCapabilities::all(),
resizable: true,
shadow: Shadow::default(),
hide_titlebar: frame_config.hide_titlebar,
})
}

Expand Down Expand Up @@ -210,6 +215,12 @@ where
if self.state.contains(WindowState::FULLSCREEN) {
decorations.hide();
return Some(true);
} else {
decorations.show();
}

if self.hide_titlebar {
decorations.hide_titlebar();
}

let colors = if self.state.contains(WindowState::ACTIVATED) {
Expand All @@ -228,10 +239,7 @@ where
let border_paint = colors.border_paint();

// Draw the borders.
for (idx, part) in decorations
.parts()
.filter(|(idx, _)| *idx == DecorationParts::HEADER || draw_borders)
{
for (idx, part) in decorations.parts().filter(|(_, part)| !part.hide) {
let scale = self.scale_factor;

let mut rect = part.surface_rect;
Expand Down Expand Up @@ -329,6 +337,21 @@ where
visible_border_size as f32,
)
}
// Unless titlebar is disabled
DecorationParts::TOP if self.hide_titlebar => {
let x = rect.x.unsigned_abs() * scale;
let x = x.saturating_sub(visible_border_size);

let y = rect.y.unsigned_abs() * scale;
let y = y.saturating_sub(visible_border_size);

Rect::from_xywh(
x as f32,
y as f32,
(rect.width - 2 * x) as f32,
visible_border_size as f32,
)
}
_ => None,
};

Expand Down Expand Up @@ -407,6 +430,7 @@ where
&self.base_surface,
&self.subcompositor,
&self.queue_handle,
self.hide_titlebar,
));
self.dirty = true;
self.should_sync = true;
Expand Down Expand Up @@ -440,7 +464,10 @@ where
width: NonZeroU32,
height: NonZeroU32,
) -> (Option<NonZeroU32>, Option<NonZeroU32>) {
if self.decorations.is_none() || self.state.contains(WindowState::FULLSCREEN) {
if self.decorations.is_none()
|| self.state.contains(WindowState::FULLSCREEN)
|| self.hide_titlebar
{
(Some(width), Some(height))
} else {
(
Expand Down Expand Up @@ -545,39 +572,44 @@ where
#[derive(Debug, Clone)]
pub struct FrameConfig {
pub theme: ColorTheme,
/// Draw decorations but without the titlebar
pub hide_titlebar: bool,
}

impl FrameConfig {
/// Create the new configuration with the given `theme`.
pub fn new(theme: ColorTheme) -> Self {
Self { theme }
Self {
theme,
hide_titlebar: false,
}
}

/// This is equivalent of calling `FrameConfig::new(ColorTheme::auto())`.
///
/// For details see [`ColorTheme::auto`].
pub fn auto() -> Self {
Self {
theme: ColorTheme::auto(),
}
Self::new(ColorTheme::auto())
}

/// This is equivalent of calling `FrameConfig::new(ColorTheme::light())`.
///
/// For details see [`ColorTheme::light`].
pub fn light() -> Self {
Self {
theme: ColorTheme::light(),
}
Self::new(ColorTheme::light())
}

/// This is equivalent of calling `FrameConfig::new(ColorTheme::dark())`.
///
/// For details see [`ColorTheme::dark`].
pub fn dark() -> Self {
Self {
theme: ColorTheme::dark(),
}
Self::new(ColorTheme::dark())
}

/// Draw decorations but without the titlebar
pub fn hide_titlebar(mut self, hide: bool) -> Self {
self.hide_titlebar = hide;
self
}
}

Expand Down
77 changes: 59 additions & 18 deletions src/parts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::{pointer::Location, wl_typed::WlTyped};
#[derive(Debug)]
pub struct DecorationParts {
parts: [Part; 5],
hide_titlebar: bool,
}

impl DecorationParts {
Expand All @@ -32,10 +33,13 @@ impl DecorationParts {
base_surface: &WlTyped<WlSurface, SurfaceData>,
subcompositor: &SubcompositorState,
queue_handle: &QueueHandle<State>,
hide_titlebar: bool,
) -> Self
where
State: Dispatch<WlSurface, SurfaceData> + Dispatch<WlSubsurface, SubsurfaceData> + 'static,
{
let header_offset = if hide_titlebar { 0 } else { HEADER_SIZE };

// XXX the order must be in sync with associated constants.
let parts = [
// Top.
Expand All @@ -45,7 +49,7 @@ impl DecorationParts {
queue_handle,
Rect {
x: -(BORDER_SIZE as i32),
y: -(HEADER_SIZE as i32 + BORDER_SIZE as i32),
y: -(header_offset as i32 + BORDER_SIZE as i32),
width: 0, // Defined by `Self::resize`.
height: BORDER_SIZE,
},
Expand All @@ -63,7 +67,7 @@ impl DecorationParts {
queue_handle,
Rect {
x: -(BORDER_SIZE as i32),
y: -(HEADER_SIZE as i32),
y: -(header_offset as i32),
width: BORDER_SIZE,
height: 0, // Defined by `Self::resize`.
},
Expand All @@ -81,7 +85,7 @@ impl DecorationParts {
queue_handle,
Rect {
x: 0, // Defined by `Self::resize`.
y: -(HEADER_SIZE as i32),
y: -(header_offset as i32),
width: BORDER_SIZE,
height: 0, // Defined by `Self::resize`.
},
Expand Down Expand Up @@ -125,32 +129,72 @@ impl DecorationParts {
),
];

Self { parts }
Self {
parts,
hide_titlebar,
}
}

pub fn parts(&self) -> std::iter::Enumerate<std::slice::Iter<Part>> {
self.parts.iter().enumerate()
}

pub fn hide(&self) {
for part in self.parts.iter() {
pub fn parts_mut(&mut self) -> std::iter::Enumerate<std::slice::IterMut<Part>> {
self.parts.iter_mut().enumerate()
}

pub fn borders_mut(&mut self) -> impl Iterator<Item = &mut Part> {
self.parts_mut()
.filter(|(idx, _)| *idx != Self::HEADER)
.map(|(_, p)| p)
}

pub fn header(&self) -> &Part {
&self.parts[Self::HEADER]
}

pub fn header_mut(&mut self) -> &mut Part {
&mut self.parts[Self::HEADER]
}

pub fn hide(&mut self) {
for part in self.parts.iter_mut() {
part.hide = true;
part.subsurface.set_sync();
part.surface.attach(None, 0, 0);
part.surface.commit();
}
}

pub fn hide_borders(&self) {
for (_, part) in self.parts().filter(|(idx, _)| *idx != Self::HEADER) {
pub fn show(&mut self) {
for part in self.parts.iter_mut() {
part.hide = false;
}
}

pub fn hide_borders(&mut self) {
for part in self.borders_mut() {
part.hide = true;
part.surface.attach(None, 0, 0);
part.surface.commit();
}
}

pub fn hide_titlebar(&mut self) {
let part = self.header_mut();
part.hide = true;
part.surface.attach(None, 0, 0);
part.surface.commit();
}

// These unwraps are guaranteed to succeed because the affected options are filled above
// and then never emptied afterwards.
#[allow(clippy::unwrap_used)]
pub fn resize(&mut self, width: u32, height: u32) {
let header_size = if self.hide_titlebar { 0 } else { HEADER_SIZE };

let height_with_header = height + header_size;

self.parts[Self::HEADER].surface_rect.width = width;

self.parts[Self::BOTTOM].surface_rect.width = width + 2 * BORDER_SIZE;
Expand All @@ -163,18 +207,12 @@ impl DecorationParts {
self.parts[Self::TOP].input_rect.as_mut().unwrap().width =
self.parts[Self::TOP].surface_rect.width - (BORDER_SIZE * 2) + (RESIZE_HANDLE_SIZE * 2);

self.parts[Self::LEFT].surface_rect.height = height + HEADER_SIZE;
self.parts[Self::LEFT].input_rect.as_mut().unwrap().height =
self.parts[Self::LEFT].surface_rect.height;
self.parts[Self::LEFT].surface_rect.height = height_with_header;
self.parts[Self::LEFT].input_rect.as_mut().unwrap().height = height_with_header;

self.parts[Self::RIGHT].surface_rect.height = self.parts[Self::LEFT].surface_rect.height;
self.parts[Self::RIGHT].surface_rect.height = height_with_header;
self.parts[Self::RIGHT].surface_rect.x = width as i32;
self.parts[Self::RIGHT].input_rect.as_mut().unwrap().height =
self.parts[Self::RIGHT].surface_rect.height;
}

pub fn header(&self) -> &Part {
&self.parts[Self::HEADER]
self.parts[Self::RIGHT].input_rect.as_mut().unwrap().height = height_with_header;
}

pub fn side_height(&self) -> u32 {
Expand Down Expand Up @@ -221,6 +259,8 @@ pub struct Part {
///
/// `None` if it fully covers `surface_rect`.
pub input_rect: Option<Rect>,

pub hide: bool,
}

impl Part {
Expand Down Expand Up @@ -248,6 +288,7 @@ impl Part {
subsurface,
surface_rect,
input_rect,
hide: false,
}
}
}
Expand Down

0 comments on commit 2cbc306

Please sign in to comment.