serenity/Ports/SDL2/patches/0001-Add-SerenityOS-platform-support.patch
Jelle Raaijmakers 055f78f528 Ports: Update SDL2 scancode mapping
This was broken since c8f27d7cb8 introduced a new enum value in
between existing values. Since the Serenity platform support in SDL2
relied on a sequential array index, a lot of keys were now incorrectly
mapped.

This introduces a new way to map Serenity `KeyCode` to SDL2's scancode
constants that is less prone to breaking in the future.
2024-01-14 15:06:37 -07:00

1658 lines
58 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Andreas Kling <kling@serenityos.org>
Date: Sat, 27 Mar 2021 22:05:09 +0100
Subject: [PATCH] Add SerenityOS platform support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-Authored-By: Robin Burchell <robin+git@viroteck.net>
Co-Authored-By: tgsm <doodrabbit@hotmail.com>
Co-Authored-By: TheMorc <r.gracik@gmail.com>
Co-Authored-By: thatdutchguy <thatdutchguy@users.noreply.github.com>
Co-Authored-By: Oleg Sikorskiy <olegsik@gmail.com>
Co-Authored-By: Gunnar Beutner <gunnar@beutner.name>
Co-Authored-By: AnicJov <contact.andrija@gmail.com>
Co-Authored-By: Jelle Raaijmakers <jelle@gmta.nl>
Co-Authored-By: Kenneth Myhra <kennethmyhra@gmail.com>
Co-Authored-By: Stephan Unverwerth <s.unverwerth@gmx.de>
Co-Authored-By: Tim Schumacher <timschumi@gmx.de>
Co-Authored-By: circl <circl.lastname@gmail.com>
Co-Authored-By: kleines Filmröllchen <filmroellchen@serenityos.org>
Co-Authored-By: Linus Groh <mail@linusgroh.de>
Co-Authored-By: Tim Ledbetter <timledbetter@gmail.com>
---
CMakeLists.txt | 25 +-
build-scripts/config.sub | 3 +
cmake/sdlchecks.cmake | 20 +
include/SDL_config.h.cmake | 2 +
include/SDL_syswm.h | 3 +-
src/SDL_error.c | 7 +-
src/audio/SDL_audio.c | 3 +
src/audio/SDL_sysaudio.h | 1 +
src/audio/serenity/SDL_serenityaudio.cpp | 166 +++++
src/audio/serenity/SDL_serenityaudio.h | 38 +
src/stdlib/SDL_stdlib.c | 2 +-
src/video/SDL_sysvideo.h | 1 +
src/video/SDL_video.c | 13 +
src/video/serenity/SDL_serenityevents.cpp | 52 ++
src/video/serenity/SDL_serenityevents_c.h | 33 +
src/video/serenity/SDL_serenitymessagebox.cpp | 40 ++
src/video/serenity/SDL_serenitymessagebox.h | 38 +
src/video/serenity/SDL_serenitymouse.cpp | 142 ++++
src/video/serenity/SDL_serenitymouse.h | 39 ++
src/video/serenity/SDL_serenityvideo.cpp | 655 ++++++++++++++++++
src/video/serenity/SDL_serenityvideo.h | 101 +++
21 files changed, 1358 insertions(+), 26 deletions(-)
create mode 100644 src/audio/serenity/SDL_serenityaudio.cpp
create mode 100644 src/audio/serenity/SDL_serenityaudio.h
create mode 100644 src/video/serenity/SDL_serenityevents.cpp
create mode 100644 src/video/serenity/SDL_serenityevents_c.h
create mode 100644 src/video/serenity/SDL_serenitymessagebox.cpp
create mode 100644 src/video/serenity/SDL_serenitymessagebox.h
create mode 100644 src/video/serenity/SDL_serenitymouse.cpp
create mode 100644 src/video/serenity/SDL_serenitymouse.h
create mode 100644 src/video/serenity/SDL_serenityvideo.cpp
create mode 100644 src/video/serenity/SDL_serenityvideo.h
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 00cf9b43fb496c339c2f1968862f9a1dd0ff7ee2..20164e2761d8848df6eb6c9736a4bd14d53c816b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -29,6 +29,9 @@ set(PKGCONFIG_DEPENDS)
# etc. See https://github.com/libsdl-org/SDL/issues/4150
add_library(sdl-build-options INTERFACE)
+set(UNIX 1)
+set(VIDEO_WAYLAND OFF)
+
if(WINDOWS_STORE)
target_compile_definitions(sdl-build-options INTERFACE "-DSDL_BUILDING_WINRT=1")
target_compile_options(sdl-build-options INTERFACE "-ZW")
@@ -416,7 +419,7 @@ set_option(SDL_SYSTEM_ICONV "Use iconv() from system-installed libraries"
set_option(SDL_OPENGL "Include OpenGL support" ON)
set_option(SDL_OPENGLES "Include OpenGL ES support" ON)
set_option(SDL_PTHREADS "Use POSIX threads for multi-threading" ${SDL_PTHREADS_ENABLED_BY_DEFAULT})
-dep_option(SDL_PTHREADS_SEM "Use pthread semaphores" ON "SDL_PTHREADS" OFF)
+dep_option(SDL_PTHREADS_SEM "Use pthread semaphores" OFF "SDL_PTHREADS" OFF)
dep_option(SDL_OSS "Support the OSS audio API" ON "UNIX_SYS OR RISCOS" OFF)
set_option(SDL_ALSA "Support the ALSA audio API" ${UNIX_SYS})
dep_option(SDL_ALSA_SHARED "Dynamically load ALSA audio support" ON "SDL_ALSA" OFF)
@@ -1435,25 +1438,7 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
CheckFusionSound()
endif()
- if(SDL_VIDEO)
- # Need to check for Raspberry PI first and add platform specific compiler flags, otherwise the test for GLES fails!
- CheckRPI()
- CheckX11()
- CheckDirectFB()
- # Need to check for EGL first because KMSDRM and Wayland depends on it.
- CheckEGL()
- CheckKMSDRM()
- CheckGLX()
- CheckOpenGL()
- CheckOpenGLES()
- CheckWayland()
- CheckVivante()
- # FIXME: implement CheckVulkan()
- if(SDL_VULKAN)
- set(SDL_VIDEO_VULKAN 1)
- set(HAVE_VULKAN TRUE)
- endif()
- endif()
+ CheckSerenity()
if(UNIX)
file(GLOB CORE_UNIX_SOURCES ${SDL2_SOURCE_DIR}/src/core/unix/*.c)
diff --git a/build-scripts/config.sub b/build-scripts/config.sub
index 312ad817c61e0dd18b57ecb8e1cd3be6edc924d7..c2582352995fafe32e0431b290390ee4c2c22598 100755
--- a/build-scripts/config.sub
+++ b/build-scripts/config.sub
@@ -1427,6 +1427,9 @@ case $os in
os400*)
os=os400
;;
+ serenity*)
+ os=serenity
+ ;;
sunos5*)
os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
;;
diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake
index c4aec174e35ee653c4c4e0449939054e0f68ad9d..2f88b7f8790df95838e7de7a45789804e1eb9fde 100644
--- a/cmake/sdlchecks.cmake
+++ b/cmake/sdlchecks.cmake
@@ -801,6 +801,26 @@ macro(CheckDirectFB)
endif()
endmacro()
+# Requires:
+# - n/a
+macro(CheckSerenity)
+ message_warn("Configuring SerenityOS!")
+ set(HAVE_VIDEO_SERENITY TRUE)
+ set(HAVE_AUDIO_SERENITY TRUE)
+ set(HAVE_SDL_VIDEO TRUE)
+ set(HAVE_SDL_AUDIO TRUE)
+
+ set(CMAKE_CXX_FLAGS "-std=c++2a ${CMAKE_CXX_FLAGS}")
+ file(GLOB SERENITY_SOURCES ${SDL2_SOURCE_DIR}/src/video/serenity/*.cpp ${SDL2_SOURCE_DIR}/src/audio/serenity/*.cpp)
+ set(SOURCE_FILES ${SOURCE_FILES} ${SERENITY_SOURCES})
+ set(SDL_VIDEO_DRIVER_SERENITY 1)
+ set(SDL_AUDIO_DRIVER_SERENITY 1)
+ set(SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1)
+ set(HAVE_VIDEO_OPENGL TRUE)
+ set(SDL_VIDEO_OPENGL 1)
+ list(APPEND EXTRA_LIBS ipc gui gfx gl core)
+endmacro(CheckSerenity)
+
# Requires:
# - n/a
macro(CheckVivante)
diff --git a/include/SDL_config.h.cmake b/include/SDL_config.h.cmake
index 7512bb1cc51e67350f63ed0f2074f7f44b6a1113..57e2a70937c3faf39b29e4ffe9dc08d97388e392 100644
--- a/include/SDL_config.h.cmake
+++ b/include/SDL_config.h.cmake
@@ -317,6 +317,7 @@
#cmakedefine SDL_AUDIO_DRIVER_PULSEAUDIO @SDL_AUDIO_DRIVER_PULSEAUDIO@
#cmakedefine SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC @SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC@
#cmakedefine SDL_AUDIO_DRIVER_QSA @SDL_AUDIO_DRIVER_QSA@
+#cmakedefine SDL_AUDIO_DRIVER_SERENITY @SDL_AUDIO_DRIVER_SERENITY@
#cmakedefine SDL_AUDIO_DRIVER_SNDIO @SDL_AUDIO_DRIVER_SNDIO@
#cmakedefine SDL_AUDIO_DRIVER_SNDIO_DYNAMIC @SDL_AUDIO_DRIVER_SNDIO_DYNAMIC@
#cmakedefine SDL_AUDIO_DRIVER_SUNAUDIO @SDL_AUDIO_DRIVER_SUNAUDIO@
@@ -410,6 +411,7 @@
#cmakedefine SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC @SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC@
#cmakedefine SDL_VIDEO_DRIVER_DUMMY @SDL_VIDEO_DRIVER_DUMMY@
#cmakedefine SDL_VIDEO_DRIVER_OFFSCREEN @SDL_VIDEO_DRIVER_OFFSCREEN@
+#cmakedefine SDL_VIDEO_DRIVER_SERENITY @SDL_VIDEO_DRIVER_SERENITY@
#cmakedefine SDL_VIDEO_DRIVER_WINDOWS @SDL_VIDEO_DRIVER_WINDOWS@
#cmakedefine SDL_VIDEO_DRIVER_WINRT @SDL_VIDEO_DRIVER_WINRT@
#cmakedefine SDL_VIDEO_DRIVER_WAYLAND @SDL_VIDEO_DRIVER_WAYLAND@
diff --git a/include/SDL_syswm.h b/include/SDL_syswm.h
index b35734deb334508c6fbfcc0b635417a9d2841052..65a0c8173b376a94ee8650af44ab57dce55d3cb1 100644
--- a/include/SDL_syswm.h
+++ b/include/SDL_syswm.h
@@ -148,7 +148,8 @@ typedef enum
SDL_SYSWM_OS2,
SDL_SYSWM_HAIKU,
SDL_SYSWM_KMSDRM,
- SDL_SYSWM_RISCOS
+ SDL_SYSWM_RISCOS,
+ SDL_SYSWM_SERENITY
} SDL_SYSWM_TYPE;
/**
diff --git a/src/SDL_error.c b/src/SDL_error.c
index 501d3958457de93f75a8c68e1329964247319054..797267c8e24abc6b65f453c93f447e7239f4f8d7 100644
--- a/src/SDL_error.c
+++ b/src/SDL_error.c
@@ -51,10 +51,9 @@ int SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
}
}
- if (SDL_LogGetPriority(SDL_LOG_CATEGORY_ERROR) <= SDL_LOG_PRIORITY_DEBUG) {
- /* If we are in debug mode, print out the error message */
- SDL_LogDebug(SDL_LOG_CATEGORY_ERROR, "%s", error->str);
- }
+ // # HACK(SerenityOS): show everything that's going on
+ dbgputstr(error->str, strlen(error->str));
+ dbgputstr("\n", 1);
}
return -1;
diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c
index 60242e60a06de322281cc0b32b7d3dbc913a80b3..46ec7f9ef0375058e9f95cfea5c213a39b61346e 100644
--- a/src/audio/SDL_audio.c
+++ b/src/audio/SDL_audio.c
@@ -36,6 +36,9 @@ static SDL_AudioDevice *open_devices[16];
/* Available audio drivers */
static const AudioBootStrap *const bootstrap[] = {
+#if SDL_AUDIO_DRIVER_SERENITY
+ &SERENITYAUDIO_bootstrap,
+#endif
#if SDL_AUDIO_DRIVER_PULSEAUDIO
&PULSEAUDIO_bootstrap,
#endif
diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h
index c755d4341521104d369b4d5ff731617680c70215..3ee517796ab467ad5ac3debca738d1cb1cc54f1c 100644
--- a/src/audio/SDL_sysaudio.h
+++ b/src/audio/SDL_sysaudio.h
@@ -209,6 +209,7 @@ extern AudioBootStrap VITAAUD_bootstrap;
extern AudioBootStrap N3DSAUDIO_bootstrap;
extern AudioBootStrap EMSCRIPTENAUDIO_bootstrap;
extern AudioBootStrap OS2AUDIO_bootstrap;
+extern AudioBootStrap SERENITYAUDIO_bootstrap;
#endif /* SDL_sysaudio_h_ */
diff --git a/src/audio/serenity/SDL_serenityaudio.cpp b/src/audio/serenity/SDL_serenityaudio.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..29fa1fcdb1bf018bae6129819648afccdf87c342
--- /dev/null
+++ b/src/audio/serenity/SDL_serenityaudio.cpp
@@ -0,0 +1,166 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_AUDIO_DRIVER_SERENITY
+# define AK_DONT_REPLACE_STD
+
+extern "C" {
+
+# include "SDL_audio.h"
+
+# include "../SDL_audio_c.h"
+# include "../SDL_audiodev_c.h"
+}
+
+# include <AK/Time.h>
+# include <LibAudio/ConnectionToServer.h>
+# include <LibAudio/SampleFormats.h>
+# include <time.h>
+# include "SDL_serenityaudio.h"
+
+static Array<Audio::Sample, Audio::AUDIO_BUFFER_SIZE> output_buffer {};
+static size_t output_buffer_samples_remaining { 0 };
+
+static void SERENITYAUDIO_CloseDevice(_THIS)
+{
+ dbgln("SERENITYAUDIO_CloseDevice");
+
+ struct SDL_PrivateAudioData* h = that->hidden;
+ if (h->client)
+ h->client->die();
+
+ SDL_free(that->hidden->mixbuf);
+ SDL_free(that->hidden);
+}
+
+static int SERENITYAUDIO_OpenDevice(_THIS, char const*)
+{
+ /* Initialize all variables that we clean on shutdown */
+ that->hidden = static_cast<struct SDL_PrivateAudioData*>(SDL_malloc(sizeof *that->hidden));
+ if (!that->hidden)
+ return SDL_OutOfMemory();
+ SDL_zerop(that->hidden);
+
+ that->spec.freq = 44100;
+ that->spec.format = AUDIO_S16LSB;
+ that->spec.channels = 2;
+ that->spec.samples = 1024;
+
+ /* Calculate the final parameters for this audio specification */
+ SDL_CalculateAudioSpec(&that->spec);
+
+ /* Allocate mixing buffer */
+ if (!that->iscapture) {
+ that->hidden->mixlen = that->spec.size;
+ that->hidden->mixbuf = (Uint8*)SDL_malloc(that->hidden->mixlen);
+ if (!that->hidden->mixbuf)
+ return SDL_OutOfMemory();
+ SDL_memset(that->hidden->mixbuf, that->spec.silence, that->spec.size);
+ }
+
+ /* We're ready to rock and roll. :-) */
+ return 0;
+}
+
+static void SERENITYAUDIO_PlayDevice(_THIS)
+{
+ struct SDL_PrivateAudioData* h = that->hidden;
+
+ // We need to create our audio connection and event loop here, in order to register them with SDL's audio thread
+ if (!h->event_loop)
+ h->event_loop = make<Core::EventLoop>();
+ if (!h->client)
+ h->client = MUST(Audio::ConnectionToServer::try_create());
+
+ h->client->async_start_playback();
+
+ auto convert_i16_to_double = [](i16 input) -> auto {
+ return (static_cast<double>(input) - NumericLimits<i16>::min()) / NumericLimits<u16>::max() * 2. - 1.;
+ };
+
+ auto const sleep_spec = Duration::from_nanoseconds(100).to_timespec();
+ auto input_buffer = reinterpret_cast<i16*>(h->mixbuf);
+ auto input_samples = h->mixlen / that->spec.channels / sizeof(i16);
+ size_t input_position = 0;
+
+ while (input_samples > 0) {
+ // Fill up the output buffer
+ auto const input_samples_to_process = min(input_samples, Audio::AUDIO_BUFFER_SIZE - output_buffer_samples_remaining);
+ for (size_t i = 0; i < input_samples_to_process; ++i) {
+ auto left = convert_i16_to_double(input_buffer[input_position]);
+ auto right = convert_i16_to_double(input_buffer[input_position + 1]);
+ output_buffer[output_buffer_samples_remaining + i] = Audio::Sample(left, right);
+ input_position += 2;
+ }
+ output_buffer_samples_remaining += input_samples_to_process;
+ input_samples -= input_samples_to_process;
+
+ // Stop if we don't have enough samples to fill a buffer
+ if (output_buffer_samples_remaining < Audio::AUDIO_BUFFER_SIZE)
+ break;
+
+ // Try to enqueue our output buffer
+ for (;;) {
+ auto enqueue_result = h->client->realtime_enqueue(output_buffer);
+ if (!enqueue_result.is_error())
+ break;
+ if (enqueue_result.error() != Audio::AudioQueue::QueueStatus::Full)
+ return;
+
+ nanosleep(&sleep_spec, nullptr);
+ }
+ output_buffer_samples_remaining = 0;
+ }
+
+ // Pump our event loop - should just be the IPC call to start playback
+ for (;;) {
+ auto number_of_events_pumped = h->event_loop->pump(Core::EventLoop::WaitMode::PollForEvents);
+ if (number_of_events_pumped == 0)
+ break;
+ }
+}
+
+static Uint8* SERENITYAUDIO_GetDeviceBuf(_THIS)
+{
+ return that->hidden->mixbuf;
+}
+
+static SDL_bool SERENITYAUDIO_Init(SDL_AudioDriverImpl* impl)
+{
+ /* Set the function pointers */
+ impl->OpenDevice = SERENITYAUDIO_OpenDevice;
+ impl->PlayDevice = SERENITYAUDIO_PlayDevice;
+ impl->GetDeviceBuf = SERENITYAUDIO_GetDeviceBuf;
+ impl->CloseDevice = SERENITYAUDIO_CloseDevice;
+
+ impl->AllowsArbitraryDeviceNames = SDL_TRUE;
+ impl->HasCaptureSupport = SDL_FALSE;
+ impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
+
+ return SDL_TRUE; // this audio target is available.
+}
+
+AudioBootStrap SERENITYAUDIO_bootstrap = {
+ "serenity", "Serenity using AudioServer", SERENITYAUDIO_Init, SDL_FALSE
+};
+
+#endif
diff --git a/src/audio/serenity/SDL_serenityaudio.h b/src/audio/serenity/SDL_serenityaudio.h
new file mode 100644
index 0000000000000000000000000000000000000000..8d152ca843e732d2d5a8127fc191ca22ce690a83
--- /dev/null
+++ b/src/audio/serenity/SDL_serenityaudio.h
@@ -0,0 +1,38 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#pragma once
+
+#include "../SDL_sysaudio.h"
+#include <AK/OwnPtr.h>
+#include <AK/RefPtr.h>
+#include <LibAudio/ConnectionToServer.h>
+#include <LibCore/EventLoop.h>
+
+#define _THIS SDL_AudioDevice* that
+
+struct SDL_PrivateAudioData {
+ RefPtr<Audio::ConnectionToServer> client;
+ OwnPtr<Core::EventLoop> event_loop;
+ Uint8* mixbuf { nullptr };
+ size_t mixlen { 0 };
+};
diff --git a/src/stdlib/SDL_stdlib.c b/src/stdlib/SDL_stdlib.c
index 8c9d196ac27cbb9db35faa03d29b9b301bf08622..3ab89a91506d6522f5dcd5a58cc77312a50f03e7 100644
--- a/src/stdlib/SDL_stdlib.c
+++ b/src/stdlib/SDL_stdlib.c
@@ -618,7 +618,7 @@ void *SDL_memset(SDL_OUT_BYTECAP(len) void *dst, int c, size_t len)
#endif /* HAVE_MEMSET */
}
-#if defined(HAVE_CTYPE_H) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#if defined(HAVE_CTYPE_H) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && !defined(__serenity__)
int SDL_isblank(int x)
{
return isblank(x);
diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h
index d7a42cc64d905cd1f8b3a03bf8ffd894c0c9b7ac..26e3b457f6fbb5d811d55254d1fb486aa6aa79e7 100644
--- a/src/video/SDL_sysvideo.h
+++ b/src/video/SDL_sysvideo.h
@@ -482,6 +482,7 @@ extern VideoBootStrap OFFSCREEN_bootstrap;
extern VideoBootStrap NGAGE_bootstrap;
extern VideoBootStrap OS2DIVE_bootstrap;
extern VideoBootStrap OS2VMAN_bootstrap;
+extern VideoBootStrap SERENITYVIDEO_bootstrap;
/* Use SDL_OnVideoThread() sparingly, to avoid regressions in use cases that currently happen to work */
extern SDL_bool SDL_OnVideoThread(void);
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 8065a0b8cfc71e8d4dadd7d40fbe15303ce7e05d..fdebdac17e72e280fbe55fbb6e8bc7f42e0fc154 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -65,6 +65,9 @@
/* Available video drivers */
static VideoBootStrap *bootstrap[] = {
+#if SDL_VIDEO_DRIVER_SERENITY
+ &SERENITYVIDEO_bootstrap,
+#endif
#if SDL_VIDEO_DRIVER_COCOA
&COCOA_bootstrap,
#endif
@@ -4240,6 +4243,10 @@ void SDL_WM_SetIcon(SDL_Surface * icon, Uint8 * mask)
}
}
#endif
+#if SDL_VIDEO_DRIVER_SERENITY
+#include "serenity/SDL_serenitymessagebox.h"
+#endif
+
SDL_bool SDL_GetWindowWMInfo(SDL_Window * window, struct SDL_SysWMinfo *info)
{
@@ -4522,6 +4529,12 @@ int SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
VITA_ShowMessageBox(messageboxdata, buttonid) == 0) {
retval = 0;
}
+#endif
+#if SDL_VIDEO_DRIVER_SERENITY
+ if (retval == -1 &&
+ SERENITY_ShowMessageBox(messageboxdata, buttonid) == 0) {
+ retval = 0;
+ }
#endif
if (retval == -1) {
const char *error = SDL_GetError();
diff --git a/src/video/serenity/SDL_serenityevents.cpp b/src/video/serenity/SDL_serenityevents.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..04cbf21ce74fb11e6713ba3a4beaad808751e80b
--- /dev/null
+++ b/src/video/serenity/SDL_serenityevents.cpp
@@ -0,0 +1,52 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_SERENITY
+#define AK_DONT_REPLACE_STD
+
+#include "../../events/SDL_events_c.h"
+
+#include "SDL_serenityvideo.h"
+#include "SDL_serenityevents_c.h"
+#include "SDL_timer.h"
+
+#include <LibCore/EventLoop.h>
+
+void
+SERENITY_PumpEvents(_THIS)
+{
+ auto& loop = Core::EventLoop::current();
+ if (loop.was_exit_requested())
+ exit(0);
+
+ auto const event_loop_timeout_ms = SDL_GetTicks() + 100;
+ while (loop.pump(Core::EventLoop::WaitMode::PollForEvents) > 0) {
+ if (SDL_TICKS_PASSED(SDL_GetTicks(), event_loop_timeout_ms))
+ break;
+ }
+
+}
+
+
+#endif /* SDL_VIDEO_DRIVER_SERENITY */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/serenity/SDL_serenityevents_c.h b/src/video/serenity/SDL_serenityevents_c.h
new file mode 100644
index 0000000000000000000000000000000000000000..89e9e919e319c701144da8f6d73bbb2ea519758d
--- /dev/null
+++ b/src/video/serenity/SDL_serenityevents_c.h
@@ -0,0 +1,33 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_serenityevents_c_h_
+#define SDL_serenityevents_c_h_
+
+#include "../../SDL_internal.h"
+
+#include "SDL_serenityvideo.h"
+
+extern void SERENITY_PumpEvents(_THIS);
+
+#endif /* SDL_serenityevents_c_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/serenity/SDL_serenitymessagebox.cpp b/src/video/serenity/SDL_serenitymessagebox.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fe41a8beecc4f1e6b9cc17831d53b43c05f167f1
--- /dev/null
+++ b/src/video/serenity/SDL_serenitymessagebox.cpp
@@ -0,0 +1,40 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_SERENITY
+# define AK_DONT_REPLACE_STD
+
+# include "SDL_messagebox.h"
+# include "SDL_serenitymessagebox.h"
+
+# include <LibGUI/MessageBox.h>
+
+extern "C" int SERENITY_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
+{
+ GUI::MessageBox::show(nullptr, { messageboxdata->message, strlen(messageboxdata->message) }, { messageboxdata->title, strlen(messageboxdata->title) });
+ return 0;
+}
+
+#endif /* SDL_VIDEO_DRIVER_SERENITY */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/serenity/SDL_serenitymessagebox.h b/src/video/serenity/SDL_serenitymessagebox.h
new file mode 100644
index 0000000000000000000000000000000000000000..34e607783310310ac8956bccf584b5ab12d45907
--- /dev/null
+++ b/src/video/serenity/SDL_serenitymessagebox.h
@@ -0,0 +1,38 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_serenitymessagebox_h_
+#define SDL_serenitymessagebox_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int SERENITY_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SDL_serenitymessagebox_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/serenity/SDL_serenitymouse.cpp b/src/video/serenity/SDL_serenitymouse.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5d0cb527a03dc0ac775ed68d66451495bf993ec6
--- /dev/null
+++ b/src/video/serenity/SDL_serenitymouse.cpp
@@ -0,0 +1,142 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_SERENITY
+#define AK_DONT_REPLACE_STD
+
+/*
+ * SDL includes:
+ */
+extern "C" {
+#include "../../events/SDL_mouse_c.h"
+#include "../../events/SDL_touch_c.h"
+#include "../SDL_sysvideo.h"
+#include "SDL_events.h"
+}
+
+#include "SDL_serenitymouse.h"
+#include "SDL_serenityvideo.h"
+
+#include <LibGfx/StandardCursor.h>
+
+struct SerenityCursorData final {
+ Gfx::StandardCursor cursor_type;
+};
+
+static SDL_Cursor*
+SERENITY_CreateSystemCursor(SDL_SystemCursor id)
+{
+ auto cursor = static_cast<SDL_Cursor*>(SDL_calloc(1, sizeof(SDL_Cursor)));
+ if (!cursor)
+ SDL_OutOfMemory();
+
+ auto cursor_data = static_cast<SerenityCursorData*>(SDL_calloc(1, sizeof(SerenityCursorData)));
+ if (!cursor_data)
+ SDL_OutOfMemory();
+ cursor->driverdata = static_cast<void*>(cursor_data);
+
+ switch(id)
+ {
+ case SDL_SYSTEM_CURSOR_ARROW: cursor_data->cursor_type = Gfx::StandardCursor::Arrow; break;
+ case SDL_SYSTEM_CURSOR_IBEAM: cursor_data->cursor_type = Gfx::StandardCursor::IBeam; break;
+ case SDL_SYSTEM_CURSOR_WAIT: cursor_data->cursor_type = Gfx::StandardCursor::Wait; break;
+ case SDL_SYSTEM_CURSOR_CROSSHAIR: cursor_data->cursor_type = Gfx::StandardCursor::Crosshair; break;
+ case SDL_SYSTEM_CURSOR_WAITARROW: cursor_data->cursor_type = Gfx::StandardCursor::Wait; break;
+ case SDL_SYSTEM_CURSOR_SIZENWSE: cursor_data->cursor_type = Gfx::StandardCursor::ResizeDiagonalTLBR; break;
+ case SDL_SYSTEM_CURSOR_SIZENESW: cursor_data->cursor_type = Gfx::StandardCursor::ResizeDiagonalBLTR; break;
+ case SDL_SYSTEM_CURSOR_SIZEWE: cursor_data->cursor_type = Gfx::StandardCursor::ResizeHorizontal; break;
+ case SDL_SYSTEM_CURSOR_SIZENS: cursor_data->cursor_type = Gfx::StandardCursor::ResizeVertical; break;
+ case SDL_SYSTEM_CURSOR_SIZEALL: cursor_data->cursor_type = Gfx::StandardCursor::Move; break;
+ case SDL_SYSTEM_CURSOR_NO: cursor_data->cursor_type = Gfx::StandardCursor::Disallowed; break;
+ case SDL_SYSTEM_CURSOR_HAND: cursor_data->cursor_type = Gfx::StandardCursor::Hand; break;
+ default:
+ SDL_assert(0);
+ return nullptr;
+ }
+ return cursor;
+}
+
+static SDL_Cursor*
+SERENITY_CreateDefaultCursor()
+{
+ return SERENITY_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
+}
+
+static void
+SERENITY_FreeCursor(SDL_Cursor* cursor)
+{
+ if (cursor->driverdata)
+ SDL_free(cursor->driverdata);
+ SDL_free(cursor);
+}
+
+static int
+SERENITY_ShowCursor(SDL_Cursor* cursor)
+{
+ auto focused_window = SDL_GetMouseFocus();
+ if (!focused_window)
+ return -1;
+
+ auto platform_window = SerenityPlatformWindow::from_sdl_window(focused_window);
+
+ // Hide the cursor
+ if (cursor == nullptr) {
+ platform_window->window()->set_cursor(Gfx::StandardCursor::Hidden);
+ return 0;
+ }
+
+ auto cursor_data = static_cast<SerenityCursorData*>(cursor->driverdata);
+ if (!cursor_data)
+ return -1;
+
+ platform_window->window()->set_cursor(cursor_data->cursor_type);
+ return 0;
+}
+
+void
+SERENITY_InitMouse(_THIS)
+{
+ dbgln("SERENITY_InitMouse");
+
+ auto mouse = SDL_GetMouse();
+
+ mouse->CreateSystemCursor = SERENITY_CreateSystemCursor;
+ mouse->ShowCursor = SERENITY_ShowCursor;
+ mouse->FreeCursor = SERENITY_FreeCursor;
+
+ // FIXME: implement below methods
+ //mouse->CreateCursor = ...;
+ //mouse->WarpMouse = ...;
+ //mouse->SetRelativeMouseMode = ...;
+
+ SDL_SetDefaultCursor(SERENITY_CreateDefaultCursor());
+}
+
+void
+SERENITY_QuitMouse(_THIS)
+{
+ dbgln("SERENITY_QuitMouse");
+}
+
+#endif /* SDL_VIDEO_DRIVER_SERENITY */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/serenity/SDL_serenitymouse.h b/src/video/serenity/SDL_serenitymouse.h
new file mode 100644
index 0000000000000000000000000000000000000000..039f0361b3d1b248e218ea69495f58e52ad532c6
--- /dev/null
+++ b/src/video/serenity/SDL_serenitymouse.h
@@ -0,0 +1,39 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_config.h"
+
+#ifndef SDL_serenitymouse_h_
+#define SDL_serenitymouse_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void SERENITY_InitMouse(_THIS);
+extern void SERENITY_QuitMouse(_THIS);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SDL_serenitymouse_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/serenity/SDL_serenityvideo.cpp b/src/video/serenity/SDL_serenityvideo.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..26ff18b1c878f7a14c32554859bd088522806b91
--- /dev/null
+++ b/src/video/serenity/SDL_serenityvideo.cpp
@@ -0,0 +1,655 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+extern "C" {
+
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_SERENITY
+# define AK_DONT_REPLACE_STD
+
+# include "../../events/SDL_events_c.h"
+# include "../SDL_pixels_c.h"
+# include "../SDL_sysvideo.h"
+# include "SDL_mouse.h"
+# include "SDL_syswm.h"
+# include "SDL_video.h"
+}
+
+# include "SDL_serenityevents_c.h"
+# include "SDL_serenitymouse.h"
+# include "SDL_serenityvideo.h"
+
+# include <AK/Array.h>
+# include <Kernel/API/KeyCode.h>
+# include <LibCore/EventLoop.h>
+# include <LibGUI/Application.h>
+# include <LibGUI/Desktop.h>
+# include <LibGUI/Painter.h>
+# include <LibGUI/Widget.h>
+# include <LibGUI/Window.h>
+# include <LibGfx/Bitmap.h>
+# include <LibMain/Main.h>
+# include <dlfcn.h>
+
+static consteval AK::Array<SDL_Scancode, key_code_count> generate_scancode_map()
+{
+ auto map = AK::Array<SDL_Scancode, key_code_count>::from_repeated_value(SDL_SCANCODE_UNKNOWN);
+
+ // Below list is in order of Kernel/API/KeyCode.h; the shift modifier is applied by SDL
+ // and as such, unshifted scancodes must be used (e.g. dollar sign => 4).
+# define MAP_KEYCODE(A,B) map[to_underlying(KeyCode::Key_##A)] = SDL_SCANCODE_##B;
+ MAP_KEYCODE(Escape, ESCAPE);
+ MAP_KEYCODE(Tab, TAB);
+ MAP_KEYCODE(Backspace, BACKSPACE);
+ MAP_KEYCODE(Return, RETURN);
+ MAP_KEYCODE(Insert, INSERT);
+ MAP_KEYCODE(Delete, DELETE);
+ MAP_KEYCODE(PrintScreen, PRINTSCREEN);
+ MAP_KEYCODE(PauseBreak, PAUSE);
+ MAP_KEYCODE(SysRq, SYSREQ);
+ MAP_KEYCODE(Home, HOME);
+ MAP_KEYCODE(End, END);
+ MAP_KEYCODE(Left, LEFT);
+ MAP_KEYCODE(Up, UP);
+ MAP_KEYCODE(Right, RIGHT);
+ MAP_KEYCODE(Down, DOWN);
+ MAP_KEYCODE(PageUp, PAGEUP);
+ MAP_KEYCODE(PageDown, PAGEDOWN);
+ MAP_KEYCODE(LeftShift, LSHIFT);
+ MAP_KEYCODE(RightShift, RSHIFT);
+ MAP_KEYCODE(Control, LCTRL);
+ MAP_KEYCODE(RightControl, RCTRL);
+ MAP_KEYCODE(Alt, LALT);
+ MAP_KEYCODE(RightAlt, RALT);
+ MAP_KEYCODE(CapsLock, CAPSLOCK);
+ MAP_KEYCODE(NumLock, NUMLOCKCLEAR);
+ MAP_KEYCODE(ScrollLock, SCROLLLOCK);
+ MAP_KEYCODE(F1, F1);
+ MAP_KEYCODE(F2, F2);
+ MAP_KEYCODE(F3, F3);
+ MAP_KEYCODE(F4, F4);
+ MAP_KEYCODE(F5, F5);
+ MAP_KEYCODE(F6, F6);
+ MAP_KEYCODE(F7, F7);
+ MAP_KEYCODE(F8, F8);
+ MAP_KEYCODE(F9, F9);
+ MAP_KEYCODE(F10, F10);
+ MAP_KEYCODE(F11, F11);
+ MAP_KEYCODE(F12, F12);
+ MAP_KEYCODE(Space, SPACE);
+ MAP_KEYCODE(ExclamationPoint, 1);
+ MAP_KEYCODE(DoubleQuote, APOSTROPHE);
+ MAP_KEYCODE(Hashtag, 3);
+ MAP_KEYCODE(Dollar, 4);
+ MAP_KEYCODE(Percent, 5);
+ MAP_KEYCODE(Ampersand, 7);
+ MAP_KEYCODE(Apostrophe, APOSTROPHE);
+ MAP_KEYCODE(LeftParen, 9);
+ MAP_KEYCODE(RightParen, 0);
+ MAP_KEYCODE(Asterisk, 8);
+ MAP_KEYCODE(Plus, EQUALS);
+ MAP_KEYCODE(Comma, COMMA);
+ MAP_KEYCODE(Minus, MINUS);
+ MAP_KEYCODE(Period, PERIOD);
+ MAP_KEYCODE(Slash, SLASH);
+ MAP_KEYCODE(0, 0);
+ MAP_KEYCODE(1, 1);
+ MAP_KEYCODE(2, 2);
+ MAP_KEYCODE(3, 3);
+ MAP_KEYCODE(4, 4);
+ MAP_KEYCODE(5, 5);
+ MAP_KEYCODE(6, 6);
+ MAP_KEYCODE(7, 7);
+ MAP_KEYCODE(8, 8);
+ MAP_KEYCODE(9, 9);
+ MAP_KEYCODE(Colon, SEMICOLON);
+ MAP_KEYCODE(Semicolon, SEMICOLON);
+ MAP_KEYCODE(LessThan, COMMA);
+ MAP_KEYCODE(Equal, EQUALS);
+ MAP_KEYCODE(GreaterThan, PERIOD);
+ MAP_KEYCODE(QuestionMark, SLASH);
+ MAP_KEYCODE(A, A);
+ MAP_KEYCODE(B, B);
+ MAP_KEYCODE(C, C);
+ MAP_KEYCODE(D, D);
+ MAP_KEYCODE(E, E);
+ MAP_KEYCODE(F, F);
+ MAP_KEYCODE(G, G);
+ MAP_KEYCODE(H, H);
+ MAP_KEYCODE(I, I);
+ MAP_KEYCODE(J, J);
+ MAP_KEYCODE(K, K);
+ MAP_KEYCODE(L, L);
+ MAP_KEYCODE(M, M);
+ MAP_KEYCODE(N, N);
+ MAP_KEYCODE(O, O);
+ MAP_KEYCODE(P, P);
+ MAP_KEYCODE(Q, Q);
+ MAP_KEYCODE(R, R);
+ MAP_KEYCODE(S, S);
+ MAP_KEYCODE(T, T);
+ MAP_KEYCODE(U, U);
+ MAP_KEYCODE(V, V);
+ MAP_KEYCODE(W, W);
+ MAP_KEYCODE(X, X);
+ MAP_KEYCODE(Y, Y);
+ MAP_KEYCODE(Z, Z);
+ MAP_KEYCODE(LeftBracket, LEFTBRACKET);
+ MAP_KEYCODE(RightBracket, RIGHTBRACKET);
+ MAP_KEYCODE(Backslash, BACKSLASH);
+ MAP_KEYCODE(Circumflex, 6);
+ MAP_KEYCODE(Underscore, MINUS);
+ MAP_KEYCODE(LeftBrace, LEFTBRACKET);
+ MAP_KEYCODE(RightBrace, RIGHTBRACKET);
+ MAP_KEYCODE(Pipe, BACKSLASH);
+ MAP_KEYCODE(Tilde, GRAVE);
+ MAP_KEYCODE(Backtick, GRAVE);
+ MAP_KEYCODE(Super, LGUI);
+ MAP_KEYCODE(BrowserSearch, AC_SEARCH);
+ MAP_KEYCODE(BrowserFavorites, AC_BOOKMARKS);
+ MAP_KEYCODE(BrowserHome, AC_HOME);
+ MAP_KEYCODE(PreviousTrack, AUDIOPREV);
+ MAP_KEYCODE(BrowserBack, AC_BACK);
+ MAP_KEYCODE(BrowserForward, AC_FORWARD);
+ MAP_KEYCODE(BrowserRefresh, AC_REFRESH);
+ MAP_KEYCODE(BrowserStop, AC_STOP);
+ MAP_KEYCODE(VolumeDown, VOLUMEDOWN);
+ MAP_KEYCODE(VolumeUp, VOLUMEUP);
+ // Unmapped: Wake
+ MAP_KEYCODE(Sleep, SLEEP);
+ MAP_KEYCODE(NextTrack, AUDIONEXT);
+ MAP_KEYCODE(MediaSelect, MEDIASELECT);
+ MAP_KEYCODE(Email, MAIL);
+ MAP_KEYCODE(MyComputer, COMPUTER);
+ MAP_KEYCODE(Power, POWER);
+ MAP_KEYCODE(Stop, STOP);
+ MAP_KEYCODE(LeftGUI, LGUI);
+ MAP_KEYCODE(Mute, MUTE);
+ MAP_KEYCODE(RightGUI, RGUI);
+ MAP_KEYCODE(Calculator, CALCULATOR);
+ // Unmapped: Apps
+ MAP_KEYCODE(PlayPause, AUDIOPLAY);
+ MAP_KEYCODE(Menu, APPLICATION);
+
+ return map;
+}
+
+static constexpr auto scancode_map = generate_scancode_map();
+
+/* Initialization/Query functions */
+static int SERENITY_VideoInit(_THIS);
+static int SERENITY_SetDisplayMode(_THIS, SDL_VideoDisplay* display,
+ SDL_DisplayMode* mode);
+static void SERENITY_VideoQuit(_THIS);
+
+/* SERENITY driver bootstrap functions */
+
+static int SERENITY_Available(void) { return (1); }
+
+static void SERENITY_DeleteDevice(SDL_VideoDevice* device)
+{
+ dbgln("SERENITY_DeleteDevice");
+ SDL_free(device);
+}
+
+extern int Serenity_CreateWindow(_THIS, SDL_Window* window);
+extern void Serenity_ShowWindow(_THIS, SDL_Window* window);
+extern void Serenity_HideWindow(_THIS, SDL_Window* window);
+extern void Serenity_SetWindowTitle(_THIS, SDL_Window* window);
+extern void Serenity_SetWindowSize(_THIS, SDL_Window* window);
+extern void Serenity_SetWindowFullscreen(_THIS, SDL_Window* window,
+ SDL_VideoDisplay* display,
+ SDL_bool fullscreen);
+extern void Serenity_SetWindowIcon(_THIS, SDL_Window* window, SDL_Surface* icon);
+extern void Serenity_DestroyWindow(_THIS, SDL_Window* window);
+extern SDL_bool Serenity_GetWindowWMInfo(_THIS, SDL_Window *window, struct SDL_SysWMinfo *info);
+extern int Serenity_CreateWindowFramebuffer(_THIS, SDL_Window* window,
+ Uint32* format, void** pixels,
+ int* pitch);
+extern int Serenity_UpdateWindowFramebuffer(_THIS, SDL_Window* window,
+ const SDL_Rect* rects,
+ int numrects);
+extern void Serenity_DestroyWindowFramebuffer(_THIS, SDL_Window* window);
+extern SDL_GLContext Serenity_GL_CreateContext(_THIS, SDL_Window* window);
+extern void Serenity_GL_DeleteContext(_THIS, SDL_GLContext context);
+extern void* Serenity_GL_GetProcAddress(_THIS, const char* proc);
+extern int Serenity_GL_LoadLibrary(_THIS, const char* path);
+extern int Serenity_GL_MakeCurrent(_THIS, SDL_Window* window, SDL_GLContext context);
+extern int Serenity_GL_SwapWindow(_THIS, SDL_Window* window);
+
+static SDL_VideoDevice* SERENITY_CreateDevice(void)
+{
+ SDL_VideoDevice* device;
+
+ /* Initialize all variables that we clean on shutdown */
+ device = (SDL_VideoDevice*)SDL_calloc(1, sizeof(SDL_VideoDevice));
+ if (!device) {
+ SDL_OutOfMemory();
+ return (0);
+ }
+ device->is_dummy = SDL_FALSE;
+
+ /* Set the function pointers */
+ device->VideoInit = SERENITY_VideoInit;
+ device->VideoQuit = SERENITY_VideoQuit;
+ device->SetDisplayMode = SERENITY_SetDisplayMode;
+ device->PumpEvents = SERENITY_PumpEvents;
+
+ device->CreateWindowFramebuffer = Serenity_CreateWindowFramebuffer;
+ device->UpdateWindowFramebuffer = Serenity_UpdateWindowFramebuffer;
+ device->DestroyWindowFramebuffer = Serenity_DestroyWindowFramebuffer;
+ device->CreateSDLWindow = Serenity_CreateWindow;
+ device->ShowWindow = Serenity_ShowWindow;
+ device->HideWindow = Serenity_HideWindow;
+ device->SetWindowTitle = Serenity_SetWindowTitle;
+ device->SetWindowSize = Serenity_SetWindowSize;
+ device->SetWindowFullscreen = Serenity_SetWindowFullscreen;
+ device->SetWindowIcon = Serenity_SetWindowIcon;
+ device->DestroyWindow = Serenity_DestroyWindow;
+ device->GetWindowWMInfo = Serenity_GetWindowWMInfo;
+
+ device->GL_CreateContext = Serenity_GL_CreateContext;
+ device->GL_DeleteContext = Serenity_GL_DeleteContext;
+ device->GL_GetProcAddress = Serenity_GL_GetProcAddress;
+ device->GL_LoadLibrary = Serenity_GL_LoadLibrary;
+ device->GL_MakeCurrent = Serenity_GL_MakeCurrent;
+ device->GL_SwapWindow = Serenity_GL_SwapWindow;
+
+ device->free = SERENITY_DeleteDevice;
+
+ Serenity_GL_LoadLibrary(device, nullptr);
+
+ return device;
+}
+
+VideoBootStrap SERENITYVIDEO_bootstrap = { "serenity", "SDL serenity video driver", SERENITY_CreateDevice };
+
+static RefPtr<GUI::Application> g_app;
+
+int SERENITY_VideoInit(_THIS)
+{
+ dbgln("{}: Initialising SDL application", __FUNCTION__);
+
+ if (!g_app) {
+ g_app = MUST(GUI::Application::create(Main::Arguments {}));
+ g_app->set_quit_when_last_window_deleted(false);
+ }
+
+ SERENITY_InitMouse(_this);
+
+ // We only add the active desktop resolution until we properly support multiple
+ // fullscreen resolutions
+ auto desktop_rect = GUI::Desktop::the().rect();
+
+ SDL_DisplayMode mode;
+ mode.format = SDL_PIXELFORMAT_RGB888;
+ mode.w = desktop_rect.width();
+ mode.h = desktop_rect.height();
+ mode.refresh_rate = 60;
+ mode.driverdata = nullptr;
+
+ if (SDL_AddBasicVideoDisplay(&mode) < 0)
+ return -1;
+
+ SDL_AddDisplayMode(&_this->displays[0], &mode);
+
+ /* We're done! */
+ return 0;
+}
+
+static int SERENITY_SetDisplayMode(_THIS, SDL_VideoDisplay* display,
+ SDL_DisplayMode* mode)
+{
+ dbgln("SERENITY_SetDisplayMode");
+ return 0;
+}
+
+void SERENITY_VideoQuit(_THIS)
+{
+ dbgln("SERENITY_VideoQuit");
+ SERENITY_QuitMouse(_this);
+}
+
+SerenitySDLWidget::SerenitySDLWidget(SDL_Window* sdl_window)
+ : m_sdl_window(sdl_window)
+{
+}
+
+void SerenitySDLWidget::paint_event(GUI::PaintEvent& event)
+{
+ if (!m_buffer)
+ return;
+
+ GUI::Painter painter(*this);
+ painter.add_clip_rect(event.rect());
+ painter.blit(event.rect().location(), *m_buffer, event.rect());
+}
+
+void SerenitySDLWidget::resize_event(GUI::ResizeEvent&)
+{
+ SDL_SendWindowEvent(m_sdl_window, SDL_WINDOWEVENT_RESIZED, width(), height());
+}
+void SerenitySDLWidget::show_event(GUI::ShowEvent&)
+{
+ SDL_SendWindowEvent(m_sdl_window, SDL_WINDOWEVENT_SHOWN, 0, 0);
+}
+void SerenitySDLWidget::hide_event(GUI::HideEvent&)
+{
+ SDL_SendWindowEvent(m_sdl_window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
+}
+
+static int map_button(GUI::MouseButton button)
+{
+ switch (button) {
+ case GUI::MouseButton::Primary:
+ return SDL_BUTTON_LEFT;
+ case GUI::MouseButton::Middle:
+ return SDL_BUTTON_MIDDLE;
+ case GUI::MouseButton::Secondary:
+ return SDL_BUTTON_RIGHT;
+ case GUI::MouseButton::Forward:
+ return SDL_BUTTON_X1;
+ case GUI::MouseButton::Backward:
+ return SDL_BUTTON_X2;
+ }
+
+ VERIFY_NOT_REACHED();
+ return 0;
+}
+
+void SerenitySDLWidget::mousedown_event(GUI::MouseEvent& event)
+{
+ SDL_SendMouseMotion(m_sdl_window, 0, 0, event.x(), event.y());
+ SDL_SendMouseButton(m_sdl_window, 0, SDL_PRESSED, map_button(event.button()));
+}
+
+void SerenitySDLWidget::mousemove_event(GUI::MouseEvent& event)
+{
+ SDL_SendMouseMotion(m_sdl_window, 0, 0, event.x(), event.y());
+}
+
+void SerenitySDLWidget::mouseup_event(GUI::MouseEvent& event)
+{
+ SDL_SendMouseMotion(m_sdl_window, 0, 0, event.x(), event.y());
+ SDL_SendMouseButton(m_sdl_window, 0, SDL_RELEASED, map_button(event.button()));
+}
+
+void SerenitySDLWidget::mousewheel_event(GUI::MouseEvent& event)
+{
+ SDL_SendMouseMotion(m_sdl_window, 0, 0, event.x(), event.y());
+ SDL_SendMouseWheel(m_sdl_window, 0, (float)event.wheel_raw_delta_x(), -(float)event.wheel_raw_delta_y(), SDL_MOUSEWHEEL_NORMAL);
+}
+
+void SerenitySDLWidget::keydown_event(GUI::KeyEvent& event)
+{
+ SDL_SendKeyboardKey(SDL_PRESSED, scancode_map[event.key()]);
+ auto text = event.text();
+ if (!text.is_empty())
+ SDL_SendKeyboardText(text.characters());
+}
+
+void SerenitySDLWidget::keyup_event(GUI::KeyEvent& event)
+{
+ SDL_SendKeyboardKey(SDL_RELEASED, scancode_map[event.key()]);
+}
+
+void SerenitySDLWidget::enter_event(Core::Event&)
+{
+ SDL_SetMouseFocus(m_sdl_window);
+}
+
+void SerenitySDLWidget::leave_event(Core::Event&)
+{
+ SDL_SetMouseFocus(nullptr);
+}
+
+int Serenity_CreateWindow(_THIS, SDL_Window* window)
+{
+ dbgln("{}: Creating new window of size {}x{}", __FUNCTION__, window->w, window->h);
+
+ auto w = new SerenityPlatformWindow(window);
+ window->driverdata = w;
+ w->window()->set_double_buffering_enabled(false);
+ w->widget()->set_fill_with_background_color(false);
+ w->window()->set_main_widget(w->widget());
+ w->window()->on_close_request = [window] {
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_CLOSE, 0, 0);
+ return GUI::Window::CloseRequestDecision::StayOpen;
+ };
+ w->window()->on_active_window_change = [window](bool is_active_window) {
+ SDL_SetKeyboardFocus(is_active_window ? window : nullptr);
+ };
+ w->window()->on_input_preemption_change = [window](bool is_preempted) {
+ SDL_SetKeyboardFocus(is_preempted ? nullptr : window);
+ };
+ SERENITY_PumpEvents(_this);
+
+ return 0;
+}
+
+void Serenity_ShowWindow(_THIS, SDL_Window* window)
+{
+ SerenityPlatformWindow::from_sdl_window(window)->window()->show();
+}
+
+void Serenity_HideWindow(_THIS, SDL_Window* window)
+{
+ SerenityPlatformWindow::from_sdl_window(window)->window()->hide();
+}
+
+void Serenity_SetWindowTitle(_THIS, SDL_Window* window)
+{
+ SerenityPlatformWindow::from_sdl_window(window)->window()->set_title(window->title);
+}
+
+void Serenity_SetWindowSize(_THIS, SDL_Window* window)
+{
+ SerenityPlatformWindow::from_sdl_window(window)->window()->resize(window->w, window->h);
+}
+
+void Serenity_SetWindowFullscreen(_THIS, SDL_Window* window,
+ SDL_VideoDisplay* display,
+ SDL_bool fullscreen)
+{
+ dbgln("Attempting to set SDL Window fullscreen to {}", (bool)fullscreen);
+ SerenityPlatformWindow::from_sdl_window(window)->window()->set_fullscreen(fullscreen);
+}
+
+static Gfx::Color get_color_from_sdl_pixel(SDL_PixelFormat const& format, u32 pixel)
+{
+ u8 r = ((pixel & format.Rmask) >> format.Rshift) << format.Rloss;
+ u8 g = ((pixel & format.Gmask) >> format.Gshift) << format.Gloss;
+ u8 b = ((pixel & format.Bmask) >> format.Bshift) << format.Bloss;
+ u8 a = ((pixel & format.Amask) >> format.Ashift) << format.Aloss;
+ return {r, g, b, a};
+}
+
+static RefPtr<Gfx::Bitmap> create_bitmap_from_surface(SDL_Surface& icon)
+{
+ auto bitmap_or_error = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, {icon.w, icon.h});
+ if (bitmap_or_error.is_error())
+ return {};
+ auto bitmap = bitmap_or_error.release_value();
+
+ SDL_LockSurface(&icon);
+
+ auto const& pixel_format = *icon.format;
+ auto pixels = static_cast<u32*>(icon.pixels);
+ size_t offset = 0;
+ switch (pixel_format.format) {
+ case SDL_PIXELFORMAT_ARGB8888:
+ for (size_t y = 0; y < icon.h; ++y) {
+ for (size_t x = 0; x < icon.w; ++x) {
+ bitmap->set_pixel({x, y}, get_color_from_sdl_pixel(pixel_format, pixels[offset]));
+ ++offset;
+ }
+ }
+ break;
+ default:
+ warnln("Unable to convert SDL_Surface with format {} to bitmap", SDL_GetPixelFormatName(pixel_format.format));
+ }
+
+ SDL_UnlockSurface(&icon);
+
+ return bitmap;
+}
+
+void Serenity_SetWindowIcon(_THIS, SDL_Window* window, SDL_Surface* icon)
+{
+ auto serenity_window = SerenityPlatformWindow::from_sdl_window(window)->window();
+ if (!icon) {
+ serenity_window->set_icon(nullptr);
+ return;
+ }
+
+ auto icon_bitmap = create_bitmap_from_surface(*icon);
+ if (icon_bitmap)
+ serenity_window->set_icon(icon_bitmap);
+}
+
+void Serenity_DestroyWindow(_THIS, SDL_Window* window)
+{
+ auto platform_window = SerenityPlatformWindow::from_sdl_window(window);
+ delete platform_window;
+ window->driverdata = nullptr;
+}
+
+SDL_bool Serenity_GetWindowWMInfo(_THIS, SDL_Window *window, SDL_SysWMinfo *info)
+{
+ info->subsystem = SDL_SYSWM_SERENITY;
+ return SDL_TRUE;
+}
+
+int Serenity_CreateWindowFramebuffer(_THIS, SDL_Window* window, Uint32* format,
+ void** pixels, int* pitch)
+{
+ dbgln("{}: Creating a new framebuffer of size {}x{}", __FUNCTION__, window->w, window->h);
+ auto win = SerenityPlatformWindow::from_sdl_window(window);
+ *format = SDL_PIXELFORMAT_RGB888;
+ auto bitmap_or_error = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRx8888, {window->w, window->h});
+ if (bitmap_or_error.is_error())
+ return SDL_OutOfMemory();
+ win->widget()->m_buffer = bitmap_or_error.release_value();
+ *pitch = win->widget()->m_buffer->pitch();
+ *pixels = win->widget()->m_buffer->scanline(0);
+ return 0;
+}
+
+int Serenity_UpdateWindowFramebuffer(_THIS, SDL_Window* window,
+ const SDL_Rect* rects, int numrects)
+{
+ auto win = SerenityPlatformWindow::from_sdl_window(window);
+ for (int i = 0; i < numrects; i++) {
+ win->widget()->update(Gfx::IntRect(rects[i].x, rects[i].y, rects[i].w, rects[i].h));
+ }
+ SERENITY_PumpEvents(_this);
+
+ return 0;
+}
+
+void Serenity_DestroyWindowFramebuffer(_THIS, SDL_Window* window)
+{
+ auto widget = SerenityPlatformWindow::from_sdl_window(window)->widget();
+ dbgln("{}: Destroy framebuffer {}", __FUNCTION__, widget->m_buffer->size());
+ widget->m_buffer = nullptr;
+}
+
+SDL_GLContext Serenity_GL_CreateContext(_THIS, SDL_Window* window)
+{
+ auto platform_window = SerenityPlatformWindow::from_sdl_window(window);
+
+ Uint32 format;
+ void* pixels;
+ int pitch;
+ Serenity_CreateWindowFramebuffer(_this, window, &format, &pixels, &pitch);
+
+ auto gl_context_or_error = GL::create_context(*platform_window->widget()->m_buffer);
+ if (gl_context_or_error.is_error()) {
+ SDL_SetError("Failed to initialize the GL context");
+ return nullptr;
+ }
+ auto gl_context = gl_context_or_error.release_value();
+ auto serenity_gl_context = new SerenityGLContext(move(gl_context));
+ platform_window->set_serenity_gl_context(serenity_gl_context);
+ GL::make_context_current(&serenity_gl_context->gl_context());
+ return serenity_gl_context;
+}
+
+void Serenity_GL_DeleteContext(_THIS, SDL_GLContext context)
+{
+ auto platform_context = static_cast<SerenityGLContext*>(context);
+ delete platform_context;
+}
+
+int Serenity_GL_LoadLibrary(_THIS, const char* path)
+{
+ if (_this->gl_config.driver_loaded) {
+ SDL_SetError("OpenGL library is already loaded");
+ return -1;
+ }
+
+ _this->gl_config.dll_handle = dlopen("libgl.so.serenity", RTLD_LAZY | RTLD_LOCAL);
+ if (!_this->gl_config.dll_handle) {
+ dbgln("Could not load OpenGL library: {}", dlerror());
+ _this->gl_config.driver_loaded = SDL_FALSE;
+ return -1;
+ }
+
+ _this->gl_config.driver_loaded = SDL_TRUE;
+ return 0;
+}
+
+void* Serenity_GL_GetProcAddress(_THIS, const char* proc)
+{
+ if (!_this->gl_config.dll_handle) {
+ SDL_SetError("OpenGL library not available");
+ return nullptr;
+ }
+ auto* res = dlsym(_this->gl_config.dll_handle, proc);
+ dbgln("GetProcAddress: {} -> {}", proc, res);
+ return res;
+}
+
+int Serenity_GL_MakeCurrent(_THIS, SDL_Window* window, SDL_GLContext context)
+{
+ if (!window || !context)
+ return 0;
+
+ auto platform_window = SerenityPlatformWindow::from_sdl_window(window);
+ auto serenity_gl_context = static_cast<SerenityGLContext*>(context);
+ platform_window->set_serenity_gl_context(serenity_gl_context);
+ GL::make_context_current(&serenity_gl_context->gl_context());
+ return 0;
+}
+
+int Serenity_GL_SwapWindow(_THIS, SDL_Window* window)
+{
+ auto platform_window = SerenityPlatformWindow::from_sdl_window(window);
+ if (platform_window->serenity_gl_context())
+ platform_window->serenity_gl_context()->gl_context().present();
+
+ platform_window->widget()->repaint();
+ return 0;
+}
+
+#endif /* SDL_VIDEO_DRIVER_SERENITY */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/serenity/SDL_serenityvideo.h b/src/video/serenity/SDL_serenityvideo.h
new file mode 100644
index 0000000000000000000000000000000000000000..f74e1bd981734caf023b77a9b9fa30c46be40e4c
--- /dev/null
+++ b/src/video/serenity/SDL_serenityvideo.h
@@ -0,0 +1,101 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_serenityvideo_h_
+#define SDL_serenityvideo_h_
+
+#include "../SDL_sysvideo.h"
+
+#include <LibGL/GLContext.h>
+#include <LibGUI/Widget.h>
+#include <LibGUI/Window.h>
+
+class SerenitySDLWidget final : public GUI::Widget {
+ C_OBJECT(SerenitySDLWidget)
+public:
+ explicit SerenitySDLWidget(SDL_Window*);
+ RefPtr<Gfx::Bitmap> m_buffer;
+
+protected:
+ void paint_event(GUI::PaintEvent&) override;
+ void resize_event(GUI::ResizeEvent&) override;
+ void show_event(GUI::ShowEvent&) override;
+ void hide_event(GUI::HideEvent&) override;
+
+ void mousedown_event(GUI::MouseEvent&) override;
+ void mousemove_event(GUI::MouseEvent&) override;
+ void mouseup_event(GUI::MouseEvent&) override;
+ void mousewheel_event(GUI::MouseEvent&) override;
+
+ void keydown_event(GUI::KeyEvent& event) override;
+ void keyup_event(GUI::KeyEvent& event) override;
+
+ void enter_event(Core::Event&) override;
+ void leave_event(Core::Event&) override;
+
+private:
+ SDL_Window* m_sdl_window = nullptr;
+};
+
+class SerenityGLContext final {
+public:
+ explicit SerenityGLContext(NonnullOwnPtr<GL::GLContext> gl_context)
+ : m_gl_context(move(gl_context))
+ {
+ }
+
+ GL::GLContext& gl_context() { return *m_gl_context; }
+
+private:
+ NonnullOwnPtr<GL::GLContext> m_gl_context;
+};
+
+class SerenityPlatformWindow final {
+public:
+ explicit SerenityPlatformWindow(SDL_Window* sdl_window)
+ : m_window(MUST(GUI::Window::try_create()))
+ , m_widget(MUST(SerenitySDLWidget::try_create(sdl_window)))
+ {
+ m_window->resize(sdl_window->w, sdl_window->h);
+ m_window->set_resizable(false);
+ }
+
+ static SerenityPlatformWindow* from_sdl_window(SDL_Window* window)
+ {
+ return static_cast<SerenityPlatformWindow*>(window->driverdata);
+ }
+
+ SerenityGLContext* serenity_gl_context() { return m_serenity_gl_context; }
+ void set_serenity_gl_context(SerenityGLContext* serenity_gl_context) { m_serenity_gl_context = serenity_gl_context; }
+
+ NonnullRefPtr<GUI::Window> window() { return m_window; }
+ NonnullRefPtr<SerenitySDLWidget> widget() { return m_widget; }
+
+private:
+ SerenityGLContext* m_serenity_gl_context;
+ NonnullRefPtr<GUI::Window> m_window;
+ NonnullRefPtr<SerenitySDLWidget> m_widget;
+};
+
+#endif /* SDL_serenityvideo_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */