mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-09 02:07:04 +08:00
feat(window): add exclusive fullscreen support with WM detection
This commit is contained in:
@@ -9,5 +9,6 @@ struct Argument {
|
|||||||
std::optional<bool> no_debug;
|
std::optional<bool> no_debug;
|
||||||
std::optional<std::string> language;
|
std::optional<std::string> language;
|
||||||
std::optional<std::string> video_driver;
|
std::optional<std::string> video_driver;
|
||||||
|
std::optional<bool> enable_exclusive;
|
||||||
};
|
};
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -184,14 +184,14 @@ inline std::string get_compiler_info() {
|
|||||||
#else
|
#else
|
||||||
result = "Unknown Compiler";
|
result = "Unknown Compiler";
|
||||||
#endif
|
#endif
|
||||||
constexpr long cpp_version =
|
constexpr long CPP_VERSION =
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
_MSVC_LANG;
|
_MSVC_LANG;
|
||||||
#else
|
#else
|
||||||
__cplusplus;
|
__cplusplus;
|
||||||
#endif
|
#endif
|
||||||
result += " (C++";
|
result += " (C++";
|
||||||
result += std::to_string(cpp_version);
|
result += std::to_string(CPP_VERSION);
|
||||||
result += ")";
|
result += ")";
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
45
include/Cubed/tools/system_window_manager.hpp
Normal file
45
include/Cubed/tools/system_window_manager.hpp
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Cubed/tools/log.hpp"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <string>
|
||||||
|
namespace Cubed {
|
||||||
|
enum class WindowManager { WINDOWS, UNKNOWN, NIRI, SWAY, HYPRLAND, KDE, GNOME };
|
||||||
|
|
||||||
|
namespace Tools {
|
||||||
|
inline WindowManager detect_wm() {
|
||||||
|
#ifdef _WIN32
|
||||||
|
return WindowManager::WINDOWS;
|
||||||
|
#endif
|
||||||
|
#ifdef __linux__
|
||||||
|
|
||||||
|
const char* desktop = getenv("XDG_CURRENT_DESKTOP");
|
||||||
|
|
||||||
|
if (!desktop)
|
||||||
|
return WindowManager::UNKNOWN;
|
||||||
|
Logger::info("XDG_CURRENT_DESKTOP {}", desktop);
|
||||||
|
std::string wm(desktop);
|
||||||
|
|
||||||
|
if (wm.find("niri") != std::string::npos)
|
||||||
|
return WindowManager::NIRI;
|
||||||
|
|
||||||
|
if (wm.find("sway") != std::string::npos)
|
||||||
|
return WindowManager::SWAY;
|
||||||
|
|
||||||
|
if (wm.find("Hyprland") != std::string::npos)
|
||||||
|
return WindowManager::HYPRLAND;
|
||||||
|
|
||||||
|
if (wm.find("KDE") != std::string::npos)
|
||||||
|
return WindowManager::KDE;
|
||||||
|
|
||||||
|
if (wm.find("GNOME") != std::string::npos)
|
||||||
|
return WindowManager::GNOME;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return WindowManager::UNKNOWN;
|
||||||
|
}
|
||||||
|
} // namespace Tools
|
||||||
|
|
||||||
|
} // namespace Cubed
|
||||||
@@ -49,6 +49,7 @@ private:
|
|||||||
bool m_mouse_enable = true;
|
bool m_mouse_enable = true;
|
||||||
bool m_imgui_init = false;
|
bool m_imgui_init = false;
|
||||||
bool m_game_running = false;
|
bool m_game_running = false;
|
||||||
|
bool m_enable_exclusive = false;
|
||||||
SDL_Window* m_window;
|
SDL_Window* m_window;
|
||||||
SDL_GLContext m_context;
|
SDL_GLContext m_context;
|
||||||
int m_window_width = 0;
|
int m_window_width = 0;
|
||||||
@@ -61,6 +62,9 @@ private:
|
|||||||
bool handle_key_event(const KeyEvent& e);
|
bool handle_key_event(const KeyEvent& e);
|
||||||
bool handle_window_resize_event(const WindowResizeEvent& e);
|
bool handle_window_resize_event(const WindowResizeEvent& e);
|
||||||
bool handle_mouse_button_event(const MouseButtonEvent& e);
|
bool handle_mouse_button_event(const MouseButtonEvent& e);
|
||||||
|
|
||||||
|
void set_exclusive_fullscreen(bool full);
|
||||||
|
void set_borderless_fullscreen(bool full);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -132,9 +132,9 @@ void App::handle_argument(int argc, char** argv) {
|
|||||||
[&](ArgParser& p) {
|
[&](ArgParser& p) {
|
||||||
auto arg = p.require_next("--video-driver");
|
auto arg = p.require_next("--video-driver");
|
||||||
m_argument.video_driver = arg;
|
m_argument.video_driver = arg;
|
||||||
}
|
}},
|
||||||
|
{"--enable-exclusive",
|
||||||
}
|
[&](ArgParser&) { m_argument.enable_exclusive = true; }}
|
||||||
|
|
||||||
};
|
};
|
||||||
ArgParser parser(argc, argv);
|
ArgParser parser(argc, argv);
|
||||||
|
|||||||
131
src/window.cpp
131
src/window.cpp
@@ -6,6 +6,7 @@
|
|||||||
#include "Cubed/tools/env_tools.hpp"
|
#include "Cubed/tools/env_tools.hpp"
|
||||||
#include "Cubed/tools/font.hpp"
|
#include "Cubed/tools/font.hpp"
|
||||||
#include "Cubed/tools/log.hpp"
|
#include "Cubed/tools/log.hpp"
|
||||||
|
#include "Cubed/tools/system_window_manager.hpp"
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <imgui_impl_opengl3.h>
|
#include <imgui_impl_opengl3.h>
|
||||||
@@ -110,6 +111,67 @@ bool Window::handle_mouse_button_event(const MouseButtonEvent& e) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Window::set_exclusive_fullscreen(bool full) {
|
||||||
|
|
||||||
|
if (full) {
|
||||||
|
SDL_GetWindowPosition(m_window, &windowed_xpos, &windowed_ypos);
|
||||||
|
SDL_GetWindowSize(m_window, &windowed_width, &windowed_height);
|
||||||
|
SDL_SetWindowFullscreen(m_window, true);
|
||||||
|
m_fullscreen = true;
|
||||||
|
m_config.set("window.fullscreen", true);
|
||||||
|
} else {
|
||||||
|
SDL_SetWindowFullscreen(m_window, false);
|
||||||
|
SDL_SetWindowPosition(m_window, windowed_xpos, windowed_ypos);
|
||||||
|
SDL_SetWindowSize(m_window, windowed_width, windowed_height);
|
||||||
|
m_fullscreen = false;
|
||||||
|
m_config.set("window.fullscreen", false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Window::set_borderless_fullscreen(bool full) {
|
||||||
|
if (full) {
|
||||||
|
// If the window is maximized, restore it first.
|
||||||
|
if (SDL_GetWindowFlags(m_window) & SDL_WINDOW_MAXIMIZED) {
|
||||||
|
SDL_RestoreWindow(m_window);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_GetWindowPosition(m_window, &windowed_xpos, &windowed_ypos);
|
||||||
|
|
||||||
|
SDL_GetWindowSize(m_window, &windowed_width, &windowed_height);
|
||||||
|
|
||||||
|
m_windowed_display = SDL_GetDisplayForWindow(m_window);
|
||||||
|
|
||||||
|
SDL_Rect display_bounds{};
|
||||||
|
if (!SDL_GetDisplayBounds(m_windowed_display, &display_bounds)) {
|
||||||
|
|
||||||
|
Logger::error("SDL_GetDisplayBounds failed: {}", SDL_GetError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_SetWindowBordered(m_window, false);
|
||||||
|
|
||||||
|
SDL_SetWindowPosition(m_window, display_bounds.x, display_bounds.y);
|
||||||
|
|
||||||
|
SDL_SetWindowSize(m_window, display_bounds.w, display_bounds.h);
|
||||||
|
|
||||||
|
SDL_RaiseWindow(m_window);
|
||||||
|
|
||||||
|
m_fullscreen = true;
|
||||||
|
m_config.set("window.fullscreen", true);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
SDL_SetWindowBordered(m_window, true);
|
||||||
|
|
||||||
|
SDL_SetWindowSize(m_window, windowed_width, windowed_height);
|
||||||
|
|
||||||
|
SDL_SetWindowPosition(m_window, windowed_xpos, windowed_ypos);
|
||||||
|
|
||||||
|
SDL_RaiseWindow(m_window);
|
||||||
|
|
||||||
|
m_fullscreen = false;
|
||||||
|
m_config.set("window.fullscreen", false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Window::init(const Argument& argument) {
|
void Window::init(const Argument& argument) {
|
||||||
auto video_driver = m_config.get("video_driver", std::string("auto"));
|
auto video_driver = m_config.get("video_driver", std::string("auto"));
|
||||||
if (argument.video_driver) {
|
if (argument.video_driver) {
|
||||||
@@ -125,6 +187,31 @@ void Window::init(const Argument& argument) {
|
|||||||
Logger::warn("Unknow Vider Driver {}", video_driver);
|
Logger::warn("Unknow Vider Driver {}", video_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool default_exclusive = false;
|
||||||
|
auto wm = Tools::detect_wm();
|
||||||
|
switch (wm) {
|
||||||
|
case WindowManager::NIRI:
|
||||||
|
case WindowManager::SWAY:
|
||||||
|
case WindowManager::HYPRLAND:
|
||||||
|
default_exclusive = true;
|
||||||
|
break;
|
||||||
|
case WindowManager::WINDOWS:
|
||||||
|
case WindowManager::GNOME:
|
||||||
|
case WindowManager::KDE:
|
||||||
|
case WindowManager::UNKNOWN:
|
||||||
|
default_exclusive = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_enable_exclusive =
|
||||||
|
m_config.get("enable_exclusive_fullscreen", default_exclusive);
|
||||||
|
|
||||||
|
if (argument.enable_exclusive) {
|
||||||
|
m_enable_exclusive = *argument.enable_exclusive;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::info("Exclusive Fullscreen {}", m_enable_exclusive);
|
||||||
|
|
||||||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||||||
Logger::error("sdl3 init fail");
|
Logger::error("sdl3 init fail");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@@ -194,49 +281,11 @@ void Window::toggle_fullscreen() {
|
|||||||
void Window::set_fullscreen(bool full) {
|
void Window::set_fullscreen(bool full) {
|
||||||
if (full == m_fullscreen)
|
if (full == m_fullscreen)
|
||||||
return;
|
return;
|
||||||
if (full) {
|
if (m_enable_exclusive) {
|
||||||
// If the window is maximized, restore it first.
|
set_exclusive_fullscreen(full);
|
||||||
if (SDL_GetWindowFlags(m_window) & SDL_WINDOW_MAXIMIZED) {
|
|
||||||
SDL_RestoreWindow(m_window);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_GetWindowPosition(m_window, &windowed_xpos, &windowed_ypos);
|
|
||||||
|
|
||||||
SDL_GetWindowSize(m_window, &windowed_width, &windowed_height);
|
|
||||||
|
|
||||||
m_windowed_display = SDL_GetDisplayForWindow(m_window);
|
|
||||||
|
|
||||||
SDL_Rect display_bounds{};
|
|
||||||
if (!SDL_GetDisplayBounds(m_windowed_display, &display_bounds)) {
|
|
||||||
|
|
||||||
Logger::error("SDL_GetDisplayBounds failed: {}", SDL_GetError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_SetWindowBordered(m_window, false);
|
|
||||||
|
|
||||||
SDL_SetWindowPosition(m_window, display_bounds.x, display_bounds.y);
|
|
||||||
|
|
||||||
SDL_SetWindowSize(m_window, display_bounds.w, display_bounds.h);
|
|
||||||
|
|
||||||
SDL_RaiseWindow(m_window);
|
|
||||||
|
|
||||||
m_fullscreen = true;
|
|
||||||
m_config.set("window.fullscreen", true);
|
|
||||||
} else {
|
} else {
|
||||||
|
set_borderless_fullscreen(full);
|
||||||
SDL_SetWindowBordered(m_window, true);
|
|
||||||
|
|
||||||
SDL_SetWindowSize(m_window, windowed_width, windowed_height);
|
|
||||||
|
|
||||||
SDL_SetWindowPosition(m_window, windowed_xpos, windowed_ypos);
|
|
||||||
|
|
||||||
SDL_RaiseWindow(m_window);
|
|
||||||
|
|
||||||
m_fullscreen = false;
|
|
||||||
m_config.set("window.fullscreen", false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int w, h;
|
int w, h;
|
||||||
SDL_GetWindowSize(m_window, &w, &h);
|
SDL_GetWindowSize(m_window, &w, &h);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user