Skip to content

Commit 6db696d

Browse files
authored
Add basic window control (#670)
This is the first merge-able part of #606. It allows to implement custom CSDs via window management signals and a new `WindowHandle` widget which is useful to implement a custom titlebar.
1 parent a6800f4 commit 6db696d

File tree

4 files changed

+88
-1
lines changed

4 files changed

+88
-1
lines changed

masonry/src/contexts.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
use std::time::Duration;
77

88
use accesskit::TreeUpdate;
9+
use dpi::LogicalPosition;
910
use parley::{FontContext, LayoutContext};
1011
use tracing::{trace, warn};
1112
use vello::kurbo::Vec2;
13+
use winit::window::ResizeDirection;
1214

1315
use crate::action::Action;
1416
use crate::passes::layout::run_layout_on;
@@ -606,6 +608,58 @@ impl_context_method!(
606608
.emit_signal(RenderRootSignal::Action(action, self.widget_state.id));
607609
}
608610

611+
/// Start a window drag.
612+
///
613+
/// Moves the window with the left mouse button until the button is released.
614+
pub fn drag_window(&mut self) {
615+
trace!("drag_window");
616+
self.global_state
617+
.signal_queue
618+
.push_back(RenderRootSignal::DragWindow);
619+
}
620+
621+
/// Start a window resize.
622+
///
623+
/// Resizes the window with the left mouse button until the button is released.
624+
pub fn drag_resize_window(&mut self, direction: ResizeDirection) {
625+
trace!("drag_resize_window");
626+
self.global_state
627+
.signal_queue
628+
.push_back(RenderRootSignal::DragResizeWindow(direction));
629+
}
630+
631+
/// Toggle the maximized state of the window.
632+
pub fn toggle_maximized(&mut self) {
633+
trace!("toggle_maximized");
634+
self.global_state
635+
.signal_queue
636+
.push_back(RenderRootSignal::ToggleMaximized);
637+
}
638+
639+
/// Minimize the window.
640+
pub fn minimize(&mut self) {
641+
trace!("minimize");
642+
self.global_state
643+
.signal_queue
644+
.push_back(RenderRootSignal::Minimize);
645+
}
646+
647+
/// Exit the application.
648+
pub fn exit(&mut self) {
649+
trace!("exit");
650+
self.global_state
651+
.signal_queue
652+
.push_back(RenderRootSignal::Exit);
653+
}
654+
655+
/// Show the window menu at a specified position.
656+
pub fn show_window_menu(&mut self, position: LogicalPosition<f64>) {
657+
trace!("show_window_menu");
658+
self.global_state
659+
.signal_queue
660+
.push_back(RenderRootSignal::ShowWindowMenu(position));
661+
}
662+
609663
/// Request a timer event.
610664
///
611665
/// The return value is a token, which can be used to associate the

masonry/src/event_loop_runner.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ impl MasonryState<'_> {
649649
pub fn handle_memory_warning(&mut self, _: &ActiveEventLoop) {}
650650

651651
// --- MARK: SIGNALS ---
652-
fn handle_signals(&mut self, _event_loop: &ActiveEventLoop, app_driver: &mut dyn AppDriver) {
652+
fn handle_signals(&mut self, event_loop: &ActiveEventLoop, app_driver: &mut dyn AppDriver) {
653653
let WindowState::Rendering { window, .. } = &mut self.window else {
654654
tracing::warn!("Tried to handle a signal whilst suspended or before window created");
655655
return;
@@ -696,6 +696,26 @@ impl MasonryState<'_> {
696696
render_root::RenderRootSignal::SetTitle(title) => {
697697
window.set_title(&title);
698698
}
699+
render_root::RenderRootSignal::DragWindow => {
700+
// TODO - Handle return value?
701+
let _ = window.drag_window();
702+
}
703+
render_root::RenderRootSignal::DragResizeWindow(direction) => {
704+
// TODO - Handle return value?
705+
let _ = window.drag_resize_window(direction);
706+
}
707+
render_root::RenderRootSignal::ToggleMaximized => {
708+
window.set_maximized(!window.is_maximized());
709+
}
710+
render_root::RenderRootSignal::Minimize => {
711+
window.set_minimized(true);
712+
}
713+
render_root::RenderRootSignal::Exit => {
714+
event_loop.exit();
715+
}
716+
render_root::RenderRootSignal::ShowWindowMenu(position) => {
717+
window.show_window_menu(position);
718+
}
699719
}
700720
}
701721

masonry/src/render_root.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use parley::{FontContext, LayoutContext};
99
use tracing::{info_span, warn};
1010
use vello::kurbo::{self, Rect};
1111
use vello::Scene;
12+
use winit::window::ResizeDirection;
1213

1314
#[cfg(not(target_arch = "wasm32"))]
1415
use std::time::Instant;
@@ -123,6 +124,12 @@ pub enum RenderRootSignal {
123124
SetCursor(CursorIcon),
124125
SetSize(PhysicalSize<u32>),
125126
SetTitle(String),
127+
DragWindow,
128+
DragResizeWindow(ResizeDirection),
129+
ToggleMaximized,
130+
Minimize,
131+
Exit,
132+
ShowWindowMenu(LogicalPosition<f64>),
126133
}
127134

128135
impl RenderRoot {

masonry/src/testing/harness.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,12 @@ impl TestHarness {
264264
RenderRootSignal::SetTitle(title) => {
265265
self.title = title;
266266
}
267+
RenderRootSignal::DragWindow => (),
268+
RenderRootSignal::DragResizeWindow(_) => (),
269+
RenderRootSignal::ToggleMaximized => (),
270+
RenderRootSignal::Minimize => (),
271+
RenderRootSignal::Exit => (),
272+
RenderRootSignal::ShowWindowMenu(_) => (),
267273
}
268274
}
269275
}

0 commit comments

Comments
 (0)