src/video/mir/SDL_mirwindow.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 03 Jan 2018 10:03:25 -0800
changeset 11811 5d94cb6b24d3
parent 10971 94f32f14e377
permissions -rw-r--r--
Updated copyright for 2018
     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
    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     MirWindowSpec* 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_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)
   129         SDL_SetKeyboardFocus(window);
   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
   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_window_release_sync(mir_window->window);
   171 
   172         mir_data->current_window = NULL;
   173 
   174         SDL_free(mir_window);
   175     }
   176     window->driverdata = NULL;
   177 }
   178 
   179 SDL_bool
   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         // 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
   210 MIR_SetWindowFullscreen(_THIS, SDL_Window* window,
   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
   229 MIR_MaximizeWindow(_THIS, SDL_Window* window)
   230 {
   231     UpdateMirWindowState(_this->driverdata, window->driverdata, mir_window_state_maximized);
   232 }
   233 
   234 void
   235 MIR_MinimizeWindow(_THIS, SDL_Window* window)
   236 {
   237     UpdateMirWindowState(_this->driverdata, window->driverdata, mir_window_state_minimized);
   238 }
   239 
   240 void
   241 MIR_RestoreWindow(_THIS, SDL_Window * window)
   242 {
   243     UpdateMirWindowState(_this->driverdata, window->driverdata, mir_window_state_restored);
   244 }
   245 
   246 void
   247 MIR_HideWindow(_THIS, SDL_Window* window)
   248 {
   249     UpdateMirWindowState(_this->driverdata, window->driverdata, mir_window_state_hidden);
   250 }
   251 
   252 void
   253 MIR_SetWindowSize(_THIS, SDL_Window* window)
   254 {
   255     MIR_Data* mir_data     = _this->driverdata;
   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
   268 MIR_SetWindowMinimumSize(_THIS, SDL_Window* window)
   269 {
   270     MIR_Data* mir_data     = _this->driverdata;
   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
   283 MIR_SetWindowMaximumSize(_THIS, SDL_Window* window)
   284 {
   285     MIR_Data* mir_data     = _this->driverdata;
   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
   298 MIR_SetWindowTitle(_THIS, SDL_Window* window)
   299 {
   300     MIR_Data*   mir_data   = _this->driverdata;
   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
   316 MIR_SetWindowGrab(_THIS, SDL_Window* window, SDL_bool grabbed)
   317 {
   318     MIR_Data*   mir_data   = _this->driverdata;
   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
   334 MIR_SetWindowGammaRamp(_THIS, SDL_Window* window, Uint16 const* ramp)
   335 {
   336     MirOutput* output = SDL_GetDisplayForWindow(window)->driverdata;
   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
   353 MIR_GetWindowGammaRamp(_THIS, SDL_Window* window, Uint16* ramp)
   354 {
   355     MirOutput* output = SDL_GetDisplayForWindow(window)->driverdata;
   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: */