Skip to content

Commit

Permalink
Core: Add new display_index option
Browse files Browse the repository at this point in the history
Allow users to pick on which screen to run the game
  • Loading branch information
julianxhokaxhiu committed Jan 21, 2025
1 parent 8948bba commit 5898473
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 8 deletions.
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

## Commmon

- Core: Users can now choose on which screen to run the game, using the new `display_index` option.
- Music: Add the ability to play a custom `main_menu` music file on the new game screen.

## FF7
Expand Down
6 changes: 6 additions & 0 deletions misc/FFNx.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
## DISPLAY
#########################

#[DISPLAY INDEX]
# The display where you want the game to run. By default the window will be created on the primary display.
# NOTE: If the value is set lower than 1, it will pick the primary display. If the value is set higher to the maximum number of screens, it will pick the last one.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~
display_index = -1

#[RENDERING BACKEND]
# Available choices are:
# - 0: Auto ( default, will pick the best rendering backend for your GPU )
Expand Down
5 changes: 5 additions & 0 deletions src/cfg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ long external_voice_volume;
long external_ambient_volume;
long ffmpeg_video_volume;
bool ff7_advanced_blinking;
long display_index;

std::vector<std::string> get_string_or_array_of_strings(const toml::node_view<toml::node> &node)
{
Expand Down Expand Up @@ -317,6 +318,7 @@ void read_cfg()
external_ambient_volume = config["external_ambient_volume"].value_or(-1);
ffmpeg_video_volume = config["ffmpeg_video_volume"].value_or(-1);
ff7_advanced_blinking = config["ff7_advanced_blinking"].value_or(false);
display_index = config["display_index"].value_or(-1);

// Windows x or y size can't be less then 0
if (window_size_x < 0) window_size_x = 0;
Expand Down Expand Up @@ -517,4 +519,7 @@ void read_cfg()
// GAME LIGHTING
if (ff8) game_lighting = GAME_LIGHTING_ORIGINAL;
else if (enable_lighting) game_lighting = GAME_LIGHTING_PER_PIXEL;

// DISPLAY INDEX
if (display_index < 1) display_index = -1;
}
1 change: 1 addition & 0 deletions src/cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,5 +166,6 @@ extern long external_voice_volume;
extern long external_ambient_volume;
extern long ffmpeg_video_volume;
extern bool ff7_advanced_blinking;
extern long display_index;

void read_cfg();
55 changes: 47 additions & 8 deletions src/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ struct {
uint32_t h;
} gameWindow[GameWindowState::COUNT];

struct MonitorInfo {
RECT rcMonitor;
std::string deviceName;
};
std::vector<MonitorInfo> monitors;

// global game window handler
RECT gameWindowRect;
HINSTANCE gameHinstance;
Expand Down Expand Up @@ -493,7 +499,6 @@ void adjust_maximized_client_rect(HWND window, RECT& rect) {
rect = monitor_info.rcWork;
}


