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

Transparent windows, optional decorations #380

Merged
merged 25 commits into from
Feb 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
74ee219
EventMgr::handle_winit: pass &mut RootWidget
dhardy Jan 27, 2023
22e4dc4
Add Window::drag_anywhere
dhardy Jan 27, 2023
310c883
Fix: remove Deref impl on RootWidget
dhardy Jan 27, 2023
64a1b2f
Revise ThemeControl API
dhardy Jan 27, 2023
01d08bf
Add Window::transparent; make examples/clock transparent
dhardy Jan 27, 2023
183acac
Tweak examples/clock.rs for appearance
dhardy Jan 27, 2023
6cf3dc1
Add Window::decorations; support Decorations::None
dhardy Jan 27, 2023
bfda455
Doc: CustomPipe::render_final
dhardy Jan 31, 2023
56ea8c4
Add Decorations::Border, Theme
dhardy Feb 5, 2023
b3e523a
Automatically adjust clear_color when window is transparent
dhardy Feb 5, 2023
81ff153
MarkButton: highlight on hover
dhardy Feb 5, 2023
6698c37
Add a basic TitleBar
dhardy Feb 9, 2023
8d8fc8a
Move TitleBar to kas-core
dhardy Feb 9, 2023
b45b052
Add a title bar to RootWidget
dhardy Feb 9, 2023
1f7ce6f
Make min/maximize buttons functional
dhardy Feb 9, 2023
009ed36
Add kas_core::shell::PlatformWrapper as backend abstraction
dhardy Feb 9, 2023
791a5b9
Add Platform enumeration
dhardy Feb 9, 2023
87d923b
Add ConfigMgr::platform
dhardy Feb 9, 2023
0112f69
Automatically use toolkit decorations instead of server on Wayland
dhardy Feb 9, 2023
0f98595
Make x11, wayland optional; do not use winit/wayland-csd-adwaita
dhardy Feb 9, 2023
3909515
Fix: winit without Wayland
dhardy Feb 9, 2023
ff84aeb
Make Clippy happy
dhardy Feb 9, 2023
78678a9
Fix test without winit feature
dhardy Feb 9, 2023
7469930
More fixes
dhardy Feb 9, 2023
d50a0df
More CI fixes
dhardy Feb 10, 2023
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
10 changes: 5 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ jobs:
run: cargo test --manifest-path crates/kas-resvg/Cargo.toml --all-features
- name: Test kas-wgpu
run: |
cargo test --manifest-path crates/kas-wgpu/Cargo.toml --no-default-features --features raster
cargo test --manifest-path crates/kas-wgpu/Cargo.toml --all-features
cargo test --manifest-path crates/kas-wgpu/Cargo.toml --no-default-features --features raster,kas/x11
cargo test --manifest-path crates/kas-wgpu/Cargo.toml --all-features --features kas/x11
- name: Test kas-dylib
run: cargo test --manifest-path crates/kas-dylib/Cargo.toml --all-features
run: cargo test --manifest-path crates/kas-dylib/Cargo.toml --all-features --features kas-core/x11
- name: Test kas
run: cargo test --all-features
- name: Test examples/mandlebrot
Expand Down Expand Up @@ -89,9 +89,9 @@ jobs:
- name: Test kas-resvg
run: cargo test --manifest-path crates/kas-resvg/Cargo.toml --all-features
- name: Test kas-wgpu
run: cargo test --manifest-path crates/kas-wgpu/Cargo.toml
run: cargo test --manifest-path crates/kas-wgpu/Cargo.toml --features kas/x11
- name: Test kas-dylib
run: cargo test --manifest-path crates/kas-dylib/Cargo.toml
run: cargo test --manifest-path crates/kas-dylib/Cargo.toml --features kas-core/x11
- name: Test kas
run: cargo test
- name: Test examples/mandlebrot
Expand Down
8 changes: 7 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ rustdoc-args = ["--cfg", "doc_cfg"]
######### meta / build features #########

# All recommended features for optimal experience
default = ["minimal", "view", "yaml", "image", "resvg", "clipboard", "markdown", "shaping", "dark-light", "spawn"]
default = ["minimal", "view", "yaml", "image", "resvg", "clipboard", "markdown", "shaping", "dark-light", "spawn", "wayland", "x11"]

# Include only "required" features.
#
Expand Down Expand Up @@ -104,6 +104,12 @@ macros_log = ["kas-core/macros_log"]

winit = ["kas-core/winit"]

# Support Wayland
wayland = ["kas-core/wayland"]

# Support X11
x11 = ["kas-core/x11"]

