mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-23 18:02:05 -05:00
77e890b15e
Now that oss-fuzz is on a clang commit > the 17.x release candidates, we can start looking at some shiny new features to enable.
1680 lines
59 KiB
Diff
1680 lines
59 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>
|
|
Co-Authored-By: Refrag <R3FR4GYT@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 | 47 ++
|
|
src/video/serenity/SDL_serenitymessagebox.h | 38 +
|
|
src/video/serenity/SDL_serenitymouse.cpp | 169 +++++
|
|
src/video/serenity/SDL_serenitymouse.h | 39 ++
|
|
src/video/serenity/SDL_serenityvideo.cpp | 655 ++++++++++++++++++
|
|
src/video/serenity/SDL_serenityvideo.h | 101 +++
|
|
21 files changed, 1392 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++23 ${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 coreminimal)
|
|
+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..a0c7d0772be7198a521708abb9d69ef9cc413597
|
|
--- /dev/null
|
|
+++ b/src/video/serenity/SDL_serenitymessagebox.cpp
|
|
@@ -0,0 +1,47 @@
|
|
+/*
|
|
+ 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/Application.h>
|
|
+# include <LibGUI/MessageBox.h>
|
|
+# include <LibMain/Main.h>
|
|
+
|
|
+extern "C" int SERENITY_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
|
+{
|
|
+ // From the docs: "[SDL_ShowMessageBox] may be called at any time, even before SDL_Init()."
|
|
+ AK::RefPtr<GUI::Application> app = GUI::Application::the();
|
|
+ if (app == nullptr)
|
|
+ app = MUST(GUI::Application::create(Main::Arguments {}));
|
|
+
|
|
+ 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..c603fe8cedaae61ab8ae84407734d1c89f99ff06
|
|
--- /dev/null
|
|
+++ b/src/video/serenity/SDL_serenitymouse.cpp
|
|
@@ -0,0 +1,157 @@
|
|
+/*
|
|
+ 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>
|
|
+#include <LibGUI/ConnectionToWindowServer.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;
|
|
+}
|
|
+
|
|
+static void
|
|
+SERENITY_WarpMouse(SDL_Window *window, int x, int y)
|
|
+{
|
|
+ auto platform_window = SerenityPlatformWindow::from_sdl_window(window);
|
|
+
|
|
+ auto window_position = platform_window->window()->position();
|
|
+ auto warp_position = Gfx::Point(x, y);
|
|
+
|
|
+ auto absolute_warp_position = window_position + warp_position;
|
|
+
|
|
+ GUI::ConnectionToWindowServer::the().async_set_global_cursor_position(absolute_warp_position);
|
|
+ SDL_SendMouseMotion(window, 0, 0, warp_position.x(), warp_position.y());
|
|
+}
|
|
+
|
|
+void
|
|
+SERENITY_InitMouse(_THIS)
|
|
+{
|
|
+ dbgln("SERENITY_InitMouse");
|
|
+
|
|
+ auto mouse = SDL_GetMouse();
|
|
+
|
|
+ mouse->CreateSystemCursor = SERENITY_CreateSystemCursor;
|
|
+ mouse->ShowCursor = SERENITY_ShowCursor;
|
|
+ mouse->FreeCursor = SERENITY_FreeCursor;
|
|
+ mouse->WarpMouse = SERENITY_WarpMouse;
|
|
+
|
|
+ // FIXME: implement below methods
|
|
+ //mouse->CreateCursor = ...;
|
|
+ //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: */
|