mirror of
https://github.com/SerenityOS/serenity
synced 2024-07-24 03:25:02 +00:00
1700 lines
55 KiB
Diff
1700 lines
55 KiB
Diff
From ab6529f3d53a3d596dcf8697aec2f1ca27cf6956 Mon Sep 17 00:00:00 2001
|
|
From: Andreas Kling <kling@serenityos.org>
|
|
Date: Sat, 27 Mar 2021 22:05:09 +0100
|
|
Subject: [PATCH 1/2] Add SerenityOS platform support
|
|
|
|
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>
|
|
---
|
|
CMakeLists.txt | 24 +-
|
|
build-scripts/config.sub | 3 +
|
|
cmake/sdlchecks.cmake | 20 +
|
|
include/SDL_config.h.cmake | 2 +
|
|
src/SDL_error.c | 9 +-
|
|
src/audio/SDL_audio.c | 3 +
|
|
src/audio/SDL_sysaudio.h | 1 +
|
|
src/audio/serenity/SDL_serenityaudio.cpp | 159 ++++
|
|
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 | 717 ++++++++++++++++++
|
|
src/video/serenity/SDL_serenityvideo.h | 98 +++
|
|
20 files changed, 1410 insertions(+), 24 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 358f32f..e744d17 100644
|
|
--- a/CMakeLists.txt
|
|
+++ b/CMakeLists.txt
|
|
@@ -1,10 +1,9 @@
|
|
-if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
|
|
- message(FATAL_ERROR "Prevented in-tree built. Please create a build directory outside of the SDL source code and call cmake from there")
|
|
-endif()
|
|
-
|
|
cmake_minimum_required(VERSION 3.0.0)
|
|
project(SDL2 C CXX)
|
|
|
|
+set(UNIX 1)
|
|
+set(VIDEO_WAYLAND off)
|
|
+
|
|
if(WINDOWS_STORE)
|
|
cmake_minimum_required(VERSION 3.11)
|
|
add_definitions(-DSDL_BUILDING_WINRT=1 -ZW)
|
|
@@ -360,7 +359,7 @@ set_option(VIDEO_DUMMY "Use dummy video driver" ON)
|
|
set_option(VIDEO_OPENGL "Include OpenGL support" ON)
|
|
set_option(VIDEO_OPENGLES "Include OpenGL ES support" ON)
|
|
set_option(PTHREADS "Use POSIX threads for multi-threading" ${SDL_PTHREADS_ENABLED_BY_DEFAULT})
|
|
-dep_option(PTHREADS_SEM "Use pthread semaphores" ON "PTHREADS" OFF)
|
|
+dep_option(PTHREADS_SEM "Use pthread semaphores" OFF "PTHREADS" OFF)
|
|
set_option(SDL_DLOPEN "Use dlopen for shared object loading" ${SDL_DLOPEN_ENABLED_BY_DEFAULT})
|
|
dep_option(OSS "Support the OSS audio API" ON "UNIX_SYS OR RISCOS" OFF)
|
|
set_option(ALSA "Support the ALSA audio API" ${UNIX_SYS})
|
|
@@ -1197,20 +1196,7 @@ elseif(UNIX AND NOT APPLE AND NOT ANDROID AND NOT RISCOS)
|
|
CheckLibSampleRate()
|
|
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()
|
|
- CheckOpenGLX11()
|
|
- CheckOpenGLESX11()
|
|
- CheckWayland()
|
|
- CheckVivante()
|
|
- # Need to check EGL before checking KMSDRM because KMSDRM depends on it.
|
|
- CheckEGLKMSDRM()
|
|
- CheckKMSDRM()
|
|
- CheckOpenGLKMSDRM()
|
|
- 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 a525aab..717488d 100755
|
|
--- a/build-scripts/config.sub
|
|
+++ b/build-scripts/config.sub
|
|
@@ -1403,6 +1403,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 f21a900..e3b8643 100644
|
|
--- a/cmake/sdlchecks.cmake
|
|
+++ b/cmake/sdlchecks.cmake
|
|
@@ -777,6 +777,26 @@ macro(CheckVivante)
|
|
endif(VIDEO_VIVANTE)
|
|
endmacro(CheckVivante)
|
|
|
|
+# 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:
|
|
# - libglvnd
|
|
macro(CheckOpenGLKMSDRM)
|
|
diff --git a/include/SDL_config.h.cmake b/include/SDL_config.h.cmake
|
|
index 0446547..d7002b1 100644
|
|
--- a/include/SDL_config.h.cmake
|
|
+++ b/include/SDL_config.h.cmake
|
|
@@ -291,6 +291,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@
|
|
@@ -367,6 +368,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/src/SDL_error.c b/src/SDL_error.c
|
|
index 3a5667b..d00654b 100644
|
|
--- a/src/SDL_error.c
|
|
+++ b/src/SDL_error.c
|
|
@@ -33,6 +33,7 @@ SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
|
/* Ignore call if invalid format pointer was passed */
|
|
if (fmt != NULL) {
|
|
va_list ap;
|
|
+ char errmsg[SDL_ERRBUFIZE];
|
|
SDL_error *error = SDL_GetErrBuf();
|
|
|
|
error->error = 1; /* mark error as valid */
|
|
@@ -41,10 +42,10 @@ SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
|
SDL_vsnprintf(error->str, ERR_MAX_STRLEN, fmt, ap);
|
|
va_end(ap);
|
|
|
|
- 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
|
|
+ SDL_GetErrorMsg(errmsg, sizeof(errmsg));
|
|
+ dbgputstr(errmsg, strlen(errmsg));
|
|
+ dbgputstr("\n", 1);
|
|
}
|
|
|
|
return -1;
|
|
diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c
|
|
index 5ce94d1..b98645b 100644
|
|
--- a/src/audio/SDL_audio.c
|
|
+++ b/src/audio/SDL_audio.c
|
|
@@ -121,6 +121,9 @@ static const AudioBootStrap *const bootstrap[] = {
|
|
#endif
|
|
#if SDL_AUDIO_DRIVER_DUMMY
|
|
&DUMMYAUDIO_bootstrap,
|
|
+#endif
|
|
+#if SDL_AUDIO_DRIVER_SERENITY
|
|
+ &SERENITYAUDIO_bootstrap,
|
|
#endif
|
|
NULL
|
|
};
|
|
diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h
|
|
index 17b9e70..fde6b68 100644
|
|
--- a/src/audio/SDL_sysaudio.h
|
|
+++ b/src/audio/SDL_sysaudio.h
|
|
@@ -212,6 +212,7 @@ extern AudioBootStrap PSPAUDIO_bootstrap;
|
|
extern AudioBootStrap VITAAUD_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 0000000..01633cd
|
|
--- /dev/null
|
|
+++ b/src/audio/serenity/SDL_serenityaudio.cpp
|
|
@@ -0,0 +1,159 @@
|
|
+/*
|
|
+ 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/ConnectionFromClient.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)
|
|
+{
|
|
+ SDL_free(that->hidden->mixbuf);
|
|
+ SDL_free(that->hidden);
|
|
+}
|
|
+
|
|
+static int SERENITYAUDIO_OpenDevice(_THIS, void*, char const*, int iscapture)
|
|
+{
|
|
+ /* 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 (!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>(Core::EventLoop::MakeInspectable::No);
|
|
+ if (!h->client)
|
|
+ h->client = MUST(Audio::ConnectionFromClient::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 = Time::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 int 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 = 1;
|
|
+ impl->HasCaptureSupport = SDL_FALSE;
|
|
+
|
|
+ return 1; // this audio target is available.
|
|
+}
|
|
+
|
|
+AudioBootStrap SERENITYAUDIO_bootstrap = {
|
|
+ "serenity", "Serenity using AudioServer", SERENITYAUDIO_Init, 0
|
|
+};
|
|
+
|
|
+#endif
|
|
diff --git a/src/audio/serenity/SDL_serenityaudio.h b/src/audio/serenity/SDL_serenityaudio.h
|
|
new file mode 100644
|
|
index 0000000..e1b98b3
|
|
--- /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/ConnectionFromClient.h>
|
|
+#include <LibCore/EventLoop.h>
|
|
+
|
|
+#define _THIS SDL_AudioDevice* that
|
|
+
|
|
+struct SDL_PrivateAudioData {
|
|
+ RefPtr<Audio::ConnectionFromClient> 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 b6dc32a..5eda105 100644
|
|
--- a/src/stdlib/SDL_stdlib.c
|
|
+++ b/src/stdlib/SDL_stdlib.c
|
|
@@ -533,7 +533,7 @@ int SDL_toupper(int x) { return ((x) >= 'a') && ((x) <= 'z') ? ('A'+((x)-'a')) :
|
|
int SDL_tolower(int x) { return ((x) >= 'A') && ((x) <= 'Z') ? ('a'+((x)-'A')) : (x); }
|
|
#endif
|
|
|
|
-#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); }
|
|
#else
|
|
int SDL_isblank(int x) { return ((x) == ' ') || ((x) == '\t'); }
|
|
diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h
|
|
index 682e525..c1047f7 100644
|
|
--- a/src/video/SDL_sysvideo.h
|
|
+++ b/src/video/SDL_sysvideo.h
|
|
@@ -442,6 +442,7 @@ extern VideoBootStrap QNX_bootstrap;
|
|
extern VideoBootStrap OFFSCREEN_bootstrap;
|
|
extern VideoBootStrap OS2DIVE_bootstrap;
|
|
extern VideoBootStrap OS2VMAN_bootstrap;
|
|
+extern VideoBootStrap SERENITYVIDEO_bootstrap;
|
|
|
|
extern SDL_VideoDevice *SDL_GetVideoDevice(void);
|
|
extern int SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode);
|
|
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
|
|
index a5cbe69..a83fb1a 100644
|
|
--- a/src/video/SDL_video.c
|
|
+++ b/src/video/SDL_video.c
|
|
@@ -119,6 +119,9 @@ static VideoBootStrap *bootstrap[] = {
|
|
&OS2DIVE_bootstrap,
|
|
&OS2VMAN_bootstrap,
|
|
#endif
|
|
+#if SDL_VIDEO_DRIVER_SERENITY
|
|
+ &SERENITYVIDEO_bootstrap,
|
|
+#endif
|
|
#if SDL_VIDEO_DRIVER_DUMMY
|
|
&DUMMY_bootstrap,
|
|
#endif
|
|
@@ -4073,6 +4076,10 @@ SDL_IsScreenKeyboardShown(SDL_Window *window)
|
|
#if SDL_VIDEO_DRIVER_VITA
|
|
#include "vita/SDL_vitamessagebox.h"
|
|
#endif
|
|
+#if SDL_VIDEO_DRIVER_SERENITY
|
|
+#include "serenity/SDL_serenitymessagebox.h"
|
|
+#endif
|
|
+
|
|
|
|
#if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT || SDL_VIDEO_DRIVER_COCOA || SDL_VIDEO_DRIVER_UIKIT || SDL_VIDEO_DRIVER_X11 || SDL_VIDEO_DRIVER_WAYLAND || SDL_VIDEO_DRIVER_HAIKU || SDL_VIDEO_DRIVER_OS2
|
|
static SDL_bool SDL_MessageboxValidForDriver(const SDL_MessageBoxData *messageboxdata, SDL_SYSWM_TYPE drivertype)
|
|
@@ -4199,6 +4206,12 @@ 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) {
|
|
SDL_SetError("No message system available");
|
|
diff --git a/src/video/serenity/SDL_serenityevents.cpp b/src/video/serenity/SDL_serenityevents.cpp
|
|
new file mode 100644
|
|
index 0000000..04cbf21
|
|
--- /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 0000000..89e9e91
|
|
--- /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 0000000..ac5e358
|
|
--- /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, 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 0000000..34e6077
|
|
--- /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 0000000..5d0cb52
|
|
--- /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 0000000..039f036
|
|
--- /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 0000000..30fcadb
|
|
--- /dev/null
|
|
+++ b/src/video/serenity/SDL_serenityvideo.cpp
|
|
@@ -0,0 +1,717 @@
|
|
+/*
|
|
+ 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_video.h"
|
|
+# include "../../../include/SDL_scancode.h"
|
|
+}
|
|
+
|
|
+# include "SDL_serenityevents_c.h"
|
|
+# include "SDL_serenitymouse.h"
|
|
+# include "SDL_serenityvideo.h"
|
|
+
|
|
+# include <dlfcn.h>
|
|
+# include <LibCore/EventLoop.h>
|
|
+# include <LibGfx/Bitmap.h>
|
|
+# include <LibGUI/Application.h>
|
|
+# include <LibGUI/Desktop.h>
|
|
+# include <LibGUI/Painter.h>
|
|
+# include <LibGUI/Widget.h>
|
|
+# include <LibGUI/Window.h>
|
|
+
|
|
+static int conversion_map[] = {
|
|
+ SDLK_UNKNOWN,
|
|
+ SDLK_ESCAPE,
|
|
+ SDLK_TAB,
|
|
+ SDLK_BACKSPACE,
|
|
+ SDLK_RETURN,
|
|
+ SDLK_INSERT,
|
|
+ SDLK_DELETE,
|
|
+ SDLK_PRINTSCREEN,
|
|
+ SDLK_SYSREQ,
|
|
+ SDLK_HOME,
|
|
+ SDLK_END,
|
|
+ SDLK_LEFT,
|
|
+ SDLK_UP,
|
|
+ SDLK_RIGHT,
|
|
+ SDLK_DOWN,
|
|
+ SDLK_PAGEUP,
|
|
+ SDLK_PAGEDOWN,
|
|
+ SDLK_LSHIFT,
|
|
+ SDLK_RSHIFT,
|
|
+ SDLK_LCTRL,
|
|
+ SDLK_LALT,
|
|
+ SDLK_CAPSLOCK,
|
|
+ SDLK_NUMLOCKCLEAR,
|
|
+ SDLK_SCROLLLOCK,
|
|
+ SDLK_F1,
|
|
+ SDLK_F2,
|
|
+ SDLK_F3,
|
|
+ SDLK_F4,
|
|
+ SDLK_F5,
|
|
+ SDLK_F6,
|
|
+ SDLK_F7,
|
|
+ SDLK_F8,
|
|
+ SDLK_F9,
|
|
+ SDLK_F10,
|
|
+ SDLK_F11,
|
|
+ SDLK_F12,
|
|
+ SDLK_SPACE,
|
|
+ SDLK_EXCLAIM,
|
|
+ SDLK_QUOTE,
|
|
+ SDLK_3,
|
|
+ SDLK_4,
|
|
+ SDLK_5,
|
|
+ SDLK_7,
|
|
+ SDLK_QUOTE,
|
|
+ SDLK_9,
|
|
+ SDLK_0,
|
|
+ SDLK_8,
|
|
+ SDLK_PLUS,
|
|
+ SDLK_COMMA,
|
|
+ SDLK_MINUS,
|
|
+ SDLK_PERIOD,
|
|
+ SDLK_SLASH,
|
|
+ SDLK_0,
|
|
+ SDLK_1,
|
|
+ SDLK_2,
|
|
+ SDLK_3,
|
|
+ SDLK_4,
|
|
+ SDLK_5,
|
|
+ SDLK_6,
|
|
+ SDLK_7,
|
|
+ SDLK_8,
|
|
+ SDLK_9,
|
|
+ SDLK_SEMICOLON,
|
|
+ SDLK_SEMICOLON,
|
|
+ SDLK_COMMA,
|
|
+ SDLK_EQUALS,
|
|
+ SDLK_PERIOD,
|
|
+ SDLK_SLASH,
|
|
+ SDLK_2,
|
|
+ SDLK_a,
|
|
+ SDLK_b,
|
|
+ SDLK_c,
|
|
+ SDLK_d,
|
|
+ SDLK_e,
|
|
+ SDLK_f,
|
|
+ SDLK_g,
|
|
+ SDLK_h,
|
|
+ SDLK_i,
|
|
+ SDLK_j,
|
|
+ SDLK_k,
|
|
+ SDLK_l,
|
|
+ SDLK_m,
|
|
+ SDLK_n,
|
|
+ SDLK_o,
|
|
+ SDLK_p,
|
|
+ SDLK_q,
|
|
+ SDLK_r,
|
|
+ SDLK_s,
|
|
+ SDLK_t,
|
|
+ SDLK_u,
|
|
+ SDLK_v,
|
|
+ SDLK_w,
|
|
+ SDLK_x,
|
|
+ SDLK_y,
|
|
+ SDLK_z,
|
|
+ SDLK_LEFTBRACKET,
|
|
+ SDLK_RIGHTBRACKET,
|
|
+ SDLK_BACKSLASH,
|
|
+ SDLK_6,
|
|
+ SDLK_MINUS,
|
|
+ SDLK_LEFTBRACKET,
|
|
+ SDLK_RIGHTBRACKET,
|
|
+ SDLK_BACKSLASH,
|
|
+ SDLK_BACKQUOTE,
|
|
+ SDLK_BACKQUOTE,
|
|
+ SDLK_UNKNOWN,
|
|
+};
|
|
+
|
|
+static SDL_Scancode scancode_map[] = {
|
|
+ SDL_SCANCODE_UNKNOWN,
|
|
+ SDL_SCANCODE_ESCAPE,
|
|
+ SDL_SCANCODE_TAB,
|
|
+ SDL_SCANCODE_BACKSPACE,
|
|
+ SDL_SCANCODE_RETURN,
|
|
+ SDL_SCANCODE_INSERT,
|
|
+ SDL_SCANCODE_DELETE,
|
|
+ SDL_SCANCODE_PRINTSCREEN,
|
|
+ SDL_SCANCODE_SYSREQ,
|
|
+ SDL_SCANCODE_HOME,
|
|
+ SDL_SCANCODE_END,
|
|
+ SDL_SCANCODE_LEFT,
|
|
+ SDL_SCANCODE_UP,
|
|
+ SDL_SCANCODE_RIGHT,
|
|
+ SDL_SCANCODE_DOWN,
|
|
+ SDL_SCANCODE_PAGEUP,
|
|
+ SDL_SCANCODE_PAGEDOWN,
|
|
+ SDL_SCANCODE_LSHIFT,
|
|
+ SDL_SCANCODE_RSHIFT,
|
|
+ SDL_SCANCODE_LCTRL,
|
|
+ SDL_SCANCODE_LALT,
|
|
+ SDL_SCANCODE_CAPSLOCK,
|
|
+ SDL_SCANCODE_NUMLOCKCLEAR,
|
|
+ SDL_SCANCODE_SCROLLLOCK,
|
|
+ SDL_SCANCODE_F1,
|
|
+ SDL_SCANCODE_F2,
|
|
+ SDL_SCANCODE_F3,
|
|
+ SDL_SCANCODE_F4,
|
|
+ SDL_SCANCODE_F5,
|
|
+ SDL_SCANCODE_F6,
|
|
+ SDL_SCANCODE_F7,
|
|
+ SDL_SCANCODE_F8,
|
|
+ SDL_SCANCODE_F9,
|
|
+ SDL_SCANCODE_F10,
|
|
+ SDL_SCANCODE_F11,
|
|
+ SDL_SCANCODE_F12,
|
|
+ SDL_SCANCODE_SPACE,
|
|
+ SDL_SCANCODE_1,
|
|
+ SDL_SCANCODE_APOSTROPHE,
|
|
+ SDL_SCANCODE_3,
|
|
+ SDL_SCANCODE_4,
|
|
+ SDL_SCANCODE_5,
|
|
+ SDL_SCANCODE_7,
|
|
+ SDL_SCANCODE_APOSTROPHE,
|
|
+ SDL_SCANCODE_9,
|
|
+ SDL_SCANCODE_0,
|
|
+ SDL_SCANCODE_8,
|
|
+ SDL_SCANCODE_EQUALS,
|
|
+ SDL_SCANCODE_COMMA,
|
|
+ SDL_SCANCODE_MINUS,
|
|
+ SDL_SCANCODE_PERIOD,
|
|
+ SDL_SCANCODE_SLASH,
|
|
+ SDL_SCANCODE_0,
|
|
+ SDL_SCANCODE_1,
|
|
+ SDL_SCANCODE_2,
|
|
+ SDL_SCANCODE_3,
|
|
+ SDL_SCANCODE_4,
|
|
+ SDL_SCANCODE_5,
|
|
+ SDL_SCANCODE_6,
|
|
+ SDL_SCANCODE_7,
|
|
+ SDL_SCANCODE_8,
|
|
+ SDL_SCANCODE_9,
|
|
+ SDL_SCANCODE_SEMICOLON,
|
|
+ SDL_SCANCODE_SEMICOLON,
|
|
+ SDL_SCANCODE_COMMA,
|
|
+ SDL_SCANCODE_EQUALS,
|
|
+ SDL_SCANCODE_PERIOD,
|
|
+ SDL_SCANCODE_SLASH,
|
|
+ SDL_SCANCODE_2,
|
|
+ SDL_SCANCODE_A,
|
|
+ SDL_SCANCODE_B,
|
|
+ SDL_SCANCODE_C,
|
|
+ SDL_SCANCODE_D,
|
|
+ SDL_SCANCODE_E,
|
|
+ SDL_SCANCODE_F,
|
|
+ SDL_SCANCODE_G,
|
|
+ SDL_SCANCODE_H,
|
|
+ SDL_SCANCODE_I,
|
|
+ SDL_SCANCODE_J,
|
|
+ SDL_SCANCODE_K,
|
|
+ SDL_SCANCODE_L,
|
|
+ SDL_SCANCODE_M,
|
|
+ SDL_SCANCODE_N,
|
|
+ SDL_SCANCODE_O,
|
|
+ SDL_SCANCODE_P,
|
|
+ SDL_SCANCODE_Q,
|
|
+ SDL_SCANCODE_R,
|
|
+ SDL_SCANCODE_S,
|
|
+ SDL_SCANCODE_T,
|
|
+ SDL_SCANCODE_U,
|
|
+ SDL_SCANCODE_V,
|
|
+ SDL_SCANCODE_W,
|
|
+ SDL_SCANCODE_X,
|
|
+ SDL_SCANCODE_Y,
|
|
+ SDL_SCANCODE_Z,
|
|
+ SDL_SCANCODE_LEFTBRACKET,
|
|
+ SDL_SCANCODE_RIGHTBRACKET,
|
|
+ SDL_SCANCODE_BACKSLASH,
|
|
+ SDL_SCANCODE_6,
|
|
+ SDL_SCANCODE_MINUS,
|
|
+ SDL_SCANCODE_LEFTBRACKET,
|
|
+ SDL_SCANCODE_RIGHTBRACKET,
|
|
+ SDL_SCANCODE_BACKSLASH,
|
|
+ SDL_SCANCODE_GRAVE,
|
|
+ SDL_SCANCODE_GRAVE,
|
|
+ SDL_SCANCODE_UNKNOWN,
|
|
+};
|
|
+
|
|
+/* 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 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(int devindex)
|
|
+{
|
|
+ SDL_VideoDevice* device;
|
|
+
|
|
+ dbgln("SERENITY_CreateDevice {}", devindex);
|
|
+ /* 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->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)
|
|
+{
|
|
+ VERIFY(!g_app);
|
|
+ g_app = GUI::Application::construct(0, nullptr);
|
|
+ g_app->set_quit_when_last_window_deleted(false);
|
|
+
|
|
+ dbgln("SDL2: Initialising SDL application");
|
|
+
|
|
+ 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);
|
|
+ g_app->quit();
|
|
+}
|
|
+
|
|
+SerenitySDLWidget::SerenitySDLWidget(SDL_Window* window)
|
|
+ : m_sdl_window(window)
|
|
+{
|
|
+ SDL_Keycode keymap[SDL_NUM_SCANCODES];
|
|
+ SDL_GetDefaultKeymap(keymap);
|
|
+
|
|
+ for (int i = 0; i < (sizeof(scancode_map) / sizeof(SDL_Keycode)); ++i) {
|
|
+ if (scancode_map[i] != SDL_SCANCODE_UNKNOWN)
|
|
+ keymap[scancode_map[i]] = conversion_map[i];
|
|
+ }
|
|
+ SDL_SetKeymap(0, keymap, SDL_NUM_SCANCODES);
|
|
+
|
|
+ update();
|
|
+}
|
|
+
|
|
+void SerenitySDLWidget::paint_event(GUI::PaintEvent& event)
|
|
+{
|
|
+ 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("SDL2: Creating new window of size {}x{}", 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 = [] {
|
|
+ if (SDL_SendQuit())
|
|
+ return GUI::Window::CloseRequestDecision::Close;
|
|
+ return GUI::Window::CloseRequestDecision::StayOpen;
|
|
+ };
|
|
+ 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::try_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;
|
|
+}
|
|
+
|
|
+int Serenity_CreateWindowFramebuffer(_THIS, SDL_Window* window, Uint32* format,
|
|
+ void** pixels, int* pitch)
|
|
+{
|
|
+ dbgln("SDL2: Creating a new framebuffer of size {}x{}", window->w, window->h);
|
|
+ auto win = SerenityPlatformWindow::from_sdl_window(window);
|
|
+ *format = SDL_PIXELFORMAT_RGB888;
|
|
+ auto bitmap_or_error = Gfx::Bitmap::try_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);
|
|
+ dbgln("Created framebuffer {}x{}", win->widget()->width(), win->widget()->height());
|
|
+ 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("SDL2: Destroy framebuffer {}", widget->m_buffer->size());
|
|
+ widget->m_buffer = nullptr;
|
|
+}
|
|
+
|
|
+SDL_GLContext Serenity_GL_CreateContext(_THIS, SDL_Window* window)
|
|
+{
|
|
+ auto win = SerenityPlatformWindow::from_sdl_window(window);
|
|
+
|
|
+ Uint32 format;
|
|
+ void* pixels;
|
|
+ int pitch;
|
|
+ Serenity_CreateWindowFramebuffer(_this, window, &format, &pixels, &pitch);
|
|
+
|
|
+ win->widget()->m_gl_context = GL::create_context(*win->widget()->m_buffer);
|
|
+ GL::make_context_current(win->widget()->m_gl_context);
|
|
+
|
|
+ return new SerenityGLContext(*window);
|
|
+}
|
|
+
|
|
+void Serenity_GL_DeleteContext(_THIS, SDL_GLContext context)
|
|
+{
|
|
+ auto platform_context = static_cast<SerenityGLContext*>(context);
|
|
+ auto sdl_window = platform_context->sdl_window();
|
|
+ auto platform_window = SerenityPlatformWindow::from_sdl_window(&sdl_window);
|
|
+
|
|
+ platform_window->widget()->m_gl_context = nullptr;
|
|
+ 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);
|
|
+ GL::make_context_current(platform_window->widget()->m_gl_context);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int Serenity_GL_SwapWindow(_THIS, SDL_Window* window)
|
|
+{
|
|
+ auto win = SerenityPlatformWindow::from_sdl_window(window);
|
|
+ if (win->widget()->m_gl_context)
|
|
+ GL::present_context(win->widget()->m_gl_context);
|
|
+
|
|
+ win->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 0000000..b5c6759
|
|
--- /dev/null
|
|
+++ b/src/video/serenity/SDL_serenityvideo.h
|
|
@@ -0,0 +1,98 @@
|
|
+/*
|
|
+ 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;
|
|
+ OwnPtr<GL::GLContext> m_gl_context;
|
|
+
|
|
+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 SerenityPlatformWindow final {
|
|
+public:
|
|
+ SerenityPlatformWindow(SDL_Window* sdl_window)
|
|
+ : m_window(GUI::Window::construct())
|
|
+ , m_widget(SerenitySDLWidget::construct(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);
|
|
+ }
|
|
+
|
|
+ NonnullRefPtr<GUI::Window> window() { return m_window; }
|
|
+ NonnullRefPtr<SerenitySDLWidget> widget() { return m_widget; }
|
|
+
|
|
+private:
|
|
+ NonnullRefPtr<GUI::Window> m_window;
|
|
+ NonnullRefPtr<SerenitySDLWidget> m_widget;
|
|
+};
|
|
+
|
|
+class SerenityGLContext final {
|
|
+public:
|
|
+ explicit SerenityGLContext(SDL_Window& sdl_window)
|
|
+ : m_sdl_window(sdl_window)
|
|
+ {
|
|
+ }
|
|
+
|
|
+ SDL_Window& sdl_window() const { return m_sdl_window; }
|
|
+
|
|
+private:
|
|
+ SDL_Window& m_sdl_window;
|
|
+};
|
|
+
|
|
+#endif /* SDL_serenityvideo_h_ */
|
|
+
|
|
+/* vi: set ts=4 sw=4 expandtab: */
|
|
--
|
|
2.36.1
|
|
|