Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Misc: make PRIMARY default backend, fix transparency, public kas::decorations module #452

Merged
merged 6 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/kas-core/src/app/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ pub trait AppGraphicsBuilder {
fn new_surface<'window, W>(
shared: &mut Self::Shared,
window: W,
transparent: bool,
) -> Result<Self::Surface<'window>>
where
W: rwh::HasWindowHandle + rwh::HasDisplayHandle + Send + Sync + 'window,
Expand Down
6 changes: 5 additions & 1 deletion crates/kas-core/src/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,11 @@ mod test {
todo!()
}

fn new_surface<'window, W>(_: &mut Self::Shared, _: W) -> Result<Self::Surface<'window>>
fn new_surface<'window, W>(
_: &mut Self::Shared,
_: W,
_: bool,
) -> Result<Self::Surface<'window>>
where
W: rwh::HasWindowHandle + rwh::HasDisplayHandle + Send + Sync + 'window,
Self: Sized,
Expand Down
9 changes: 7 additions & 2 deletions crates/kas-core/src/app/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use super::shared::{AppSharedState, AppState};
use super::{AppData, AppGraphicsBuilder};
use crate::cast::{Cast, Conv};
use crate::config::WindowConfig;
use crate::decorations::Decorations;
use crate::draw::{color::Rgba, AnimationState, DrawSharedImpl};
use crate::event::{ConfigCx, CursorIcon, EventState};
use crate::geom::{Coord, Rect, Size};
Expand Down Expand Up @@ -109,7 +110,7 @@ impl<A: AppData, G: AppGraphicsBuilder, T: Theme<G::Shared>> Window<A, G, T> {
attrs.title = self.widget.title().to_string();
attrs.visible = false;
attrs.transparent = self.widget.transparent();
attrs.decorations = self.widget.decorations() == kas::Decorations::Server;
attrs.decorations = self.widget.decorations() == Decorations::Server;
attrs.window_icon = self.widget.icon();
let (restrict_min, restrict_max) = self.widget.restrictions();
if restrict_min {
Expand Down Expand Up @@ -173,7 +174,11 @@ impl<A: AppData, G: AppGraphicsBuilder, T: Theme<G::Shared>> Window<A, G, T> {

// NOTE: usage of Arc is inelegant, but avoids lots of unsafe code
let window = Arc::new(window);
let mut surface = G::new_surface(&mut state.shared.draw.draw, window.clone())?;
let mut surface = G::new_surface(
&mut state.shared.draw.draw,
window.clone(),
self.widget.transparent(),
)?;
surface.do_resize(&mut state.shared.draw.draw, size);

let winit_id = window.id();
Expand Down
84 changes: 58 additions & 26 deletions crates/kas-core/src/decorations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// You may obtain a copy of the License in the LICENSE-APACHE file or at:
// https://www.apache.org/licenses/LICENSE-2.0

//! Title bar
//! Window title-bar and border decorations
//!
//! Note: due to definition in kas-core, some widgets must be duplicated.

Expand Down Expand Up @@ -104,7 +104,7 @@ impl_scope! {
#[widget {
Data = ();
}]
pub struct Label {
pub(crate) struct Label {
core: widget_core!(),
text: Text<String>,
}
Expand Down Expand Up @@ -166,7 +166,7 @@ impl_scope! {
#[widget {
hover_highlight = true;
}]
pub struct MarkButton<M: Clone + Debug + 'static> {
pub(crate) struct MarkButton<M: Clone + Debug + 'static> {
core: widget_core!(),
style: MarkStyle,
msg: M,
Expand Down Expand Up @@ -215,21 +215,72 @@ enum TitleBarButton {
}

impl_scope! {
/// A window's title bar (part of decoration)
/// A set of title-bar buttons
///
/// Currently, this consists of minimise, maximise and close buttons.
#[derive(Clone, Default)]
#[widget{
layout = row! [
// self.icon,
self.title,
MarkButton::new(MarkStyle::Point(Direction::Down), TitleBarButton::Minimize),
MarkButton::new(MarkStyle::Point(Direction::Up), TitleBarButton::Maximize),
MarkButton::new(MarkStyle::X, TitleBarButton::Close),
];
}]
pub struct TitleBarButtons {
core: widget_core!(),
}

impl Self {
/// Construct
#[inline]
pub fn new() -> Self {
TitleBarButtons {
core: Default::default(),
}
}
}

impl Events for Self {
type Data = ();

fn handle_messages(&mut self, cx: &mut EventCx, _: &Self::Data) {
if let Some(msg) = cx.try_pop() {
match msg {
TitleBarButton::Minimize => {
#[cfg(winit)]
if let Some(w) = cx.winit_window() {
w.set_minimized(true);
}
}
TitleBarButton::Maximize => {
#[cfg(winit)]
if let Some(w) = cx.winit_window() {
w.set_maximized(!w.is_maximized());
}
}
TitleBarButton::Close => cx.action(self, Action::CLOSE),
}
}
}
}
}

impl_scope! {
/// A window's title bar (part of decoration)
#[derive(Clone, Default)]
#[widget{
layout = row! [
// self.icon,
self.title,
self.buttons,
];
}]
pub struct TitleBar {
core: widget_core!(),
#[widget]
title: Label,
#[widget]
buttons: TitleBarButtons,
}

impl Self {
Expand All @@ -239,6 +290,7 @@ impl_scope! {
TitleBar {
core: Default::default(),
title: Label::new(title),
buttons: Default::default(),
}
}

Expand All @@ -265,25 +317,5 @@ impl_scope! {
_ => Unused,
}
}