bool composition_enabled() {
BOOL composition_enabled = FALSE;
bool success = DwmIsCompositionEnabled(&composition_enabled) == S_OK;
Expand Down Expand Up @@ -680,10 +685,11 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_MENUCHAR:
if (LOWORD(wParam) == VK_RETURN)
{
const auto& targetMonitor = monitors[display_index-1];
if (fullscreen)
{
// Bring back the original resolution
ChangeDisplaySettingsEx(0, &dmCurrentScreenSettings, 0, CDS_FULLSCREEN, 0);
ChangeDisplaySettingsExA(targetMonitor.deviceName.c_str(), &dmCurrentScreenSettings, 0, CDS_FULLSCREEN, 0);

// Move to window
SetWindowLongPtr(gameHwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE);
Expand All @@ -700,7 +706,7 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
gameWindow[GameWindowState::PRE_FULLSCREEN] = gameWindow[GameWindowState::CURRENT];

// Bring back the user resolution
ChangeDisplaySettingsEx(0, &dmNewScreenSettings, 0, CDS_FULLSCREEN, 0);
ChangeDisplaySettingsExA(targetMonitor.deviceName.c_str(), &dmNewScreenSettings, 0, CDS_FULLSCREEN, 0);

// Move to fullscreen
SetWindowLongPtr(gameHwnd, GWL_STYLE, WS_SYSMENU | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE);
Expand Down Expand Up @@ -737,6 +743,21 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
return common_externals.engine_wndproc(hwnd, uMsg, wParam, lParam);
}

BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
std::vector<MonitorInfo>* monitors = reinterpret_cast<std::vector<MonitorInfo>*>(dwData);

MONITORINFOEX monitorInfoEx;
monitorInfoEx.cbSize = sizeof(MONITORINFOEX);

if (GetMonitorInfo(hMonitor, &monitorInfoEx)) {
bool isPrimary = (monitorInfoEx.dwFlags & MONITORINFOF_PRIMARY) != 0;
monitors->push_back({ monitorInfoEx.rcMonitor, monitorInfoEx.szDevice });
if (isPrimary && display_index < 1) display_index = monitors->size();
}

return TRUE;
}

int common_create_window(HINSTANCE hInstance, struct game_obj* game_object)
{
uint32_t ret = FALSE;
Expand Down Expand Up @@ -775,8 +796,15 @@ int common_create_window(HINSTANCE hInstance, struct game_obj* game_object)
g_FF7SteamAchievements = std::make_unique<SteamAchievementsFF7>();
}

// fetch current user screen settings
EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &dmCurrentScreenSettings);
// Enumerate available monitors
EnumDisplayMonitors(nullptr, nullptr, MonitorEnumProc, reinterpret_cast<LPARAM>(&monitors));
if (display_index > monitors.size()) display_index = monitors.size();

// Get the target monitor
auto& targetMonitor = monitors[display_index-1];

// fetch current screen settings
EnumDisplaySettingsA(targetMonitor.deviceName.c_str(), ENUM_CURRENT_SETTINGS, &dmCurrentScreenSettings);

// store all settings so we can change only few parameters
dmNewScreenSettings = dmCurrentScreenSettings;
Expand Down Expand Up @@ -824,13 +852,23 @@ int common_create_window(HINSTANCE hInstance, struct game_obj* game_object)

if (fullscreen)
{
if (ChangeDisplaySettingsEx(0, &dmNewScreenSettings, 0, CDS_FULLSCREEN, 0) != DISP_CHANGE_SUCCESSFUL)
if (ChangeDisplaySettingsExA(targetMonitor.deviceName.c_str(), &dmNewScreenSettings, 0, CDS_FULLSCREEN, 0) != DISP_CHANGE_SUCCESSFUL)
{
MessageBoxA(gameHwnd, "Failed to set the requested fullscreen mode, reverting to the original resolution.\n", "Error", 0);
ffnx_error("failed to set fullscreen mode\n");
window_size_x = dmCurrentScreenSettings.dmPelsWidth;
window_size_y = dmCurrentScreenSettings.dmPelsHeight;
}
else
{
// re-fetch current monitors
monitors.clear();
EnumDisplayMonitors(nullptr, nullptr, MonitorEnumProc, reinterpret_cast<LPARAM>(&monitors));
// Get the target monitor
targetMonitor = monitors[display_index-1];
// update current screen settings
dmCurrentScreenSettings = dmNewScreenSettings;
}
}
}

Expand Down Expand Up @@ -859,13 +897,14 @@ int common_create_window(HINSTANCE hInstance, struct game_obj* game_object)
else
calc_window_size(window_size_x, window_size_y);

const RECT& monitorRect = targetMonitor.rcMonitor;
hWnd = CreateWindowExA(
WS_EX_APPWINDOW,
VREF(game_object, window_class),
VREF(game_object, window_title),
fullscreen ? WS_SYSMENU | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS : WS_OVERLAPPEDWINDOW,
fullscreen ? 0 : gameWindow[GameWindowState::CURRENT].x,
fullscreen ? 0 : gameWindow[GameWindowState::CURRENT].y,
monitorRect.left + (fullscreen ? 0 : gameWindow[GameWindowState::CURRENT].x),
monitorRect.top + (fullscreen ? 0 : gameWindow[GameWindowState::CURRENT].y),
fullscreen ? window_size_x : gameWindow[GameWindowState::CURRENT].w,
fullscreen ? window_size_y : gameWindow[GameWindowState::CURRENT].h,
0,
Expand Down

0 comments on commit 5898473

Please sign in to comment.