ltk/widget/
laid_out.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
// SPDX-License-Identifier: LGPL-2.1-only
// Copyright (C) 2026 Liberux Labs, S. L. <info@liberux.net>

use crate::types::{ Rect, WidgetId };
use super::handlers::WidgetHandlers;

/// Result of laying out one *interactive* widget — i.e. a widget that should
/// receive pointer / touch hit-testing. Captures both the *hit rect* (where
/// input lands) and the *paint rect* (the bounding box of everything the
/// widget actually paints, including hover circles, focus rings, shadows…).
/// The paint rect is used by the partial-redraw path to know how much of the
/// canvas must be invalidated when a widget transitions in/out of a given
/// state — it is always `>= rect`.
///
/// `handlers` carries the snapshot of the widget's callbacks/values at layout
/// time so input dispatch is O(1) instead of re-walking the [`super::Element`] tree.
///
/// `keyboard_focusable` snapshots whether the widget should participate in the
/// Tab / Shift+Tab cycle. Most interactive widgets are also keyboard-focusable
/// (`Button`, `TextEdit`, `Slider`, …) but window-decoration chrome
/// (`WindowButton`) is interactive without taking keyboard focus by default —
/// matching the convention of macOS / GNOME / Windows title bars.
pub struct LaidOutWidget<Msg: Clone>
{
	pub rect:               Rect,
	pub flat_idx:           usize,
	pub id:                 Option<WidgetId>,
	pub paint_rect:         Rect,
	pub handlers:           WidgetHandlers<Msg>,
	pub keyboard_focusable: bool,
	/// Cursor shape this widget wants to show on hover. Snapshotted
	/// from [`super::Element::cursor_shape`] at layout time so the input
	/// dispatch can pick the right shape without re-walking the
	/// element tree.
	pub cursor:             crate::types::CursorShape,
	pub tooltip:            Option<String>,
	/// Visible text of the widget, captured for the accessibility
	/// tree. `None` for non-textual widgets (icons, dividers).
	pub accessible_label:   Option<String>,
	pub is_live_region:     bool,
}

impl<Msg: Clone> Clone for LaidOutWidget<Msg>
{
	fn clone( &self ) -> Self
	{
		Self
		{
			rect:               self.rect,
			flat_idx:           self.flat_idx,
			id:                 self.id,
			paint_rect:         self.paint_rect,
			handlers:           self.handlers.clone(),
			keyboard_focusable: self.keyboard_focusable,
			cursor:             self.cursor,
			tooltip:            self.tooltip.clone(),
			accessible_label:   self.accessible_label.clone(),
			is_live_region:     self.is_live_region,
		}
	}
}