mirror of
https://github.com/RGBCube/serenity
synced 2025-07-13 16:27:35 +00:00

Some SDL applications will not process inputs that they receive without ensuring that they have the keyboard input focus.
1709 lines
56 KiB
Diff
1709 lines
56 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
|
|
|
|
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 | 29 +-
|
|
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 | 160 ++++
|
|
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 | 720 ++++++++++++++++++
|
|
src/video/serenity/SDL_serenityvideo.h | 98 +++
|
|
20 files changed, 1414 insertions(+), 29 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 644715a..2400d53 100644
|
|
--- a/CMakeLists.txt
|
|
+++ b/CMakeLists.txt
|
|
@@ -1,7 +1,3 @@
|
|
-if(${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR})
|
|
- message(FATAL_ERROR "Prevented in-tree build. Please create a build directory outside of the SDL source code and run \"cmake -S ${CMAKE_SOURCE_DIR} -B .\" from there")
|
|
-endif()
|
|
-
|
|
cmake_minimum_required(VERSION 3.0.0)
|
|
project(SDL2 C CXX)
|
|
|
|
@@ -17,6 +13,9 @@ endif()
|
|
# 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)
|
|
cmake_minimum_required(VERSION 3.11.0)
|
|
target_compile_definitions(sdl-build-options INTERFACE "-DSDL_BUILDING_WINRT=1")
|
|
@@ -397,7 +396,7 @@ set_option(SDL_DUMMYVIDEO "Use dummy video driver" ON)
|
|
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)
|
|
@@ -1268,25 +1267,7 @@ elseif(UNIX AND NOT APPLE AND NOT ANDROID AND NOT RISCOS AND NOT HAIKU)
|
|
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()
|
|
- # 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 dba16e8..39c9ecb 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 8dcb392..a34c781 100644
|
|
--- a/cmake/sdlchecks.cmake
|
|
+++ b/cmake/sdlchecks.cmake
|
|
@@ -771,6 +771,26 @@ macro(CheckDirectFB)
|
|
endif()
|
|
endmacro()
|
|
|
|
+# Requires:
|
|
+# - n/a
|
|
+macro(CheckSerenity)
|
|
+ message_warn("Configuring SerenityOS!")
|
|
+ set(HAVE_VIDEO_SERENITY TRUE)
|
|
+ set(HAVE_AUDIO_SERENITY TRUE)
|
|
+ set(HAVE_SDL_VIDEO TRUE)
|
|
+ set(HAVE_SDL_AUDIO TRUE)
|
|
+
|
|
+ set(CMAKE_CXX_FLAGS "-std=c++2a ${CMAKE_CXX_FLAGS}")
|
|
+ file(GLOB SERENITY_SOURCES ${SDL2_SOURCE_DIR}/src/video/serenity/*.cpp ${SDL2_SOURCE_DIR}/src/audio/serenity/*.cpp)
|
|
+ set(SOURCE_FILES ${SOURCE_FILES} ${SERENITY_SOURCES})
|
|
+ set(SDL_VIDEO_DRIVER_SERENITY 1)
|
|
+ set(SDL_AUDIO_DRIVER_SERENITY 1)
|
|
+ set(SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1)
|
|
+ set(HAVE_VIDEO_OPENGL TRUE)
|
|
+ set(SDL_VIDEO_OPENGL 1)
|
|
+ list(APPEND EXTRA_LIBS ipc gui gfx gl core)
|
|
+endmacro(CheckSerenity)
|
|
+
|
|
# Requires:
|
|
# - n/a
|
|
macro(CheckVivante)
|
|
diff --git a/include/SDL_config.h.cmake b/include/SDL_config.h.cmake
|
|
index fcd18e5..d7b9cfc 100644
|
|
--- a/include/SDL_config.h.cmake
|
|
+++ b/include/SDL_config.h.cmake
|
|
@@ -312,6 +312,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@
|
|
@@ -394,6 +395,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 4d25999..24491ee 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 fb363f7..59c36e5 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 8aa7298..c16af45 100644
|
|
--- a/src/audio/SDL_sysaudio.h
|
|
+++ b/src/audio/SDL_sysaudio.h
|
|
@@ -208,6 +208,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..7f770ed
|
|
--- /dev/null
|
|
+++ b/src/audio/serenity/SDL_serenityaudio.cpp
|
|
@@ -0,0 +1,160 @@
|
|
+/*
|
|
+ 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, 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>(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 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 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 9d785aa..6c31981 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 2384a64..5090f3e 100644
|
|
--- a/src/video/SDL_sysvideo.h
|
|
+++ b/src/video/SDL_sysvideo.h
|
|
@@ -458,6 +458,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 93c803e..36960a1 100644
|
|
--- a/src/video/SDL_video.c
|
|
+++ b/src/video/SDL_video.c
|
|
@@ -122,6 +122,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
|
|
@@ -4146,6 +4149,10 @@ 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)
|
|
@@ -4425,6 +4432,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) {
|
|
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 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..494766f
|
|
--- /dev/null
|
|
+++ b/src/video/serenity/SDL_serenityvideo.cpp
|
|
@@ -0,0 +1,720 @@
|
|
+/*
|
|
+ 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;
|
|
+ };
|
|
+ w->window()->on_active_input_change = [window](bool is_active_input) {
|
|
+ SDL_SetKeyboardFocus(is_active_input ? window : nullptr);
|
|
+ };
|
|
+ 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: */
|