1 /*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20 */
21
22 /*
23 Contributed by Brandon Schaefer, <brandon.schaefer@canonical.com>
24 */
25
26 #include "../../SDL_internal.h"
27
28 #if SDL_VIDEO_DRIVER_MIR
29
30 #include "../SDL_egl_c.h"
31 #include "../SDL_sysvideo.h"
32 #include "../../events/SDL_keyboard_c.h"
33
34 #include "SDL_mirevents.h"
35 #include "SDL_mirwindow.h"
36
37 #include "SDL_mirdyn.h"
38
39 int
IsSurfaceValid(MIR_Window * mir_window)40 IsSurfaceValid(MIR_Window* mir_window)
41 {
42 if (!MIR_mir_surface_is_valid(mir_window->surface)) {
43 const char* error = MIR_mir_surface_get_error_message(mir_window->surface);
44 return SDL_SetError("Failed to created a mir surface: %s", error);
45 }
46
47 return 0;
48 }
49
50 MirPixelFormat
FindValidPixelFormat(MIR_Data * mir_data)51 FindValidPixelFormat(MIR_Data* mir_data)
52 {
53 unsigned int pf_size = 32;
54 unsigned int valid_formats;
55 unsigned int f;
56
57 MirPixelFormat formats[pf_size];
58 MIR_mir_connection_get_available_surface_formats(mir_data->connection, formats,
59 pf_size, &valid_formats);
60
61 for (f = 0; f < valid_formats; f++) {
62 MirPixelFormat cur_pf = formats[f];
63
64 if (cur_pf == mir_pixel_format_abgr_8888 ||
65 cur_pf == mir_pixel_format_xbgr_8888 ||
66 cur_pf == mir_pixel_format_argb_8888 ||
67 cur_pf == mir_pixel_format_xrgb_8888) {
68
69 return cur_pf;
70 }
71 }
72
73 return mir_pixel_format_invalid;
74 }
75
76 int
MIR_CreateWindow(_THIS,SDL_Window * window)77 MIR_CreateWindow(_THIS, SDL_Window* window)
78 {
79 MIR_Window* mir_window;
80 MIR_Data* mir_data;
81 MirPixelFormat pixel_format;
82 MirBufferUsage buffer_usage;
83
84 MirSurfaceSpec* spec;
85
86 mir_window = SDL_calloc(1, sizeof(MIR_Window));
87 if (!mir_window)
88 return SDL_OutOfMemory();
89
90 mir_data = _this->driverdata;
91 window->driverdata = mir_window;
92
93 if (window->x == SDL_WINDOWPOS_UNDEFINED)
94 window->x = 0;
95
96 if (window->y == SDL_WINDOWPOS_UNDEFINED)
97 window->y = 0;
98
99 mir_window->mir_data = mir_data;
100 mir_window->sdl_window = window;
101
102 if (window->flags & SDL_WINDOW_OPENGL) {
103 pixel_format = MIR_mir_connection_get_egl_pixel_format(mir_data->connection,
104 _this->egl_data->egl_display,
105 _this->egl_data->egl_config);
106 }
107 else {
108 pixel_format = FindValidPixelFormat(mir_data);
109 }
110
111 mir_data->pixel_format = pixel_format;
112 if (pixel_format == mir_pixel_format_invalid) {
113 return SDL_SetError("Failed to find a valid pixel format.");
114 }
115
116 buffer_usage = mir_buffer_usage_hardware;
117 if (mir_data->software)
118 buffer_usage = mir_buffer_usage_software;
119
120 spec = MIR_mir_connection_create_spec_for_normal_surface(mir_data->connection,
121 window->w,
122 window->h,
123 pixel_format);
124
125 MIR_mir_surface_spec_set_buffer_usage(spec, buffer_usage);
126 MIR_mir_surface_spec_set_name(spec, "Mir surface");
127
128 if (window->flags & SDL_WINDOW_INPUT_FOCUS)
129 SDL_SetKeyboardFocus(window);
130
131 mir_window->surface = MIR_mir_surface_create_sync(spec);
132 MIR_mir_surface_set_event_handler(mir_window->surface, MIR_HandleEvent, window);
133
134 MIR_mir_surface_spec_release(spec);
135
136 if (!MIR_mir_surface_is_valid(mir_window->surface)) {
137 return SDL_SetError("Failed to created a mir surface: %s",
138 MIR_mir_surface_get_error_message(mir_window->surface));
139 }
140
141 if (window->flags & SDL_WINDOW_OPENGL) {
142 EGLNativeWindowType egl_native_window =
143 (EGLNativeWindowType)MIR_mir_buffer_stream_get_egl_native_window(
144 MIR_mir_surface_get_buffer_stream(mir_window->surface));
145
146 mir_window->egl_surface = SDL_EGL_CreateSurface(_this, egl_native_window);
147
148 if (mir_window->egl_surface == EGL_NO_SURFACE) {
149 return SDL_SetError("Failed to created a window surface %p",
150 _this->egl_data->egl_display);
151 }
152 }
153 else {
154 mir_window->egl_surface = EGL_NO_SURFACE;
155 }
156
157 mir_data->current_window = mir_window;
158
159 return 0;
160 }
161
162 void
MIR_DestroyWindow(_THIS,SDL_Window * window)163 MIR_DestroyWindow(_THIS, SDL_Window* window)
164 {
165 MIR_Data* mir_data = _this->driverdata;
166 MIR_Window* mir_window = window->driverdata;
167
168 if (mir_data) {
169 SDL_EGL_DestroySurface(_this, mir_window->egl_surface);
170 MIR_mir_surface_release_sync(mir_window->surface);
171
172 mir_data->current_window = NULL;
173
174 SDL_free(mir_window);
175 }
176 window->driverdata = NULL;
177 }
178
179 SDL_bool
MIR_GetWindowWMInfo(_THIS,SDL_Window * window,SDL_SysWMinfo * info)180 MIR_GetWindowWMInfo(_THIS, SDL_Window* window, SDL_SysWMinfo* info)
181 {
182 if (info->version.major == SDL_MAJOR_VERSION &&
183 info->version.minor == SDL_MINOR_VERSION) {
184 MIR_Window* mir_window = window->driverdata;
185
186 info->subsystem = SDL_SYSWM_MIR;
187 info->info.mir.connection = mir_window->mir_data->connection;
188 info->info.mir.surface = mir_window->surface;
189
190 return SDL_TRUE;
191 }
192
193 return SDL_FALSE;
194 }
195
196 void
MIR_SetWindowFullscreen(_THIS,SDL_Window * window,SDL_VideoDisplay * display,SDL_bool fullscreen)197 MIR_SetWindowFullscreen(_THIS, SDL_Window* window,
198 SDL_VideoDisplay* display,
199 SDL_bool fullscreen)
200 {
201 MIR_Data* mir_data = _this->driverdata;
202 MIR_Window* mir_window = window->driverdata;
203 MirSurfaceSpec* spec;
204 MirSurfaceState state;
205
206 if (IsSurfaceValid(mir_window) < 0)
207 return;
208
209 if (fullscreen) {
210 state = mir_surface_state_fullscreen;
211 } else {
212 state = mir_surface_state_restored;
213 }
214
215 spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
216 MIR_mir_surface_spec_set_state(spec, state);
217
218 MIR_mir_surface_apply_spec(mir_window->surface, spec);
219 MIR_mir_surface_spec_release(spec);
220 }
221
222 void
MIR_MaximizeWindow(_THIS,SDL_Window * window)223 MIR_MaximizeWindow(_THIS, SDL_Window* window)
224 {
225 MIR_Data* mir_data = _this->driverdata;
226 MIR_Window* mir_window = window->driverdata;
227 MirSurfaceSpec* spec;
228
229 if (IsSurfaceValid(mir_window) < 0)
230 return;
231
232 spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
233 MIR_mir_surface_spec_set_state(spec, mir_surface_state_maximized);
234
235 MIR_mir_surface_apply_spec(mir_window->surface, spec);
236 MIR_mir_surface_spec_release(spec);
237 }
238
239 void
MIR_MinimizeWindow(_THIS,SDL_Window * window)240 MIR_MinimizeWindow(_THIS, SDL_Window* window)
241 {
242 MIR_Data* mir_data = _this->driverdata;
243 MIR_Window* mir_window = window->driverdata;
244 MirSurfaceSpec* spec;
245
246 if (IsSurfaceValid(mir_window) < 0)
247 return;
248
249 spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
250 MIR_mir_surface_spec_set_state(spec, mir_surface_state_minimized);
251
252 MIR_mir_surface_apply_spec(mir_window->surface, spec);
253 MIR_mir_surface_spec_release(spec);
254 }
255
256 void
MIR_RestoreWindow(_THIS,SDL_Window * window)257 MIR_RestoreWindow(_THIS, SDL_Window * window)
258 {
259 MIR_Data* mir_data = _this->driverdata;
260 MIR_Window* mir_window = window->driverdata;
261 MirSurfaceSpec* spec;
262
263 if (IsSurfaceValid(mir_window) < 0)
264 return;
265
266 spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
267 MIR_mir_surface_spec_set_state(spec, mir_surface_state_restored);
268
269 MIR_mir_surface_apply_spec(mir_window->surface, spec);
270 MIR_mir_surface_spec_release(spec);
271 }
272
273 void
MIR_HideWindow(_THIS,SDL_Window * window)274 MIR_HideWindow(_THIS, SDL_Window* window)
275 {
276 MIR_Data* mir_data = _this->driverdata;
277 MIR_Window* mir_window = window->driverdata;
278 MirSurfaceSpec* spec;
279
280 if (IsSurfaceValid(mir_window) < 0)
281 return;
282
283 spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
284 MIR_mir_surface_spec_set_state(spec, mir_surface_state_hidden);
285
286 MIR_mir_surface_apply_spec(mir_window->surface, spec);
287 MIR_mir_surface_spec_release(spec);
288 }
289
290 void
MIR_SetWindowSize(_THIS,SDL_Window * window)291 MIR_SetWindowSize(_THIS, SDL_Window* window)
292 {
293 MIR_Data* mir_data = _this->driverdata;
294 MIR_Window* mir_window = window->driverdata;
295 MirSurfaceSpec* spec;
296
297 if (IsSurfaceValid(mir_window) < 0)
298 return;
299
300 /* You cannot set the x/y of a mir window! So only update w/h */
301 spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
302 MIR_mir_surface_spec_set_width (spec, window->w);
303 MIR_mir_surface_spec_set_height(spec, window->h);
304
305 MIR_mir_surface_apply_spec(mir_window->surface, spec);
306 MIR_mir_surface_spec_release(spec);
307 }
308
309 void
MIR_SetWindowMinimumSize(_THIS,SDL_Window * window)310 MIR_SetWindowMinimumSize(_THIS, SDL_Window* window)
311 {
312 MIR_Data* mir_data = _this->driverdata;
313 MIR_Window* mir_window = window->driverdata;
314 MirSurfaceSpec* spec;
315
316 if (IsSurfaceValid(mir_window) < 0)
317 return;
318
319 spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
320 MIR_mir_surface_spec_set_min_width (spec, window->min_w);
321 MIR_mir_surface_spec_set_min_height(spec, window->min_h);
322
323 MIR_mir_surface_apply_spec(mir_window->surface, spec);
324 MIR_mir_surface_spec_release(spec);
325 }
326
327 void
MIR_SetWindowMaximumSize(_THIS,SDL_Window * window)328 MIR_SetWindowMaximumSize(_THIS, SDL_Window* window)
329 {
330 MIR_Data* mir_data = _this->driverdata;
331 MIR_Window* mir_window = window->driverdata;
332 MirSurfaceSpec* spec;
333
334 if (IsSurfaceValid(mir_window) < 0)
335 return;
336
337 spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
338 MIR_mir_surface_spec_set_max_width (spec, window->max_w);
339 MIR_mir_surface_spec_set_max_height(spec, window->max_h);
340
341 MIR_mir_surface_apply_spec(mir_window->surface, spec);
342 MIR_mir_surface_spec_release(spec);
343 }
344
345 void
MIR_SetWindowTitle(_THIS,SDL_Window * window)346 MIR_SetWindowTitle(_THIS, SDL_Window* window)
347 {
348 MIR_Data* mir_data = _this->driverdata;
349 MIR_Window* mir_window = window->driverdata;
350 char const* title = window->title ? window->title : "";
351 MirSurfaceSpec* spec;
352
353 if (IsSurfaceValid(mir_window) < 0)
354 return;
355
356 spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
357 MIR_mir_surface_spec_set_name(spec, title);
358
359 MIR_mir_surface_apply_spec(mir_window->surface, spec);
360 MIR_mir_surface_spec_release(spec);
361 }
362
363 void
MIR_SetWindowGrab(_THIS,SDL_Window * window,SDL_bool grabbed)364 MIR_SetWindowGrab(_THIS, SDL_Window* window, SDL_bool grabbed)
365 {
366 MIR_Data* mir_data = _this->driverdata;
367 MIR_Window* mir_window = window->driverdata;
368 MirPointerConfinementState confined = mir_pointer_unconfined;
369 MirSurfaceSpec* spec;
370
371 if (grabbed)
372 confined = mir_pointer_confined_to_surface;
373
374 spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
375 MIR_mir_surface_spec_set_pointer_confinement(spec, confined);
376
377 MIR_mir_surface_apply_spec(mir_window->surface, spec);
378 MIR_mir_surface_spec_release(spec);
379 }
380
381 int
MIR_SetWindowGammaRamp(_THIS,SDL_Window * window,Uint16 const * ramp)382 MIR_SetWindowGammaRamp(_THIS, SDL_Window* window, Uint16 const* ramp)
383 {
384 MirOutput* output = SDL_GetDisplayForWindow(window)->driverdata;
385 Uint32 ramp_size = 256;
386
387 // FIXME Need to apply the changes to the output, once that public API function is around
388 if (MIR_mir_output_is_gamma_supported(output) == mir_output_gamma_supported) {
389 MIR_mir_output_set_gamma(output,
390 ramp + ramp_size * 0,
391 ramp + ramp_size * 1,
392 ramp + ramp_size * 2,
393 ramp_size);
394 return 0;
395 }
396
397 return -1;
398 }
399
400 int
MIR_GetWindowGammaRamp(_THIS,SDL_Window * window,Uint16 * ramp)401 MIR_GetWindowGammaRamp(_THIS, SDL_Window* window, Uint16* ramp)
402 {
403 MirOutput* output = SDL_GetDisplayForWindow(window)->driverdata;
404 Uint32 ramp_size = 256;
405
406 if (MIR_mir_output_is_gamma_supported(output) == mir_output_gamma_supported) {
407 if (MIR_mir_output_get_gamma_size(output) == ramp_size) {
408 MIR_mir_output_get_gamma(output,
409 ramp + ramp_size * 0,
410 ramp + ramp_size * 1,
411 ramp + ramp_size * 2,
412 ramp_size);
413 return 0;
414 }
415 }
416
417 return -1;
418 }
419
420 #endif /* SDL_VIDEO_DRIVER_MIR */
421
422 /* vi: set ts=4 sw=4 expandtab: */
423