Files
WickedEngine/Editor/main_SDL2.cpp
T
Dennis Brakhane 764fd0c5ca fix exit button on Windows, and in edge cases on Linux (#1262)
After #1258, the exit button (not close) didn't work at all in Windows
and on Linux it didn't actually cause the application to close if an
untitled file had been saved.

Rewrite the logic to work both for close as well as exit.
2025-10-30 07:09:46 +01:00

249 lines
7.0 KiB
C++

#include "stdafx.h"
#include "Editor.h"
#include "sdl2.h"
#include <fstream>
#include "icon.h"
#ifdef __linux__
# include <execinfo.h>
# include <csignal>
# include <cstdio>
# include <unistd.h>
#endif
using namespace std;
class EditorWithDevInfo : public Editor
{
public:
const char* GetAdapterName() const
{
return graphicsDevice == nullptr ? "(no device)" : graphicsDevice->GetAdapterName().c_str();
}
const char* GetDriverDescription() const
{
return graphicsDevice == nullptr ? "(no device)" : graphicsDevice->GetDriverDescription().c_str();
}
} editor;
int sdl_loop()
{
while (editor.KeepRunning())
{
editor.Run();
SDL_Event event;
while(SDL_PollEvent(&event)){
bool textinput_action_delete = false;
switch(event.type){
case SDL_QUIT:
editor.Exit();
break;
case SDL_WINDOWEVENT:
switch (event.window.event) {
case SDL_WINDOWEVENT_RESIZED:
// Tells the engine to reload window configuration (size and dpi)
editor.SetWindow(editor.window);
break;
case SDL_WINDOWEVENT_FOCUS_LOST:
editor.is_window_active = false;
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
editor.is_window_active = true;
editor.HotReload();
break;
default:
break;
}
case SDL_KEYDOWN:
if(event.key.keysym.scancode == SDL_SCANCODE_BACKSPACE
|| event.key.keysym.scancode == SDL_SCANCODE_DELETE
|| event.key.keysym.scancode == SDL_SCANCODE_KP_BACKSPACE){
wi::gui::TextInputField::DeleteFromInput();
textinput_action_delete = true;
}
break;
case SDL_TEXTINPUT:
if(!textinput_action_delete){
if(event.text.text[0] >= 21){
wi::gui::TextInputField::AddInput(event.text.text[0]);
}
}
break;
case SDL_DROPFILE:
editor.renderComponent.Open(event.drop.file);
editor.is_window_active = true;
break;
default:
break;
}
wi::input::sdlinput::ProcessEvent(event);
}
}
return 0;
}
void set_window_icon(SDL_Window *window) {
// these masks are needed to tell SDL_CreateRGBSurface(From)
// to assume the data it gets is byte-wise RGB(A) data
Uint32 rmask, gmask, bmask, amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
int shift = (embedded_image.bytes_per_pixel == 3) ? 8 : 0;
rmask = 0xff000000 >> shift;
gmask = 0x00ff0000 >> shift;
bmask = 0x0000ff00 >> shift;
amask = 0x000000ff >> shift;
#else // little endian, like x86
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = (embedded_image.bytes_per_pixel == 3) ? 0 : 0xff000000;
#endif
SDL_Surface* icon = SDL_CreateRGBSurfaceFrom((void*)embedded_image.pixel_data, embedded_image.width,
embedded_image.height, embedded_image.bytes_per_pixel*8, embedded_image.bytes_per_pixel* embedded_image.width,
rmask, gmask, bmask, amask);
SDL_SetWindowIcon(window, icon);
SDL_FreeSurface(icon);
}
#ifdef __linux__
void crash_handler(int sig)
{
static bool already_handled = false;
void* btbuf[100];
char outbuf[512];
if (already_handled) return;
already_handled = true;
size_t size = backtrace(btbuf, 100);
snprintf(
outbuf, sizeof(outbuf),
"Signal: %i (%s)\n"
"Version: %s\n"
"Adapter: %s\n"
"Driver: %s\n"
"Stacktrace:\n",
sig, sigdescr_np(sig),
wi::version::GetVersionString(),
editor.GetAdapterName(),
editor.GetDriverDescription()
);
fprintf(
stderr,
"\e[31m" // red
"The editor just crashed, sorry about that! If you make a bug report, please include the following information:\n\n%s",
outbuf
);
backtrace_symbols_fd(btbuf, size, STDERR_FILENO); // backtrace_symbols does a malloc which could crash, backtrace_symbols_fd does not.
fprintf(stderr, "\e[m"); // back to normal
// finally, we also try to write the crash data to a file
// this might fail because we're in a weird state right now, but there's no harm done if it doesn't work
// Use C interface because some stuff in the c++ stdlib could be calling malloc
const char* filename = "wicked-editor-crash-log.txt";
FILE* logfile = fopen(filename, "w");
if (logfile != nullptr)
{
fputs(outbuf, logfile);
fflush(logfile);
backtrace_symbols_fd(btbuf, size, fileno(logfile));
fputs("\nBacklog:\n", logfile);
wi::backlog::_forEachLogEntry_unsafe([&logfile] (auto&& entry) {
fputs(entry.text.c_str(), logfile);
fflush(logfile);
});
fclose(logfile);
char cwdbuf[200];
fprintf(stderr, "\e[1mcrash log written to %s/%s\e[m\n", getcwd(cwdbuf, sizeof(cwdbuf)), filename);
}
abort();
}
#endif
int main(int argc, char *argv[])
{
#ifdef __linux__
// dummy backtrace() call to force libgcc to be loaded ahead of time.
// Otherwise it might lead to malloc calls in the crash_handler, which we want to avoid
void* dummy[1];
backtrace(dummy, 1);
for (int sig : std::array{SIGABRT, SIGBUS, SIGILL, SIGFPE, SIGSEGV})
{
signal(sig, crash_handler);
}
#endif
wi::arguments::Parse(argc, argv);
sdl2::sdlsystem_ptr_t system = sdl2::make_sdlsystem(SDL_INIT_EVERYTHING | SDL_INIT_EVENTS);
if (*system) {
throw sdl2::SDLError("Error creating SDL2 system");
}
int width = 1920;
int height = 1080;
bool fullscreen = false;
wi::Timer timer;
if (editor.config.Open("config.ini"))
{
if (editor.config.Has("width"))
{
width = editor.config.GetInt("width");
height = editor.config.GetInt("height");
}
fullscreen = editor.config.GetBool("fullscreen");
editor.allow_hdr = editor.config.GetBool("allow_hdr");
wilog("config.ini loaded in %.2f milliseconds\n", (float)timer.elapsed_milliseconds());
}
width = std::max(100, width);
height = std::max(100, height);
sdl2::window_ptr_t window = sdl2::make_window(
wi::helper::StringRemoveTrailingWhitespaces(exe_customization.name_padded).c_str(),
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
width, height,
SDL_WINDOW_SHOWN | SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
if (!window) {
throw sdl2::SDLError("Error creating window");
}
set_window_icon(window.get());
if (fullscreen)
{
//SDL_SetWindowFullscreen(window.get(), SDL_TRUE);
//SDL_SetWindowFullscreen(window.get(), SDL_WINDOW_FULLSCREEN);
SDL_SetWindowFullscreen(window.get(), SDL_WINDOW_FULLSCREEN_DESKTOP);
}
editor.SetWindow(window.get());
int ret = sdl_loop();
wi::jobsystem::ShutDown();
return ret;
}