Skip to main content

tauri_runtime/
window.rs

1// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
2// SPDX-License-Identifier: Apache-2.0
3// SPDX-License-Identifier: MIT
4
5//! A layer between raw [`Runtime`] windows and Tauri.
6
7use crate::{
8  Icon, Runtime, UserEvent, WindowDispatch,
9  webview::{DetachedWebview, PendingWebview},
10};
11
12use dpi::PixelUnit;
13use serde::{Deserialize, Deserializer, Serialize};
14use tauri_utils::{
15  Theme,
16  config::{Color, WindowConfig},
17};
18#[cfg(windows)]
19use windows::Win32::Foundation::HWND;
20
21use std::{
22  hash::{Hash, Hasher},
23  marker::PhantomData,
24  path::PathBuf,
25  sync::mpsc::Sender,
26};
27
28/// An event from a window.
29#[derive(Debug, Clone)]
30pub enum WindowEvent {
31  /// The size of the window has changed. Contains the client area's new dimensions.
32  Resized(dpi::PhysicalSize<u32>),
33  /// The position of the window has changed. Contains the window's new position.
34  Moved(dpi::PhysicalPosition<i32>),
35  /// The window has been requested to close.
36  CloseRequested {
37    /// A signal sender. If a `true` value is emitted, the window won't be closed.
38    signal_tx: Sender<bool>,
39  },
40  /// The window has been destroyed.
41  Destroyed,
42  /// The window gained or lost focus.
43  ///
44  /// The parameter is true if the window has gained focus, and false if it has lost focus.
45  Focused(bool),
46  /// The window's scale factor has changed.
47  ///
48  /// The following user actions can cause DPI changes:
49  ///
50  /// - Changing the display's resolution.
51  /// - Changing the display's scale factor (e.g. in Control Panel on Windows).
52  /// - Moving the window to a display with a different scale factor.
53  ScaleFactorChanged {
54    /// The new scale factor.
55    scale_factor: f64,
56    /// The window inner size.
57    new_inner_size: dpi::PhysicalSize<u32>,
58  },
59  /// An event associated with the drag and drop action.
60  DragDrop(DragDropEvent),
61  /// The system window theme has changed.
62  ///
63  /// Applications might wish to react to this to change the theme of the content of the window when the system changes the window theme.
64  ThemeChanged(Theme),
65
66  /// Emitted when the application has been suspended.
67  ///
68  /// ## Platform-specific
69  ///
70  /// - **Android**: This is triggered by `onPause` method of the Activity.
71  /// - **iOS**: This is triggered by `applicationWillResignActive` method of the UIApplicationDelegate.
72  /// - **Linux / macOS / Windows**: Unsupported.
73  #[cfg(mobile)]
74  Suspended,
75
76  /// Emitted when the application has been resumed.
77  ///
78  /// ## Platform-specific
79  ///
80  /// - **Android**: This is triggered by `onResume` method of the Activity. The first onResume() is ignored to match the iOS implementation, since that is called on activity creation.
81  /// - **iOS**: This is triggered by `applicationWillEnterForeground` method of the UIApplicationDelegate.
82  /// - **Linux / macOS / Windows**: Unsupported.
83  #[cfg(mobile)]
84  Resumed,
85}
86
87/// An event from a window.
88#[derive(Debug, Clone)]
89pub enum WebviewEvent {
90  /// An event associated with the drag and drop action.
91  DragDrop(DragDropEvent),
92}
93
94/// The drag drop event payload.
95#[derive(Debug, Clone)]
96#[non_exhaustive]
97pub enum DragDropEvent {
98  /// A drag operation has entered the webview.
99  Enter {
100    /// List of paths that are being dragged onto the webview.
101    paths: Vec<PathBuf>,
102    /// The position of the mouse cursor.
103    position: dpi::PhysicalPosition<f64>,
104  },
105  /// A drag operation is moving over the webview.
106  Over {
107    /// The position of the mouse cursor.
108    position: dpi::PhysicalPosition<f64>,
109  },
110  /// The file(s) have been dropped onto the webview.
111  Drop {
112    /// List of paths that are being dropped onto the window.
113    paths: Vec<PathBuf>,
114    /// The position of the mouse cursor.
115    position: dpi::PhysicalPosition<f64>,
116  },
117  /// The drag operation has been cancelled or left the window.
118  Leave,
119}
120
121/// Describes the appearance of the mouse cursor.
122#[non_exhaustive]
123#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash)]
124pub enum CursorIcon {
125  /// The platform-dependent default cursor.
126  #[default]
127  Default,
128  /// A simple crosshair.
129  Crosshair,
130  /// A hand (often used to indicate links in web browsers).
131  Hand,
132  /// Self explanatory.
133  Arrow,
134  /// Indicates something is to be moved.
135  Move,
136  /// Indicates text that may be selected or edited.
137  Text,
138  /// Program busy indicator.
139  Wait,
140  /// Help indicator (often rendered as a "?")
141  Help,
142  /// Progress indicator. Shows that processing is being done. But in contrast
143  /// with "Wait" the user may still interact with the program. Often rendered
144  /// as a spinning beach ball, or an arrow with a watch or hourglass.
145  Progress,
146
147  /// Cursor showing that something cannot be done.
148  NotAllowed,
149  ContextMenu,
150  Cell,
151  VerticalText,
152  Alias,
153  Copy,
154  NoDrop,
155  /// Indicates something can be grabbed.
156  Grab,
157  /// Indicates something is grabbed.
158  Grabbing,
159  AllScroll,
160  ZoomIn,
161  ZoomOut,
162
163  /// Indicate that some edge is to be moved. For example, the 'SeResize' cursor
164  /// is used when the movement starts from the south-east corner of the box.
165  EResize,
166  NResize,
167  NeResize,
168  NwResize,
169  SResize,
170  SeResize,
171  SwResize,
172  WResize,
173  EwResize,
174  NsResize,
175  NeswResize,
176  NwseResize,
177  ColResize,
178  RowResize,
179}
180
181impl<'de> Deserialize<'de> for CursorIcon {
182  fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
183  where
184    D: Deserializer<'de>,
185  {
186    let s = String::deserialize(deserializer)?;
187    Ok(match s.to_lowercase().as_str() {
188      "default" => CursorIcon::Default,
189      "crosshair" => CursorIcon::Crosshair,
190      "hand" => CursorIcon::Hand,
191      "arrow" => CursorIcon::Arrow,
192      "move" => CursorIcon::Move,
193      "text" => CursorIcon::Text,
194      "wait" => CursorIcon::Wait,
195      "help" => CursorIcon::Help,
196      "progress" => CursorIcon::Progress,
197      "notallowed" => CursorIcon::NotAllowed,
198      "contextmenu" => CursorIcon::ContextMenu,
199      "cell" => CursorIcon::Cell,
200      "verticaltext" => CursorIcon::VerticalText,
201      "alias" => CursorIcon::Alias,
202      "copy" => CursorIcon::Copy,
203      "nodrop" => CursorIcon::NoDrop,
204      "grab" => CursorIcon::Grab,
205      "grabbing" => CursorIcon::Grabbing,
206      "allscroll" => CursorIcon::AllScroll,
207      "zoomin" => CursorIcon::ZoomIn,
208      "zoomout" => CursorIcon::ZoomOut,
209      "eresize" => CursorIcon::EResize,
210      "nresize" => CursorIcon::NResize,
211      "neresize" => CursorIcon::NeResize,
212      "nwresize" => CursorIcon::NwResize,
213      "sresize" => CursorIcon::SResize,
214      "seresize" => CursorIcon::SeResize,
215      "swresize" => CursorIcon::SwResize,
216      "wresize" => CursorIcon::WResize,
217      "ewresize" => CursorIcon::EwResize,
218      "nsresize" => CursorIcon::NsResize,
219      "neswresize" => CursorIcon::NeswResize,
220      "nwseresize" => CursorIcon::NwseResize,
221      "colresize" => CursorIcon::ColResize,
222      "rowresize" => CursorIcon::RowResize,
223      _ => CursorIcon::Default,
224    })
225  }
226}
227
228/// Window size constraints
229#[derive(Clone, Copy, PartialEq, Debug, Default, Serialize, Deserialize)]
230#[serde(rename_all = "camelCase")]
231pub struct WindowSizeConstraints {
232  /// The minimum width a window can be, If this is `None`, the window will have no minimum width.
233  ///
234  /// The default is `None`.
235  pub min_width: Option<PixelUnit>,
236  /// The minimum height a window can be, If this is `None`, the window will have no minimum height.
237  ///
238  /// The default is `None`.
239  pub min_height: Option<PixelUnit>,
240  /// The maximum width a window can be, If this is `None`, the window will have no maximum width.
241  ///
242  /// The default is `None`.
243  pub max_width: Option<PixelUnit>,
244  /// The maximum height a window can be, If this is `None`, the window will have no maximum height.
245  ///
246  /// The default is `None`.
247  pub max_height: Option<PixelUnit>,
248}
249
250/// Do **NOT** implement this trait except for use in a custom [`Runtime`]
251///
252/// This trait is separate from [`WindowBuilder`] to prevent "accidental" implementation.
253pub trait WindowBuilderBase: std::fmt::Debug + Clone + Sized + 'static {}
254
255/// A builder for all attributes related to a single window.
256///
257/// This trait is only meant to be implemented by a custom [`Runtime`]
258/// and not by applications.
259pub trait WindowBuilder: WindowBuilderBase {
260  /// Initializes a new window attributes builder.
261  fn new() -> Self;
262
263  /// Initializes a new window builder from a [`WindowConfig`]
264  fn with_config(config: &WindowConfig) -> Self;
265
266  /// Show window in the center of the screen.
267  #[must_use]
268  fn center(self) -> Self;
269
270  /// The initial position of the window in logical pixels.
271  #[must_use]
272  fn position(self, x: f64, y: f64) -> Self;
273
274  /// Window size in logical pixels.
275  #[must_use]
276  fn inner_size(self, width: f64, height: f64) -> Self;
277
278  /// Window min inner size in logical pixels.
279  #[must_use]
280  fn min_inner_size(self, min_width: f64, min_height: f64) -> Self;
281
282  /// Window max inner size in logical pixels.
283  #[must_use]
284  fn max_inner_size(self, max_width: f64, max_height: f64) -> Self;
285
286  /// Window inner size constraints.
287  #[must_use]
288  fn inner_size_constraints(self, constraints: WindowSizeConstraints) -> Self;
289
290  /// Prevent the window from overflowing the working area (e.g. monitor size - taskbar size) on creation
291  ///
292  /// ## Platform-specific
293  ///
294  /// - **iOS / Android:** Unsupported.
295  #[must_use]
296  fn prevent_overflow(self) -> Self;
297
298  /// Prevent the window from overflowing the working area (e.g. monitor size - taskbar size)
299  /// on creation with a margin
300  ///
301  /// ## Platform-specific
302  ///
303  /// - **iOS / Android:** Unsupported.
304  #[must_use]
305  fn prevent_overflow_with_margin(self, margin: dpi::Size) -> Self;
306
307  /// Whether the window is resizable or not.
308  /// When resizable is set to false, native window's maximize button is automatically disabled.
309  #[must_use]
310  fn resizable(self, resizable: bool) -> Self;
311
312  /// Whether the window's native maximize button is enabled or not.
313  /// If resizable is set to false, this setting is ignored.
314  ///
315  /// ## Platform-specific
316  ///
317  /// - **macOS:** Disables the "zoom" button in the window titlebar, which is also used to enter fullscreen mode.
318  /// - **Linux / iOS / Android:** Unsupported.
319  #[must_use]
320  fn maximizable(self, maximizable: bool) -> Self;
321
322  /// Whether the window's native minimize button is enabled or not.
323  ///
324  /// ## Platform-specific
325  ///
326  /// - **Linux / iOS / Android:** Unsupported.
327  #[must_use]
328  fn minimizable(self, minimizable: bool) -> Self;
329
330  /// Whether the window's native close button is enabled or not.
331  ///
332  /// ## Platform-specific
333  ///
334  /// - **Linux:** "GTK+ will do its best to convince the window manager not to show a close button.
335  ///   Depending on the system, this function may not have any effect when called on a window that is already visible"
336  /// - **iOS / Android:** Unsupported.
337  #[must_use]
338  fn closable(self, closable: bool) -> Self;
339
340  /// The title of the window in the title bar.
341  #[must_use]
342  fn title<S: Into<String>>(self, title: S) -> Self;
343
344  /// Whether to start the window in fullscreen or not.
345  #[must_use]
346  fn fullscreen(self, fullscreen: bool) -> Self;
347
348  /// Whether the window will be initially focused or not.
349  #[must_use]
350  fn focused(self, focused: bool) -> Self;
351
352  /// Whether the window will be focusable or not.
353  #[must_use]
354  fn focusable(self, focusable: bool) -> Self;
355
356  /// Whether the window should be maximized upon creation.
357  #[must_use]
358  fn maximized(self, maximized: bool) -> Self;
359
360  /// Whether the window should be immediately visible upon creation.
361  #[must_use]
362  fn visible(self, visible: bool) -> Self;
363
364  /// Whether the window should be transparent. If this is true, writing colors
365  /// with alpha values different than `1.0` will produce a transparent window.
366  ///
367  /// On Windows, using `no_redirection_bitmap` can help avoid a white flash when
368  /// creating a transparent window.
369  #[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))]
370  #[cfg_attr(
371    docsrs,
372    doc(cfg(any(not(target_os = "macos"), feature = "macos-private-api")))
373  )]
374  #[must_use]
375  fn transparent(self, transparent: bool) -> Self;
376
377  /// Whether the window should have borders and bars.
378  #[must_use]
379  fn decorations(self, decorations: bool) -> Self;
380
381  /// Whether the window should always be below other windows.
382  #[must_use]
383  fn always_on_bottom(self, always_on_bottom: bool) -> Self;
384
385  /// Whether the window should always be on top of other windows.
386  #[must_use]
387  fn always_on_top(self, always_on_top: bool) -> Self;
388
389  /// Whether the window should be visible on all workspaces or virtual desktops.
390  #[must_use]
391  fn visible_on_all_workspaces(self, visible_on_all_workspaces: bool) -> Self;
392
393  /// Prevents the window contents from being captured by other apps.
394  #[must_use]
395  fn content_protected(self, protected: bool) -> Self;
396
397  /// Sets the window icon.
398  fn icon(self, icon: Icon) -> crate::Result<Self>;
399
400  /// Sets whether or not the window icon should be added to the taskbar.
401  #[must_use]
402  fn skip_taskbar(self, skip: bool) -> Self;
403
404  /// Set the window background color.
405  #[must_use]
406  fn background_color(self, color: Color) -> Self;
407
408  /// Sets whether or not the window has shadow.
409  ///
410  /// ## Platform-specific
411  ///
412  /// - **Windows:**
413  ///   - `false` has no effect on decorated window, shadows are always ON.
414  ///   - `true` will make undecorated window have a 1px white border,
415  ///     and on Windows 11, it will have a rounded corners.
416  /// - **Linux:** Unsupported.
417  #[must_use]
418  fn shadow(self, enable: bool) -> Self;
419
420  /// Set an owner to the window to be created.
421  ///
422  /// From MSDN:
423  /// - An owned window is always above its owner in the z-order.
424  /// - The system automatically destroys an owned window when its owner is destroyed.
425  /// - An owned window is hidden when its owner is minimized.
426  ///
427  /// For more information, see <https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#owned-windows>
428  #[cfg(windows)]
429  #[must_use]
430  fn owner(self, owner: HWND) -> Self;
431
432  /// Sets a parent to the window to be created.
433  ///
434  /// A child window has the WS_CHILD style and is confined to the client area of its parent window.
435  ///
436  /// For more information, see <https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#child-windows>
437  #[cfg(windows)]
438  #[must_use]
439  fn parent(self, parent: HWND) -> Self;
440
441  /// Sets a parent to the window to be created.
442  ///
443  /// See <https://developer.apple.com/documentation/appkit/nswindow/1419152-addchildwindow?language=objc>
444  #[cfg(target_os = "macos")]
445  #[must_use]
446  fn parent(self, parent: *mut std::ffi::c_void) -> Self;
447
448  /// Sets the window to be created transient for parent.
449  ///
450  /// See <https://docs.gtk.org/gtk3/method.Window.set_transient_for.html>
451  ///
452  /// # Ownership
453  ///
454  /// `parent` is a `GtkWindow*` passed as *transfer full*: the implementation takes ownership of
455  /// the strong reference and must release it (`g_object_unref`, i.e. glib's `from_glib_full`),
456  /// including when it does not support transient windows.
457  #[cfg(any(
458    target_os = "linux",
459    target_os = "dragonfly",
460    target_os = "freebsd",
461    target_os = "netbsd",
462    target_os = "openbsd"
463  ))]
464  fn transient_for(self, parent: *mut std::ffi::c_void) -> Self;
465
466  /// Enables or disables drag and drop support.
467  #[cfg(windows)]
468  #[must_use]
469  fn drag_and_drop(self, enabled: bool) -> Self;
470
471  /// Hide the titlebar. Titlebar buttons will still be visible.
472  #[cfg(target_os = "macos")]
473  #[must_use]
474  fn title_bar_style(self, style: tauri_utils::TitleBarStyle) -> Self;
475
476  /// Change the position of the window controls on macOS.
477  ///
478  /// Requires titleBarStyle: Overlay and decorations: true.
479  #[cfg(target_os = "macos")]
480  #[must_use]
481  fn traffic_light_position<P: Into<dpi::Position>>(self, position: P) -> Self;
482
483  /// Hide the window title.
484  #[cfg(target_os = "macos")]
485  #[must_use]
486  fn hidden_title(self, hidden: bool) -> Self;
487
488  /// Defines the window [tabbing identifier] for macOS.
489  ///
490  /// Windows with matching tabbing identifiers will be grouped together.
491  /// If the tabbing identifier is not set, automatic tabbing will be disabled.
492  ///
493  /// [tabbing identifier]: <https://developer.apple.com/documentation/appkit/nswindow/1644704-tabbingidentifier>
494  #[cfg(target_os = "macos")]
495  #[must_use]
496  fn tabbing_identifier(self, identifier: &str) -> Self;
497
498  /// Forces a theme or uses the system settings if None was provided.
499  fn theme(self, theme: Option<Theme>) -> Self;
500
501  /// Whether the icon was set or not.
502  fn has_icon(&self) -> bool;
503
504  fn get_theme(&self) -> Option<Theme>;
505
506  /// Sets custom name for Windows' window class. **Windows only**.
507  #[must_use]
508  fn window_classname<S: Into<String>>(self, window_classname: S) -> Self;
509
510  /// This sets `WS_EX_NOREDIRECTIONBITMAP`.
511  ///
512  /// This can avoid the white flash that may appear before the webview content is rendered
513  /// when using a transparent window. **Windows only**.
514  #[must_use]
515  fn no_redirection_bitmap(self, enable: bool) -> Self;
516
517  /// The name of the activity to create for this webview window.
518  #[cfg(target_os = "android")]
519  fn activity_name<S: Into<String>>(self, class_name: S) -> Self;
520
521  /// Sets the name of the activity that is creating this webview window.
522  ///
523  /// This is important to determine which stack the activity will belong to.
524  #[cfg(target_os = "android")]
525  fn created_by_activity_name<S: Into<String>>(self, class_name: S) -> Self;
526
527  /// Sets the identifier of the UIScene that is requesting the creation of this new scene,
528  /// establishing a relationship between the two scenes.
529  ///
530  /// By default the system uses the foreground scene.
531  #[cfg(target_os = "ios")]
532  fn requested_by_scene_identifier<S: Into<String>>(self, identifier: S) -> Self;
533}
534
535/// A window that has yet to be built.
536pub struct PendingWindow<T: UserEvent, R: Runtime<T>> {
537  /// The label that the window will be named.
538  pub label: String,
539
540  /// The [`WindowBuilder`] that the window will be created with.
541  pub window_builder: <R::WindowDispatcher as WindowDispatch<T>>::WindowBuilder,
542
543  /// The webview that gets added to the window. Optional in case you want to use child webviews or other window content instead.
544  pub webview: Option<PendingWebview<T, R>>,
545}
546
547pub fn is_label_valid(label: &str) -> bool {
548  label
549    .chars()
550    .all(|c| char::is_alphanumeric(c) || c == '-' || c == '/' || c == ':' || c == '_')
551}
552
553pub fn assert_label_is_valid(label: &str) {
554  assert!(
555    is_label_valid(label),
556    "Window label must include only alphanumeric characters, `-`, `/`, `:` and `_`."
557  );
558}
559
560impl<T: UserEvent, R: Runtime<T>> PendingWindow<T, R> {
561  /// Create a new [`PendingWindow`] with a label from the given [`WindowBuilder`].
562  pub fn new(
563    window_builder: <R::WindowDispatcher as WindowDispatch<T>>::WindowBuilder,
564    label: impl Into<String>,
565  ) -> crate::Result<Self> {
566    let label = label.into();
567    if !is_label_valid(&label) {
568      Err(crate::Error::InvalidWindowLabel)
569    } else {
570      Ok(Self {
571        window_builder,
572        label,
573        webview: None,
574      })
575    }
576  }
577
578  /// Sets a webview to be created on the window.
579  pub fn set_webview(&mut self, webview: PendingWebview<T, R>) -> &mut Self {
580    self.webview.replace(webview);
581    self
582  }
583}
584
585/// Identifier of a window.
586#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd)]
587pub struct WindowId(u32);
588
589impl From<u32> for WindowId {
590  fn from(value: u32) -> Self {
591    Self(value)
592  }
593}
594
595/// A window that is not yet managed by Tauri.
596#[derive(Debug)]
597pub struct DetachedWindow<T: UserEvent, R: Runtime<T>> {
598  /// The identifier of the window.
599  pub id: WindowId,
600  /// Name of the window
601  pub label: String,
602
603  /// The [`WindowDispatch`] associated with the window.
604  pub dispatcher: R::WindowDispatcher,
605
606  /// The webview dispatcher in case this window has an attached webview.
607  pub webview: Option<DetachedWindowWebview<T, R>>,
608}
609
610/// A detached webview associated with a window.
611#[derive(Debug)]
612pub struct DetachedWindowWebview<T: UserEvent, R: Runtime<T>> {
613  pub webview: DetachedWebview<T, R>,
614  pub use_https_scheme: bool,
615  /// Whether devtools was enabled in [`crate::webview::WebviewAttributes`]. `Some(false)` disables the inspector.
616  pub devtools: Option<bool>,
617}
618
619impl<T: UserEvent, R: Runtime<T>> Clone for DetachedWindowWebview<T, R> {
620  fn clone(&self) -> Self {
621    Self {
622      webview: self.webview.clone(),
623      use_https_scheme: self.use_https_scheme,
624      devtools: self.devtools,
625    }
626  }
627}
628
629impl<T: UserEvent, R: Runtime<T>> Clone for DetachedWindow<T, R> {
630  fn clone(&self) -> Self {
631    Self {
632      id: self.id,
633      label: self.label.clone(),
634      dispatcher: self.dispatcher.clone(),
635      webview: self.webview.clone(),
636    }
637  }
638}
639
640impl<T: UserEvent, R: Runtime<T>> Hash for DetachedWindow<T, R> {
641  /// Only use the [`DetachedWindow`]'s label to represent its hash.
642  fn hash<H: Hasher>(&self, state: &mut H) {
643    self.label.hash(state)
644  }
645}
646
647impl<T: UserEvent, R: Runtime<T>> Eq for DetachedWindow<T, R> {}
648impl<T: UserEvent, R: Runtime<T>> PartialEq for DetachedWindow<T, R> {
649  /// Only use the [`DetachedWindow`]'s label to compare equality.
650  fn eq(&self, other: &Self) -> bool {
651    self.label.eq(&other.label)
652  }
653}
654
655/// A raw window type that contains fields to access
656/// the HWND on Windows, GTK object pointers on Linux
657///
658/// # Ownership
659///
660/// Unlike the [`WindowDispatch`](crate::WindowDispatch) getters, the GTK pointers here are
661/// *transfer none*: they are borrowed from the window that is being created and are only valid for
662/// the duration of the callback that receives this struct. Wrap them with glib's `from_glib_none`
663/// (which takes its own reference) and do not store them - the `'a` lifetime is not enforced by
664/// the raw pointers, so retaining one past the callback dereferences freed memory.
665///
666/// The GTK major version of the objects is the one the runtime was built against, so consumers must
667/// wrap them with matching bindings.
668pub struct RawWindow<'a> {
669  /// The window handle on Windows.
670  #[cfg(windows)]
671  pub hwnd: isize,
672  /// A borrowed `GtkApplicationWindow*`. Never null.
673  #[cfg(any(
674    target_os = "linux",
675    target_os = "dragonfly",
676    target_os = "freebsd",
677    target_os = "netbsd",
678    target_os = "openbsd"
679  ))]
680  pub gtk_window: *mut std::ffi::c_void,
681  /// A borrowed `GtkBox*`, or [`None`] when the runtime does not add a default vertical box.
682  /// When set, it is never null.
683  #[cfg(any(
684    target_os = "linux",
685    target_os = "dragonfly",
686    target_os = "freebsd",
687    target_os = "netbsd",
688    target_os = "openbsd"
689  ))]
690  pub default_vbox: Option<*mut std::ffi::c_void>,
691  /// Ties this struct to the lifetime of the window the pointers above are borrowed from.
692  pub _marker: &'a PhantomData<()>,
693}