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
// window.rs -- Aldaron's Window Interface
// Copyright (c) 2017-2018  Jeron A. Lau <jeron.lau@plopgrizzly.com>
// Licensed under the MIT LICENSE

use afi;

use WindowOps;

/// A window on Windows, Android, IOS, Wayland, XWindows, Direct to Display,
/// Aldaron's OS, Arduino, Nintendo Switch, A Web Page, or No OS.
pub struct Window {
	os_window: ::os_window::OSWindow,
	input_queue: ::input::InputQueue,
	dimensions: (u32, u32),
	keyboard: ::Keyboard,
	reset: bool,
}

impl Window {
	/// Create a window, using `title` as the title, and `icon` as the
	/// window icon.  The format of icon is as follows:
	/// `(width, height, pixels)`.  You can load icons with aci.  `v` should
	/// be either `None` or `Some(visual_id from EGL)`.
	pub fn new(title: &str, icon: &afi::Graphic, v: Option<i32>)
		-> Window
	{
		let mut icon = (*icon).clone();

		icon.bgra();

		let os_window = ::os_window::OSWindow::new(title,
			icon.as_slice(), v);
		let dimensions = (::MWW, ::MWH); // Width & Height
		let input_queue = ::input::InputQueue::new();
		let keyboard = ::Keyboard::new();
		let reset = false;

		// Make the window visible.
		os_window.show();
		// Update the window.
		os_window.update();

		Window { os_window, dimensions, input_queue, keyboard, reset }
	}

	/// Toggle whether the window is fullscreen.
	pub fn fullscreen(&mut self) {
		self.os_window.fullscreen();
	}

	/// Get the type of connection, plus native window and connection
	/// handles to pass to ffi.  See `WindowConnection` for more details.
	pub fn get_connection(&self) -> ::WindowConnection {
		self.os_window.get_connection()
	}

	/// Get the width and height of the window, as a tuple.
	pub fn wh(&self) -> (u32, u32) {
		self.dimensions
	}

	/// Poll window input, return `None` when finished.  After returning
	/// `None`, the next call will update the window.
	pub fn update(&mut self) -> Option<::Input> {
		// First, update & get events
		// Next, cycle them
		// Then, Return None when through event loop.
		if let Some(input) = self.input_queue.pop() {
			return Some(input);
		} else if self.reset {
			self.reset = false;
			return None;
		}

		self.reset = true;
		self.os_window.update();
		self.get_events();

		self.update()
	}

	/// Poll for events.
	fn get_events(&mut self) {
		// Get window events, and update keyboard state.
		while self.os_window.poll_event(&mut self.input_queue,
			&mut self.dimensions, &mut self.keyboard) {}

		// Generate keyboard events from keyboard state.
		self.keyboard.add(&mut self.input_queue);

		// If F11 pressed, toggle fullscreen.
		if self.input_queue.get_fullscreen() {
			self.fullscreen();
		}
	}
}