fn handle_messages(&mut self, cx: &mut EventCx, _: &Self::Data) {
if let Some(msg) = cx.try_pop() {
match msg {
TitleBarButton::Minimize => {
#[cfg(winit)]
if let Some(w) = cx.winit_window() {
w.set_minimized(true);
}
}
TitleBarButton::Maximize => {
#[cfg(winit)]
if let Some(w) = cx.winit_window() {
w.set_maximized(!w.is_maximized());
}
}
TitleBarButton::Close => cx.action(self, Action::CLOSE),
}
}
}
}
}
96 changes: 48 additions & 48 deletions crates/kas-core/src/draw/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,53 @@ impl Rgba8Srgb {
)
}
}

/// Compile-time parser for sRGB and sRGBA colours
pub const fn try_parse_srgb(s: &[u8]) -> Result<Rgba8Srgb, ParseError> {
if s.len() != 6 && s.len() != 8 {
return Err(ParseError::Length);
}

// `val` is copied from the hex crate:
// Copyright (c) 2013-2014 The Rust Project Developers.
// Copyright (c) 2015-2020 The rust-hex Developers.
const fn val(c: u8) -> Result<u8, ()> {
match c {
b'A'..=b'F' => Ok(c - b'A' + 10),
b'a'..=b'f' => Ok(c - b'a' + 10),
b'0'..=b'9' => Ok(c - b'0'),
_ => Err(()),
}
}

const fn byte(a: u8, b: u8) -> Result<u8, ()> {
match (val(a), val(b)) {
(Ok(hi), Ok(lo)) => Ok(hi << 4 | lo),
_ => Err(()),
}
}

let r = byte(s[0], s[1]);
let g = byte(s[2], s[3]);
let b = byte(s[4], s[5]);
let a = if s.len() == 8 { byte(s[6], s[7]) } else { Ok(0xFF) };

match (r, g, b, a) {
(Ok(r), Ok(g), Ok(b), Ok(a)) => Ok(Rgba8Srgb([r, g, b, a])),
_ => Err(ParseError::InvalidHex),
}
}

/// Compile-time parser for sRGB and sRGBA colours
///
/// This method has worse diagnostics on error due to limited const-
pub const fn parse_srgb(s: &[u8]) -> Rgba8Srgb {
match Self::try_parse_srgb(s) {
Ok(result) => result,
Err(ParseError::Length) => panic!("invalid length (expected 6 or 8 bytes"),
Err(ParseError::InvalidHex) => panic!("invalid hex byte (expected 0-9, a-f or A-F)"),
}
}
}

impl From<Rgba8Srgb> for [u8; 4] {
Expand Down Expand Up @@ -303,54 +350,7 @@ impl std::str::FromStr for Rgba8Srgb {
if s[0] == b'#' {
s = &s[1..];
}
try_parse_srgb(&s)
}
}

/// Compile-time parser for sRGB and sRGBA colours
pub const fn try_parse_srgb(s: &[u8]) -> Result<Rgba8Srgb, ParseError> {
if s.len() != 6 && s.len() != 8 {
return Err(ParseError::Length);
}

// `val` is copied from the hex crate:
// Copyright (c) 2013-2014 The Rust Project Developers.
// Copyright (c) 2015-2020 The rust-hex Developers.
const fn val(c: u8) -> Result<u8, ()> {
match c {
b'A'..=b'F' => Ok(c - b'A' + 10),
b'a'..=b'f' => Ok(c - b'a' + 10),
b'0'..=b'9' => Ok(c - b'0'),
_ => Err(()),
}
}

const fn byte(a: u8, b: u8) -> Result<u8, ()> {
match (val(a), val(b)) {
(Ok(hi), Ok(lo)) => Ok(hi << 4 | lo),
_ => Err(()),
}
}

let r = byte(s[0], s[1]);
let g = byte(s[2], s[3]);
let b = byte(s[4], s[5]);
let a = if s.len() == 8 { byte(s[6], s[7]) } else { Ok(0xFF) };

match (r, g, b, a) {
(Ok(r), Ok(g), Ok(b), Ok(a)) => Ok(Rgba8Srgb([r, g, b, a])),
_ => Err(ParseError::InvalidHex),
}
}

/// Compile-time parser for sRGB and sRGBA colours
///
/// This method has worse diagnostics on error due to limited const-
pub const fn parse_srgb(s: &[u8]) -> Rgba8Srgb {
match try_parse_srgb(s) {
Ok(result) => result,
Err(ParseError::Length) => panic!("invalid length (expected 6 or 8 bytes"),
Err(ParseError::InvalidHex) => panic!("invalid hex byte (expected 0-9, a-f or A-F)"),
Rgba8Srgb::try_parse_srgb(&s)
}
}

Expand Down
3 changes: 1 addition & 2 deletions crates/kas-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,12 @@ extern crate self as kas;
// internal modules:
mod action;
mod core;
mod decorations;
pub mod decorations;
mod popup;
mod root;

pub use crate::core::*;
pub use action::Action;
pub use decorations::Decorations;
pub use kas_macros::{autoimpl, extends, impl_default, widget};
pub use kas_macros::{cell_collection, collection, impl_anon, impl_scope, widget_index};
#[doc(inline)] pub use popup::Popup;
Expand Down
2 changes: 1 addition & 1 deletion crates/kas-core/src/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ impl<Data: 'static> Window<Data> {
}

/// Get the preference for window decorations
pub fn decorations(&self) -> crate::Decorations {
pub fn decorations(&self) -> Decorations {
self.decorations
}

Expand Down
Loading