Repository navigation
Expand file tree
/
Copy pathwindow.h
More file actions
2137 lines (1946 loc) · 82.5 KB
/
Copy pathwindow.h
File metadata and controls
2137 lines (1946 loc) · 82.5 KB
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#pragma once
#include <memory>
#include <string>
#include "foundation/color.h"
#include "foundation/event.h"
#include "foundation/event_emitter.h"
#include "foundation/geometry.h"
#include "foundation/id_allocator.h"
#include "foundation/native_object_provider.h"
namespace nativeapi {
class EventRequest;
namespace detail { struct WindowEventSubscription; struct WindowPropertyDispatch; }
class View;
class WindowShape;
class WindowShadow;
/**
* @typedef WindowId
* @brief Unique identifier for a window instance.
*
* This type is used to uniquely identify window instances across the system.
* Each window gets assigned a unique ID when created.
*/
typedef IdAllocator::IdType WindowId;
/**
* Base class for all window-related events
*
* This class provides common functionality for window events,
* including access to the window ID that triggered the event.
*
* WindowManager reports observed changes for every process window. Window
* subscriptions receive those observations for their native identity, and
* Window itself produces cancellable close requests before its native action.
*/
class WindowEvent : public Event {
public:
/**
* Constructor for WindowEvent
* @param window_id The window ID associated with this event
*/
explicit WindowEvent(WindowId window_id) : window_id_(window_id) {}
/**
* Virtual destructor
*/
virtual ~WindowEvent() = default;
/**
* Get the window ID associated with this event
* @return The window ID
*/
WindowId GetWindowId() const { return window_id_; }
/**
* Get a string representation of the event type (for debugging)
* Default implementation returns "WindowEvent"
*/
std::string GetTypeName() const override { return "WindowEvent"; }
private:
WindowId window_id_;
};
/**
* @brief Title bar style options for windows.
*
* Defines how a window's title bar should be displayed. This affects the
* appearance and visibility of the standard window title bar including the
* title text and window control buttons (minimize, maximize, close).
*
* @note Platform behavior may vary:
* - Windows: Hidden style removes the title bar; the desktop compositor's frame (border,
* shadow, rounded corners) stays. Without a shadow, or with a custom shadow or a shape,
* the window has no frame at all and its edges resize from inside the content
* - macOS: Hidden style creates a borderless window with transparent title bar
* - Linux: Hidden style removes window decorations entirely
*/
enum class TitleBarStyle {
/**
* Standard title bar with default platform appearance.
* Shows title text and standard window control buttons.
*/
Normal,
/**
* No title bar and no window control buttons: the window is bare on every
* platform, for an application that draws its own chrome.
*
* The content owns the area where the title bar was: dragging there does
* not move the window. Move it from custom chrome with
* Window::StartDragging() (or a WindowDragSession). Handle a double-click
* in that custom chrome with Window::PerformTitleBarDoubleClick(). On macOS,
* empty backgrounds in the original title-bar band automatically perform that
* action; controls, custom mouse handlers and host window dispatchers keep it.
* - macOS: the content extends under a title bar that is transparent and
* empty; the window buttons are hidden. The system is kept from moving
* the window, even while IsMovable() is true. To keep the buttons over
* the content, use Normal with SetContentUnderTitleBar() instead,
* or turn them back on with SetWindowControlButtonsVisible() after
* setting this style.
* - Windows: the content reaches the top edge of the window; the resize
* border stays on the other sides. A band as thick as that border along
* the top of the content still resizes the window, also over child
* windows of the same thread (such as a Flutter view), so content there
* does not receive the mouse.
* - Linux: the window's header bar is hidden, which takes its buttons with
* it.
*
* Switching between styles keeps the window's frame (position and outer
* size); the content area grows or shrinks by the title bar instead, and
* the window control buttons go back to what the style implies - set
* SetWindowControlButtonsVisible() afterwards to override that.
*/
Hidden
};
/**
* @brief Preferred rounding of the corners drawn by the window compositor.
* @see Window::SetCornerPreference() for platform availability.
*/
enum class WindowCornerPreference {
/** Let the system choose its normal corner style. */
Default,
/** Ask the system to leave the corners square. */
DoNotRound,
/** Ask the system to round the corners. */
Round,
/** Ask the system to use a smaller corner radius. */
RoundSmall
};
/**
* @brief A window property reported by WindowPropertyChangedEvent.
*
* Each value names a getter on Window; read it there for the new value.
*/
enum class WindowProperty {
/** Window::GetTitle() */
Title,
/** Window::IsResizable() */
Resizable,
/** Window::IsMovable() */
Movable,
/** Window::IsMinimizable() */
Minimizable,
/** Window::IsMaximizable() */
Maximizable,
/** Window::IsFullScreenable() */
FullScreenable,
/** Window::IsClosable() */
Closable,
/** Window::IsWindowControlButtonsVisible() */
WindowControlButtonsVisible,
/** Window::IsAlwaysOnTop() */
AlwaysOnTop,
/** Window::IsAlwaysOnBottom() */
AlwaysOnBottom,
/** Window::GetTitleBarStyle() */
TitleBarStyle
};
/**
* @brief Whether any part of a window can be seen.
* @see Window::GetOcclusionState() for platform availability.
*/
enum class WindowOcclusionState {
/** The platform cannot tell. */
Unknown,
/** Some part of the window is on screen and not covered. */
Visible,
/** Nothing of the window can be seen: hidden, minimized, on another
workspace, off screen or covered by other windows. */
Occluded
};
/**
* @brief Translucent materials that can replace a window's background.
*
* A visual effect blurs or samples whatever is behind the window and draws the
* result where the background color would be. The window's content has to leave
* that area unpainted for the material to show.
*
* The values are named after the platform that defines the material. Each of
* them is accepted on every platform that has visual effects at all; where the
* exact material does not exist, the closest one is used, as listed per value.
* Linux, Android, iOS and OpenHarmony have no visual effects.
*
* @see Window::SetVisualEffect() for platform availability.
*/
enum class VisualEffect {
/** No visual effect: the window shows its background color. */
None,
/**
* A plain blur of what is behind the window, the most see-through material.
* - Windows: the acrylic system backdrop on Windows 11 22H2 and later, the
* nearest material that covers the whole window there; the plain blur behind
* on Windows 10, which stops at the title bar
* - macOS: NSVisualEffectMaterialSidebar
*/
Blur,
/**
* A heavier, tinted blur.
* - Windows: Acrylic - the system backdrop on Windows 11 22H2 and later, the
* acrylic blur-behind on Windows 10 1803 and later
* - macOS: NSVisualEffectMaterialUnderWindowBackground
*/
Acrylic,
/**
* A nearly opaque material tinted by the desktop wallpaper.
* - Windows: Mica (Windows 11 22H2 and later)
* - macOS: NSVisualEffectMaterialWindowBackground
*/
Mica,
/**
* Mica with a stronger tint, meant for windows with tabs in the title bar.
* - Windows: Mica Alt (Windows 11 22H2 and later)
* - macOS: NSVisualEffectMaterialTitlebar
*/
MicaAlt,
/**
* The dark material of heads-up panels.
* - Windows: same as Acrylic
* - macOS: NSVisualEffectMaterialHUDWindow
*/
Hud,
/**
* The material of popovers.
* - Windows: same as Acrylic
* - macOS: NSVisualEffectMaterialPopover
*/
Popover,
/**
* The material of menus, which suits a window shown from a tray icon.
* - Windows: same as Acrylic
* - macOS: NSVisualEffectMaterialMenu
*/
Menu
};
/**
* @brief Window edges and corners that a user-driven resize can start from.
*
* Passed to Window::StartResizing() to select which edge or corner follows
* the mouse. Edges are named from the user's point of view, so Top is the
* edge nearest the title bar on every platform.
*/
enum class ResizeEdge {
/** The top edge; dragging changes the height while the bottom edge stays. */
Top,
/** The left edge; dragging changes the width while the right edge stays. */
Left,
/** The right edge; dragging changes the width while the left edge stays. */
Right,
/** The bottom edge; dragging changes the height while the top edge stays. */
Bottom,
/** The top-left corner; both width and height change. */
TopLeft,
/** The top-right corner; both width and height change. */
TopRight,
/** The bottom-left corner; both width and height change. */
BottomLeft,
/** The bottom-right corner; both width and height change. */
BottomRight
};
/**
* @class Window
* @brief Cross-platform window abstraction class.
*
* This class provides a unified interface for creating and managing windows
* across different operating systems. It encapsulates all window-related
* functionality including size, position, visibility, focus, and appearance.
*
* The Window class uses the PIMPL idiom to hide platform-specific implementation
* details and provide a clean, consistent API across all supported platforms.
*
* @note This class is not thread-safe. All window operations should be performed
* on the main UI thread.
*/
class Window : public EventEmitter<WindowEvent>, public NativeObjectProvider,
public std::enable_shared_from_this<Window> {
public:
/**
* @brief Default constructor creates a new window with default settings.
*
* Creates a new window with platform-default size, position, and properties.
* The window is initially hidden and must be explicitly shown.
* The window is automatically registered in the WindowRegistry.
*/
Window();
/**
* @brief Constructor that wraps an existing native window object.
*
* @param window Pointer to an existing platform-specific window object
* @note The Window instance takes ownership of the native window object
*/
Window(void* native_window);
/**
* @brief Virtual destructor ensures proper cleanup of resources.
*
* Destroys the window and releases all associated resources including
* the native window object.
*/
virtual ~Window();
Window(const Window&) = delete;
Window& operator=(const Window&) = delete;
Window(Window&&) = delete;
Window& operator=(Window&&) = delete;
/**
* @brief Whether cancellable close requests are supported on this platform.
* @return True on desktop platforms, false on mobile platforms.
*/
static bool IsCloseSupported();
/**
* @brief Requests closing this native window, subject to confirmation.
*
* Emits WindowCloseRequestedEvent on this window's subscribed wrappers. A
* listener may cancel, or keep an owned EventDecision while awaiting work.
* All approvals continue the host's original close handling on the UI thread;
* a host can still refuse. Repeated calls share the pending request. Native
* destruction invalidates its decisions, even if a handle still exists.
* Close requests are object-level events, not WindowManager notifications.
*
* @return True if the request was submitted (not proof the window closed),
* false for unsupported platforms, immediate invalidity or dispatch failure.
* @note May queue a lifetime-guarded request to the target UI loop. Successful
* submission does not prove native validity; it is rechecked on UI.
* Host close handling may also exit the app.
* @note Platform availability:
* - macOS: ✅ Supported - Continues performClose and the host delegate.
* - Windows: ✅ Supported - Continues the host WM_CLOSE handler.
* - Linux: ✅ Supported - Continues GTK delete-event handling, X11 or Wayland.
* - Android: ❌ Unsupported - Returns false.
* - iOS: ❌ Unsupported - Returns false.
* - OpenHarmony: ❌ Unsupported - Returns false.
*/
bool Close();
/**
* @brief Gets the unique identifier for this window.
*
* @return WindowId The unique identifier assigned to this window
*/
WindowId GetId() const;
// === Content view ===
/**
* @brief Gets the view filling the window's content area.
*
* Created on first call and cached: the same instance is returned for the
* life of the window. It wraps the window's existing content view (a Flutter
* or GPUI view when a host framework owns the window), so subviews added to
* it sit on top of that content. Its frame follows the content area;
* View::SetFrame() on it is ignored.
*
* @return The root view, or nullptr when View::IsSupported() is false or
* the native window is gone.
*/
std::shared_ptr<View> GetContentView() const;
// === Focus Management ===
/**
* @brief Brings the window to the front and gives it keyboard focus.
*
* Makes this window the active window and brings it to the foreground,
* restoring it first when minimized. Does nothing while IsFocusable() is
* false. The window that had the focus before is remembered for Blur(); so
* is it by Show(). The request is asynchronous on every platform: check
* IsFocused() after the platform reports the change (WindowFocusedEvent).
*
* @note Platform availability:
* - macOS: ✅ Supported - Activates the application unless IsNonActivating().
* macOS 14+ activation is cooperative, so the system can still decline it.
* - Windows: ⚠️ Best effort - When the foreground lock refuses the request it
* is retried with the foreground thread's input state attached; the
* system may still only flash the taskbar button.
* - Linux: ⚠️ Best effort - Presents with the current event or X server time;
* the window manager or compositor (Wayland: activation tokens) decides.
* - Android: ❌ Not applicable - Focus follows the Activity lifecycle
* - iOS: ⚠️ Partial - Makes the window the key window
* - OpenHarmony: ❌ Not applicable - Focus follows the Ability lifecycle
*/
void Focus();
/**
* @brief Removes keyboard focus from the window and returns it to where it
* was before.
*
* The window stays visible and in place. The focus goes to the window that
* had it before the last Focus() or Show() of this window, if that one can
* still take it: another window of this application, or another
* application (the launcher case: hide a search bar and type into the
* previous app again). Otherwise the platform picks the next window. Does
* nothing when the window does not have the focus.
*
* @note Platform availability:
* - macOS: ✅ Supported - Another app is activated after yielding activation
* to it; with no target, the app this one last took the focus from.
* - Windows: ✅ Supported - Without a usable target, the next window down the
* Z order gets the foreground.
* - Linux: ⚠️ Partial - X11 asks the window manager to activate the previous
* window, else the next one down its stacking order. Wayland can only
* return focus to another window of this application; otherwise the
* window is lowered and the compositor decides.
* - Android: ❌ Not applicable - Focus follows the Activity lifecycle
* - iOS: ⚠️ Partial - Resigns the key window
* - OpenHarmony: ❌ Not applicable - Focus follows the Ability lifecycle
*/
void Blur();
/**
* @brief Checks if the window currently has keyboard focus.
*
* @return true if the window has focus, false otherwise
*/
bool IsFocused() const;
// === Visibility Management ===
/**
* @brief Shows the window and brings it to the front.
*
* Makes the window visible and typically gives it focus. If the window
* was minimized, it will be restored to its previous state.
*/
void Show();
/**
* @brief Shows the window without giving it focus.
*
* Makes the window visible but does not change the currently focused window.
* Useful for showing auxiliary windows or notifications.
*/
void ShowInactive();
/**
* @brief Hides the window from view.
*
* Makes the window invisible but does not destroy it. The window can
* be shown again later with Show() or ShowInactive().
*/
void Hide();
/**
* @brief Checks if the window is currently visible.
*
* @return true if the window is visible, false if hidden or minimized
*/
bool IsVisible() const;
/**
* @brief Tells whether any part of the window can be seen.
*
* Unlike IsVisible(), which only says the window is shown, this accounts for
* minimizing, other workspaces and other windows on top of it. Useful to
* pause rendering or video nobody can see. WindowOcclusionChangedEvent
* reports changes.
*
* @return The current state, or WindowOcclusionState::Unknown where the
* platform cannot tell.
*
* @note Platform availability:
* - macOS: ✅ Supported - NSWindow.occlusionState, as the system computes it.
* - Windows: ⚠️ Approximated - Hidden, minimized and cloaked (another
* virtual desktop) windows are occluded; otherwise the window is occluded
* when the opaque windows above it in the Z order, clipped to the screens,
* cover it entirely. Click-through and translucent layered windows do not
* count as covering.
* - Linux: ⚠️ Partial - Hidden and minimized windows are occluded; whether
* other windows cover a shown one is not known, so it is Unknown (X11
* visibility is meaningless under a compositing manager, and Wayland
* does not tell).
* - Android: ❌ Not applicable - Always Unknown
* - iOS: ❌ Not applicable - Always Unknown
* - OpenHarmony: ❌ Not applicable - Always Unknown
*/
WindowOcclusionState GetOcclusionState() const;
/**
* @brief Whether GetOcclusionState() can report anything but Unknown here.
* @see GetOcclusionState() for platform availability.
*/
static bool IsOcclusionStateSupported();
// === Window State Management ===
/**
* @brief Maximizes the window to fill the available screen space.
*
* Expands the window to occupy the maximum available area on the screen,
* typically excluding taskbars and docks. A window that is not shown yet
* stays hidden and appears maximized when it is shown, also when its host
* shows it as a restored window (a Flutter runner on its first frame);
* IsMaximized() already reports true, and Unmaximize() takes it back.
*/
void Maximize();
/**
* @brief Restores the window from maximized state to its previous size.
*
* Returns the window to the size and position it had before being maximized.
*/
void Unmaximize();
/**
* @brief Checks if the window is currently maximized.
*
* @return true if the window is maximized, false otherwise
*/
bool IsMaximized() const;
/**
* @brief Minimizes the window, hiding it from the desktop.
*
* Reduces the window to an icon in the taskbar or dock. The window
* remains open but is not visible on the desktop.
*/
void Minimize();
/**
* @brief Restores a minimized window: the opposite of Minimize().
*
* The window comes back in the state it was minimized from, maximized
* included. A window that is not minimized is left as it is; Unmaximize()
* is the opposite of Maximize().
*/
void Restore();
/**
* @brief Checks if the window is currently minimized.
*
* @return true if the window is minimized, false otherwise
*/
bool IsMinimized() const;
/**
* @brief Sets the window's fullscreen state.
*
* @param is_full_screen true to enter fullscreen mode, false to exit
*
* In fullscreen mode, the window occupies the entire screen with no
* window decorations (title bar, borders) visible. The change is reported by
* WindowEnteredFullScreenEvent and WindowExitedFullScreenEvent; on macOS and
* Linux it completes asynchronously, so IsFullScreen() may still return the old
* state right after this call.
*/
void SetFullScreen(bool is_full_screen);
/**
* @brief Checks if the window is currently in fullscreen mode.
*
* @return true if the window is fullscreen, false otherwise
*/
bool IsFullScreen() const;
// === Size and Bounds Management ===
// void SetBackgroundColor(Color color);
// Color GetBackgroundColor() const;
/**
* @brief Sets the window's position and size simultaneously.
*
* @param bounds Rectangle containing the desired position and size
*
* This method sets both the window's position and size in a single operation,
* which can be more efficient than separate calls to SetPosition() and SetSize().
*/
void SetBounds(Rectangle bounds);
/**
* @brief Gets the window's current position and size.
*
* @return Rectangle containing the current position and size of the window
*
* The returned rectangle includes the window frame and decorations.
*/
Rectangle GetBounds() const;
/**
* @brief Sets the position and size of the window's content area.
*
* @param bounds Rectangle containing the desired position and size of the content area
*
* This method sets both the content area's position and size in a single operation,
* which can be more efficient than separate calls to SetPosition() and SetContentSize().
* The content area excludes window decorations like title bar and borders.
*/
void SetContentBounds(Rectangle bounds);
/**
* @brief Gets the position and size of the window's content area.
*
* @return Rectangle containing the current position and size of the content area
*
* The returned rectangle excludes window decorations and represents the drawable
* content area of the window.
*/
Rectangle GetContentBounds() const;
/**
* @brief Sets the window's size with optional animation.
*
* @param size The new size for the window
* @param animate Whether to animate the size change
*
* Changes the window's outer size including frame and decorations.
* If animate is true, the resize will be smoothly animated on supported platforms.
*/
void SetSize(Size size, bool animate);
/**
* @brief Gets the window's current outer size.
*
* @return Size The current size of the window including frame and decorations
*/
Size GetSize() const;
/**
* @brief Sets the size of the window's content area.
*
* @param size The desired size of the content area
*
* This sets the size of the drawable content area, excluding window
* decorations like title bar and borders. The actual window size will
* be larger to accommodate the frame.
*/
void SetContentSize(Size size);
/**
* @brief Gets the size of the window's content area.
*
* @return Size The current size of the content area excluding decorations
*/
Size GetContentSize() const;
/**
* @brief Sets the minimum size the window can be resized to.
*
* @param size The minimum allowed size
*
* Prevents the user from resizing the window smaller than the specified size.
* This applies to the outer window size including decorations.
*/
void SetMinimumSize(Size size);
/**
* @brief Gets the current minimum size constraint.
*
* @return Size The minimum size the window can be resized to
*/
Size GetMinimumSize() const;
/**
* @brief Sets the maximum size the window can be resized to.
*
* @param size The maximum allowed size
*
* Prevents the user from resizing the window larger than the specified size.
* This applies to the outer window size including decorations.
*/
void SetMaximumSize(Size size);
/**
* @brief Gets the current maximum size constraint.
*
* @return Size The maximum size the window can be resized to
*/
Size GetMaximumSize() const;
/**
* @brief Constrains user-driven resizing to a fixed width/height ratio.
*
* @param aspect_ratio Desired width divided by height, e.g. 16.0 / 9.0.
* Values of 0 or less remove the constraint.
*
* The ratio applies to the content area (the title bar and borders are not
* counted) while the user drags a window edge. It does not change the current
* size and is not enforced by SetSize(), SetContentSize() or SetBounds().
* Minimum and maximum sizes still apply on top of the ratio.
*
* @note Platform availability:
* - macOS: ✅ Fully supported
* - Windows: ✅ Fully supported
* - Linux: ⚠️ Partial - Applied via GDK aspect geometry hints, which the
* window manager may honor loosely. GTK also applies them to programmatic
* resizes, so SetSize(), SetContentSize() and SetBounds() are adjusted to
* the ratio while one is set. With client-side decorations the content
* ratio can be off by a pixel after a resize.
* - Android: ❌ Not applicable - Always ignored
* - iOS: ❌ Not applicable - Always ignored
* - OpenHarmony: ❌ Not applicable - Always ignored
*/
void SetAspectRatio(double aspect_ratio);
/**
* @brief Gets the aspect ratio constraint set by SetAspectRatio().
*
* @return Width divided by height, or 0 when no constraint is set
*/
double GetAspectRatio() const;
// === Window Behavior Properties ===
/**
* @brief Sets whether the window can be resized by the user.
*
* @param is_resizable true to allow resizing, false to disable
*
* When disabled, the user cannot resize the window by dragging its edges
* or corners. Programmatic resizing via SetSize() is still possible.
*/
void SetResizable(bool is_resizable);
/**
* @brief Checks if the window can be resized by the user.
*
* @return true if user can resize the window, false otherwise
*/
bool IsResizable() const;
/**
* @brief Sets whether the window can be moved by the user.
*
* @param is_movable true to allow moving, false to disable
*
* When disabled, the user cannot move the window by dragging its title bar.
* Programmatic positioning via SetPosition() is still possible.
*
* With TitleBarStyle::Hidden the system does not move the window on its
* own regardless; this setting is kept and applies again once the title
* bar is shown.
*/
void SetMovable(bool is_movable);
/**
* @brief Checks if the window can be moved by the user.
*
* @return true if user can move the window, false otherwise
*/
bool IsMovable() const;
/**
* @brief Sets whether the window can be minimized by the user.
*
* @param is_minimizable true to allow minimizing, false to disable
*
* Controls the availability of minimize functionality in the window's
* title bar and system menu. Programmatic minimizing is still possible.
*/
void SetMinimizable(bool is_minimizable);
/**
* @brief Checks if the window can be minimized by the user.
*
* @return true if user can minimize the window, false otherwise
*/
bool IsMinimizable() const;
/**
* @brief Sets whether the window can be maximized by the user.
*
* @param is_maximizable true to allow maximizing, false to disable
*
* Controls the availability of maximize functionality in the window's
* title bar and system menu. Programmatic maximizing is still possible.
*/
void SetMaximizable(bool is_maximizable);
/**
* @brief Checks if the window can be maximized by the user.
*
* @return true if user can maximize the window, false otherwise
*/
bool IsMaximizable() const;
/**
* @brief Sets whether the window can enter fullscreen mode.
*
* @param is_full_screenable true to allow fullscreen, false to disable
*
* Controls whether the window supports fullscreen mode. On some platforms,
* this affects the availability of fullscreen controls in the UI.
*/
void SetFullScreenable(bool is_full_screenable);
/**
* @brief Checks if the window supports fullscreen mode.
*
* @return true if fullscreen is supported, false otherwise
*/
bool IsFullScreenable() const;
/**
* @brief Sets whether the window can be closed by the user.
*
* @param is_closable true to allow closing, false to disable
*
* When disabled, the close button in the title bar is hidden or disabled.
* The window can still be closed programmatically.
*/
void SetClosable(bool is_closable);
/**
* @brief Checks if the window can be closed by the user.
*
* @return true if user can close the window, false otherwise
*/
bool IsClosable() const;
/**
* @brief Sets the visibility of window control buttons.
*
* @param is_visible true to show window control buttons, false to hide them
*
* Controls the visibility of window control buttons (minimize, maximize, close)
* in the title bar. When hidden, the buttons are not visible but the window
* can still be controlled programmatically.
*
* @note Platform availability:
* - macOS: ✅ Fully supported - Hides/shows the traffic light buttons (red, yellow, green)
* - Windows: ❌ Not implemented - Returns default value (visible)
* - Linux: ❌ Not implemented - Returns default value (visible)
* - Android: ❌ Not applicable - Mobile apps don't have window control buttons
* - iOS: ❌ Not applicable - Mobile apps don't have window control buttons
* - OpenHarmony: ❌ Not applicable - Mobile apps don't have window control buttons
*/
void SetWindowControlButtonsVisible(bool is_visible);
/**
* @brief Checks if the window control buttons are visible.
*
* @return true if window control buttons are visible, false if hidden
*
* @note Platform availability:
* - macOS: ✅ Fully supported - Returns actual visibility state
* - Windows: ❌ Not implemented - Always returns true
* - Linux: ❌ Not implemented - Always returns true
* - Android: ❌ Not applicable - Always returns false
* - iOS: ❌ Not applicable - Always returns false
* - OpenHarmony: ❌ Not applicable - Always returns false
*/
bool IsWindowControlButtonsVisible() const;
/**
* @brief Sets whether the window stays on top of other windows.
*
* @param is_always_on_top true to keep on top, false for normal behavior
*
* When enabled, the window will remain visible above other windows
* even when it doesn't have focus.
*/
void SetAlwaysOnTop(bool is_always_on_top);
/**
* @brief Checks if the window is set to always stay on top.
*
* @return true if window stays on top, false otherwise
*/
bool IsAlwaysOnTop() const;
/**
* @brief Sets whether the window stays beneath all other normal windows.
*
* @param is_always_on_bottom true to keep the window at the bottom of the
* stacking order, false for normal behavior
*
* When enabled the window stays behind every other application window,
* even while it has focus, but remains above the desktop. Use this for
* desktop widgets or wallpaper-like windows. Enabling this clears any
* SetAlwaysOnTop() setting and vice versa.
*
* @note Platform availability:
* - macOS: ✅ Fully supported - The window level is lowered below the normal
* window level.
* - Windows: ✅ Fully supported - The window is pinned to the bottom of the
* Z order and stays there when activated.
* - Linux: ✅ Fully supported - Uses the _NET_WM_STATE_BELOW hint; honored by
* most window managers.
* - Android: ❌ Not applicable - Always ignored
* - iOS: ❌ Not applicable - Always ignored
* - OpenHarmony: ❌ Not applicable - Always ignored
*/
void SetAlwaysOnBottom(bool is_always_on_bottom);
/**
* @brief Checks if the window is set to always stay at the bottom.
*
* @return true if the window stays beneath other windows, false otherwise
*/
bool IsAlwaysOnBottom() const;
/**
* @brief Sets the window this window belongs to, making it a child window.
*
* A child window always stays above its parent and is hidden while the parent
* is minimized. Tool palettes, floating toolbars and inspectors are child
* windows. The relationship does not keep either window alive, and a window
* has at most one parent.
*
* What else follows from the relationship is decided by the platform, see
* below. For behaviour that must be the same everywhere — a child that
* follows its parent — listen to the parent's WindowMovedEvent and
* WindowResizedEvent; closing the children before their parent avoids the
* difference in what closing the parent does to them.
*
* @param parent The new parent window, or nullptr to make this window
* independent again
* @return false if the relationship was not established: parent is this
* window or one of its descendants, either native window is gone, or
* the platform has no child windows
*
* @note Platform availability:
* - macOS: ✅ Fully supported - The child also moves with its parent. A hidden
* child is attached when it is shown, because AppKit shows a window that is
* attached to a visible parent.
* - Windows: ⚠️ Owned window - Stays above its parent and is hidden with it,
* but does not move with it, and is destroyed when its parent is.
* - Linux: ⚠️ Transient window - Stays above its parent; does not move with
* it, and minimizing with the parent is up to the window manager. On Wayland
* nothing an application does can make it follow: a client neither places
* its toplevels nor learns where they are.
* - Android: ❌ Not applicable - Always ignored, returns false
* - iOS: ❌ Not applicable - Always ignored, returns false
* - OpenHarmony: ❌ Not applicable - Always ignored, returns false
*/
bool SetParentWindow(std::shared_ptr<Window> parent);
/**
* @brief Gets the window this window belongs to.
*
* Read from the native window, so it also reports a parent the embedding
* framework has set.
*
* @return The parent window, or nullptr if this window has none
* @see SetParentWindow() for platform availability.
*/
std::shared_ptr<Window> GetParentWindow() const;
/**
* @brief Sets whether showing or focusing the window activates the application.
*
* @param is_non_activating true to make the window non-activating, false for
* normal behavior
*
* A non-activating window can be shown and clicked without activating its
* application. On macOS it can also receive keyboard input. The
* previously active application keeps its activation state, and hiding the
* window does not bring the application's other windows forward. Use this
* for floating helper windows (quick-input palettes, pop-up translators,
* pickers) that should sit above a foreign app while the user keeps working
* in it.
*
* The window level is not changed by this call; combine it with
* SetAlwaysOnTop() to keep the window above other applications' windows.
*
* @note Platform availability:
* - macOS: ✅ Fully supported - The window becomes a non-activating NSPanel
* that can become key but never main.
* - Windows: ✅ Supported - Uses WS_EX_NOACTIVATE and declines mouse activation;
* Show() and Focus() do not take keyboard focus while this flag is set.
* - Linux: ⚠️ Window-manager dependent - Sets GTK/GDK accept-focus and
* focus-on-map hints; Show() and Focus() do not request activation. X11
* window managers normally honor these hints; Wayland compositors may ignore them.
* - Android: ❌ Not applicable - Always ignored
* - iOS: ❌ Not applicable - Always ignored
* - OpenHarmony: ❌ Not applicable - Always ignored
*/
void SetNonActivating(bool is_non_activating);
/**
* @brief Checks if the window is non-activating.
*
* @return true if the non-activating policy is enabled, false otherwise.
* See SetNonActivating() for window-manager restrictions.
*
* @see SetNonActivating() for platform availability.
*/
bool IsNonActivating() const;
// === Position and Title ===
/**
* @brief Sets the window's position on the screen.
*
* @param point The new position for the window's top-left corner