/
display.d
206 lines (163 loc) · 5.59 KB
/
display.d
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
module hardware.display;
import std.array;
import std.string;
import basics.cmdargs;
import basics.help; // positive mod
import basics.alleg5;
import basics.globals; // nameOfTheGame
import basics.user; // what windowed resolution does the user want
import file.log;
static import hardware.keyboard; // clear after changing resolution
static import hardware.mouse; // untrap the mouse when we leave the display
/* A module for setting a screen resolution.
* Right now, if you switch the screen resolution after having created all
* the bitmaps, they will be put into RAM, and subsequent drawing will be
* extremely slow. Avoid switching the resolution at all costs, or implement
* something to improve performance after the switch.
*/
ALLEGRO_DISPLAY* display;
private:
ALLEGRO_EVENT_QUEUE* queue;
bool _displayCloseWasClicked;
long[] _fpsArr;
public:
bool
displayCloseWasClicked() {
return _displayCloseWasClicked;
}
void
flip_display() {
assert (display, "display hasn't been created");
al_flip_display();
// compute FPS, query result with displayFps()
_fpsArr ~= timerTicks;
while (_fpsArr != null && _fpsArr[0] <= _fpsArr[$-1] - ticksPerSecond)
_fpsArr = _fpsArr[1 .. $];
}
@property int
displayFps()
{
return _fpsArr.len;
}
@property int
displayXl()
{
assert(display, "display hasn't been created");
return al_get_display_width(display);
}
@property int
displayYl()
{
assert(display, "display hasn't been created");
return al_get_display_height(display);
}
// This is like initialize() of other modules.
// For fullscreen, query the underlying desktop environment for resolution.
// For winwoded, use the wanted resolution, or fall back to 640 x 480.
void setScreenMode(in Cmdargs cmdargs)
{
struct TryMode {
bool full;
int x, y;
}
// FIFO queue of screen modes to try
TryMode[] try_modes;
// first priority goes to using setScreenMode()'s arguments, if they exist
if (cmdargs.forceHardwareFullscreen) {
if (cmdargs.wantResolutionX > 0 && cmdargs.wantResolutionY > 0)
try_modes ~= TryMode(true, cmdargs.wantResolutionX,
cmdargs.wantResolutionY);
else try_modes ~= TryMode(true, 640, 480);
}
if (cmdargs.forceWindowed) {
if (cmdargs.wantResolutionX > 0 && cmdargs.wantResolutionY > 0)
try_modes ~= TryMode(false, cmdargs.wantResolutionX,
cmdargs.wantResolutionY);
else try_modes ~= TryMode(false, 640, 480);
}
// second priority goes to the normal fullscreen/windowed modes
void addFullscreenTryModes() {
try_modes ~= TryMode(true, 0, 0);
try_modes ~= TryMode(true, 640, 480);
}
void addWindowedTryModes() {
if (screenWindowedX.value > 0 && screenWindowedY.value > 0) {
try_modes ~= TryMode(false, screenWindowedX, screenWindowedY);
}
try_modes ~= TryMode(false, 640, 480);
}
if (! cmdargs.forceSoftwareFullscreen
&& (cmdargs.forceWindowed || basics.user.screenWindowed.value)
) {
addWindowedTryModes();
addFullscreenTryModes();
}
else {
addFullscreenTryModes();
addWindowedTryModes();
}
immutable fullscreen_flag = cmdargs.forceHardwareFullscreen
? ALLEGRO_FULLSCREEN : ALLEGRO_FULLSCREEN_WINDOW;
// now try the modes in the desired order
foreach (ref mode; try_modes) {
int flags = al_get_new_display_flags()
& ~ ALLEGRO_WINDOWED
& ~ ALLEGRO_FULLSCREEN
& ~ ALLEGRO_FULLSCREEN_WINDOW;
if (mode.full) flags = flags | fullscreen_flag;
else flags = flags | ALLEGRO_WINDOWED;
al_set_new_display_flags(flags);
deinitialize();
display = al_create_display(mode.x, mode.y);
if (display) {
// Shotgun debugging to prevent Icho's white window.
// An Allegro 5 user reported that this makes the window black.
al_flip_display();
// If that doesn't help with Icho, try this instead:
// al_clear_to_color(ALLEGRO_COLOR(0, 0, 0, 1)); // black
// al_flip_display();
// don't try further modes on success
break;
}
}
// cleaning up after the change, (re)instantiating the event queue
assert (display);
immutable int al_x = al_get_display_width (display);
immutable int al_y = al_get_display_height(display);
immutable int al_f = al_get_display_flags (display) & fullscreen_flag;
assert (al_x > 0);
assert (al_y > 0);
al_set_window_title(display, nameOfTheGame.toStringz);
queue = al_create_event_queue();
al_register_event_source(queue, al_get_display_event_source(display));
}
void deinitialize()
{
if (display) {
al_unregister_event_source(queue,al_get_display_event_source(display));
al_destroy_display(display);
display = null;
}
if (queue) {
al_destroy_event_queue(queue);
queue = null;
}
}
void calc()
{
ALLEGRO_EVENT event;
while(al_get_next_event(queue, &event))
{
if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
_displayCloseWasClicked = true;
}
else if (event.type == ALLEGRO_EVENT_DISPLAY_SWITCH_OUT) {
hardware.mouse.trapMouse(false);
}
else if (event.type == ALLEGRO_EVENT_DISPLAY_SWITCH_IN) {
hardware.keyboard.clearKeyBufferAfterAltTab();
// Don't affect the mouse: the mouse shall only be trapped
// when it is clicked in the game window
}
}
}