SDL  2.0
SDL_mirwindow.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2018 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 static int
40 IsMirWindowValid(MIR_Window* mir_window)
41 {
42  if (!MIR_mir_window_is_valid(mir_window->window)) {
43  const char* error = MIR_mir_window_get_error_message(mir_window->window);
44  return SDL_SetError("Failed to create a mir surface: %s", error);
45  }
46 
47  return 1;
48 }
49 
50 static 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  MirWindowSpec* spec;
85 
86  mir_window = SDL_calloc(1, sizeof(MIR_Window));
87  if (!mir_window)
88  return SDL_OutOfMemory();
89 
91  window->driverdata = mir_window;
92 
94  window->x = 0;
95 
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_create_normal_window_spec(mir_data->connection,
121  window->w,
122  window->h);
123 
124  MIR_mir_window_spec_set_buffer_usage(spec, buffer_usage);
125  MIR_mir_window_spec_set_name(spec, "Mir surface");
126  MIR_mir_window_spec_set_pixel_format(spec, pixel_format);
127 
128  if (window->flags & SDL_WINDOW_INPUT_FOCUS)
130 
131  mir_window->window = MIR_mir_create_window_sync(spec);
132  MIR_mir_window_set_event_handler(mir_window->window, MIR_HandleEvent, window);
133 
134  MIR_mir_window_spec_release(spec);
135 
136  if (!MIR_mir_window_is_valid(mir_window->window)) {
137  return SDL_SetError("Failed to create a mir surface: %s",
138  MIR_mir_window_get_error_message(mir_window->window));
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_window_get_buffer_stream(mir_window->window));
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 create 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 {
166  MIR_Window* mir_window = window->driverdata;
167 
168  if (mir_data) {
169  SDL_EGL_DestroySurface(_this, mir_window->egl_surface);
170  MIR_mir_window_release_sync(mir_window->window);
171 
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  // Cannot change this to window due to it being in the public API
189  info->info.mir.surface = mir_window->window;
190 
191  return SDL_TRUE;
192  }
193 
194  return SDL_FALSE;
195 }
196 
197 static void
198 UpdateMirWindowState(MIR_Data* mir_data, MIR_Window* mir_window, MirWindowState window_state)
199 {
200  if (IsMirWindowValid(mir_window)) {
201  MirWindowSpec* spec = MIR_mir_create_window_spec(mir_data->connection);
202  MIR_mir_window_spec_set_state(spec, window_state);
203 
204  MIR_mir_window_apply_spec(mir_window->window, spec);
205  MIR_mir_window_spec_release(spec);
206  }
207 }
208 
209 void
211  SDL_VideoDisplay* display,
212  SDL_bool fullscreen)
213 {
214  if (IsMirWindowValid(window->driverdata)) {
215  MirWindowState state;
216 
217  if (fullscreen) {
218  state = mir_window_state_fullscreen;
219  }
220  else {
221  state = mir_window_state_restored;
222  }
223 
224  UpdateMirWindowState(_this->driverdata, window->driverdata, state);
225  }
226 }
227 
228 void
230 {
231  UpdateMirWindowState(_this->driverdata, window->driverdata, mir_window_state_maximized);
232 }
233 
234 void
236 {
237  UpdateMirWindowState(_this->driverdata, window->driverdata, mir_window_state_minimized);
238 }
239 
240 void
242 {
243  UpdateMirWindowState(_this->driverdata, window->driverdata, mir_window_state_restored);
244 }
245 
246 void
248 {
249  UpdateMirWindowState(_this->driverdata, window->driverdata, mir_window_state_hidden);
250 }
251 
252 void
254 {
256  MIR_Window* mir_window = window->driverdata;
257 
258  if (IsMirWindowValid(mir_window)) {
259  MirWindowSpec* spec = MIR_mir_create_window_spec(mir_data->connection);
260  MIR_mir_window_spec_set_width (spec, window->w);
261  MIR_mir_window_spec_set_height(spec, window->h);
262 
263  MIR_mir_window_apply_spec(mir_window->window, spec);
264  }
265 }
266 
267 void
269 {
271  MIR_Window* mir_window = window->driverdata;
272 
273  if (IsMirWindowValid(mir_window)) {
274  MirWindowSpec* spec = MIR_mir_create_window_spec(mir_data->connection);
275  MIR_mir_window_spec_set_min_width (spec, window->min_w);
276  MIR_mir_window_spec_set_min_height(spec, window->min_h);
277 
278  MIR_mir_window_apply_spec(mir_window->window, spec);
279  }
280 }
281 
282 void
284 {
286  MIR_Window* mir_window = window->driverdata;
287 
288  if (IsMirWindowValid(mir_window)) {
289  MirWindowSpec* spec = MIR_mir_create_window_spec(mir_data->connection);
290  MIR_mir_window_spec_set_max_width (spec, window->max_w);
291  MIR_mir_window_spec_set_max_height(spec, window->max_h);
292 
293  MIR_mir_window_apply_spec(mir_window->window, spec);
294  }
295 }
296 
297 void
299 {
301  MIR_Window* mir_window = window->driverdata;
302  char const* title = window->title ? window->title : "";
303  MirWindowSpec* spec;
304 
305  if (IsMirWindowValid(mir_window) < 0)
306  return;
307 
308  spec = MIR_mir_create_window_spec(mir_data->connection);
309  MIR_mir_window_spec_set_name(spec, title);
310 
311  MIR_mir_window_apply_spec(mir_window->window, spec);
312  MIR_mir_window_spec_release(spec);
313 }
314 
315 void
317 {
319  MIR_Window* mir_window = window->driverdata;
320  MirPointerConfinementState confined = mir_pointer_unconfined;
321  MirWindowSpec* spec;
322 
323  if (grabbed)
324  confined = mir_pointer_confined_to_window;
325 
326  spec = MIR_mir_create_window_spec(mir_data->connection);
327  MIR_mir_window_spec_set_pointer_confinement(spec, confined);
328 
329  MIR_mir_window_apply_spec(mir_window->window, spec);
330  MIR_mir_window_spec_release(spec);
331 }
332 
333 int
335 {
337  Uint32 ramp_size = 256;
338 
339  // FIXME Need to apply the changes to the output, once that public API function is around
340  if (MIR_mir_output_is_gamma_supported(output) == mir_output_gamma_supported) {
341  MIR_mir_output_set_gamma(output,
342  ramp + ramp_size * 0,
343  ramp + ramp_size * 1,
344  ramp + ramp_size * 2,
345  ramp_size);
346  return 0;
347  }
348 
349  return -1;
350 }
351 
352 int
354 {
356  Uint32 ramp_size = 256;
357 
358  if (MIR_mir_output_is_gamma_supported(output) == mir_output_gamma_supported) {
359  if (MIR_mir_output_get_gamma_size(output) == ramp_size) {
360  MIR_mir_output_get_gamma(output,
361  ramp + ramp_size * 0,
362  ramp + ramp_size * 1,
363  ramp + ramp_size * 2,
364  ramp_size);
365  return 0;
366  }
367  }
368 
369  return -1;
370 }
371 
372 #endif /* SDL_VIDEO_DRIVER_MIR */
373 
374 /* vi: set ts=4 sw=4 expandtab: */
MIR_Window::window
MirWindow * window
Definition: SDL_mirwindow.h:38
MIR_Window
Definition: SDL_mirwindow.h:34
MIR_SetWindowTitle
void MIR_SetWindowTitle(_THIS, SDL_Window *window)
SDL_VideoDevice::driverdata
void * driverdata
Definition: SDL_sysvideo.h:381
Uint16
uint16_t Uint16
Definition: SDL_stdinc.h:191
MIR_Data::pixel_format
MirPixelFormat pixel_format
Definition: SDL_mirvideo.h:41
SDL_mirwindow.h
MIR_Window::mir_data
MIR_Data * mir_data
Definition: SDL_mirwindow.h:36
MIR_SetWindowFullscreen
void MIR_SetWindowFullscreen(_THIS, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen)
NULL
#define NULL
Definition: begin_code.h:164
SDL_SysWMinfo
Definition: SDL_syswm.h:195
SDL_mirevents.h
SDL_version::minor
Uint8 minor
Definition: SDL_version.h:54
SDL_GetDisplayForWindow
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:1092
SDL_WINDOW_OPENGL
@ SDL_WINDOW_OPENGL
Definition: SDL_video.h:101
SDL_WINDOWPOS_UNDEFINED
#define SDL_WINDOWPOS_UNDEFINED
Definition: SDL_video.h:130
MIR_Window::egl_surface
EGLSurface egl_surface
Definition: SDL_mirwindow.h:39
SDL_SetKeyboardFocus
void SDL_SetKeyboardFocus(SDL_Window *window)
Definition: SDL_keyboard.c:630
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:203
MIR_DestroyWindow
void MIR_DestroyWindow(_THIS, SDL_Window *window)
MIR_MinimizeWindow
void MIR_MinimizeWindow(_THIS, SDL_Window *window)
SDL_WINDOW_INPUT_FOCUS
@ SDL_WINDOW_INPUT_FOCUS
Definition: SDL_video.h:109
SDL_Window
The type used to identify a window.
Definition: SDL_sysvideo.h:74
MIR_SetWindowMinimumSize
void MIR_SetWindowMinimumSize(_THIS, SDL_Window *window)
MIR_SetWindowGammaRamp
int MIR_SetWindowGammaRamp(_THIS, SDL_Window *window, Uint16 const *ramp)
_this
static SDL_VideoDevice * _this
Definition: SDL_video.c:121
SDL_MINOR_VERSION
#define SDL_MINOR_VERSION
Definition: SDL_version.h:61
SDL_SysWMinfo::subsystem
SDL_SYSWM_TYPE subsystem
Definition: SDL_syswm.h:197
window
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
EGL_NO_SURFACE
#define EGL_NO_SURFACE
Definition: egl.h:100
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
SDL_SysWMinfo::info
union SDL_SysWMinfo::@18 info
f
GLfloat f
Definition: SDL_opengl_glext.h:1870
MIR_Data
Definition: SDL_mirvideo.h:36
MIR_Data::connection
MirConnection * connection
Definition: SDL_mirvideo.h:37
MIR_Window::sdl_window
SDL_Window * sdl_window
Definition: SDL_mirwindow.h:35
_THIS
#define _THIS
Definition: SDL_alsa_audio.h:31
MIR_Data::software
SDL_bool software
Definition: SDL_mirvideo.h:40
SDL_TRUE
@ SDL_TRUE
Definition: SDL_stdinc.h:164
MIR_SetWindowMaximumSize
void MIR_SetWindowMaximumSize(_THIS, SDL_Window *window)
formats
EGLint EGLint * formats
Definition: eglext.h:718
SDL_VideoDisplay::driverdata
void * driverdata
Definition: SDL_sysvideo.h:139
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
spec
SDL_AudioSpec spec
Definition: loopwave.c:31
MIR_HandleEvent
void MIR_HandleEvent(MirWindow *, MirEvent const *ev, void *context)
SDL_calloc
#define SDL_calloc
Definition: SDL_dynapi_overrides.h:375
SDL_mirdyn.h
MIR_Data::current_window
MIR_Window * current_window
Definition: SDL_mirvideo.h:39
MIR_MaximizeWindow
void MIR_MaximizeWindow(_THIS, SDL_Window *window)
EGLNativeWindowType
HWND EGLNativeWindowType
Definition: eglplatform.h:78
MIR_SetWindowGrab
void MIR_SetWindowGrab(_THIS, SDL_Window *window, SDL_bool grabbed)
SDL_SysWMinfo::version
SDL_version version
Definition: SDL_syswm.h:196
MIR_RestoreWindow
void MIR_RestoreWindow(_THIS, SDL_Window *window)
sort_controllers.output
output
Definition: sort_controllers.py:10
SDL_VideoDisplay
Definition: SDL_sysvideo.h:126
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
MIR_HideWindow
void MIR_HideWindow(_THIS, SDL_Window *window)
MIR_SetWindowSize
void MIR_SetWindowSize(_THIS, SDL_Window *window)
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:162
SDL_FALSE
@ SDL_FALSE
Definition: SDL_stdinc.h:163
SDL_SYSWM_MIR
@ SDL_SYSWM_MIR
Definition: SDL_syswm.h:125
SDL_version::major
Uint8 major
Definition: SDL_version.h:53
SDL_MAJOR_VERSION
#define SDL_MAJOR_VERSION
Definition: SDL_version.h:60
MIR_GetWindowGammaRamp
int MIR_GetWindowGammaRamp(_THIS, SDL_Window *window, Uint16 *ramp)
MIR_CreateWindow
int MIR_CreateWindow(_THIS, SDL_Window *window)
state
struct xkb_state * state
Definition: SDL_waylandsym.h:113
SDL_SysWMinfo::surface
struct wl_surface * surface
Definition: SDL_syswm.h:256
MIR_GetWindowWMInfo
SDL_bool MIR_GetWindowWMInfo(_THIS, SDL_Window *window, SDL_SysWMinfo *info)