[dependencies]
kas-core = { version = "0.12.1", path = "crates/kas-core" }
kas-dylib = { version = "0.12.0", path = "crates/kas-dylib", optional = true }
Expand Down
8 changes: 8 additions & 0 deletions crates/kas-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ macros_log = ["kas-macros/log"]
# Enable winit support
winit = ["dep:winit"]

# Support Wayland
wayland = ["winit?/wayland", "winit?/wayland-dlopen"]

# Support X11
x11 = ["winit?/x11"]

# Enable serde integration (mainly config read/write)
serde = ["dep:serde", "kas-text/serde", "winit?/serde"]

Expand All @@ -80,6 +86,7 @@ dark-light = { version = "0.2.2", optional = true }
raw-window-handle = "0.5.0"
window_clipboard = { version = "0.2.0", optional = true }
async-global-executor = { version = "2.3.1", optional = true }
cfg-if = "1.0.0"

[dependencies.kas-macros]
version = "0.12.0"
Expand All @@ -95,3 +102,4 @@ version = "0.5.0" # used in doc links
# Provides translations for several winit types
version = "0.27"
optional = true
default-features = false
69 changes: 67 additions & 2 deletions crates/kas-core/src/core/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,32 @@ impl WindowId {
}
}

/// Available decoration modes
///
/// See [`Window::decorations`].
#[derive(PartialEq, Eq, Hash, Debug)]
pub enum Decorations {
/// No decorations
///
/// The root widget is drawn as a simple rectangle with no borders.
None,
/// Add a simple themed border to the widget
///
/// Probably looks better if [`Window::transparent`] is true.
Border,
/// Toolkit-drawn decorations
///
/// Decorations will match the toolkit theme, not the platform theme.
/// These decorations may not have all the same capabilities.
///
/// Probably looks better if [`Window::transparent`] is true.
Toolkit,
/// Server-side decorations
///
/// Decorations are drawn by the window manager, if available.
Server,
}

