2021-03-09 23:51:28 -05:00
|
|
|
/*!
|
|
|
|
* @file display.cpp
|
|
|
|
* Display for graphics. This is the game window, distinct from the runtime console.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "display.h"
|
2022-06-22 23:37:46 -04:00
|
|
|
|
2022-08-21 18:13:27 -04:00
|
|
|
#include <optional>
|
|
|
|
|
2021-08-09 19:16:39 -04:00
|
|
|
#include "gfx.h"
|
2021-03-09 23:51:28 -05:00
|
|
|
|
|
|
|
#include "common/log/log.h"
|
2022-08-21 18:13:27 -04:00
|
|
|
#include "common/util/FileUtil.h"
|
|
|
|
#include "common/util/json_util.h"
|
|
|
|
|
|
|
|
#include "game/runtime.h"
|
|
|
|
|
|
|
|
#include "third-party/json.hpp"
|
2021-03-09 23:51:28 -05:00
|
|
|
|
2021-08-14 16:00:50 -04:00
|
|
|
/*
|
|
|
|
********************************
|
|
|
|
* Internal functions
|
|
|
|
********************************
|
|
|
|
*/
|
2021-08-09 19:16:39 -04:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
void set_main_display(std::shared_ptr<GfxDisplay> display) {
|
|
|
|
if (Display::g_displays.size() > 0) {
|
|
|
|
Display::g_displays[0] = display;
|
|
|
|
} else {
|
|
|
|
Display::g_displays.push_back(display);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
2021-03-09 23:51:28 -05:00
|
|
|
|
2021-08-14 16:00:50 -04:00
|
|
|
/*
|
|
|
|
********************************
|
|
|
|
* GfxDisplay
|
|
|
|
********************************
|
|
|
|
*/
|
2021-03-09 23:51:28 -05:00
|
|
|
|
2021-08-09 19:16:39 -04:00
|
|
|
void GfxDisplay::set_title(const char* title) {
|
|
|
|
if (!is_active()) {
|
|
|
|
lg::error("No window to set title `{}`.", title);
|
2021-03-09 23:51:28 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-06-16 22:46:12 -04:00
|
|
|
// TODO set title?
|
2021-08-09 19:16:39 -04:00
|
|
|
m_title = title;
|
|
|
|
}
|
|
|
|
|
2021-12-30 18:48:37 -05:00
|
|
|
int GfxDisplay::width() {
|
|
|
|
int w;
|
2022-06-16 22:46:12 -04:00
|
|
|
get_size(&w, NULL);
|
2021-12-30 18:48:37 -05:00
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
|
|
|
int GfxDisplay::height() {
|
|
|
|
int h;
|
2022-06-16 22:46:12 -04:00
|
|
|
get_size(NULL, &h);
|
2022-03-01 20:15:15 -05:00
|
|
|
#ifdef _WIN32
|
2022-06-16 22:46:12 -04:00
|
|
|
if (last_fullscreen_mode() == GfxDisplayMode::Borderless) {
|
2022-03-01 20:15:15 -05:00
|
|
|
// windows borderless hack
|
|
|
|
h--;
|
|
|
|
}
|
|
|
|
#endif
|
2021-12-30 18:48:37 -05:00
|
|
|
return h;
|
|
|
|
}
|
|
|
|
|
2022-08-21 18:13:27 -04:00
|
|
|
void GfxDisplay::save_display_settings() {
|
|
|
|
nlohmann::json json;
|
|
|
|
json["window_xpos"] = m_last_windowed_xpos;
|
|
|
|
json["window_ypos"] = m_last_windowed_ypos;
|
|
|
|
std::string file_path =
|
|
|
|
(file_util::get_user_settings_dir(g_game_version) / "display-settings.json").string();
|
2022-10-15 17:43:02 -04:00
|
|
|
file_util::create_dir_if_needed_for_file(file_path);
|
2022-08-21 18:13:27 -04:00
|
|
|
file_util::write_text_file(file_path, json.dump(2));
|
|
|
|
}
|
|
|
|
|
|
|
|
void GfxDisplay::restore_display_settings() {
|
|
|
|
try {
|
|
|
|
std::string file_path =
|
|
|
|
(file_util::get_user_settings_dir(g_game_version) / "display-settings.json").string();
|
|
|
|
if (!file_util::file_exists(file_path)) {
|
|
|
|
return;
|
|
|
|
}
|
2022-10-01 11:58:36 -04:00
|
|
|
lg::info("reading {}", file_path);
|
2022-08-21 18:13:27 -04:00
|
|
|
auto raw = file_util::read_text_file(file_path);
|
|
|
|
auto json = parse_commented_json(raw, "display-settings.json");
|
|
|
|
if (json.contains("window_xpos")) {
|
|
|
|
m_last_windowed_xpos = json.at("window_xpos").get<int>();
|
|
|
|
}
|
|
|
|
if (json.contains("window_ypos")) {
|
|
|
|
m_last_windowed_ypos = json.at("window_ypos").get<int>();
|
|
|
|
}
|
|
|
|
} catch (std::exception& e) {
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-14 16:00:50 -04:00
|
|
|
/*
|
|
|
|
********************************
|
|
|
|
* DISPLAY
|
|
|
|
********************************
|
|
|
|
*/
|
2021-08-09 19:16:39 -04:00
|
|
|
|
|
|
|
namespace Display {
|
|
|
|
|
|
|
|
std::vector<std::shared_ptr<GfxDisplay>> g_displays;
|
|
|
|
std::shared_ptr<GfxDisplay> GetMainDisplay() {
|
|
|
|
if (g_displays.size() == 0)
|
|
|
|
return NULL;
|
|
|
|
return g_displays.front()->is_active() ? g_displays.front() : NULL;
|
|
|
|
}
|
|
|
|
|
2022-06-30 21:11:58 -04:00
|
|
|
int InitMainDisplay(int width,
|
|
|
|
int height,
|
|
|
|
const char* title,
|
|
|
|
GfxSettings& settings,
|
|
|
|
GameVersion version) {
|
2021-08-09 19:16:39 -04:00
|
|
|
if (GetMainDisplay() != NULL) {
|
|
|
|
lg::warn("InitMainDisplay called when main display already exists.");
|
|
|
|
return 1;
|
|
|
|
}
|
2021-03-09 23:51:28 -05:00
|
|
|
|
2022-06-30 21:11:58 -04:00
|
|
|
auto display =
|
|
|
|
Gfx::GetCurrentRenderer()->make_display(width, height, title, settings, version, true);
|
2021-08-09 19:16:39 -04:00
|
|
|
if (display == NULL) {
|
|
|
|
lg::error("Failed to make main display.");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
set_main_display(display);
|
2022-08-21 18:13:27 -04:00
|
|
|
// Restore window settings
|
|
|
|
display->restore_display_settings();
|
2021-08-09 21:42:05 -04:00
|
|
|
return 0;
|
2021-03-09 23:51:28 -05:00
|
|
|
}
|
|
|
|
|
2021-08-13 20:06:16 -04:00
|
|
|
void KillMainDisplay() {
|
|
|
|
KillDisplay(GetMainDisplay());
|
|
|
|
}
|
|
|
|
|
2021-08-09 19:16:39 -04:00
|
|
|
void KillDisplay(std::shared_ptr<GfxDisplay> display) {
|
|
|
|
// lg::debug("kill display #x{:x}", (uintptr_t)display);
|
|
|
|
if (!display->is_active()) {
|
|
|
|
lg::warn("display #x{:x} cant be killed because it is not active");
|
2021-03-09 23:51:28 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-08-09 19:16:39 -04:00
|
|
|
if (GetMainDisplay() == display) {
|
2022-08-21 18:13:27 -04:00
|
|
|
// Save the main display's position to a file so it can be restored upon re-opening
|
|
|
|
display->save_display_settings();
|
2021-08-09 19:16:39 -04:00
|
|
|
// killing the main display, kill all children displays too!
|
2021-08-13 20:06:16 -04:00
|
|
|
while (g_displays.size() > 1) {
|
|
|
|
KillDisplay(g_displays.at(1));
|
2021-08-09 19:16:39 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// find this display in the list and remove it from there
|
|
|
|
// if everything went right the smart pointer should delete the display.
|
|
|
|
auto this_disp = std::find(g_displays.begin(), g_displays.end(), display);
|
|
|
|
g_displays.erase(this_disp);
|
2021-03-09 23:51:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace Display
|