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
//! `Window` to display web content in an [`App`].
//!
//! An [`App`] can have multiple [`Window`]s, and each [`Window`] can
//! have multiple [`Overlay`]s managing multiple [`View`]s.
//!
//! [`App`]: crate::app::App
use std::{self, ffi::CString, sync::Arc};
use crate::{overlay::Overlay, view::Cursor, view::View, Library};
/// Window creation flags
pub struct WindowFlags {
/// Whether the window has borders or not
pub borderless: bool,
/// Whether the window has title or not
pub titled: bool,
/// Whether the window is resizable or not
pub resizable: bool,
/// Whether the window is maximizable or not
pub maximizable: bool,
/// The initial hide/show state of the window
pub hidden: bool,
}
impl WindowFlags {
/// Helper to convert this struct to a union enum for the C API
fn to_u32(&self) -> u32 {
let mut n = 0;
if self.borderless {
n |= ul_sys::ULWindowFlags_kWindowFlags_Borderless;
}
if self.titled {
n |= ul_sys::ULWindowFlags_kWindowFlags_Titled;
}
if self.resizable {
n |= ul_sys::ULWindowFlags_kWindowFlags_Resizable;
}
if self.maximizable {
n |= ul_sys::ULWindowFlags_kWindowFlags_Maximizable;
}
if self.hidden {
n |= ul_sys::ULWindowFlags_kWindowFlags_Hidden;
}
n
}
}
/// Window struct, represents a platform window.
pub struct Window {
lib: Arc<Library>,
internal: ul_sys::ULWindow,
need_to_destroy: bool,
}
impl Window {
/// Internal function helper to create a view.
/// (See [`App::create_window`](crate::app::App::create_window))
///
/// Returns [`None`] if failed to create the window.
pub(crate) unsafe fn create(
lib: Arc<Library>,
monitor_raw: ul_sys::ULMonitor,
width: u32,
height: u32,
fullscreen: bool,
window_flags: WindowFlags,
) -> Option<Self> {
let internal = lib.appcore().ulCreateWindow(
monitor_raw,
width,
height,
fullscreen,
window_flags.to_u32(),
);
if internal.is_null() {
None
} else {
Some(Self {
lib,
internal,
need_to_destroy: true,
})
}
}
/// Helper internal function to allow getting a reference to a managed
/// session.
pub(crate) unsafe fn from_raw(lib: Arc<Library>, raw: ul_sys::ULWindow) -> Option<Self> {
if raw.is_null() {
None
} else {
Some(Self {
lib,
internal: raw,
need_to_destroy: false,
})
}
}
/// Get the window width (in screen coordinates).
pub fn screen_width(&self) -> u32 {
unsafe { self.lib.appcore().ulWindowGetScreenWidth(self.internal) }
}
/// Get the window width (in pixels).
pub fn width(&self) -> u32 {
unsafe { self.lib.appcore().ulWindowGetWidth(self.internal) }
}
/// Get the window height (in screen coordinates).
pub fn screen_height(&self) -> u32 {
unsafe { self.lib.appcore().ulWindowGetScreenHeight(self.internal) }
}
/// Get the window height (in pixels).
pub fn height(&self) -> u32 {
unsafe { self.lib.appcore().ulWindowGetHeight(self.internal) }
}
/// Move the window to a new position (in screen coordinates) relative
/// to the top-left of the monitor area.
pub fn move_to(&self, x: i32, y: i32) {
unsafe { self.lib.appcore().ulWindowMoveTo(self.internal, x, y) }
}
/// Move the window to the center of the monitor.
pub fn move_to_center(&self) {
unsafe { self.lib.appcore().ulWindowMoveToCenter(self.internal) }
}
/// Get the x-position of the window (in screen coordinates) relative
/// to the top-left of the monitor area.
pub fn x(&self) -> i32 {
unsafe { self.lib.appcore().ulWindowGetPositionX(self.internal) }
}
/// Get the y-position of the window (in screen coordinates) relative
/// to the top-left of the monitor area.
pub fn y(&self) -> i32 {
unsafe { self.lib.appcore().ulWindowGetPositionY(self.internal) }
}
/// Whether or not the window is fullscreen.
pub fn is_fullscreen(&self) -> bool {
unsafe { self.lib.appcore().ulWindowIsFullscreen(self.internal) }
}
/// The DPI scale of the window.
pub fn scale(&self) -> f64 {
unsafe { self.lib.appcore().ulWindowGetScale(self.internal) }
}
/// Set the window title.
pub fn set_title(&self, title: &str) {
let c_string = CString::new(title).unwrap();
unsafe {
self.lib
.appcore()
.ulWindowSetTitle(self.internal, c_string.as_ptr())
}
}
/// Set the cursor.
pub fn set_cursor(&self, cursor: Cursor) {
unsafe {
self.lib
.appcore()
.ulWindowSetCursor(self.internal, cursor as u32)
}
}
/// Show the window (if it was previously hidden).
pub fn show(&self) {
unsafe { self.lib.appcore().ulWindowShow(self.internal) }
}
/// Hide the window.
pub fn hide(&self) {
unsafe { self.lib.appcore().ulWindowHide(self.internal) }
}
/// Whether or not the window is currently visible (not hidden).
pub fn is_visible(&self) -> bool {
unsafe { self.lib.appcore().ulWindowIsVisible(self.internal) }
}
/// Close the window.
pub fn close(&self) {
unsafe { self.lib.appcore().ulWindowClose(self.internal) }
}
/// Convert screen coordinates to pixels using the current DPI scale.
pub fn screen_to_pixels(&self, val: i32) -> i32 {
unsafe {
self.lib
.appcore()
.ulWindowScreenToPixels(self.internal, val)
}
}
/// Convert pixels to screen coordinates using the current DPI scale.
pub fn pixels_to_screen(&self, val: i32) -> i32 {
unsafe {
self.lib
.appcore()
.ulWindowPixelsToScreen(self.internal, val)
}
}
set_callback! {
/// Called when the Window is closed.
///
/// # Callback Arguments
/// * `window: &Window` - The window that fired the event (eg. self)
pub fn set_close_callback(&self, callback: FnMut(window: &Window)) :
[Window::lib.appcore()][s] ulWindowSetCloseCallback(ul_window: ul_sys::ULWindow) {
let window = &Window::from_raw(s.lib.clone(), ul_window).unwrap();
}
}
set_callback! {
/// Called when the Window is resized.
///
/// # Callback Arguments
/// * `window: &Window` - The window that fired the event (eg. self)
/// * `width: u32` - The new width of the window (in pixels)
/// * `height: u32` - The new height of the window (in pixels)
pub fn set_resize_callback(&self, callback: FnMut(window: &Window, width: u32, height: u32)) :
[Window::lib.appcore()][s] ulWindowSetResizeCallback(ul_window: ul_sys::ULWindow, width: u32, height: u32) {
let window = &Window::from_raw(s.lib.clone(), ul_window).unwrap();
}
}
//pub fn is_accelerated(&self) -> bool {
//}
//
//pub fn render_buff_id(&self) -> u32 {
//}
//
//pub fn draw_surface(&self, surface: &Surface) {
//}
}
impl Window {
/// Create a new Overlay.
///
/// # Arguments
/// * `width` - The width in pixels.
/// * `height` - The height in pixels.
/// * `x` - The x-position (offset from the left of this Window), in pixels.
/// * `y` - The y-position (offset from the top of this Window), in pixels.
///
/// Returns [`None`] if failed to create [`Overlay`].
pub fn create_overlay(&self, width: u32, height: u32, x: i32, y: i32) -> Option<Overlay> {
unsafe { Overlay::create(self.lib.clone(), self.internal, width, height, x, y) }
}
/// Create a new Overlay, wrapping an existing view.
///
/// # Arguments
/// * `view` - The view to wrap (will use its width and height).
/// * `x` - The x-position (offset from the left of this Window), in pixels.
/// * `y` - The y-position (offset from the top of this Window), in pixels.
///
/// Returns [`None`] if failed to create [`Overlay`].
pub fn create_overlay_with_view(&self, view: View, x: i32, y: i32) -> Option<Overlay> {
unsafe { Overlay::create_with_view(self.lib.clone(), self.internal, view, x, y) }
}
}
impl Drop for Window {
fn drop(&mut self) {
if self.need_to_destroy {
unsafe { self.lib.appcore().ulDestroyWindow(self.internal) }
}
}
}