/// Functionality required by a window
pub trait Window: Widget {
/// Get the window title
Expand All @@ -33,11 +59,25 @@ pub trait Window: Widget {
/// Get the window icon, if any
///
/// Default: `None`
#[inline]
fn icon(&self) -> Option<Icon> {
None
}

/// Get the preference for window decorations
///
/// "Windowing" platforms (i.e. not mobile or web) usually include a
/// title-bar, icons and potentially side borders. These are known as
/// **decorations**.
///
/// This controls the *preferred* type of decorations on windowing
/// platforms. It is not always followed (e.g. Wayland does not support
/// server-side decorations by default).
///
/// Default: [`Decorations::Server`].
fn decorations(&self) -> Decorations {
Decorations::Server
}

/// Whether to limit the maximum size of a window
///
/// All widgets' size rules allow calculation of two sizes: the minimum
Expand All @@ -50,11 +90,36 @@ pub trait Window: Widget {
/// windows.
///
/// Default: `(true, false)`
#[inline]
fn restrict_dimensions(&self) -> (bool, bool) {
(true, false)
}

/// Whether to allow dragging the window from the background
///
/// If true, then any unhandled click+drag in the window may be used to
/// drag the window. Probably more useful for small pop-ups than large
/// windows.
///
/// Default: `true`.
fn drag_anywhere(&self) -> bool {
true
}

/// Whether the window supports transparency
///
/// If true, painting with `alpha < 1.0` makes the background visible.
/// Additionally, window draw targets are cleared to transparent. This does
/// not stop theme elements from drawing a solid background.
///
/// Note: results may vary by platform. Current output does *not* use
/// pre-multiplied alpha which *some* platforms expect, thus pixels with
/// partial transparency may have incorrect appearance.
///
/// Default: `false`.
fn transparent(&self) -> bool {
false
}

/// Handle closure of self
///
/// This allows for actions on destruction.
Expand Down
14 changes: 12 additions & 2 deletions crates/kas-core/src/draw/draw_shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use super::color::Rgba;
use super::{DrawImpl, PassId};
use crate::cast::Cast;
use crate::geom::{Quad, Rect, Size};
use crate::shell::Platform;
use crate::text::{Effect, TextDisplay};
use std::any::Any;
use std::num::NonZeroU32;
Expand Down Expand Up @@ -74,21 +75,25 @@ pub struct AllocError;
pub struct SharedState<DS: DrawSharedImpl> {
/// The shell's [`DrawSharedImpl`] object
pub draw: DS,
platform: Platform,
}

#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
#[cfg_attr(doc_cfg, doc(cfg(internal_doc)))]
impl<DS: DrawSharedImpl> SharedState<DS> {
/// Construct (this is only called by the shell)
pub fn new(draw: DS) -> Self {
SharedState { draw }
pub fn new(draw: DS, platform: Platform) -> Self {
SharedState { draw, platform }
}
}

/// Interface over [`SharedState`]
///
/// All methods concern management of resources for drawing.
pub trait DrawShared {
/// Get the platform
fn platform(&self) -> Platform;

/// Allocate an image
///
/// Use [`SharedState::image_upload`] to set contents of the new image.
Expand All @@ -115,6 +120,11 @@ pub trait DrawShared {
}

impl<DS: DrawSharedImpl> DrawShared for SharedState<DS> {
#[inline]
fn platform(&self) -> Platform {
self.platform
}

#[inline]
fn image_alloc(&mut self, size: (u32, u32)) -> Result<ImageHandle, AllocError> {
self.draw
Expand Down
13 changes: 10 additions & 3 deletions crates/kas-core/src/event/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -701,20 +701,27 @@ impl<'a> EventMgr<'a> {
self.send_recurse(widget, id, disabled, event) == Response::Used
}

fn send_popup_first(&mut self, widget: &mut dyn Widget, id: Option<WidgetId>, event: Event) {
// Returns true if event is used
fn send_popup_first(
&mut self,
widget: &mut dyn Widget,
id: Option<WidgetId>,
event: Event,
) -> bool {
while let Some((wid, parent)) = self
.popups
.last()
.map(|(wid, p, _)| (*wid, p.parent.clone()))
{
log::trace!("send_popup_first: parent={parent}: {event:?}");
if self.send_event(widget, parent, event.clone()) {
return;
return true;
}
self.close_window(wid, false);
}
if let Some(id) = id {
self.send_event(widget, id, event);
return self.send_event(widget, id, event);
}
false
}
}
6 changes: 6 additions & 0 deletions crates/kas-core/src/event/manager/config_mgr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::draw::DrawShared;
use crate::event::EventState;
use crate::geom::{Rect, Size};
use crate::layout::AlignPair;
use crate::shell::Platform;
use crate::text::TextApi;
use crate::theme::{Feature, SizeMgr, TextClass, ThemeSize};
use crate::{Action, Widget, WidgetExt, WidgetId};
Expand Down Expand Up @@ -37,6 +38,11 @@ impl<'a> ConfigMgr<'a> {
ConfigMgr { sh, ds, ev }
}

/// Get the platform
pub fn platform(&self) -> Platform {
self.ds.platform()
}

/// Access a [`SizeMgr`]
///
/// Warning: sizes are calculated using the window's current scale factor.
Expand Down
8 changes: 8 additions & 0 deletions crates/kas-core/src/event/manager/mgr_pub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,14 @@ impl<'a> EventMgr<'a> {
result.expect("ShellWindow::size_and_draw_shared impl failed to call function argument")
}

/// Directly access Winit Window
///
/// This is a temporary API, allowing e.g. to minimize the window.
#[cfg(features = "winit")]
pub fn winit_window(&self) -> Option<&winit::window::Window> {
self.shell.winit_window()
}

/// Grab "press" events for `source` (a mouse or finger)
///
/// When a "press" source is "grabbed", events for this source will be sent
Expand Down
10 changes: 7 additions & 3 deletions crates/kas-core/src/event/manager/mgr_shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::cast::traits::*;
use crate::geom::{Coord, DVec2};
use crate::model::SharedRc;
use crate::shell::ShellWindow;
use crate::{Action, Widget, WidgetId};
use crate::{Action, Layout, RootWidget, Widget, WidgetId, Window};

// TODO: this should be configurable or derived from the system
const DOUBLE_CLICK_TIMEOUT: Duration = Duration::from_secs(1);
Expand Down Expand Up @@ -324,7 +324,7 @@ impl<'a> EventMgr<'a> {
#[cfg_attr(doc_cfg, doc(cfg(feature = "winit")))]
pub(crate) fn handle_winit(
&mut self,
widget: &mut dyn Widget,
widget: &mut RootWidget,
event: winit::event::WindowEvent,
) {
use winit::event::{ElementState, MouseScrollDelta, TouchPhase, WindowEvent::*};
Expand Down Expand Up @@ -494,7 +494,11 @@ impl<'a> EventMgr<'a> {
start_id: self.hover.clone(),
coord,
};
self.send_popup_first(widget, self.hover.clone(), event);
let used = self.send_popup_first(widget, self.hover.clone(), event);

if !used && widget.drag_anywhere() {
self.shell.drag_window();
}
}
}
// TouchpadPressure { pressure: f32, stage: i64, },
Expand Down
1 change: 1 addition & 0 deletions crates/kas-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ mod action;
mod core;
mod erased;
mod root;
mod title_bar;

pub use crate::core::*;
pub use action::Action;
Expand Down
Loading