Allow toggling fullscreen without restart and add keybind (#14714)

This commit is contained in:
grorp 2024-06-02 21:05:16 +02:00 committed by GitHub
parent 981d67324b
commit 833bb542fc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 120 additions and 15 deletions

View File

@ -723,6 +723,11 @@ local function eventhandler(event)
mm_game_theme.set_engine(true)
return true
end
if event == "FullscreenChange" then
-- Refresh the formspec to keep the fullscreen checkbox up to date.
ui.update()
return true
end
return false
end

View File

@ -2399,6 +2399,9 @@ keymap_minimap (Minimap key) key KEY_KEY_V
# Key for taking screenshots.
keymap_screenshot (Screenshot) key KEY_F12
# Key for toggling fullscreen mode.
keymap_fullscreen (Fullscreen key) key KEY_F11
# Key for dropping the currently selected item.
keymap_drop (Drop item key) key KEY_KEY_Q

View File

@ -14,7 +14,8 @@ Callbacks
* `core.button_handler(fields)`: called when a button is pressed.
* `fields` = `{name1 = value1, name2 = value2, ...}`
* `core.event_handler(event)`
* `event`: `"MenuQuit"`, `"KeyEnter"`, `"ExitButton"` or `"EditBoxEnter"`
* `event`: `"MenuQuit"`, `"KeyEnter"`, `"ExitButton"`, `"EditBoxEnter"` or
`"FullscreenChange"`
Gamedata

View File

@ -179,6 +179,11 @@ public:
/** \return True if window is fullscreen. */
virtual bool isFullscreen() const = 0;
//! Enables or disables fullscreen mode.
/** Only works on SDL.
\return True on success. */
virtual bool setFullscreen(bool fullscreen) { return false; }
//! Checks if the window could possibly be visible.
/** If this returns false, you should not do any rendering. */
virtual bool isWindowVisible() const { return true; };

View File

@ -463,13 +463,7 @@ bool CIrrDeviceSDL::createWindowWithContext()
{
u32 SDL_Flags = 0;
if (CreationParams.Fullscreen) {
#ifdef _IRR_EMSCRIPTEN_PLATFORM_
SDL_Flags |= SDL_WINDOW_FULLSCREEN;
#else
SDL_Flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
#endif
}
SDL_Flags |= getFullscreenFlag(CreationParams.Fullscreen);
if (Resizable)
SDL_Flags |= SDL_WINDOW_RESIZABLE;
if (CreationParams.WindowMaximized)
@ -889,6 +883,14 @@ bool CIrrDeviceSDL::run()
IsInBackground = false;
break;
case SDL_RENDER_TARGETS_RESET:
os::Printer::log("Received SDL_RENDER_TARGETS_RESET. Rendering is probably broken.", ELL_ERROR);
break;
case SDL_RENDER_DEVICE_RESET:
os::Printer::log("Received SDL_RENDER_DEVICE_RESET. Rendering is probably broken.", ELL_ERROR);
break;
default:
break;
} // end switch
@ -1157,14 +1159,37 @@ bool CIrrDeviceSDL::isWindowMaximized() const
bool CIrrDeviceSDL::isFullscreen() const
{
#ifdef _IRR_EMSCRIPTEN_PLATFORM_
return SDL_GetWindowFlags(0) == SDL_WINDOW_FULLSCREEN;
#else
if (!Window)
return false;
u32 flags = SDL_GetWindowFlags(Window);
return (flags & SDL_WINDOW_FULLSCREEN) != 0 ||
(flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0;
}
return CIrrDeviceStub::isFullscreen();
u32 CIrrDeviceSDL::getFullscreenFlag(bool fullscreen)
{
if (!fullscreen)
return 0;
#ifdef _IRR_EMSCRIPTEN_PLATFORM_
return SDL_WINDOW_FULLSCREEN;
#else
return SDL_WINDOW_FULLSCREEN_DESKTOP;
#endif
}
bool CIrrDeviceSDL::setFullscreen(bool fullscreen)
{
if (!Window)
return false;
// The SDL wiki says that this may trigger SDL_RENDER_TARGETS_RESET, but
// looking at the SDL source, this only happens with D3D, so it's not
// relevant to us.
bool success = SDL_SetWindowFullscreen(Window, getFullscreenFlag(fullscreen)) == 0;
if (!success)
os::Printer::log("SDL_SetWindowFullscreen failed", SDL_GetError(), ELL_ERROR);
return success;
}
bool CIrrDeviceSDL::isWindowVisible() const
{
return !IsInBackground;

View File

@ -86,6 +86,10 @@ public:
/** \return True if window is fullscreen. */
bool isFullscreen() const override;
//! Enables or disables fullscreen mode.
/** \return True on success. */
bool setFullscreen(bool fullscreen) override;
//! Checks if the window could possibly be visible.
bool isWindowVisible() const override;
@ -299,6 +303,8 @@ private:
bool Resizable;
static u32 getFullscreenFlag(bool fullscreen);
core::rect<s32> lastElemPos;
struct SKeyMap

View File

@ -1164,7 +1164,8 @@ void Game::run()
g_settings->getU16("screen_w"),
g_settings->getU16("screen_h")
);
const bool initial_window_maximized = g_settings->getBool("window_maximized");
const bool initial_window_maximized = !g_settings->getBool("fullscreen") &&
g_settings->getBool("window_maximized");
while (m_rendering_engine->run()
&& !(*kill || g_gamecallback->shutdown_requested

View File

@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "settings.h"
#include "util/numeric.h"
#include "inputhandler.h"
#include "gui/mainmenumanager.h"
@ -113,6 +114,19 @@ bool MyEventReceiver::OnEvent(const SEvent &event)
return true;
}
// This is separate from other keyboard handling so that it also works in menus.
if (event.EventType == EET_KEY_INPUT_EVENT) {
const KeyPress keyCode(event.KeyInput);
if (keyCode == getKeySetting("keymap_fullscreen")) {
if (event.KeyInput.PressedDown && !fullscreen_is_down) {
bool fullscreen = RenderingEngine::get_raw_device()->isFullscreen();
g_settings->setBool("fullscreen", !fullscreen);
}
fullscreen_is_down = event.KeyInput.PressedDown;
return true;
}
}
// Let the menu handle events, if one is active.
if (isMenuActive()) {
if (g_touchscreengui)

View File

@ -220,6 +220,9 @@ private:
// often changing keys, and keysListenedFor is expected
// to change seldomly but contain lots of keys.
KeyList keysListenedFor;
// Intentionally not reset by clearInput/releaseAllKeys.
bool fullscreen_is_down = false;
};
class InputHandler

View File

@ -207,7 +207,12 @@ RenderingEngine::RenderingEngine(IEventReceiver *receiver)
#else
u16 screen_w = std::max<u16>(g_settings->getU16("screen_w"), 1);
u16 screen_h = std::max<u16>(g_settings->getU16("screen_h"), 1);
bool window_maximized = g_settings->getBool("window_maximized");
// If I…
// 1. … set fullscreen = true and window_maximized = true on startup
// 2. … set fullscreen = false later
// on Linux with SDL, everything breaks.
// => Don't do it.
bool window_maximized = !fullscreen && g_settings->getBool("window_maximized");
#endif
// bpp, fsaa, vsync
@ -249,18 +254,40 @@ RenderingEngine::RenderingEngine(IEventReceiver *receiver)
gui::EGST_WINDOWS_METALLIC, driver);
m_device->getGUIEnvironment()->setSkin(skin);
skin->drop();
g_settings->registerChangedCallback("fullscreen", settingChangedCallback, this);
g_settings->registerChangedCallback("window_maximized", settingChangedCallback, this);
}
RenderingEngine::~RenderingEngine()
{
sanity_check(s_singleton == this);
g_settings->deregisterChangedCallback("fullscreen", settingChangedCallback, this);
g_settings->deregisterChangedCallback("window_maximized", settingChangedCallback, this);
core.reset();
m_device->closeDevice();
m_device->drop();
s_singleton = nullptr;
}
void RenderingEngine::settingChangedCallback(const std::string &name, void *data)
{
IrrlichtDevice *device = static_cast<RenderingEngine*>(data)->m_device;
if (name == "fullscreen") {
device->setFullscreen(g_settings->getBool("fullscreen"));
} else if (name == "window_maximized") {
if (!device->isFullscreen()) {
if (g_settings->getBool("window_maximized"))
device->maximizeWindow();
else
device->restoreWindow();
}
}
}
v2u32 RenderingEngine::_getWindowSize() const
{
if (core)

View File

@ -168,6 +168,7 @@ public:
const bool initial_window_maximized);
private:
static void settingChangedCallback(const std::string &name, void *data);
v2u32 _getWindowSize() const;
std::unique_ptr<RenderingCore> core;

View File

@ -182,6 +182,7 @@ void set_default_settings()
settings->setDefault("keymap_toggle_profiler", "KEY_F6");
settings->setDefault("keymap_camera_mode", "KEY_KEY_C");
settings->setDefault("keymap_screenshot", "KEY_F12");
settings->setDefault("keymap_fullscreen", "KEY_F11");
settings->setDefault("keymap_increase_viewing_range_min", "+");
settings->setDefault("keymap_decrease_viewing_range_min", "-");
settings->setDefault("keymap_slot1", "KEY_KEY_1");

View File

@ -193,6 +193,8 @@ GUIEngine::GUIEngine(JoystickController *joystick,
m_script = std::make_unique<MainMenuScripting>(this);
g_settings->registerChangedCallback("fullscreen", fullscreenChangedCallback, this);
try {
m_script->setMainMenuData(&m_data->script_data);
m_data->script_data.errormessage.clear();
@ -319,7 +321,8 @@ void GUIEngine::run()
g_settings->getU16("screen_w"),
g_settings->getU16("screen_h")
);
const bool initial_window_maximized = g_settings->getBool("window_maximized");
const bool initial_window_maximized = !g_settings->getBool("fullscreen") &&
g_settings->getBool("window_maximized");
FpsControl fps_control;
f32 dtime = 0.0f;
@ -377,6 +380,8 @@ void GUIEngine::run()
/******************************************************************************/
GUIEngine::~GUIEngine()
{
g_settings->deregisterChangedCallback("fullscreen", fullscreenChangedCallback, this);
// deinitialize script first. gc destructors might depend on other stuff
infostream << "GUIEngine: Deinitializing scripting" << std::endl;
m_script.reset();
@ -666,3 +671,9 @@ void GUIEngine::updateTopLeftTextSize()
m_irr_toplefttext = gui::StaticText::add(m_rendering_engine->get_gui_env(),
m_toplefttext, rect, false, true, 0, -1);
}
/******************************************************************************/
void GUIEngine::fullscreenChangedCallback(const std::string &name, void *data)
{
static_cast<GUIEngine*>(data)->getScriptIface()->handleMainMenuEvent("FullscreenChange");
}

View File

@ -296,4 +296,6 @@ private:
bool m_clouds_enabled = true;
/** data used to draw clouds */
clouddata m_cloud;
static void fullscreenChangedCallback(const std::string &name, void *data);
};