SDL  2.0
SDL_mirwindow.c
Go to the documentation of this file.
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
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
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
78 {
79  MIR_Window* mir_window;
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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: */
struct SDL_SysWMinfo::@18::@21 mir
#define SDL_MINOR_VERSION
Definition: SDL_version.h:61
void MIR_MinimizeWindow(_THIS, SDL_Window *window)
void SDL_SetKeyboardFocus(SDL_Window *window)
Definition: SDL_keyboard.c:612
void MIR_HideWindow(_THIS, SDL_Window *window)
static SDL_PixelFormat * formats
Definition: SDL_pixels.c:485
int MIR_GetWindowGammaRamp(_THIS, SDL_Window *window, Uint16 *ramp)
#define SDL_MAJOR_VERSION
Definition: SDL_version.h:60
int MIR_CreateWindow(_THIS, SDL_Window *window)
static SDL_Window * window
MirPixelFormat pixel_format
Definition: SDL_mirvideo.h:40
struct xkb_state * state
SDL_version version
Definition: SDL_syswm.h:195
Uint8 major
Definition: SDL_version.h:53
GLfloat f
void MIR_DestroyWindow(_THIS, SDL_Window *window)
SDL_SYSWM_TYPE subsystem
Definition: SDL_syswm.h:196
#define SDL_WINDOWPOS_UNDEFINED
Definition: SDL_video.h:127
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:159
void MIR_SetWindowGrab(_THIS, SDL_Window *window, SDL_bool grabbed)
static SDL_VideoDevice * _this
Definition: SDL_video.c:118
SDL_AudioSpec spec
Definition: loopwave.c:35
MirConnection * connection
Definition: SDL_mirvideo.h:36
SDL_bool software
Definition: SDL_mirvideo.h:39
void * SDL_calloc(size_t nmemb, size_t size)
MIR_Window * current_window
Definition: SDL_mirvideo.h:38
#define _THIS
void MIR_RestoreWindow(_THIS, SDL_Window *window)
void SDL_free(void *mem)
void MIR_SetWindowFullscreen(_THIS, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen)
void MIR_MaximizeWindow(_THIS, SDL_Window *window)
MIR_Data * mir_data
Definition: SDL_mirwindow.h:36
Uint8 minor
Definition: SDL_version.h:54
char * title
Definition: SDL_sysvideo.h:75
int MIR_SetWindowGammaRamp(_THIS, SDL_Window *window, Uint16 const *ramp)
void MIR_SetWindowTitle(_THIS, SDL_Window *window)
#define NULL
Definition: begin_code.h:143
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:130
EGLSurface egl_surface
Definition: SDL_mirwindow.h:39
#define SDL_SetError
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:1058
The type used to identify a window.
Definition: SDL_sysvideo.h:71
uint16_t Uint16
An unsigned 16-bit integer type.
Definition: SDL_stdinc.h:151
Uint32 pixel_format
Definition: testoverlay2.c:152
union SDL_SysWMinfo::@18 info
void * driverdata
Definition: SDL_sysvideo.h:109
MirSurface * surface
Definition: SDL_mirwindow.h:38
Uint32 flags
Definition: SDL_sysvideo.h:81
SDL_bool MIR_GetWindowWMInfo(_THIS, SDL_Window *window, SDL_SysWMinfo *info)
void MIR_SetWindowMaximumSize(_THIS, SDL_Window *window)
void MIR_HandleEvent(MirSurface *surface, MirEvent const *ev, void *context)
void MIR_SetWindowMinimumSize(_THIS, SDL_Window *window)
void MIR_SetWindowSize(_THIS, SDL_Window *window)
SDL_Window * sdl_window
Definition: SDL_mirwindow.h:35