-
Notifications
You must be signed in to change notification settings - Fork 127
/
Copy pathwindow_decorations.rs
113 lines (93 loc) · 3.86 KB
/
window_decorations.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
//! A container to show window decorations.
use accesskit::Role;
use cursor_icon::CursorIcon;
use smallvec::{smallvec, SmallVec};
use tracing::{trace_span, Span};
use vello::kurbo::Insets;
use vello::Scene;
use winit::window::ResizeDirection;
use crate::paint_scene_helpers::stroke;
use crate::widget::WidgetPod;
use crate::{
theme, AccessCtx, AccessEvent, BoxConstraints, EventCtx, LayoutCtx, LifeCycle, LifeCycleCtx,
PaintCtx, PointerEvent, Size, StatusChange, TextEvent, Widget, WidgetId,
};
const BORDER_WIDTH: f64 = 2.0;
const INSETS: Insets = Insets::uniform(BORDER_WIDTH);
/// A container to show window decorations.
pub struct WindowDecorations<W> {
pub(crate) child: WidgetPod<W>,
}
impl<W: Widget> WindowDecorations<W> {
pub fn new(widget: W) -> WindowDecorations<W> {
WindowDecorations {
child: WidgetPod::new(widget),
}
}
}
impl<W: Widget> Widget for WindowDecorations<W> {
fn on_pointer_event(&mut self, ctx: &mut EventCtx, event: &PointerEvent) {
match event {
PointerEvent::PointerMove(state) => {
if state.position.y <= BORDER_WIDTH {
ctx.set_cursor(&CursorIcon::NResize);
} else if state.position.y >= ctx.size().height - BORDER_WIDTH {
ctx.set_cursor(&CursorIcon::SResize);
} else if state.position.x <= BORDER_WIDTH {
ctx.set_cursor(&CursorIcon::WResize);
} else if state.position.x >= ctx.size().width - BORDER_WIDTH {
ctx.set_cursor(&CursorIcon::EResize);
}
}
PointerEvent::PointerLeave(_) => {
ctx.set_cursor(&CursorIcon::Default);
}
PointerEvent::PointerDown(_, state) => {
if state.position.y <= BORDER_WIDTH {
ctx.drag_resize_window(ResizeDirection::North);
} else if state.position.y >= ctx.size().height - BORDER_WIDTH {
ctx.drag_resize_window(ResizeDirection::South);
} else if state.position.x <= BORDER_WIDTH {
ctx.drag_resize_window(ResizeDirection::West);
} else if state.position.x >= ctx.size().width - BORDER_WIDTH {
ctx.drag_resize_window(ResizeDirection::East);
}
}
_ => {}
}
}
fn on_text_event(&mut self, _ctx: &mut EventCtx, _event: &TextEvent) {}
fn on_access_event(&mut self, _ctx: &mut EventCtx, _event: &AccessEvent) {}
fn on_status_change(&mut self, _: &mut LifeCycleCtx, _: &StatusChange) {}
fn lifecycle(&mut self, ctx: &mut LifeCycleCtx, event: &LifeCycle) {
self.child.lifecycle(ctx, event);
}
fn layout(&mut self, ctx: &mut LayoutCtx, bc: &BoxConstraints) -> Size {
let padding = Size::new(INSETS.x_value(), INSETS.y_value());
let child_bc = bc.shrink(padding);
let child_size = ctx.run_layout(&mut self.child, &child_bc);
let size = bc.constrain(Size::new(
child_size.width + padding.width,
child_size.height + padding.height,
));
let child_offset = (size.to_vec2() - child_size.to_vec2()) / 2.0;
ctx.place_child(&mut self.child, child_offset.to_point());
size
}
fn paint(&mut self, ctx: &mut PaintCtx, scene: &mut Scene) {
let rect = ctx.size().to_rect().inset(-BORDER_WIDTH / 2.0);
stroke(scene, &rect, theme::BORDER_DARK, BORDER_WIDTH);
}
fn accessibility_role(&self) -> Role {
Role::GenericContainer
}
fn accessibility(&mut self, _ctx: &mut AccessCtx) {}
fn children_ids(&self) -> SmallVec<[WidgetId; 16]> {
smallvec![self.child.id()]
}
fn make_trace_span(&self) -> Span {
trace_span!("WindowDecorations")
}
}