RetroArch/gfx/common/win32_common.c

2751 lines
83 KiB
C
Raw Normal View History

/* RetroArch - A frontend for libretro.
2017-01-22 13:40:32 +01:00
* Copyright (C) 2011-2017 - Daniel De Matteis
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(_XBOX)
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0601 /* Windows 7 */
#endif
#if !defined(_MSC_VER) || _WIN32_WINNT >= 0x0601
#undef WINVER
#define WINVER 0x0601
#endif
#define IDI_ICON 1
#include <windows.h>
#endif /* !defined(_XBOX) */
2019-06-21 04:47:51 +02:00
#include <math.h>
#include <retro_miscellaneous.h>
2016-06-03 19:45:58 +02:00
#include <string/stdstring.h>
2016-09-08 08:15:40 +02:00
#ifdef HAVE_CONFIG_H
#include "../../config.h"
#endif
2016-09-11 14:54:34 +02:00
#include "win32_common.h"
2019-07-11 13:18:38 +02:00
#ifdef HAVE_GDI
2023-05-31 22:46:34 +02:00
#include "gdi_defines.h"
2019-07-11 13:18:38 +02:00
#endif
2016-03-04 05:01:49 +01:00
#include "../../frontend/frontend_driver.h"
2016-09-05 18:43:06 +02:00
#include "../../configuration.h"
2015-11-23 12:14:53 +01:00
#include "../../verbosity.h"
2016-09-17 15:07:45 +02:00
#include "../../paths.h"
2017-05-11 09:11:46 +02:00
#include "../../retroarch.h"
2019-01-20 03:16:58 +01:00
#include "../../tasks/task_content.h"
2016-06-03 09:14:53 +10:00
#include "../../tasks/tasks_internal.h"
#include "../../core_info.h"
2018-05-12 19:03:39 +02:00
#if !defined(_XBOX)
2015-04-09 05:16:02 +02:00
#include <commdlg.h>
2017-12-27 15:38:54 -05:00
#include <dbt.h>
2017-05-20 22:04:10 +02:00
#include "../../input/input_keymaps.h"
2016-09-15 20:54:05 +02:00
#include <shellapi.h>
#ifdef HAVE_MENU
#include "../../menu/menu_driver.h"
#endif
#include <encodings/utf.h>
/* Assume W-functions do not work below Win2K and Xbox platforms */
#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0500 || defined(_XBOX)
#ifndef LEGACY_WIN32
#define LEGACY_WIN32
#endif
#endif
/* For some reason this is missing from mingw winuser.h */
#ifndef EDS_ROTATEDMODE
#define EDS_ROTATEDMODE 4
#endif
2020-01-18 11:34:50 +01:00
/* These are defined in later SDKs, thus ifdeffed. */
2020-01-19 04:56:12 +01:00
#ifndef WM_MOUSEHWHEEL
#define WM_MOUSEHWHEEL 0x20e
#endif
#ifndef WM_MOUSEWHEEL
#define WM_MOUSEWHEEL 0x020A
#endif
2020-01-18 11:34:50 +01:00
#ifndef WM_POINTERUPDATE
#define WM_POINTERUPDATE 0x0245
#endif
#ifndef WM_POINTERDOWN
#define WM_POINTERDOWN 0x0246
#endif
#ifndef WM_POINTERUP
#define WM_POINTERUP 0x0247
#endif
const GUID GUID_DEVINTERFACE_HID = { 0x4d1e55b2, 0xf16f, 0x11Cf, { 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } };
2017-12-31 03:44:28 +01:00
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x501
2017-12-31 03:18:10 +01:00
static HDEVNOTIFY notification_handler;
2017-12-31 03:44:28 +01:00
#endif
#ifdef HAVE_DINPUT
extern bool dinput_handle_message(void *dinput, UINT message,
2016-11-06 11:52:03 +01:00
WPARAM wParam, LPARAM lParam);
#endif
2015-11-11 18:26:10 +01:00
#if !defined(_XBOX)
extern bool winraw_handle_message(UINT message,
WPARAM wParam, LPARAM lParam);
#endif
2020-05-12 14:36:27 +02:00
typedef struct DISPLAYCONFIG_RATIONAL_CUSTOM
{
UINT32 Numerator;
UINT32 Denominator;
2018-05-02 01:03:25 +02:00
} DISPLAYCONFIG_RATIONAL_CUSTOM;
2020-05-12 14:36:27 +02:00
typedef struct DISPLAYCONFIG_2DREGION_CUSTOM
{
UINT32 cx;
UINT32 cy;
2018-05-02 01:03:25 +02:00
} DISPLAYCONFIG_2DREGION_CUSTOM;
2020-05-12 14:36:27 +02:00
typedef struct DISPLAYCONFIG_VIDEO_SIGNAL_INFO_CUSTOM
{
UINT64 pixelRate;
DISPLAYCONFIG_RATIONAL_CUSTOM hSyncFreq;
DISPLAYCONFIG_RATIONAL_CUSTOM vSyncFreq;
DISPLAYCONFIG_2DREGION_CUSTOM activeSize;
DISPLAYCONFIG_2DREGION_CUSTOM totalSize;
union
{
struct
{
UINT32 videoStandard :16;
UINT32 vSyncFreqDivider :6;
UINT32 reserved :10;
} AdditionalSignalInfo;
UINT32 videoStandard;
} dummyunionname;
UINT32 scanLineOrdering;
2018-05-02 01:03:25 +02:00
} DISPLAYCONFIG_VIDEO_SIGNAL_INFO_CUSTOM;
2020-05-12 14:36:27 +02:00
typedef struct DISPLAYCONFIG_TARGET_MODE_CUSTOM
{
DISPLAYCONFIG_VIDEO_SIGNAL_INFO_CUSTOM targetVideoSignalInfo;
2018-05-02 01:03:25 +02:00
} DISPLAYCONFIG_TARGET_MODE_CUSTOM;
2020-05-12 14:36:27 +02:00
typedef struct DISPLAYCONFIG_PATH_SOURCE_INFO_CUSTOM
{
LUID adapterId;
UINT32 id;
union
{
UINT32 modeInfoIdx;
struct
{
UINT32 cloneGroupId :16;
UINT32 sourceModeInfoIdx :16;
} dummystructname;
} dummyunionname;
UINT32 statusFlags;
2018-05-02 01:03:25 +02:00
} DISPLAYCONFIG_PATH_SOURCE_INFO_CUSTOM;
2020-05-12 14:36:27 +02:00
typedef struct DISPLAYCONFIG_DESKTOP_IMAGE_INFO_CUSTOM
{
POINTL PathSourceSize;
RECTL DesktopImageRegion;
RECTL DesktopImageClip;
2018-05-02 01:03:25 +02:00
} DISPLAYCONFIG_DESKTOP_IMAGE_INFO_CUSTOM;
2020-05-12 14:36:27 +02:00
typedef struct DISPLAYCONFIG_SOURCE_MODE_CUSTOM
{
UINT32 width;
UINT32 height;
UINT32 pixelFormat;
POINTL position;
2018-05-02 01:03:25 +02:00
} DISPLAYCONFIG_SOURCE_MODE_CUSTOM;
2020-05-12 14:36:27 +02:00
typedef struct DISPLAYCONFIG_MODE_INFO_CUSTOM
{
UINT32 infoType;
UINT32 id;
LUID adapterId;
union
{
DISPLAYCONFIG_TARGET_MODE_CUSTOM targetMode;
DISPLAYCONFIG_SOURCE_MODE_CUSTOM sourceMode;
DISPLAYCONFIG_DESKTOP_IMAGE_INFO_CUSTOM desktopImageInfo;
} dummyunionname;
2018-05-02 01:03:25 +02:00
} DISPLAYCONFIG_MODE_INFO_CUSTOM;
2020-05-12 14:36:27 +02:00
typedef struct DISPLAYCONFIG_PATH_TARGET_INFO_CUSTOM
{
LUID adapterId;
UINT32 id;
union
{
UINT32 modeInfoIdx;
struct
{
UINT32 desktopModeInfoIdx :16;
UINT32 targetModeInfoIdx :16;
} dummystructname;
} dummyunionname;
UINT32 outputTechnology;
UINT32 rotation;
UINT32 scaling;
DISPLAYCONFIG_RATIONAL_CUSTOM refreshRate;
UINT32 scanLineOrdering;
BOOL targetAvailable;
UINT32 statusFlags;
2018-05-02 01:03:25 +02:00
} DISPLAYCONFIG_PATH_TARGET_INFO_CUSTOM;
2020-05-12 14:36:27 +02:00
typedef struct DISPLAYCONFIG_PATH_INFO_CUSTOM
{
DISPLAYCONFIG_PATH_SOURCE_INFO_CUSTOM sourceInfo;
DISPLAYCONFIG_PATH_TARGET_INFO_CUSTOM targetInfo;
UINT32 flags;
2018-05-02 01:03:25 +02:00
} DISPLAYCONFIG_PATH_INFO_CUSTOM;
2018-07-11 16:37:37 -05:00
typedef LONG (WINAPI *QUERYDISPLAYCONFIG)(UINT32, UINT32*, DISPLAYCONFIG_PATH_INFO_CUSTOM*, UINT32*, DISPLAYCONFIG_MODE_INFO_CUSTOM*, UINT32*);
typedef LONG (WINAPI *GETDISPLAYCONFIGBUFFERSIZES)(UINT32, UINT32*, UINT32*);
HACCEL window_accelerators;
/* Power Request APIs */
#if !defined(_XBOX) && (_MSC_VER == 1310)
typedef struct _REASON_CONTEXT
{
ULONG Version;
DWORD Flags;
union
{
struct
{
HMODULE LocalizedReasonModule;
ULONG LocalizedreasonId;
ULONG ReasonStringCount;
LPWSTR *ReasonStrings;
} Detailed;
LPWSTR SimpleReasonString;
} Reason;
} REASON_CONTEXT, *PREASON_CONTEXT;
typedef enum _POWER_REQUEST_TYPE
{
PowerRequestDisplayRequired,
PowerRequestSystemRequired,
PowerRequestAwayModeRequired,
PowerRequestExecutionRequired
} POWER_REQUEST_TYPE, *PPOWER_REQUEST_TYPE;
#define POWER_REQUEST_CONTEXT_VERSION 0
#define POWER_REQUEST_CONTEXT_SIMPLE_STRING 1
#define POWER_REQUEST_CONTEXT_DETAILED_STRING 2
#endif
2017-01-14 04:06:56 -05:00
#ifdef _WIN32_WINNT_WIN7
typedef REASON_CONTEXT POWER_REQUEST_CONTEXT, *PPOWER_REQUEST_CONTEXT, *LPPOWER_REQUEST_CONTEXT;
2017-01-14 04:06:56 -05:00
#endif
#ifndef MAX_MONITORS
#define MAX_MONITORS 9
#endif
#define MIN_WIDTH 320
#define MIN_HEIGHT 240
#if defined(_MSC_VER) && _MSC_VER <= 1200
#define INT_PTR_COMPAT int
#else
#define INT_PTR_COMPAT INT_PTR
#endif
2020-07-07 21:04:45 +02:00
typedef struct win32_common_state
{
int pos_x;
int pos_y;
unsigned pos_width;
unsigned pos_height;
2022-05-17 13:21:56 +02:00
#ifdef HAVE_TASKBAR
2020-07-07 21:04:45 +02:00
unsigned taskbar_message;
2022-05-17 13:21:56 +02:00
#endif
2020-07-07 21:04:45 +02:00
unsigned monitor_count;
} win32_common_state_t;
2020-08-03 15:48:08 +02:00
/* TODO/FIXME - globals */
unsigned g_win32_resize_width = 0;
unsigned g_win32_resize_height = 0;
float g_win32_refresh_rate = 0;
2020-08-03 15:48:08 +02:00
ui_window_win32_t main_window;
/* TODO/FIXME - static globals */
uint8_t g_win32_flags = 0;
2020-08-03 15:48:08 +02:00
static HMONITOR win32_monitor_last;
static HMONITOR win32_monitor_all[MAX_MONITORS];
2020-07-07 21:04:45 +02:00
static win32_common_state_t win32_st =
{
CW_USEDEFAULT, /* pos_x */
CW_USEDEFAULT, /* pos_y */
0, /* pos_width */
0, /* pos_height */
2022-05-17 13:21:56 +02:00
#ifdef HAVE_TASKBAR
2020-07-07 21:04:45 +02:00
0, /* taskbar_message */
2022-05-17 13:21:56 +02:00
#endif
2020-07-07 21:04:45 +02:00
0, /* monitor_count */
};
uint8_t win32_get_flags(void)
{
return g_win32_flags;
}
2020-05-12 14:36:27 +02:00
static INT_PTR_COMPAT CALLBACK pick_core_proc(
2019-08-29 10:16:26 +02:00
HWND hDlg, UINT message,
2020-05-12 14:36:27 +02:00
WPARAM wParam, LPARAM lParam)
{
2016-06-03 08:23:43 +02:00
size_t list_size;
core_info_list_t *core_info_list = NULL;
const core_info_t *core_info = NULL;
switch (message)
{
case WM_INITDIALOG:
{
HWND hwndList;
unsigned i;
/* Add items to list. */
core_info_get_list(&core_info_list);
core_info_list_get_supported_cores(core_info_list,
2016-10-03 15:43:03 +02:00
path_get(RARCH_PATH_CONTENT), &core_info, &list_size);
2016-06-03 08:23:43 +02:00
hwndList = GetDlgItem(hDlg, ID_CORELISTBOX);
2016-06-03 08:23:43 +02:00
for (i = 0; i < list_size; i++)
{
2016-06-03 08:23:43 +02:00
const core_info_t *info = (const core_info_t*)&core_info[i];
SendMessage(hwndList, LB_ADDSTRING, 0,
(LPARAM)info->display_name);
}
SetFocus(hwndList);
return TRUE;
2016-06-03 08:23:43 +02:00
}
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
EndDialog(hDlg, LOWORD(wParam));
2016-11-06 11:52:03 +01:00
break;
2016-06-03 08:23:43 +02:00
case ID_CORELISTBOX:
switch (HIWORD(wParam))
{
2016-11-06 11:52:03 +01:00
case LBN_SELCHANGE:
{
const core_info_t *info = NULL;
2017-08-09 13:28:31 +02:00
HWND hwndList = GetDlgItem(
hDlg, ID_CORELISTBOX);
2017-08-09 13:28:31 +02:00
int lbItem = (int)
SendMessage(hwndList, LB_GETCURSEL, 0, 0);
2017-08-09 13:28:31 +02:00
2016-11-06 11:52:03 +01:00
core_info_get_list(&core_info_list);
core_info_list_get_supported_cores(core_info_list,
path_get(RARCH_PATH_CONTENT), &core_info, &list_size);
info = (const core_info_t*)&core_info[lbItem];
2019-04-21 06:03:02 +02:00
path_set(RARCH_PATH_CORE, info->path);
}
2016-11-06 11:52:03 +01:00
break;
2016-06-03 08:23:43 +02:00
}
return TRUE;
}
}
return FALSE;
}
static BOOL CALLBACK win32_monitor_enum_proc(HMONITOR hMonitor,
HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
{
2020-03-13 00:11:21 +01:00
win32_common_state_t
*g_win32 = (win32_common_state_t*)&win32_st;
win32_monitor_all[g_win32->monitor_count++] = hMonitor;
return TRUE;
}
2022-05-17 13:21:56 +02:00
#ifndef _XBOX
2016-06-04 05:54:33 +02:00
void win32_monitor_from_window(void)
{
ui_window_t *window = NULL;
2017-08-12 18:15:26 +02:00
win32_monitor_last =
2017-08-09 13:28:31 +02:00
MonitorFromWindow(main_window.hwnd, MONITOR_DEFAULTTONEAREST);
2017-08-12 18:15:26 +02:00
window = (ui_window_t*)ui_companion_driver_get_window_ptr();
2016-06-06 08:01:26 +02:00
if (window)
window->destroy(&main_window);
}
2022-05-17 13:21:56 +02:00
#endif
2018-04-15 17:55:37 +02:00
int win32_change_display_settings(const char *str, void *devmode_data,
unsigned flags)
{
#if _WIN32_WINDOWS >= 0x0410 || _WIN32_WINNT >= 0x0410
/* Windows 98 and later codepath */
return ChangeDisplaySettingsEx(str, (DEVMODE*)devmode_data,
NULL, flags, NULL);
#else
/* Windows 95 / NT codepath */
return ChangeDisplaySettings((DEVMODE*)devmode_data, flags);
#endif
}
void win32_monitor_get_info(void)
{
2016-12-03 00:14:33 -05:00
MONITORINFOEX current_mon;
memset(&current_mon, 0, sizeof(current_mon));
2016-12-03 00:14:33 -05:00
current_mon.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo(win32_monitor_last, (LPMONITORINFO)&current_mon);
2017-09-03 23:39:25 -04:00
2018-04-15 17:55:37 +02:00
win32_change_display_settings(current_mon.szDevice, NULL, 0);
}
void win32_monitor_info(void *data, void *hm_data, unsigned *mon_id)
{
2017-05-22 11:33:53 +02:00
unsigned i;
2017-08-09 13:28:31 +02:00
settings_t *settings = config_get_ptr();
MONITORINFOEX *mon = (MONITORINFOEX*)data;
HMONITOR *hm_to_use = (HMONITOR*)hm_data;
unsigned fs_monitor = settings->uints.video_monitor_index;
2020-03-13 00:11:21 +01:00
win32_common_state_t
*g_win32 = (win32_common_state_t*)&win32_st;
if (!win32_monitor_last)
win32_monitor_last = MonitorFromWindow(GetDesktopWindow(),
2016-11-06 11:52:03 +01:00
MONITOR_DEFAULTTONEAREST);
*hm_to_use = win32_monitor_last;
2020-03-13 00:11:21 +01:00
if (fs_monitor && fs_monitor <= g_win32->monitor_count
&& win32_monitor_all[fs_monitor - 1])
{
*hm_to_use = win32_monitor_all[fs_monitor - 1];
*mon_id = fs_monitor - 1;
}
else
{
2020-03-13 00:11:21 +01:00
for (i = 0; i < g_win32->monitor_count; i++)
{
if (win32_monitor_all[i] != *hm_to_use)
continue;
*mon_id = i;
break;
}
}
if (hm_to_use)
{
memset(mon, 0, sizeof(*mon));
mon->cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo(*hm_to_use, (LPMONITORINFO)mon);
}
}
2023-06-20 09:37:07 +02:00
void win32_get_video_size(void *data,
unsigned *width, unsigned *height)
{
HWND window = win32_get_window();
if (window)
{
*width = g_win32_resize_width;
*height = g_win32_resize_height;
}
else
{
RECT mon_rect;
MONITORINFOEX current_mon;
unsigned mon_id = 0;
HMONITOR hm_to_use = NULL;
win32_monitor_info(&current_mon, &hm_to_use, &mon_id);
mon_rect = current_mon.rcMonitor;
*width = mon_rect.right - mon_rect.left;
*height = mon_rect.bottom - mon_rect.top;
}
}
static bool win32_load_content_from_gui(const char *szFilename)
2016-06-04 03:20:55 +02:00
{
/* poll list of current cores */
core_info_list_t *core_info_list = NULL;
core_info_get_list(&core_info_list);
if (core_info_list)
{
size_t list_size;
content_ctx_info_t content_info = { 0 };
const core_info_t *core_info = NULL;
core_info_list_get_supported_cores(core_info_list,
(const char*)szFilename, &core_info, &list_size);
if (list_size)
{
path_set(RARCH_PATH_CONTENT, szFilename);
if (!path_is_empty(RARCH_PATH_CONTENT))
{
unsigned i;
core_info_t *current_core = NULL;
core_info_get_current_core(&current_core);
/*we already have path for libretro core */
for (i = 0; i < list_size; i++)
{
const core_info_t *info = (const core_info_t*)&core_info[i];
if (string_is_equal(path_get(RARCH_PATH_CORE), info->path))
{
/* Our previous core supports the current rom */
task_push_load_content_with_current_core_from_companion_ui(
NULL,
&content_info,
CORE_TYPE_PLAIN,
NULL, NULL);
return true;
}
}
}
/* Poll for cores for current rom since none exist. */
if (list_size == 1)
{
/*pick core that only exists and is bound to work. Ish. */
const core_info_t *info = (const core_info_t*)&core_info[0];
if (info)
{
task_push_load_content_with_new_core_from_companion_ui(
info->path, NULL, NULL, NULL, NULL, &content_info, NULL, NULL);
return true;
}
}
else
{
bool okay = false;
settings_t *settings = config_get_ptr();
bool video_is_fs = settings->bools.video_fullscreen;
video_driver_state_t *video_st = video_state_get_ptr();
if ( video_is_fs
&& video_st->poke
&& video_st->poke->show_mouse)
{
/* Show mouse cursor for dialog */
video_st->poke->show_mouse(video_st->data, true);
/* Pick one core that could be compatible, ew */
if (DialogBoxParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_PICKCORE),
main_window.hwnd, pick_core_proc, (LPARAM)NULL) == IDOK)
{
task_push_load_content_with_current_core_from_companion_ui(
NULL, &content_info, CORE_TYPE_PLAIN, NULL, NULL);
okay = true;
}
/* Hide mouse cursor after dialog */
video_st->poke->show_mouse(video_st->data, false);
}
else
{
/* Pick one core that could be compatible, ew */
if (DialogBoxParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_PICKCORE),
main_window.hwnd, pick_core_proc, (LPARAM)NULL) == IDOK)
{
task_push_load_content_with_current_core_from_companion_ui(
NULL, &content_info, CORE_TYPE_PLAIN, NULL, NULL);
okay = true;
}
}
return okay;
}
}
}
return false;
}
2022-05-17 13:21:56 +02:00
#ifdef LEGACY_WIN32
static bool win32_drag_query_file(HWND hwnd, WPARAM wparam)
{
2022-05-17 13:21:56 +02:00
if (DragQueryFile((HDROP)wparam, 0xFFFFFFFF, NULL, 0))
2016-06-04 03:20:55 +02:00
{
char szFilename[1024];
szFilename[0] = '\0';
2022-05-17 13:21:56 +02:00
DragQueryFile((HDROP)wparam, 0, szFilename, sizeof(szFilename));
return win32_load_content_from_gui(szFilename);
}
return false;
}
#else
2022-05-17 13:21:56 +02:00
static bool win32_drag_query_file(HWND hwnd, WPARAM wparam)
{
if (DragQueryFileW((HDROP)wparam, 0xFFFFFFFF, NULL, 0))
{
wchar_t wszFilename[4096];
2022-05-17 13:21:56 +02:00
bool okay = false;
char *szFilename = NULL;
wszFilename[0] = L'\0';
2022-05-17 13:21:56 +02:00
DragQueryFileW((HDROP)wparam, 0, wszFilename, sizeof(wszFilename));
szFilename = utf16_to_utf8_string_alloc(wszFilename);
okay = win32_load_content_from_gui(szFilename);
if (szFilename)
free(szFilename);
return okay;
2016-06-04 03:20:55 +02:00
}
return false;
2016-06-04 03:20:55 +02:00
}
2022-05-17 13:21:56 +02:00
#endif
2016-06-04 03:20:55 +02:00
2022-05-17 13:21:56 +02:00
static void win32_resize_after_display_change(HWND hwnd, HMONITOR monitor)
Ver 0.9.2 SR2 (Switchres API) Implimantation Fixed SR close match refresh bug. Added menu high resolution option. Fixed desktop restore bug cuusing endless resolution change requests. Fixed file conflicts Added destop restore resolution back in for manu only. Pulled Switchres fixes. Added better PI rsolution support. Ver 0.7 SR2 (Switchres API) Implimantation Removed HH experimetal check. This is better done via teh switchres.ini at present. Fixed refresh rate bug. Now new resolution and refesh is added correctly. Removed SR deinit from menu restore. Meanu now stays at last content resolution. Ver 0.6.2 SR2 (Switchres API) Implimantation Fixed super resolution bug casuing abnormal video size and aspect ratio Fixed logging issue casuing seg falts on RA exit Ver 0.6 SR2 (Switchres API) Implimantation Ver 0.2 SR2 (Switchres API) Implimantation Added forced super resolutions. Added Multi-monitor/monitor selection support. Added desktop resolution restore when switching back to menu only. Added new menu items for 31KHz standard and 120hz monitor profiles. Added new menu item INI. load monitor profile from switchrss.ini. Fixed winraw driver. Coordinates new refreshed after a resolution change. Fixed Menu aspect ratio in super resolutions. Removed static glabals. These have been added to videocrt_switch struct. Ver 0.1 SR2 (Switchres API) Implimantation Removed old CRTSwitchRes method. Added new SR2 API implimantaion. Resolution swithcing is now done by switchres libs. Both Linux and Windows working with native and super resolutions. Working multi-monitor support with monitor index selection. Working 31KHz support with standard and 120Hxz modes. The monitor index selection is still done via the RA UI. Only choose native and 15KHz form the CRT options in the RA UI as all options are now set in the switchres.ini. All other CRT optoins in the RA UI currently do nothing. Added SR wrapper to fix compile issues. Added back RPi functionality Fixed windows resize/scaling issues on resolution change Thanks @Calamity no more need for crt_switch_driver_refresh() Fix broken case after prevous commit Monitor preset options 15/31KHz now active. Added new meu option. Moitor persets can now be choosen fom the RA UI. 15KHz and 31KHz will set arcade_15 and aracde_31 respectivly. New option INI, if this is chosen your monitor preset will be selected from your switchres.ini file. Added 3KHhz, 120Hz. for old RA users. Renamed 31KHz to 31 KHz, Standard Fixed winraw input coordinates after switching resolution. Code cleanup Fixed menu aspect ratio issue Added menu resolution restore after closing content Fixed aspect ratio after menu resolution restore. code clean up Fxed menu Resulition Restore Aspect Ratio. When SR uses non integer scalled resolution. super width bug with restoring menu resolution fix added super resolution check after setting desktop resolutoion variables when menu active only sr_deinit() used to restore desktop mode. Fixed menu sr_deinit bug. now setting sr_active false Removed static globals, added them to video_switch struct Fixex compile bug due to comment // Fixed compile issues doe to c++ comments in teh switchres_wrapper.h Temporarily removed SR2 logging to fix compile isses for c90 added logging back in. Removed support for winnt and osx Added define for C89. Disabled SR if defined C89 Removed all RA compile fixes fro C89 C90 etc. Swithing now working again. Put Switchres behind HAVE_SR2. HAVE_SR2=no by default. --enable-sr2 Ver 0.5 SR2 Implimentation. Ver 0.4 SR2 Implimantation. Bake SR inside RA Removed temporary log files Disable switchres when C89/C99 builds. Removed C89 and C90 checks for SR Fixed switchres_wrapper.h location Ver 0.3 SR2 Implimenation Dissable logging for C89 __STDC__ Fix For RPi fixed missing EOL fixed RPi function definition added vidrocrt_switch stuct to RPI funcion fixed xoffset for RPi Removed old RPi function call SR disabled for videocore until VC4 switching ported Reverted back to state 5c8a56c Bake SR inside RA Use native win32 api for threads. Fix static lib linking LIBERROR would be defined twice otherwise + improper function names prefixed by __imp_ Added lidstc++ to makefile.common for switchres Fixed RPi switching. Disabled Switchres for videocore unill it is ported. removed RAA.log. Should not exist Added check for when SR fails to set mode with an aspect ratio fix. added video driver re init for RPi GB, GBA and GBC core check, adjusted reseolutions and scale. Please turn on integer scalling in the RA UI Added logas back in. Checking STDC verstion >= C11 Fixed c89 for loop declaration. Code clean up. Added new functions Fix resolution switching bug introduces with HH code clean up. Fixed menu restore bug on closw content after code clean up Moved SR logging to relevant RA logs Update makefile. Checks for X11 and xrandr fixed makefile Use native win32 api for threads. Fix static lib linking LIBERROR would be defined twice otherwise + improper function names prefixed by __imp_ Update switchres_wrapper.* header comments Update year copyright DRMKMS: build only if libdrm has the required version XRANDR: build only if xrandr is available Simplified maklefile Fixed RPI compile error with unsued functions. As before Disable Griffin. No switching support available. Never has been Removed log file 1 Added Win32 static define Added SR source Removed Videocore check on destroy SR Moved SR deinit to trigger earlier on RA exit. Fixed compile error after upstream rebase Fixed aspect ration bug cused by super resolutions. Temporarily disbabled SR logging Re inabled runtim eSR loggind. Disableed all RARCH logging on retro_deinit_drivers Removed srdeinit from menu restore. Menu stays in current reolution until a fix can be found Fixed refresh rate changes when no reolution change is detected. Forgot to add teh resolution cahge in with the refresh change oops Fixed endless no detection log. Removed HH check. This can been better adjusted using the switchres.ini fixed compile issue Added better PI crt switching and fixed typo Pulled Swicthres fixes. Updated desktop restore resolution. removed unused makefile Lockec menu refresh to 60hz fixed missing new line Fixed file conflicts Forced 640x480@60 for menu Added high resolution menu option Removed item logg checker Fixed typos Removed unused functions Fixed SR close match refesh bug. Fixed typo
2021-05-11 02:08:15 -07:00
{
2022-05-17 13:21:56 +02:00
MONITORINFO info;
memset(&info, 0, sizeof(info));
info.cbSize = sizeof(info);
if (GetMonitorInfo(monitor, &info))
SetWindowPos(hwnd, 0, 0, 0,
abs(info.rcMonitor.right - info.rcMonitor.left),
abs(info.rcMonitor.bottom - info.rcMonitor.top),
SWP_NOMOVE);
Ver 0.9.2 SR2 (Switchres API) Implimantation Fixed SR close match refresh bug. Added menu high resolution option. Fixed desktop restore bug cuusing endless resolution change requests. Fixed file conflicts Added destop restore resolution back in for manu only. Pulled Switchres fixes. Added better PI rsolution support. Ver 0.7 SR2 (Switchres API) Implimantation Removed HH experimetal check. This is better done via teh switchres.ini at present. Fixed refresh rate bug. Now new resolution and refesh is added correctly. Removed SR deinit from menu restore. Meanu now stays at last content resolution. Ver 0.6.2 SR2 (Switchres API) Implimantation Fixed super resolution bug casuing abnormal video size and aspect ratio Fixed logging issue casuing seg falts on RA exit Ver 0.6 SR2 (Switchres API) Implimantation Ver 0.2 SR2 (Switchres API) Implimantation Added forced super resolutions. Added Multi-monitor/monitor selection support. Added desktop resolution restore when switching back to menu only. Added new menu items for 31KHz standard and 120hz monitor profiles. Added new menu item INI. load monitor profile from switchrss.ini. Fixed winraw driver. Coordinates new refreshed after a resolution change. Fixed Menu aspect ratio in super resolutions. Removed static glabals. These have been added to videocrt_switch struct. Ver 0.1 SR2 (Switchres API) Implimantation Removed old CRTSwitchRes method. Added new SR2 API implimantaion. Resolution swithcing is now done by switchres libs. Both Linux and Windows working with native and super resolutions. Working multi-monitor support with monitor index selection. Working 31KHz support with standard and 120Hxz modes. The monitor index selection is still done via the RA UI. Only choose native and 15KHz form the CRT options in the RA UI as all options are now set in the switchres.ini. All other CRT optoins in the RA UI currently do nothing. Added SR wrapper to fix compile issues. Added back RPi functionality Fixed windows resize/scaling issues on resolution change Thanks @Calamity no more need for crt_switch_driver_refresh() Fix broken case after prevous commit Monitor preset options 15/31KHz now active. Added new meu option. Moitor persets can now be choosen fom the RA UI. 15KHz and 31KHz will set arcade_15 and aracde_31 respectivly. New option INI, if this is chosen your monitor preset will be selected from your switchres.ini file. Added 3KHhz, 120Hz. for old RA users. Renamed 31KHz to 31 KHz, Standard Fixed winraw input coordinates after switching resolution. Code cleanup Fixed menu aspect ratio issue Added menu resolution restore after closing content Fixed aspect ratio after menu resolution restore. code clean up Fxed menu Resulition Restore Aspect Ratio. When SR uses non integer scalled resolution. super width bug with restoring menu resolution fix added super resolution check after setting desktop resolutoion variables when menu active only sr_deinit() used to restore desktop mode. Fixed menu sr_deinit bug. now setting sr_active false Removed static globals, added them to video_switch struct Fixex compile bug due to comment // Fixed compile issues doe to c++ comments in teh switchres_wrapper.h Temporarily removed SR2 logging to fix compile isses for c90 added logging back in. Removed support for winnt and osx Added define for C89. Disabled SR if defined C89 Removed all RA compile fixes fro C89 C90 etc. Swithing now working again. Put Switchres behind HAVE_SR2. HAVE_SR2=no by default. --enable-sr2 Ver 0.5 SR2 Implimentation. Ver 0.4 SR2 Implimantation. Bake SR inside RA Removed temporary log files Disable switchres when C89/C99 builds. Removed C89 and C90 checks for SR Fixed switchres_wrapper.h location Ver 0.3 SR2 Implimenation Dissable logging for C89 __STDC__ Fix For RPi fixed missing EOL fixed RPi function definition added vidrocrt_switch stuct to RPI funcion fixed xoffset for RPi Removed old RPi function call SR disabled for videocore until VC4 switching ported Reverted back to state 5c8a56c Bake SR inside RA Use native win32 api for threads. Fix static lib linking LIBERROR would be defined twice otherwise + improper function names prefixed by __imp_ Added lidstc++ to makefile.common for switchres Fixed RPi switching. Disabled Switchres for videocore unill it is ported. removed RAA.log. Should not exist Added check for when SR fails to set mode with an aspect ratio fix. added video driver re init for RPi GB, GBA and GBC core check, adjusted reseolutions and scale. Please turn on integer scalling in the RA UI Added logas back in. Checking STDC verstion >= C11 Fixed c89 for loop declaration. Code clean up. Added new functions Fix resolution switching bug introduces with HH code clean up. Fixed menu restore bug on closw content after code clean up Moved SR logging to relevant RA logs Update makefile. Checks for X11 and xrandr fixed makefile Use native win32 api for threads. Fix static lib linking LIBERROR would be defined twice otherwise + improper function names prefixed by __imp_ Update switchres_wrapper.* header comments Update year copyright DRMKMS: build only if libdrm has the required version XRANDR: build only if xrandr is available Simplified maklefile Fixed RPI compile error with unsued functions. As before Disable Griffin. No switching support available. Never has been Removed log file 1 Added Win32 static define Added SR source Removed Videocore check on destroy SR Moved SR deinit to trigger earlier on RA exit. Fixed compile error after upstream rebase Fixed aspect ration bug cused by super resolutions. Temporarily disbabled SR logging Re inabled runtim eSR loggind. Disableed all RARCH logging on retro_deinit_drivers Removed srdeinit from menu restore. Menu stays in current reolution until a fix can be found Fixed refresh rate changes when no reolution change is detected. Forgot to add teh resolution cahge in with the refresh change oops Fixed endless no detection log. Removed HH check. This can been better adjusted using the switchres.ini fixed compile issue Added better PI crt switching and fixed typo Pulled Swicthres fixes. Updated desktop restore resolution. removed unused makefile Lockec menu refresh to 60hz fixed missing new line Fixed file conflicts Forced 640x480@60 for menu Added high resolution menu option Removed item logg checker Fixed typos Removed unused functions Fixed SR close match refesh bug. Fixed typo
2021-05-11 02:08:15 -07:00
}
static bool win32_browser(
HWND owner,
char *filename,
size_t filename_size,
const char *extensions,
const char *title,
const char *initial_dir)
{
bool result = false;
const ui_browser_window_t *browser =
ui_companion_driver_get_browser_window_ptr();
if (browser)
{
ui_browser_window_state_t browser_state;
/* These need to be big enough to hold the
* path/name of any file the user may select.
* FIXME: We should really handle the
* error case when this isn't big enough. */
char new_title[PATH_MAX];
char new_file[32768];
new_title[0] = '\0';
new_file[0] = '\0';
if (!string_is_empty(title))
strlcpy(new_title, title, sizeof(new_title));
if (filename && *filename)
strlcpy(new_file, filename, sizeof(new_file));
/* OPENFILENAME.lpstrFilters is actually const,
* so this cast should be safe */
browser_state.filters = (char*)extensions;
browser_state.title = new_title;
browser_state.startdir = strdup(initial_dir);
browser_state.path = new_file;
browser_state.window = owner;
result = browser->open(&browser_state);
/* TODO/FIXME - this is weird - why is this called
* after the browser->open call? Seems to have no effect
* anymore here */
if (filename && browser_state.path)
strlcpy(filename, browser_state.path, filename_size);
free(browser_state.startdir);
}
return result;
}
static LRESULT win32_menu_loop(HWND owner, WPARAM wparam)
{
2020-01-18 09:37:16 +01:00
WPARAM mode = wparam & 0xffff;
switch (mode)
{
case ID_M_LOAD_CORE:
{
char win32_file[PATH_MAX_LENGTH] = {0};
2020-01-18 09:37:16 +01:00
settings_t *settings = config_get_ptr();
char *title_cp = NULL;
size_t converted = 0;
const char *extensions = "Libretro core (.dll)\0*.dll\0All Files\0*.*\0\0";
const char *title = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_LIST);
const char *initial_dir = settings->paths.directory_libretro;
/* Convert UTF8 to UTF16, then back to the
* local code page.
* This is needed for proper multi-byte
* string display until Unicode is
* fully supported.
*/
wchar_t *title_wide = utf8_to_utf16_string_alloc(title);
if (title_wide)
title_cp = utf16_to_utf8_string_alloc(title_wide);
if (!win32_browser(owner, win32_file, sizeof(win32_file),
extensions, title_cp, initial_dir))
{
if (title_wide)
free(title_wide);
if (title_cp)
free(title_cp);
break;
}
if (title_wide)
free(title_wide);
if (title_cp)
free(title_cp);
path_set(RARCH_PATH_CORE, win32_file);
2020-01-19 13:19:25 +01:00
command_event(CMD_EVENT_LOAD_CORE, NULL);
}
break;
case ID_M_LOAD_CONTENT:
{
char win32_file[PATH_MAX_LENGTH] = {0};
char *title_cp = NULL;
size_t converted = 0;
const char *extensions = "All Files (*.*)\0*.*\0\0";
const char *title = msg_hash_to_str(
MENU_ENUM_LABEL_VALUE_LOAD_CONTENT_LIST);
2020-01-18 09:37:16 +01:00
settings_t *settings = config_get_ptr();
const char *initial_dir = settings->paths.directory_menu_content;
/* Convert UTF8 to UTF16, then back to the
* local code page.
* This is needed for proper multi-byte
* string display until Unicode is
* fully supported.
*/
wchar_t *title_wide = utf8_to_utf16_string_alloc(title);
if (title_wide)
title_cp = utf16_to_utf8_string_alloc(title_wide);
if (!win32_browser(owner, win32_file, sizeof(win32_file),
extensions, title_cp, initial_dir))
{
if (title_wide)
free(title_wide);
if (title_cp)
free(title_cp);
break;
}
if (title_wide)
free(title_wide);
if (title_cp)
free(title_cp);
win32_load_content_from_gui(win32_file);
}
break;
case ID_M_RESET:
2020-01-19 13:19:25 +01:00
command_event(CMD_EVENT_RESET, NULL);
break;
case ID_M_MUTE_TOGGLE:
2020-01-19 13:19:25 +01:00
command_event(CMD_EVENT_AUDIO_MUTE_TOGGLE, NULL);
break;
case ID_M_MENU_TOGGLE:
2020-01-19 13:19:25 +01:00
command_event(CMD_EVENT_MENU_TOGGLE, NULL);
break;
case ID_M_PAUSE_TOGGLE:
2020-01-19 13:19:25 +01:00
command_event(CMD_EVENT_PAUSE_TOGGLE, NULL);
break;
case ID_M_LOAD_STATE:
2020-01-19 13:19:25 +01:00
command_event(CMD_EVENT_LOAD_STATE, NULL);
break;
case ID_M_SAVE_STATE:
2020-01-19 13:19:25 +01:00
command_event(CMD_EVENT_SAVE_STATE, NULL);
break;
case ID_M_DISK_CYCLE:
2020-01-19 13:19:25 +01:00
command_event(CMD_EVENT_DISK_EJECT_TOGGLE, NULL);
break;
case ID_M_DISK_NEXT:
2020-01-19 13:19:25 +01:00
command_event(CMD_EVENT_DISK_NEXT, NULL);
break;
case ID_M_DISK_PREV:
2020-01-19 13:19:25 +01:00
command_event(CMD_EVENT_DISK_PREV, NULL);
break;
case ID_M_FULL_SCREEN:
2020-01-19 13:19:25 +01:00
command_event(CMD_EVENT_FULLSCREEN_TOGGLE, NULL);
break;
case ID_M_MOUSE_GRAB:
2020-01-19 13:19:25 +01:00
command_event(CMD_EVENT_GRAB_MOUSE_TOGGLE, NULL);
break;
case ID_M_TAKE_SCREENSHOT:
2020-01-19 13:19:25 +01:00
command_event(CMD_EVENT_TAKE_SCREENSHOT, NULL);
break;
case ID_M_QUIT:
2020-01-18 09:37:16 +01:00
PostMessage(owner, WM_CLOSE, 0, 0);
break;
case ID_M_TOGGLE_DESKTOP:
2020-01-19 13:19:25 +01:00
command_event(CMD_EVENT_UI_COMPANION_TOGGLE, NULL);
break;
default:
2020-01-19 13:19:25 +01:00
if (mode >= ID_M_WINDOW_SCALE_1X && mode <= ID_M_WINDOW_SCALE_10X)
{
2020-01-19 13:19:25 +01:00
unsigned idx = (mode - (ID_M_WINDOW_SCALE_1X-1));
retroarch_ctl(RARCH_CTL_SET_WINDOWED_SCALE, &idx);
2020-01-19 13:19:25 +01:00
command_event(CMD_EVENT_RESIZE_WINDOWED_SCALE, NULL);
}
else if (mode == ID_M_STATE_INDEX_AUTO)
{
signed idx = -1;
settings_t *settings = config_get_ptr();
configuration_set_int(
settings, settings->ints.state_slot, idx);
}
else if (mode >= (ID_M_STATE_INDEX_AUTO+1)
&& mode <= (ID_M_STATE_INDEX_AUTO+10))
{
signed idx = (mode - (ID_M_STATE_INDEX_AUTO+1));
settings_t *settings = config_get_ptr();
configuration_set_int(
settings, settings->ints.state_slot, idx);
}
break;
}
return 0L;
}
2022-05-17 13:21:56 +02:00
static void win32_save_position(void)
{
RECT rect;
WINDOWPLACEMENT placement;
win32_common_state_t *g_win32 = (win32_common_state_t*)&win32_st;
settings_t *settings = config_get_ptr();
bool window_save_positions = settings->bools.video_window_save_positions;
placement.length = sizeof(placement);
placement.flags = 0;
placement.showCmd = 0;
placement.ptMinPosition.x = 0;
placement.ptMinPosition.y = 0;
placement.ptMaxPosition.x = 0;
placement.ptMaxPosition.y = 0;
placement.rcNormalPosition.left = 0;
placement.rcNormalPosition.top = 0;
placement.rcNormalPosition.right = 0;
placement.rcNormalPosition.bottom = 0;
2022-05-17 13:21:56 +02:00
if (GetWindowPlacement(main_window.hwnd, &placement))
{
g_win32->pos_x = placement.rcNormalPosition.left;
g_win32->pos_y = placement.rcNormalPosition.top;
}
2022-05-17 13:21:56 +02:00
if (GetWindowRect(main_window.hwnd, &rect))
{
g_win32->pos_width = rect.right - rect.left;
g_win32->pos_height = rect.bottom - rect.top;
2022-05-17 13:21:56 +02:00
}
2022-05-17 13:21:56 +02:00
if (window_save_positions)
{
video_driver_state_t *video_st = video_state_get_ptr();
uint32_t video_st_flags = video_st->flags;
bool video_fullscreen = settings->bools.video_fullscreen;
2022-05-17 13:21:56 +02:00
if ( !video_fullscreen
2022-10-26 22:35:04 +02:00
&& !(video_st_flags & VIDEO_FLAG_FORCE_FULLSCREEN)
&& !(video_st_flags & VIDEO_FLAG_IS_SWITCHING_DISPLAY_MODE))
2022-05-17 13:21:56 +02:00
{
bool ui_menubar_enable = settings->bools.ui_menubar_enable;
bool window_show_decor = settings->bools.video_window_show_decorations;
2022-05-17 13:21:56 +02:00
settings->uints.window_position_x = g_win32->pos_x;
settings->uints.window_position_y = g_win32->pos_y;
settings->uints.window_position_width = g_win32->pos_width;
settings->uints.window_position_height = g_win32->pos_height;
if (window_show_decor)
{
int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME);
int title_bar_height = GetSystemMetrics(SM_CYCAPTION);
settings->uints.window_position_width -= border_thickness * 2;
settings->uints.window_position_height -= border_thickness * 2;
settings->uints.window_position_height -= title_bar_height;
}
if (ui_menubar_enable)
{
int menu_bar_height = GetSystemMetrics(SM_CYMENU);
settings->uints.window_position_height -= menu_bar_height;
}
2022-05-17 13:21:56 +02:00
}
}
}
/* Get minimum window size for running core. */
static void win32_get_av_info_geometry(unsigned *width, unsigned *height)
{
video_driver_state_t *video_st = video_state_get_ptr();
runloop_state_t *runloop_st = runloop_state_get_ptr();
/* Don't bother while fast-forwarding. */
if (!video_st || runloop_st->flags & RUNLOOP_FLAG_FASTMOTION)
return;
if (video_st->av_info.geometry.aspect_ratio)
*width = roundf(
video_st->av_info.geometry.base_height
* video_st->av_info.geometry.aspect_ratio);
else
*width = video_st->av_info.geometry.base_width;
*height = video_st->av_info.geometry.base_height;
}
2022-05-17 13:21:56 +02:00
2020-05-12 14:36:27 +02:00
static LRESULT CALLBACK wnd_proc_common(
bool *quit, HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
switch (message)
{
case WM_SYSCOMMAND:
/* Prevent screensavers, etc, while running. */
switch (wparam)
{
case SC_SCREENSAVE:
case SC_MONITORPOWER:
2015-11-30 06:27:00 +01:00
*quit = true;
2016-06-04 05:09:58 +02:00
break;
}
break;
2016-06-03 09:14:53 +10:00
case WM_DROPFILES:
win32_drag_query_file(hwnd, wparam);
DragFinish((HDROP)wparam);
break;
case WM_CHAR:
2019-08-29 09:31:08 +02:00
*quit = true;
2019-08-29 02:26:32 +02:00
{
uint16_t mod = 0;
if (GetKeyState(VK_SHIFT) & 0x80)
mod |= RETROKMOD_SHIFT;
if (GetKeyState(VK_CONTROL) & 0x80)
2020-10-14 04:27:10 +03:00
mod |= RETROKMOD_CTRL;
2019-08-29 02:26:32 +02:00
if (GetKeyState(VK_MENU) & 0x80)
2020-10-14 04:27:10 +03:00
mod |= RETROKMOD_ALT;
2019-08-29 02:26:32 +02:00
if (GetKeyState(VK_CAPITAL) & 0x81)
mod |= RETROKMOD_CAPSLOCK;
if (GetKeyState(VK_SCROLL) & 0x81)
mod |= RETROKMOD_SCROLLOCK;
if ((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & 0x80)
mod |= RETROKMOD_META;
/* Seems to be hard to synchronize
* WM_CHAR and WM_KEYDOWN properly.
*/
input_keyboard_event(true, RETROK_UNKNOWN,
wparam, mod, RETRO_DEVICE_KEYBOARD);
2019-08-29 02:26:32 +02:00
}
return TRUE;
2020-08-28 01:20:54 +02:00
case WM_CLOSE:
case WM_DESTROY:
case WM_QUIT:
g_win32_flags |= WIN32_CMN_FLAG_QUIT;
2020-08-28 01:20:54 +02:00
*quit = true;
2020-01-19 12:17:26 +01:00
/* fall-through */
2020-08-28 01:20:54 +02:00
case WM_MOVE:
win32_save_position();
break;
case WM_SIZE:
/* Do not send resize message if we minimize. */
2022-05-17 13:21:56 +02:00
if ( wparam != SIZE_MAXHIDE
&& wparam != SIZE_MINIMIZED)
2020-08-28 01:20:54 +02:00
{
2022-05-17 13:21:56 +02:00
if ( LOWORD(lparam) != g_win32_resize_width
|| HIWORD(lparam) != g_win32_resize_height)
2020-08-28 01:20:54 +02:00
{
g_win32_resize_width = LOWORD(lparam);
g_win32_resize_height = HIWORD(lparam);
g_win32_flags |= WIN32_CMN_FLAG_RESIZED;
2020-08-28 01:20:54 +02:00
}
}
2015-11-30 06:27:00 +01:00
*quit = true;
2020-08-28 01:20:54 +02:00
break;
case WM_GETMINMAXINFO:
{
MINMAXINFO FAR *lpMinMaxInfo = (MINMAXINFO FAR *)lparam;
settings_t *settings = config_get_ptr();
unsigned min_width = MIN_WIDTH;
unsigned min_height = MIN_HEIGHT;
bool window_show_decor = settings ? settings->bools.video_window_show_decorations : true;
bool ui_menubar_enable = settings ? settings->bools.ui_menubar_enable : true;
if (settings && settings->bools.video_window_save_positions)
break;
win32_get_av_info_geometry(&min_width, &min_height);
if (window_show_decor)
{
int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME);
int title_bar_height = GetSystemMetrics(SM_CYCAPTION);
min_width += border_thickness * 2;
min_height += border_thickness * 2 + title_bar_height;
}
if (ui_menubar_enable)
{
int menu_bar_height = GetSystemMetrics(SM_CYMENU);
min_height += menu_bar_height;
}
lpMinMaxInfo->ptMinTrackSize.x = min_width;
lpMinMaxInfo->ptMinTrackSize.y = min_height;
lpMinMaxInfo->ptMaxTrackSize.x = min_width * 20;
lpMinMaxInfo->ptMaxTrackSize.y = min_height * 20;
}
break;
2020-08-28 01:20:54 +02:00
case WM_COMMAND:
{
settings_t *settings = config_get_ptr();
bool ui_menubar_enable = settings ? settings->bools.ui_menubar_enable : false;
if (ui_menubar_enable)
win32_menu_loop(main_window.hwnd, wparam);
}
break;
}
return 0;
}
static LRESULT CALLBACK wnd_proc_common_internal(HWND hwnd,
2020-08-28 01:20:54 +02:00
UINT message, WPARAM wparam, LPARAM lparam)
{
LRESULT ret;
bool keydown = true;
bool quit = false;
win32_common_state_t *g_win32 = (win32_common_state_t*)&win32_st;
switch (message)
{
case WM_KEYUP: /* Key released */
case WM_SYSKEYUP: /* Key released */
keydown = false;
/* fall-through */
case WM_KEYDOWN: /* Key pressed */
case WM_SYSKEYDOWN: /* Key pressed */
quit = true;
{
uint16_t mod = 0;
2021-08-21 22:27:08 +03:00
unsigned keycode = 0;
unsigned keysym = (lparam >> 16) & 0xff;
/* extended keys will map to dinput if the high bit is set */
if ((lparam >> 24 & 0x1))
keysym |= 0x80;
keycode = input_keymaps_translate_keysym_to_rk(keysym);
if (GetKeyState(VK_SHIFT) & 0x80)
mod |= RETROKMOD_SHIFT;
if (GetKeyState(VK_CONTROL) & 0x80)
mod |= RETROKMOD_CTRL;
if (GetKeyState(VK_MENU) & 0x80)
mod |= RETROKMOD_ALT;
if (GetKeyState(VK_CAPITAL) & 0x81)
mod |= RETROKMOD_CAPSLOCK;
if (GetKeyState(VK_SCROLL) & 0x81)
mod |= RETROKMOD_SCROLLOCK;
if ((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & 0x80)
mod |= RETROKMOD_META;
input_keyboard_event(keydown, keycode,
0, mod, RETRO_DEVICE_KEYBOARD);
if (message != WM_SYSKEYDOWN)
return 0;
if (
wparam == VK_F10
|| wparam == VK_MENU
|| wparam == VK_RSHIFT
)
return 0;
}
break;
case WM_MOUSEMOVE:
case WM_POINTERDOWN:
case WM_POINTERUP:
case WM_POINTERUPDATE:
case WM_DEVICECHANGE:
case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL:
case WM_NCLBUTTONDBLCLK:
2022-05-17 13:21:56 +02:00
#ifdef HAVE_TASKBAR
if (g_win32->taskbar_message && message == g_win32->taskbar_message)
g_win32_flags |= WIN32_CMN_FLAG_TASKBAR_CREATED;
#endif
break;
case WM_DROPFILES:
case WM_SYSCOMMAND:
case WM_CHAR:
case WM_CLOSE:
case WM_DESTROY:
case WM_QUIT:
case WM_MOVE:
case WM_SIZE:
case WM_GETMINMAXINFO:
case WM_COMMAND:
ret = wnd_proc_common(&quit, hwnd, message, wparam, lparam);
if (quit)
return ret;
2022-05-17 13:21:56 +02:00
#ifdef HAVE_TASKBAR
if (g_win32->taskbar_message && message == g_win32->taskbar_message)
g_win32_flags |= WIN32_CMN_FLAG_TASKBAR_CREATED;
#endif
break;
#ifdef HAVE_CLIP_WINDOW
case WM_SETFOCUS:
if (input_state_get_ptr()->flags & INP_FLAG_GRAB_MOUSE_STATE)
win32_clip_window(true);
break;
case WM_KILLFOCUS:
if (input_state_get_ptr()->flags & INP_FLAG_GRAB_MOUSE_STATE)
win32_clip_window(false);
break;
#endif
2022-05-17 13:21:56 +02:00
case WM_DISPLAYCHANGE: /* Fix size after display mode switch when using SR */
{
HMONITOR mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (mon)
win32_resize_after_display_change(hwnd, mon);
}
break;
}
return DefWindowProc(hwnd, message, wparam, lparam);
}
#ifdef HAVE_WINRAWINPUT
static LRESULT CALLBACK wnd_proc_winraw_common_internal(HWND hwnd,
UINT message, WPARAM wparam, LPARAM lparam)
{
LRESULT ret;
bool quit = false;
win32_common_state_t *g_win32 = (win32_common_state_t*)&win32_st;
2020-08-28 01:20:54 +02:00
switch (message)
{
2021-08-05 15:24:41 +03:00
case WM_KEYUP: /* Key released */
case WM_SYSKEYUP: /* Key released */
/* fall-through */
case WM_KEYDOWN: /* Key pressed */
case WM_SYSKEYDOWN: /* Key pressed */
quit = true;
2022-05-17 13:21:56 +02:00
if (message != WM_SYSKEYDOWN)
return 0;
2021-08-05 15:24:41 +03:00
/* keyboard_event in winraw_callback */
2022-05-17 13:21:56 +02:00
if (
wparam == VK_F10
2022-05-17 13:21:56 +02:00
|| wparam == VK_MENU
|| wparam == VK_RSHIFT
)
return 0;
2021-08-05 15:24:41 +03:00
break;
case WM_MOUSEMOVE:
case WM_POINTERDOWN:
case WM_POINTERUP:
case WM_POINTERUPDATE:
case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL:
case WM_NCLBUTTONDBLCLK:
2022-05-17 13:21:56 +02:00
#ifdef HAVE_TASKBAR
if (g_win32->taskbar_message && message == g_win32->taskbar_message)
g_win32_flags |= WIN32_CMN_FLAG_TASKBAR_CREATED;
2020-07-02 07:07:42 +02:00
#endif
break;
case WM_DROPFILES:
case WM_SYSCOMMAND:
case WM_CHAR:
case WM_CLOSE:
case WM_DESTROY:
case WM_QUIT:
case WM_MOVE:
case WM_SIZE:
case WM_GETMINMAXINFO:
case WM_COMMAND:
ret = wnd_proc_common(&quit, hwnd, message, wparam, lparam);
if (quit)
return ret;
2022-05-17 13:21:56 +02:00
#ifdef HAVE_TASKBAR
if (g_win32->taskbar_message && message == g_win32->taskbar_message)
g_win32_flags |= WIN32_CMN_FLAG_TASKBAR_CREATED;
2019-08-29 02:26:32 +02:00
#endif
break;
case WM_SETFOCUS:
#ifdef HAVE_CLIP_WINDOW
if (input_state_get_ptr()->flags & INP_FLAG_GRAB_MOUSE_STATE)
win32_clip_window(true);
#endif
#if !defined(_XBOX)
if (winraw_handle_message(message, wparam, lparam))
return 0;
#endif
break;
case WM_KILLFOCUS:
#ifdef HAVE_CLIP_WINDOW
if (input_state_get_ptr()->flags & INP_FLAG_GRAB_MOUSE_STATE)
win32_clip_window(false);
#endif
#if !defined(_XBOX)
if (winraw_handle_message(message, wparam, lparam))
return 0;
#endif
break;
2022-05-17 13:21:56 +02:00
case WM_DISPLAYCHANGE: /* Fix size after display mode switch when using SR */
{
HMONITOR mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (mon)
win32_resize_after_display_change(hwnd, mon);
}
Ver 0.9.2 SR2 (Switchres API) Implimantation Fixed SR close match refresh bug. Added menu high resolution option. Fixed desktop restore bug cuusing endless resolution change requests. Fixed file conflicts Added destop restore resolution back in for manu only. Pulled Switchres fixes. Added better PI rsolution support. Ver 0.7 SR2 (Switchres API) Implimantation Removed HH experimetal check. This is better done via teh switchres.ini at present. Fixed refresh rate bug. Now new resolution and refesh is added correctly. Removed SR deinit from menu restore. Meanu now stays at last content resolution. Ver 0.6.2 SR2 (Switchres API) Implimantation Fixed super resolution bug casuing abnormal video size and aspect ratio Fixed logging issue casuing seg falts on RA exit Ver 0.6 SR2 (Switchres API) Implimantation Ver 0.2 SR2 (Switchres API) Implimantation Added forced super resolutions. Added Multi-monitor/monitor selection support. Added desktop resolution restore when switching back to menu only. Added new menu items for 31KHz standard and 120hz monitor profiles. Added new menu item INI. load monitor profile from switchrss.ini. Fixed winraw driver. Coordinates new refreshed after a resolution change. Fixed Menu aspect ratio in super resolutions. Removed static glabals. These have been added to videocrt_switch struct. Ver 0.1 SR2 (Switchres API) Implimantation Removed old CRTSwitchRes method. Added new SR2 API implimantaion. Resolution swithcing is now done by switchres libs. Both Linux and Windows working with native and super resolutions. Working multi-monitor support with monitor index selection. Working 31KHz support with standard and 120Hxz modes. The monitor index selection is still done via the RA UI. Only choose native and 15KHz form the CRT options in the RA UI as all options are now set in the switchres.ini. All other CRT optoins in the RA UI currently do nothing. Added SR wrapper to fix compile issues. Added back RPi functionality Fixed windows resize/scaling issues on resolution change Thanks @Calamity no more need for crt_switch_driver_refresh() Fix broken case after prevous commit Monitor preset options 15/31KHz now active. Added new meu option. Moitor persets can now be choosen fom the RA UI. 15KHz and 31KHz will set arcade_15 and aracde_31 respectivly. New option INI, if this is chosen your monitor preset will be selected from your switchres.ini file. Added 3KHhz, 120Hz. for old RA users. Renamed 31KHz to 31 KHz, Standard Fixed winraw input coordinates after switching resolution. Code cleanup Fixed menu aspect ratio issue Added menu resolution restore after closing content Fixed aspect ratio after menu resolution restore. code clean up Fxed menu Resulition Restore Aspect Ratio. When SR uses non integer scalled resolution. super width bug with restoring menu resolution fix added super resolution check after setting desktop resolutoion variables when menu active only sr_deinit() used to restore desktop mode. Fixed menu sr_deinit bug. now setting sr_active false Removed static globals, added them to video_switch struct Fixex compile bug due to comment // Fixed compile issues doe to c++ comments in teh switchres_wrapper.h Temporarily removed SR2 logging to fix compile isses for c90 added logging back in. Removed support for winnt and osx Added define for C89. Disabled SR if defined C89 Removed all RA compile fixes fro C89 C90 etc. Swithing now working again. Put Switchres behind HAVE_SR2. HAVE_SR2=no by default. --enable-sr2 Ver 0.5 SR2 Implimentation. Ver 0.4 SR2 Implimantation. Bake SR inside RA Removed temporary log files Disable switchres when C89/C99 builds. Removed C89 and C90 checks for SR Fixed switchres_wrapper.h location Ver 0.3 SR2 Implimenation Dissable logging for C89 __STDC__ Fix For RPi fixed missing EOL fixed RPi function definition added vidrocrt_switch stuct to RPI funcion fixed xoffset for RPi Removed old RPi function call SR disabled for videocore until VC4 switching ported Reverted back to state 5c8a56c Bake SR inside RA Use native win32 api for threads. Fix static lib linking LIBERROR would be defined twice otherwise + improper function names prefixed by __imp_ Added lidstc++ to makefile.common for switchres Fixed RPi switching. Disabled Switchres for videocore unill it is ported. removed RAA.log. Should not exist Added check for when SR fails to set mode with an aspect ratio fix. added video driver re init for RPi GB, GBA and GBC core check, adjusted reseolutions and scale. Please turn on integer scalling in the RA UI Added logas back in. Checking STDC verstion >= C11 Fixed c89 for loop declaration. Code clean up. Added new functions Fix resolution switching bug introduces with HH code clean up. Fixed menu restore bug on closw content after code clean up Moved SR logging to relevant RA logs Update makefile. Checks for X11 and xrandr fixed makefile Use native win32 api for threads. Fix static lib linking LIBERROR would be defined twice otherwise + improper function names prefixed by __imp_ Update switchres_wrapper.* header comments Update year copyright DRMKMS: build only if libdrm has the required version XRANDR: build only if xrandr is available Simplified maklefile Fixed RPI compile error with unsued functions. As before Disable Griffin. No switching support available. Never has been Removed log file 1 Added Win32 static define Added SR source Removed Videocore check on destroy SR Moved SR deinit to trigger earlier on RA exit. Fixed compile error after upstream rebase Fixed aspect ration bug cused by super resolutions. Temporarily disbabled SR logging Re inabled runtim eSR loggind. Disableed all RARCH logging on retro_deinit_drivers Removed srdeinit from menu restore. Menu stays in current reolution until a fix can be found Fixed refresh rate changes when no reolution change is detected. Forgot to add teh resolution cahge in with the refresh change oops Fixed endless no detection log. Removed HH check. This can been better adjusted using the switchres.ini fixed compile issue Added better PI crt switching and fixed typo Pulled Swicthres fixes. Updated desktop restore resolution. removed unused makefile Lockec menu refresh to 60hz fixed missing new line Fixed file conflicts Forced 640x480@60 for menu Added high resolution menu option Removed item logg checker Fixed typos Removed unused functions Fixed SR close match refesh bug. Fixed typo
2021-05-11 02:08:15 -07:00
break;
case WM_DEVICECHANGE:
#if !defined(_XBOX)
if (winraw_handle_message(message, wparam, lparam))
return 0;
#endif
break;
}
return DefWindowProc(hwnd, message, wparam, lparam);
}
#endif
2022-12-02 18:47:07 +02:00
#if defined(_MSC_VER) && !defined(_XBOX)
2022-11-29 04:45:55 +01:00
#pragma comment(lib, "Imm32")
#endif
#ifdef HAVE_DINPUT
static LRESULT CALLBACK wnd_proc_common_dinput_internal(HWND hwnd,
UINT message, WPARAM wparam, LPARAM lparam)
{
LRESULT ret;
bool keydown = true;
bool quit = false;
win32_common_state_t *g_win32 = (win32_common_state_t*)&win32_st;
switch (message)
{
2022-11-29 04:45:55 +01:00
case WM_IME_ENDCOMPOSITION:
input_keyboard_event(true, 1, 0x80000000, 0, RETRO_DEVICE_KEYBOARD);
2022-11-29 04:45:55 +01:00
break;
case WM_IME_COMPOSITION:
{
2022-11-29 04:45:55 +01:00
HIMC hIMC = ImmGetContext(hwnd);
unsigned gcs = lparam & (GCS_COMPSTR|GCS_RESULTSTR);
2022-11-29 04:45:55 +01:00
if (gcs)
{
int i;
wchar_t wstr[4]={0,};
int len1 = ImmGetCompositionStringW(hIMC, gcs, wstr, 4);
2022-11-29 04:45:55 +01:00
wstr[2] = wstr[1];
wstr[1] = 0;
if ((len1 <= 0) || (len1 > 4))
break;
for (i = 0; i < len1; i = i + 2)
{
size_t len2;
char *utf8 = utf16_to_utf8_string_alloc(wstr+i);
if (!utf8)
continue;
len2 = strlen(utf8) + 1;
if (len2 >= 1 && len2 <= 3)
{
if (len2 >= 2)
utf8[3] = (gcs) | (gcs >> 4);
input_keyboard_event(true, 1, *((int*)utf8), 0, RETRO_DEVICE_KEYBOARD);
2022-11-29 04:45:55 +01:00
}
free(utf8);
}
}
ImmReleaseContext(hwnd, hIMC);
return 0;
}
break;
case WM_KEYUP: /* Key released */
case WM_SYSKEYUP: /* Key released */
keydown = false;
/* fall-through */
case WM_KEYDOWN: /* Key pressed */
case WM_SYSKEYDOWN: /* Key pressed */
quit = true;
{
uint16_t mod = 0;
unsigned keycode = 0;
unsigned keysym = (lparam >> 16) & 0xff;
/* extended keys will map to dinput if the high bit is set */
if ((lparam >> 24 & 0x1))
keysym |= 0x80;
2019-08-29 02:26:32 +02:00
keycode = input_keymaps_translate_keysym_to_rk(keysym);
2020-11-09 15:19:41 +02:00
switch (keycode)
{
/* L+R Shift handling done in dinput_poll */
case RETROK_LSHIFT:
case RETROK_RSHIFT:
return 0;
}
2019-08-29 02:26:32 +02:00
if (GetKeyState(VK_SHIFT) & 0x80)
mod |= RETROKMOD_SHIFT;
if (GetKeyState(VK_CONTROL) & 0x80)
mod |= RETROKMOD_CTRL;
if (GetKeyState(VK_MENU) & 0x80)
mod |= RETROKMOD_ALT;
if (GetKeyState(VK_CAPITAL) & 0x81)
mod |= RETROKMOD_CAPSLOCK;
if (GetKeyState(VK_SCROLL) & 0x81)
mod |= RETROKMOD_SCROLLOCK;
if ((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & 0x80)
mod |= RETROKMOD_META;
2019-08-29 02:26:32 +02:00
input_keyboard_event(keydown, keycode,
0, mod, RETRO_DEVICE_KEYBOARD);
2019-08-29 02:26:32 +02:00
if (message != WM_SYSKEYDOWN)
return 0;
if (
2022-05-17 13:21:56 +02:00
wparam == VK_F10
|| wparam == VK_MENU
|| wparam == VK_RSHIFT
2019-08-29 02:26:32 +02:00
)
return 0;
}
2015-11-28 22:00:22 +01:00
break;
2020-01-18 11:34:50 +01:00
case WM_MOUSEMOVE:
case WM_POINTERDOWN:
case WM_POINTERUP:
case WM_POINTERUPDATE:
case WM_DEVICECHANGE:
case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL:
case WM_NCLBUTTONDBLCLK:
2022-05-17 13:21:56 +02:00
#ifdef HAVE_TASKBAR
2020-03-13 00:11:21 +01:00
if (g_win32->taskbar_message && message == g_win32->taskbar_message)
g_win32_flags |= WIN32_CMN_FLAG_TASKBAR_CREATED;
2020-01-18 11:34:50 +01:00
#endif
#if !defined(_XBOX)
2020-01-18 11:34:50 +01:00
{
void* input_data = (void*)(LONG_PTR)GetWindowLongPtr(main_window.hwnd, GWLP_USERDATA);
2020-01-18 11:34:50 +01:00
if (input_data && dinput_handle_message(input_data,
message, wparam, lparam))
return 0;
}
#endif
2020-01-18 10:41:26 +01:00
break;
2016-06-03 09:14:53 +10:00
case WM_DROPFILES:
2015-11-28 22:00:22 +01:00
case WM_SYSCOMMAND:
case WM_CHAR:
case WM_CLOSE:
case WM_DESTROY:
case WM_QUIT:
case WM_MOVE:
case WM_SIZE:
case WM_GETMINMAXINFO:
2015-11-28 22:00:22 +01:00
case WM_COMMAND:
2020-05-12 14:36:27 +02:00
ret = wnd_proc_common(&quit, hwnd, message, wparam, lparam);
2015-11-30 06:27:00 +01:00
if (quit)
return ret;
2022-05-17 13:21:56 +02:00
#ifdef HAVE_TASKBAR
2020-03-13 00:11:21 +01:00
if (g_win32->taskbar_message && message == g_win32->taskbar_message)
g_win32_flags |= WIN32_CMN_FLAG_TASKBAR_CREATED;
2020-01-18 11:34:50 +01:00
#endif
2015-11-30 06:27:00 +01:00
break;
#ifdef HAVE_CLIP_WINDOW
case WM_SETFOCUS:
if (input_state_get_ptr()->flags & INP_FLAG_GRAB_MOUSE_STATE)
win32_clip_window(true);
break;
case WM_KILLFOCUS:
if (input_state_get_ptr()->flags & INP_FLAG_GRAB_MOUSE_STATE)
win32_clip_window(false);
break;
#endif
2022-05-17 13:21:56 +02:00
case WM_DISPLAYCHANGE: /* Fix size after display mode switch when using SR */
{
HMONITOR mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (mon)
win32_resize_after_display_change(hwnd, mon);
}
Ver 0.9.2 SR2 (Switchres API) Implimantation Fixed SR close match refresh bug. Added menu high resolution option. Fixed desktop restore bug cuusing endless resolution change requests. Fixed file conflicts Added destop restore resolution back in for manu only. Pulled Switchres fixes. Added better PI rsolution support. Ver 0.7 SR2 (Switchres API) Implimantation Removed HH experimetal check. This is better done via teh switchres.ini at present. Fixed refresh rate bug. Now new resolution and refesh is added correctly. Removed SR deinit from menu restore. Meanu now stays at last content resolution. Ver 0.6.2 SR2 (Switchres API) Implimantation Fixed super resolution bug casuing abnormal video size and aspect ratio Fixed logging issue casuing seg falts on RA exit Ver 0.6 SR2 (Switchres API) Implimantation Ver 0.2 SR2 (Switchres API) Implimantation Added forced super resolutions. Added Multi-monitor/monitor selection support. Added desktop resolution restore when switching back to menu only. Added new menu items for 31KHz standard and 120hz monitor profiles. Added new menu item INI. load monitor profile from switchrss.ini. Fixed winraw driver. Coordinates new refreshed after a resolution change. Fixed Menu aspect ratio in super resolutions. Removed static glabals. These have been added to videocrt_switch struct. Ver 0.1 SR2 (Switchres API) Implimantation Removed old CRTSwitchRes method. Added new SR2 API implimantaion. Resolution swithcing is now done by switchres libs. Both Linux and Windows working with native and super resolutions. Working multi-monitor support with monitor index selection. Working 31KHz support with standard and 120Hxz modes. The monitor index selection is still done via the RA UI. Only choose native and 15KHz form the CRT options in the RA UI as all options are now set in the switchres.ini. All other CRT optoins in the RA UI currently do nothing. Added SR wrapper to fix compile issues. Added back RPi functionality Fixed windows resize/scaling issues on resolution change Thanks @Calamity no more need for crt_switch_driver_refresh() Fix broken case after prevous commit Monitor preset options 15/31KHz now active. Added new meu option. Moitor persets can now be choosen fom the RA UI. 15KHz and 31KHz will set arcade_15 and aracde_31 respectivly. New option INI, if this is chosen your monitor preset will be selected from your switchres.ini file. Added 3KHhz, 120Hz. for old RA users. Renamed 31KHz to 31 KHz, Standard Fixed winraw input coordinates after switching resolution. Code cleanup Fixed menu aspect ratio issue Added menu resolution restore after closing content Fixed aspect ratio after menu resolution restore. code clean up Fxed menu Resulition Restore Aspect Ratio. When SR uses non integer scalled resolution. super width bug with restoring menu resolution fix added super resolution check after setting desktop resolutoion variables when menu active only sr_deinit() used to restore desktop mode. Fixed menu sr_deinit bug. now setting sr_active false Removed static globals, added them to video_switch struct Fixex compile bug due to comment // Fixed compile issues doe to c++ comments in teh switchres_wrapper.h Temporarily removed SR2 logging to fix compile isses for c90 added logging back in. Removed support for winnt and osx Added define for C89. Disabled SR if defined C89 Removed all RA compile fixes fro C89 C90 etc. Swithing now working again. Put Switchres behind HAVE_SR2. HAVE_SR2=no by default. --enable-sr2 Ver 0.5 SR2 Implimentation. Ver 0.4 SR2 Implimantation. Bake SR inside RA Removed temporary log files Disable switchres when C89/C99 builds. Removed C89 and C90 checks for SR Fixed switchres_wrapper.h location Ver 0.3 SR2 Implimenation Dissable logging for C89 __STDC__ Fix For RPi fixed missing EOL fixed RPi function definition added vidrocrt_switch stuct to RPI funcion fixed xoffset for RPi Removed old RPi function call SR disabled for videocore until VC4 switching ported Reverted back to state 5c8a56c Bake SR inside RA Use native win32 api for threads. Fix static lib linking LIBERROR would be defined twice otherwise + improper function names prefixed by __imp_ Added lidstc++ to makefile.common for switchres Fixed RPi switching. Disabled Switchres for videocore unill it is ported. removed RAA.log. Should not exist Added check for when SR fails to set mode with an aspect ratio fix. added video driver re init for RPi GB, GBA and GBC core check, adjusted reseolutions and scale. Please turn on integer scalling in the RA UI Added logas back in. Checking STDC verstion >= C11 Fixed c89 for loop declaration. Code clean up. Added new functions Fix resolution switching bug introduces with HH code clean up. Fixed menu restore bug on closw content after code clean up Moved SR logging to relevant RA logs Update makefile. Checks for X11 and xrandr fixed makefile Use native win32 api for threads. Fix static lib linking LIBERROR would be defined twice otherwise + improper function names prefixed by __imp_ Update switchres_wrapper.* header comments Update year copyright DRMKMS: build only if libdrm has the required version XRANDR: build only if xrandr is available Simplified maklefile Fixed RPI compile error with unsued functions. As before Disable Griffin. No switching support available. Never has been Removed log file 1 Added Win32 static define Added SR source Removed Videocore check on destroy SR Moved SR deinit to trigger earlier on RA exit. Fixed compile error after upstream rebase Fixed aspect ration bug cused by super resolutions. Temporarily disbabled SR logging Re inabled runtim eSR loggind. Disableed all RARCH logging on retro_deinit_drivers Removed srdeinit from menu restore. Menu stays in current reolution until a fix can be found Fixed refresh rate changes when no reolution change is detected. Forgot to add teh resolution cahge in with the refresh change oops Fixed endless no detection log. Removed HH check. This can been better adjusted using the switchres.ini fixed compile issue Added better PI crt switching and fixed typo Pulled Swicthres fixes. Updated desktop restore resolution. removed unused makefile Lockec menu refresh to 60hz fixed missing new line Fixed file conflicts Forced 640x480@60 for menu Added high resolution menu option Removed item logg checker Fixed typos Removed unused functions Fixed SR close match refesh bug. Fixed typo
2021-05-11 02:08:15 -07:00
break;
}
2015-11-28 21:50:28 +01:00
return DefWindowProc(hwnd, message, wparam, lparam);
}
#endif
#if defined(HAVE_D3D) || defined(HAVE_D3D8) || defined(HAVE_D3D9) || defined (HAVE_D3D10) || defined (HAVE_D3D11) || defined (HAVE_D3D12)
LRESULT CALLBACK wnd_proc_d3d_common(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
{
if (DragAcceptFiles_func)
DragAcceptFiles_func(hwnd, true);
g_win32_flags |= WIN32_CMN_FLAG_INITED;
return 0;
}
return wnd_proc_common_internal(hwnd, message, wparam, lparam);
}
2015-11-28 21:50:28 +01:00
#ifdef HAVE_WINRAWINPUT
LRESULT CALLBACK wnd_proc_d3d_winraw(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
{
if (DragAcceptFiles_func)
DragAcceptFiles_func(hwnd, true);
g_win32_flags |= WIN32_CMN_FLAG_INITED;
return 0;
}
return wnd_proc_winraw_common_internal(hwnd, message, wparam, lparam);
}
#endif
#ifdef HAVE_DINPUT
LRESULT CALLBACK wnd_proc_d3d_dinput(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
{
if (DragAcceptFiles_func)
DragAcceptFiles_func(hwnd, true);
g_win32_flags |= WIN32_CMN_FLAG_INITED;
return 0;
}
return wnd_proc_common_dinput_internal(hwnd, message, wparam, lparam);
}
#endif
#endif
2020-07-17 02:32:37 +02:00
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGL1) || defined(HAVE_OPENGL_CORE)
2023-04-03 20:25:46 +02:00
extern void create_gl_context(HWND hwnd, bool *quit);
extern void create_gles_context(HWND hwnd, bool *quit);
static LRESULT wnd_proc_wgl_wm_create(HWND hwnd)
{
extern enum gfx_ctx_api win32_api;
bool is_quit = false;
switch (win32_api)
{
case GFX_CTX_OPENGL_API:
#if (defined(HAVE_OPENGL) || defined(HAVE_OPENGL1) || defined(HAVE_OPENGL_CORE)) && !defined(HAVE_OPENGLES)
create_gl_context(hwnd, &is_quit);
#endif
break;
case GFX_CTX_OPENGL_ES_API:
#if defined (HAVE_OPENGLES)
create_gles_context(hwnd, &is_quit);
#endif
break;
case GFX_CTX_NONE:
default:
break;
}
if (is_quit)
g_win32_flags |= WIN32_CMN_FLAG_QUIT;
if (DragAcceptFiles_func)
DragAcceptFiles_func(hwnd, true);
g_win32_flags |= WIN32_CMN_FLAG_INITED;
return 0;
}
#ifdef HAVE_DINPUT
LRESULT CALLBACK wnd_proc_wgl_dinput(HWND hwnd, UINT message,
2015-11-28 21:50:28 +01:00
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
2023-04-03 20:25:46 +02:00
return wnd_proc_wgl_wm_create(hwnd);
return wnd_proc_common_dinput_internal(hwnd, message, wparam, lparam);
}
#endif
2015-11-11 18:26:10 +01:00
#ifdef HAVE_WINRAWINPUT
LRESULT CALLBACK wnd_proc_wgl_winraw(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
2023-04-03 20:25:46 +02:00
return wnd_proc_wgl_wm_create(hwnd);
return wnd_proc_winraw_common_internal(hwnd, message, wparam, lparam);
}
#endif
LRESULT CALLBACK wnd_proc_wgl_common(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
2023-04-03 20:25:46 +02:00
return wnd_proc_wgl_wm_create(hwnd);
return wnd_proc_common_internal(hwnd, message, wparam, lparam);
}
#endif
#ifdef HAVE_VULKAN
2023-04-03 20:25:46 +02:00
#include "vulkan_common.h"
static LRESULT wnd_proc_wm_vk_create(HWND hwnd)
{
RECT rect;
2023-04-03 20:25:46 +02:00
extern int win32_vk_interval;
extern gfx_ctx_vulkan_data_t win32_vk;
unsigned width = 0;
unsigned height = 0;
HINSTANCE instance = GetModuleHandle(NULL);
2023-04-03 20:25:46 +02:00
GetClientRect(hwnd, &rect);
width = rect.right - rect.left;
height = rect.bottom - rect.top;
2023-04-03 20:25:46 +02:00
if (!vulkan_surface_create(&win32_vk,
VULKAN_WSI_WIN32,
&instance, &hwnd,
width, height, win32_vk_interval))
g_win32_flags |= WIN32_CMN_FLAG_QUIT;
g_win32_flags |= WIN32_CMN_FLAG_INITED;
if (DragAcceptFiles_func)
DragAcceptFiles_func(hwnd, true);
return 0;
}
#ifdef HAVE_DINPUT
LRESULT CALLBACK wnd_proc_vk_dinput(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
2023-04-03 20:25:46 +02:00
return wnd_proc_wm_vk_create(hwnd);
return wnd_proc_common_dinput_internal(hwnd, message, wparam, lparam);
}
#endif
#ifdef HAVE_WINRAWINPUT
LRESULT CALLBACK wnd_proc_vk_winraw(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
2023-04-03 20:25:46 +02:00
return wnd_proc_wm_vk_create(hwnd);
return wnd_proc_winraw_common_internal(hwnd, message, wparam, lparam);
}
#endif
LRESULT CALLBACK wnd_proc_vk_common(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
2023-04-03 20:25:46 +02:00
return wnd_proc_wm_vk_create(hwnd);
return wnd_proc_common_internal(hwnd, message, wparam, lparam);
}
#endif
2019-07-11 13:18:38 +02:00
#ifdef HAVE_GDI
2023-04-03 20:25:46 +02:00
static LRESULT wnd_proc_wm_gdi_create(HWND hwnd)
{
extern HDC win32_gdi_hdc;
win32_gdi_hdc = GetDC(hwnd);
win32_setup_pixel_format(win32_gdi_hdc, false);
g_win32_flags |= WIN32_CMN_FLAG_INITED;
if (DragAcceptFiles_func)
DragAcceptFiles_func(hwnd, true);
return 0;
}
#ifdef HAVE_DINPUT
LRESULT CALLBACK wnd_proc_gdi_dinput(HWND hwnd, UINT message,
2017-01-04 22:57:00 -05:00
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
2023-04-03 20:25:46 +02:00
return wnd_proc_wm_gdi_create(hwnd);
else if (message == WM_PAINT)
{
2023-04-03 20:25:46 +02:00
win32_common_state_t *g_win32 = (win32_common_state_t*)&win32_st;
gdi_t *gdi = (gdi_t*)video_driver_get_ptr();
2017-08-22 23:39:05 -04:00
if (gdi && gdi->memDC)
{
gdi->bmp_old = (HBITMAP)SelectObject(gdi->memDC, gdi->bmp);
/* Draw video content */
StretchBlt(
gdi->winDC,
0,
0,
gdi->screen_width,
gdi->screen_height,
gdi->memDC,
0,
0,
gdi->video_width,
gdi->video_height,
SRCCOPY);
SelectObject(gdi->memDC, gdi->bmp_old);
}
2022-05-17 13:21:56 +02:00
#ifdef HAVE_TASKBAR
if ( g_win32->taskbar_message
&& message == g_win32->taskbar_message)
g_win32_flags |= WIN32_CMN_FLAG_TASKBAR_CREATED;
2020-01-18 11:34:50 +01:00
#endif
2017-01-04 22:57:00 -05:00
}
return wnd_proc_common_dinput_internal(hwnd, message, wparam, lparam);
2017-01-04 22:57:00 -05:00
}
2019-07-11 13:18:38 +02:00
#endif
2017-01-04 22:57:00 -05:00
#ifdef HAVE_WINRAWINPUT
LRESULT CALLBACK wnd_proc_gdi_winraw(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
2023-04-03 20:25:46 +02:00
return wnd_proc_wm_gdi_create(hwnd);
else if (message == WM_PAINT)
{
2023-04-03 20:25:46 +02:00
win32_common_state_t *g_win32 = (win32_common_state_t*)&win32_st;
gdi_t *gdi = (gdi_t*)video_driver_get_ptr();
if (gdi && gdi->memDC)
{
gdi->bmp_old = (HBITMAP)SelectObject(gdi->memDC, gdi->bmp);
/* Draw video content */
StretchBlt(
gdi->winDC,
0,
0,
gdi->screen_width,
gdi->screen_height,
gdi->memDC,
0,
0,
gdi->video_width,
gdi->video_height,
SRCCOPY);
SelectObject(gdi->memDC, gdi->bmp_old);
}
2022-05-17 13:21:56 +02:00
#ifdef HAVE_TASKBAR
if ( g_win32->taskbar_message
&& message == g_win32->taskbar_message)
g_win32_flags |= WIN32_CMN_FLAG_TASKBAR_CREATED;
#endif
}
return wnd_proc_winraw_common_internal(hwnd, message, wparam, lparam);
}
#endif
LRESULT CALLBACK wnd_proc_gdi_common(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
if (message == WM_CREATE)
2023-04-03 20:25:46 +02:00
return wnd_proc_wm_gdi_create(hwnd);
else if (message == WM_PAINT)
{
2023-04-03 20:25:46 +02:00
win32_common_state_t *g_win32 = (win32_common_state_t*)&win32_st;
gdi_t *gdi = (gdi_t*)video_driver_get_ptr();
if (gdi && gdi->memDC)
{
gdi->bmp_old = (HBITMAP)SelectObject(gdi->memDC, gdi->bmp);
/* Draw video content */
StretchBlt(
gdi->winDC,
0,
0,
gdi->screen_width,
gdi->screen_height,
gdi->memDC,
0,
0,
gdi->video_width,
gdi->video_height,
SRCCOPY);
SelectObject(gdi->memDC, gdi->bmp_old);
}
2022-05-17 13:21:56 +02:00
#ifdef HAVE_TASKBAR
if ( g_win32->taskbar_message
&& message == g_win32->taskbar_message)
g_win32_flags |= WIN32_CMN_FLAG_TASKBAR_CREATED;
#endif
}
return wnd_proc_common_internal(hwnd, message, wparam, lparam);
}
#endif
2015-11-12 02:51:40 +01:00
bool win32_window_create(void *data, unsigned style,
RECT *mon_rect, unsigned width,
unsigned height, bool fullscreen)
{
2020-03-13 00:11:21 +01:00
win32_common_state_t *g_win32 = (win32_common_state_t*)&win32_st;
settings_t *settings = config_get_ptr();
2022-05-17 13:21:56 +02:00
#ifdef HAVE_TASKBAR
2017-12-27 21:49:56 +01:00
DEV_BROADCAST_DEVICEINTERFACE notification_filter;
2022-05-17 13:21:56 +02:00
#endif
#ifdef HAVE_WINDOW_TRANSP
2020-03-13 00:11:21 +01:00
unsigned window_opacity = settings->uints.video_window_opacity;
2017-12-31 03:44:28 +01:00
#endif
2020-03-13 00:11:21 +01:00
bool window_save_positions = settings->bools.video_window_save_positions;
unsigned user_width = width;
unsigned user_height = height;
2021-10-12 11:58:22 +02:00
const char *new_label = msg_hash_to_str(MSG_PROGRAM);
#ifdef LEGACY_WIN32
2021-10-12 11:58:22 +02:00
char *title_local = utf8_to_local_string_alloc(new_label);
#else
2021-10-12 11:58:22 +02:00
wchar_t *title_local = utf8_to_utf16_string_alloc(new_label);
#endif
2020-02-19 19:31:00 +01:00
if (window_save_positions && !fullscreen)
{
2020-03-13 00:11:21 +01:00
user_width = g_win32->pos_width;
user_height = g_win32->pos_height;
}
#ifdef LEGACY_WIN32
main_window.hwnd = CreateWindowEx(0,
"RetroArch", title_local,
#else
main_window.hwnd = CreateWindowExW(0,
L"RetroArch", title_local,
#endif
2015-11-12 02:51:40 +01:00
style,
2020-03-13 00:11:21 +01:00
fullscreen ? mon_rect->left : g_win32->pos_x,
fullscreen ? mon_rect->top : g_win32->pos_y,
user_width,
user_height,
2015-11-12 02:51:40 +01:00
NULL, NULL, NULL, data);
free(title_local);
2016-06-04 05:44:06 +02:00
if (!main_window.hwnd)
2015-11-12 02:51:40 +01:00
return false;
window_accelerators = LoadAcceleratorsA(GetModuleHandleA(NULL), MAKEINTRESOURCE(IDR_ACCELERATOR1));
2022-05-17 13:21:56 +02:00
#ifdef HAVE_TASKBAR
2020-03-13 00:11:21 +01:00
g_win32->taskbar_message =
RegisterWindowMessage("TaskbarButtonCreated");
2020-01-18 10:41:26 +01:00
memset(&notification_filter, 0, sizeof(notification_filter));
notification_filter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
notification_filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
notification_filter.dbcc_classguid = GUID_DEVINTERFACE_HID;
notification_handler = RegisterDeviceNotification(
2018-04-30 14:33:05 -04:00
main_window.hwnd, &notification_filter, DEVICE_NOTIFY_WINDOW_HANDLE);
2018-02-04 10:59:02 -05:00
if (!notification_handler)
RARCH_ERR("Error registering for notifications\n");
2017-12-30 21:38:00 -05:00
#endif
video_driver_display_type_set(RARCH_DISPLAY_WIN32);
video_driver_display_set(0);
video_driver_display_userdata_set((uintptr_t)&main_window);
2016-06-04 05:44:06 +02:00
video_driver_window_set((uintptr_t)main_window.hwnd);
2022-05-17 13:21:56 +02:00
#ifdef HAVE_WINDOW_TRANSP
/* Windows 2000 and above use layered windows to enable transparency */
2020-02-19 19:31:00 +01:00
if (window_opacity < 100)
{
SetWindowLongPtr(main_window.hwnd,
GWL_EXSTYLE,
GetWindowLongPtr(main_window.hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
SetLayeredWindowAttributes(main_window.hwnd, 0, (255 *
2020-02-19 19:31:00 +01:00
window_opacity) / 100, LWA_ALPHA);
}
2015-11-12 02:51:40 +01:00
#endif
return true;
}
#endif
2022-05-17 13:21:56 +02:00
#if !defined(_XBOX) && !defined(__WINRT__)
2015-04-09 05:19:29 +02:00
bool win32_get_metrics(void *data,
enum display_metric_types type, float *value)
2015-04-09 05:19:29 +02:00
{
switch (type)
{
case DISPLAY_METRIC_PIXEL_WIDTH:
2021-08-21 02:24:32 +02:00
{
HDC monitor = GetDC(NULL);
*value = GetDeviceCaps(monitor, HORZRES);
ReleaseDC(NULL, monitor);
}
return true;
case DISPLAY_METRIC_PIXEL_HEIGHT:
2021-08-21 02:24:32 +02:00
{
HDC monitor = GetDC(NULL);
*value = GetDeviceCaps(monitor, VERTRES);
ReleaseDC(NULL, monitor);
}
return true;
2015-04-09 05:19:29 +02:00
case DISPLAY_METRIC_MM_WIDTH:
2021-08-21 02:24:32 +02:00
{
HDC monitor = GetDC(NULL);
*value = GetDeviceCaps(monitor, HORZSIZE);
ReleaseDC(NULL, monitor);
}
2018-04-16 04:20:24 +02:00
return true;
2015-04-09 05:19:29 +02:00
case DISPLAY_METRIC_MM_HEIGHT:
2021-08-21 02:24:32 +02:00
{
HDC monitor = GetDC(NULL);
*value = GetDeviceCaps(monitor, VERTSIZE);
ReleaseDC(NULL, monitor);
}
2018-04-16 04:20:24 +02:00
return true;
2015-04-09 05:19:29 +02:00
case DISPLAY_METRIC_DPI:
/* 25.4 mm in an inch. */
2021-08-21 02:24:32 +02:00
{
HDC monitor = GetDC(NULL);
int pixels_x = GetDeviceCaps(monitor, HORZRES);
int physical_width = GetDeviceCaps(monitor, HORZSIZE);
*value = 254 * pixels_x / physical_width / 10;
ReleaseDC(NULL, monitor);
}
2018-04-16 04:20:24 +02:00
return true;
2015-04-09 05:19:29 +02:00
case DISPLAY_METRIC_NONE:
default:
*value = 0;
2018-04-16 04:20:24 +02:00
break;
2015-04-09 05:19:29 +02:00
}
2018-04-16 04:20:24 +02:00
return false;
2015-04-09 05:19:29 +02:00
}
2022-05-17 13:21:56 +02:00
#endif
void win32_monitor_init(void)
{
2023-04-03 20:25:46 +02:00
#if !defined(_XBOX)
2020-03-13 00:11:21 +01:00
win32_common_state_t
*g_win32 = (win32_common_state_t*)&win32_st;
g_win32->monitor_count = 0;
2017-08-09 13:28:31 +02:00
EnumDisplayMonitors(NULL, NULL,
win32_monitor_enum_proc, 0);
#endif
g_win32_flags &= ~WIN32_CMN_FLAG_QUIT;
}
2018-05-12 19:03:39 +02:00
#if !defined(_XBOX)
void win32_show_cursor(void *data, bool state)
2015-04-10 09:30:18 +02:00
{
if (state)
while (ShowCursor(TRUE) < 0);
else
while (ShowCursor(FALSE) >= 0);
}
2015-04-10 09:36:03 +02:00
2020-07-18 17:09:07 +02:00
void win32_check_window(void *data,
bool *quit, bool *resize,
2016-11-06 11:52:03 +01:00
unsigned *width, unsigned *height)
2015-04-10 09:36:03 +02:00
{
bool video_is_threaded = video_driver_is_threaded();
if (video_is_threaded)
ui_companion_win32.application->process_events();
*quit = g_win32_flags & WIN32_CMN_FLAG_QUIT;
if (g_win32_flags & WIN32_CMN_FLAG_RESIZED)
{
2018-05-12 19:03:39 +02:00
*resize = true;
*width = g_win32_resize_width;
*height = g_win32_resize_height;
g_win32_flags &= ~WIN32_CMN_FLAG_RESIZED;
}
2015-04-10 09:36:03 +02:00
}
2022-05-17 13:21:56 +02:00
#endif
2022-05-17 13:21:56 +02:00
#ifdef HAVE_CLIP_WINDOW
void win32_clip_window(bool state)
{
RECT clip_rect;
if (state && main_window.hwnd)
{
PWINDOWINFO info;
2021-03-22 15:20:51 +01:00
info = (PWINDOWINFO)malloc(sizeof(*info));
if (info)
{
info->cbSize = sizeof(PWINDOWINFO);
if (GetWindowInfo(main_window.hwnd, info))
clip_rect = info->rcClient;
free(info);
}
info = NULL;
}
else
GetWindowRect(GetDesktopWindow(), &clip_rect);
ClipCursor(&clip_rect);
}
2022-05-17 13:21:56 +02:00
#endif
2022-05-17 13:21:56 +02:00
#ifdef HAVE_MENU
/* Given a Win32 Resource ID, return a RetroArch menu ID (for renaming the menu item) */
static enum msg_hash_enums menu_id_to_label_enum(unsigned int menuId)
{
2022-05-17 13:21:56 +02:00
switch (menuId)
{
2022-05-17 13:21:56 +02:00
case ID_M_LOAD_CONTENT:
return MENU_ENUM_LABEL_VALUE_LOAD_CONTENT_LIST;
case ID_M_RESET:
return MENU_ENUM_LABEL_VALUE_RESTART_CONTENT;
case ID_M_QUIT:
return MENU_ENUM_LABEL_VALUE_INPUT_META_QUIT_KEY;
case ID_M_MENU_TOGGLE:
return MENU_ENUM_LABEL_VALUE_INPUT_META_MENU_TOGGLE;
case ID_M_PAUSE_TOGGLE:
return MENU_ENUM_LABEL_VALUE_INPUT_META_PAUSE_TOGGLE;
case ID_M_LOAD_CORE:
return MENU_ENUM_LABEL_VALUE_CORE_LIST;
case ID_M_LOAD_STATE:
return MENU_ENUM_LABEL_VALUE_LOAD_STATE;
case ID_M_SAVE_STATE:
return MENU_ENUM_LABEL_VALUE_SAVE_STATE;
case ID_M_DISK_CYCLE:
return MENU_ENUM_LABEL_VALUE_INPUT_META_DISK_EJECT_TOGGLE;
case ID_M_DISK_NEXT:
return MENU_ENUM_LABEL_VALUE_INPUT_META_DISK_NEXT;
case ID_M_DISK_PREV:
return MENU_ENUM_LABEL_VALUE_INPUT_META_DISK_PREV;
case ID_M_FULL_SCREEN:
return MENU_ENUM_LABEL_VALUE_INPUT_META_FULLSCREEN_TOGGLE_KEY;
case ID_M_MOUSE_GRAB:
return MENU_ENUM_LABEL_VALUE_INPUT_META_GRAB_MOUSE_TOGGLE;
case ID_M_TAKE_SCREENSHOT:
return MENU_ENUM_LABEL_VALUE_INPUT_META_SCREENSHOT;
case ID_M_MUTE_TOGGLE:
return MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE;
default:
break;
}
2022-05-17 13:21:56 +02:00
return MSG_UNKNOWN;
}
2020-12-28 16:45:33 -05:00
/* Given a RetroArch menu ID, get its shortcut key (meta key) */
static unsigned int menu_id_to_meta_key(unsigned int menu_id)
{
switch (menu_id)
{
case ID_M_RESET:
return RARCH_RESET;
case ID_M_QUIT:
return RARCH_QUIT_KEY;
case ID_M_MENU_TOGGLE:
return RARCH_MENU_TOGGLE;
case ID_M_PAUSE_TOGGLE:
return RARCH_PAUSE_TOGGLE;
case ID_M_LOAD_STATE:
return RARCH_LOAD_STATE_KEY;
case ID_M_SAVE_STATE:
return RARCH_SAVE_STATE_KEY;
case ID_M_DISK_CYCLE:
return RARCH_DISK_EJECT_TOGGLE;
case ID_M_DISK_NEXT:
return RARCH_DISK_NEXT;
case ID_M_DISK_PREV:
return RARCH_DISK_PREV;
case ID_M_FULL_SCREEN:
return RARCH_FULLSCREEN_TOGGLE_KEY;
case ID_M_MOUSE_GRAB:
return RARCH_GRAB_MOUSE_TOGGLE;
case ID_M_TAKE_SCREENSHOT:
return RARCH_SCREENSHOT;
case ID_M_MUTE_TOGGLE:
return RARCH_MUTE;
default:
break;
}
return 0;
}
2020-12-28 16:45:33 -05:00
/* Given a short key (meta key), get its name as a string */
/* For single character results, may return same pointer
* with different data inside (modifying the old result) */
static const char *win32_meta_key_to_name(unsigned int meta_key)
{
2022-05-17 13:21:56 +02:00
int i = 0;
const struct retro_keybind* key = &input_config_binds[0][meta_key];
int key_code = key->key;
2022-05-17 13:21:56 +02:00
for (;;)
{
const struct input_key_map* entry = &input_config_key_map[i];
if (!entry->str)
break;
2023-06-14 19:51:31 +02:00
if (entry->key == (enum retro_key)key_code)
2022-05-17 13:21:56 +02:00
return entry->str;
i++;
}
2022-05-17 13:21:56 +02:00
if (key_code >= 32 && key_code < 127)
{
static char single_char[2] = "A";
single_char[0] = key_code;
return single_char;
}
return NULL;
}
/* Replaces Menu Item text with localized menu text,
* and displays the current shortcut key */
static void win32_localize_menu(HMENU menu)
{
#ifndef LEGACY_WIN32
MENUITEMINFOW menu_item_info;
#else
MENUITEMINFOA menu_item_info;
#endif
int index = 0;
for (;;)
{
enum msg_hash_enums label_enum;
memset(&menu_item_info, 0, sizeof(menu_item_info));
menu_item_info.cbSize = sizeof(menu_item_info);
menu_item_info.dwTypeData = NULL;
#if(WINVER >= 0x0500)
menu_item_info.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_STATE | MIIM_SUBMENU;
#else
menu_item_info.fMask = MIIM_ID | MIIM_STATE | MIIM_SUBMENU;
#endif
#ifndef LEGACY_WIN32
if (!GetMenuItemInfoW(menu, index, true, &menu_item_info))
break;
#else
if (!GetMenuItemInfoA(menu, index, true, &menu_item_info))
break;
#endif
/* Recursion - call this on submenu items too */
if (menu_item_info.hSubMenu)
win32_localize_menu(menu_item_info.hSubMenu);
label_enum = menu_id_to_label_enum(menu_item_info.wID);
if (label_enum != MSG_UNKNOWN)
{
int len;
2023-07-15 19:35:19 +02:00
size_t len2;
#ifndef LEGACY_WIN32
wchar_t* new_label_unicode = NULL;
#else
char* new_label_ansi = NULL;
#endif
const char* new_label = msg_hash_to_str(label_enum);
unsigned int meta_key = menu_id_to_meta_key(menu_item_info.wID);
const char* new_label2 = new_label;
const char* meta_key_name = NULL;
char* new_label_text = NULL;
2020-12-28 16:45:33 -05:00
/* specific replacements:
Load Content = "Ctrl+O"
Fullscreen = "Alt+Enter" */
if (label_enum ==
MENU_ENUM_LABEL_VALUE_LOAD_CONTENT_LIST)
2023-07-15 19:35:19 +02:00
{
meta_key_name = "Ctrl+O";
len2 = STRLEN_CONST("Ctrl+O");
}
else if (label_enum ==
MENU_ENUM_LABEL_VALUE_INPUT_META_FULLSCREEN_TOGGLE_KEY)
2023-07-15 19:35:19 +02:00
{
meta_key_name = "Alt+Enter";
len2 = STRLEN_CONST("Alt+Enter");
}
2022-05-17 13:21:56 +02:00
else if (meta_key != 0)
2023-07-15 19:35:19 +02:00
{
meta_key_name = win32_meta_key_to_name(meta_key);
2023-07-15 19:35:19 +02:00
len2 = strlen(meta_key_name);
}
2020-12-28 16:45:33 -05:00
/* Append localized name, tab character, and Shortcut Key */
if (meta_key_name && string_is_not_equal(meta_key_name, "nul"))
{
size_t len1 = strlen(new_label);
size_t buf_size = len1 + len2 + 2;
new_label_text = (char*)malloc(buf_size);
if (new_label_text)
2020-12-28 16:45:33 -05:00
{
size_t _len;
new_label2 = new_label_text;
_len = strlcpy(new_label_text, new_label,
buf_size);
new_label_text[ _len] = '\t';
new_label_text[++_len] = '\0';
strlcpy(new_label_text + _len, meta_key_name, buf_size - _len);
2020-12-28 16:45:33 -05:00
/* Make first character of shortcut name uppercase */
new_label_text[len1 + 1] = toupper(new_label_text[len1 + 1]);
2020-12-28 16:45:33 -05:00
}
}
#ifndef LEGACY_WIN32
/* Convert string from UTF-8, then assign menu text */
new_label_unicode = utf8_to_utf16_string_alloc(new_label2);
len = wcslen(new_label_unicode);
menu_item_info.cch = len;
menu_item_info.dwTypeData = new_label_unicode;
SetMenuItemInfoW(menu, index, true, &menu_item_info);
free(new_label_unicode);
#else
new_label_ansi = utf8_to_local_string_alloc(new_label2);
len = strlen(new_label_ansi);
menu_item_info.cch = len;
menu_item_info.dwTypeData = new_label_ansi;
SetMenuItemInfoA(menu, index, true, &menu_item_info);
free(new_label_ansi);
#endif
if (new_label_text)
free(new_label_text);
}
index++;
}
}
2022-05-17 13:21:56 +02:00
#endif
#ifdef _XBOX
static HWND GetForegroundWindow(void) { return main_window.hwnd; }
BOOL IsIconic(HWND hwnd) { return FALSE; }
bool win32_has_focus(void *data) { return true; }
HWND win32_get_window(void) { return NULL; }
#else
2022-05-17 13:21:56 +02:00
bool win32_has_focus(void *data)
{
settings_t *settings = config_get_ptr();
/* Ensure window size is big enough for core geometry. */
if ( settings
&& !settings->bools.video_fullscreen
&& !settings->bools.video_window_save_positions)
{
unsigned video_scale = settings->uints.video_scale;
unsigned extra_width = 0;
unsigned extra_height = 0;
unsigned min_width = 0;
unsigned min_height = 0;
win32_get_av_info_geometry(&min_width, &min_height);
min_width *= video_scale;
min_height *= video_scale;
if (settings->bools.video_window_show_decorations)
{
int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME);
int title_bar_height = GetSystemMetrics(SM_CYCAPTION);
extra_width += border_thickness * 2;
extra_height += border_thickness * 2 + title_bar_height;
}
if (settings->bools.ui_menubar_enable)
extra_height += GetSystemMetrics(SM_CYMENU);
if ( ( g_win32_resize_width < min_width
|| g_win32_resize_height < min_height)
2023-07-18 14:31:04 +03:00
&& min_width - g_win32_resize_width < MIN_WIDTH / 1.5f
&& min_height - g_win32_resize_height < MIN_HEIGHT / 1.5f)
SetWindowPos(main_window.hwnd, NULL, 0, 0,
min_width + extra_width,
min_height + extra_height,
SWP_NOMOVE);
}
if (g_win32_flags & WIN32_CMN_FLAG_INITED)
2022-05-17 13:21:56 +02:00
if (GetForegroundWindow() == main_window.hwnd)
return true;
return false;
}
HWND win32_get_window(void) { return main_window.hwnd; }
bool win32_suspend_screensaver(void *data, bool enable)
2022-05-17 13:21:56 +02:00
{
if (enable)
{
char tmp[PATH_MAX_LENGTH];
int major = 0;
int minor = 0;
const frontend_ctx_driver_t *frontend = frontend_get_ptr();
if (!frontend)
return false;
if (frontend->get_os)
frontend->get_os(tmp, sizeof(tmp), &major, &minor);
if (major * 100 + minor >= 601)
{
#if _WIN32_WINNT >= 0x0601
/* Windows 7, 8, 10 codepath */
typedef HANDLE(WINAPI * PowerCreateRequestPtr)(REASON_CONTEXT *context);
typedef BOOL(WINAPI * PowerSetRequestPtr)(HANDLE PowerRequest,
POWER_REQUEST_TYPE RequestType);
PowerCreateRequestPtr powerCreateRequest;
PowerSetRequestPtr powerSetRequest;
HMODULE kernel32 = GetModuleHandle("kernel32.dll");
if (kernel32)
{
powerCreateRequest =
(PowerCreateRequestPtr)GetProcAddress(
kernel32, "PowerCreateRequest");
powerSetRequest =
(PowerSetRequestPtr)GetProcAddress(
kernel32, "PowerSetRequest");
if (powerCreateRequest && powerSetRequest)
{
POWER_REQUEST_CONTEXT RequestContext;
HANDLE Request;
RequestContext.Version =
POWER_REQUEST_CONTEXT_VERSION;
RequestContext.Flags =
POWER_REQUEST_CONTEXT_SIMPLE_STRING;
RequestContext.Reason.SimpleReasonString = (LPWSTR)
L"RetroArch running";
Request =
powerCreateRequest(&RequestContext);
powerSetRequest( Request, PowerRequestDisplayRequired);
return true;
}
}
#endif
}
else if (major * 100 + minor >= 410)
{
#if _WIN32_WINDOWS >= 0x0410 || _WIN32_WINNT >= 0x0410
/* 98 / 2K / XP / Vista codepath */
SetThreadExecutionState(ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED);
return true;
#endif
2022-05-17 13:21:56 +02:00
}
else
{
/* 95 / NT codepath */
/* No way to block the screensaver. */
return true;
}
}
return false;
}
static bool win32_monitor_set_fullscreen(
unsigned width, unsigned height,
unsigned refresh, char *dev_name)
{
DEVMODE devmode;
memset(&devmode, 0, sizeof(devmode));
devmode.dmSize = sizeof(DEVMODE);
devmode.dmPelsWidth = width;
devmode.dmPelsHeight = height;
devmode.dmDisplayFrequency = refresh;
devmode.dmFields = DM_PELSWIDTH
| DM_PELSHEIGHT
| DM_DISPLAYFREQUENCY;
return win32_change_display_settings(dev_name, &devmode,
CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL;
}
void win32_set_style(MONITORINFOEX *current_mon, HMONITOR *hm_to_use,
unsigned *width, unsigned *height, bool fullscreen, bool windowed_full,
RECT *rect, RECT *mon_rect, DWORD *style)
{
settings_t *settings = config_get_ptr();
if (fullscreen)
{
/* Windows only reports the refresh rates for modelines as
* an integer, so video_refresh_rate needs to be rounded. Also, account
* for black frame insertion using video_refresh_rate set to a portion
* of the display refresh rate, as well as higher vsync swap intervals. */
float video_refresh = settings->floats.video_refresh_rate;
unsigned bfi = settings->uints.video_black_frame_insertion;
float refresh_mod = bfi + 1.0f;
float refresh_rate = video_refresh * refresh_mod;
if (windowed_full)
{
*style = WS_EX_TOPMOST | WS_POPUP;
g_win32_resize_width = *width = mon_rect->right - mon_rect->left;
g_win32_resize_height = *height = mon_rect->bottom - mon_rect->top;
}
else
{
*style = WS_POPUP | WS_VISIBLE;
if (win32_monitor_set_fullscreen(*width, *height,
(int)refresh_rate, current_mon->szDevice))
{
RARCH_LOG("[Video]: Fullscreen set to %ux%u @ %uHz on device %s.\n",
2022-06-01 18:45:33 +03:00
*width, *height, (int)refresh_rate, current_mon->szDevice);
2022-05-17 13:21:56 +02:00
}
/* Display settings might have changed, get new coordinates. */
GetMonitorInfo(*hm_to_use, (LPMONITORINFO)current_mon);
*mon_rect = current_mon->rcMonitor;
}
}
else
{
win32_common_state_t *g_win32 = (win32_common_state_t*)&win32_st;
bool position_set_from_config = false;
bool video_window_save_positions = settings->bools.video_window_save_positions;
bool window_show_decor = settings->bools.video_window_show_decorations;
2022-05-17 13:21:56 +02:00
*style = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
rect->right = *width;
rect->bottom = *height;
if (!window_show_decor)
{
*style &= ~WS_OVERLAPPEDWINDOW;
*style |= WS_POPUP;
}
2022-05-17 13:21:56 +02:00
AdjustWindowRect(rect, *style, FALSE);
if (video_window_save_positions)
{
/* Set position from config */
int border_thickness = window_show_decor ? GetSystemMetrics(SM_CXSIZEFRAME) : 0;
int title_bar_height = window_show_decor ? GetSystemMetrics(SM_CYCAPTION) : 0;
2022-05-17 13:21:56 +02:00
unsigned window_position_x = settings->uints.window_position_x;
unsigned window_position_y = settings->uints.window_position_y;
unsigned window_position_width = settings->uints.window_position_width;
unsigned window_position_height = settings->uints.window_position_height;
g_win32->pos_x = window_position_x;
g_win32->pos_y = window_position_y;
g_win32->pos_width = window_position_width
+ border_thickness * 2;
g_win32->pos_height = window_position_height
+ border_thickness * 2 + title_bar_height;
if (g_win32->pos_width != 0 && g_win32->pos_height != 0)
position_set_from_config = true;
}
if (position_set_from_config)
{
g_win32_resize_width = *width = g_win32->pos_width;
g_win32_resize_height = *height = g_win32->pos_height;
}
else
{
g_win32_resize_width = *width = rect->right - rect->left;
g_win32_resize_height = *height = rect->bottom - rect->top;
}
}
}
2016-01-09 04:59:12 +01:00
void win32_set_window(unsigned *width, unsigned *height,
2016-01-09 05:00:56 +01:00
bool fullscreen, bool windowed_full, void *rect_data)
2016-01-09 04:59:12 +01:00
{
2016-01-09 05:00:56 +01:00
RECT *rect = (RECT*)rect_data;
2016-01-09 04:59:12 +01:00
if (!fullscreen || windowed_full)
{
2017-04-25 15:31:32 +02:00
settings_t *settings = config_get_ptr();
2016-06-06 08:01:26 +02:00
const ui_window_t *window = ui_companion_driver_get_window_ptr();
2022-05-17 13:21:56 +02:00
#ifdef HAVE_MENU
2020-02-19 19:31:00 +01:00
bool ui_menubar_enable = settings->bools.ui_menubar_enable;
2016-06-06 08:01:26 +02:00
2020-02-19 19:31:00 +01:00
if (!fullscreen && ui_menubar_enable)
2016-01-09 04:59:12 +01:00
{
HMENU menuItem;
2017-05-22 11:33:53 +02:00
RECT rc_temp;
rc_temp.left = 0;
rc_temp.top = 0;
rc_temp.right = (LONG)*height;
rc_temp.bottom = 0x7FFF;
menuItem = LoadMenuA(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_MENU));
win32_localize_menu(menuItem);
SetMenu(main_window.hwnd, menuItem);
2022-05-17 13:21:56 +02:00
2016-12-03 00:14:33 -05:00
SendMessage(main_window.hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rc_temp);
2018-05-12 19:03:39 +02:00
g_win32_resize_height = *height += rc_temp.top + rect->top;
2016-06-04 05:44:06 +02:00
SetWindowPos(main_window.hwnd, NULL, 0, 0, *width, *height, SWP_NOMOVE);
2016-01-09 04:59:12 +01:00
}
2022-05-17 13:21:56 +02:00
#endif
2016-01-09 04:59:12 +01:00
2016-06-04 05:44:06 +02:00
ShowWindow(main_window.hwnd, SW_RESTORE);
UpdateWindow(main_window.hwnd);
SetForegroundWindow(main_window.hwnd);
2016-06-06 08:01:26 +02:00
if (window)
window->set_focused(&main_window);
2016-01-09 04:59:12 +01:00
}
win32_show_cursor(NULL, !fullscreen);
2016-01-09 04:59:12 +01:00
}
2015-11-12 05:16:06 +01:00
bool win32_set_video_mode(void *data,
unsigned width, unsigned height,
bool fullscreen)
{
DWORD style;
MSG msg;
RECT mon_rect;
2017-05-22 11:33:53 +02:00
RECT rect;
2017-08-09 13:28:31 +02:00
MONITORINFOEX current_mon;
2020-03-02 20:34:31 +01:00
int res = 0;
2017-08-09 13:28:31 +02:00
unsigned mon_id = 0;
2015-12-05 12:50:56 +01:00
HMONITOR hm_to_use = NULL;
settings_t *settings = config_get_ptr();
2020-03-02 20:34:31 +01:00
bool windowed_full = settings->bools.video_windowed_fullscreen;
2015-11-12 05:16:06 +01:00
2017-05-22 11:33:53 +02:00
rect.left = 0;
rect.top = 0;
rect.right = 0;
rect.bottom = 0;
2015-11-12 05:16:06 +01:00
win32_monitor_info(&current_mon, &hm_to_use, &mon_id);
2018-05-12 19:03:39 +02:00
mon_rect = current_mon.rcMonitor;
g_win32_resize_width = width;
g_win32_resize_height = height;
g_win32_refresh_rate = settings->floats.video_refresh_rate;
2015-11-12 05:16:06 +01:00
2016-11-06 11:52:03 +01:00
win32_set_style(&current_mon, &hm_to_use, &width, &height,
fullscreen, windowed_full, &rect, &mon_rect, &style);
2015-11-12 05:16:06 +01:00
2017-08-09 13:28:31 +02:00
if (!win32_window_create(data, style,
&mon_rect, width, height, fullscreen))
2015-11-12 05:19:00 +01:00
return false;
2017-08-09 13:28:31 +02:00
win32_set_window(&width, &height,
fullscreen, windowed_full, &rect);
2015-11-12 05:16:06 +01:00
2017-01-04 22:57:00 -05:00
/* Wait until context is created (or failed to do so ...).
* Please don't remove the (res = ) as GetMessage can return -1. */
while ( !(g_win32_flags & WIN32_CMN_FLAG_INITED)
&& !(g_win32_flags & WIN32_CMN_FLAG_QUIT)
2017-08-09 13:28:31 +02:00
&& (res = GetMessage(&msg, main_window.hwnd, 0, 0)) != 0)
2015-11-12 05:16:06 +01:00
{
2017-01-04 22:57:00 -05:00
if (res == -1)
{
RARCH_ERR("GetMessage error code %d\n", GetLastError());
2017-01-05 17:21:13 -05:00
break;
2017-01-04 22:57:00 -05:00
}
2018-04-16 04:20:24 +02:00
TranslateMessage(&msg);
DispatchMessage(&msg);
2015-11-12 05:16:06 +01:00
}
if (g_win32_flags & WIN32_CMN_FLAG_QUIT)
2015-11-12 05:16:06 +01:00
return false;
return true;
}
2018-01-08 23:06:09 +01:00
#endif
2015-11-17 09:44:26 +01:00
bool win32_get_client_rect(RECT* rect)
{
return GetWindowRect(main_window.hwnd, rect);
}
2015-11-17 10:16:16 +01:00
void win32_window_reset(void)
{
g_win32_flags &= ~(WIN32_CMN_FLAG_QUIT
| WIN32_CMN_FLAG_RESTORE_DESKTOP);
2015-11-17 10:16:16 +01:00
}
2015-11-17 09:44:26 +01:00
void win32_destroy_window(void)
{
#ifndef _XBOX
UnregisterClass("RetroArch",
2019-07-19 20:08:45 +02:00
GetModuleHandle(NULL));
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x500 /* 2K */
UnregisterDeviceNotification(notification_handler);
2018-01-08 23:23:37 +01:00
#endif
2017-12-30 21:38:00 -05:00
#endif
main_window.hwnd = NULL;
2015-11-17 09:44:26 +01:00
}
2017-08-09 03:44:03 +02:00
2017-08-09 03:53:19 +02:00
void win32_get_video_output_prev(
2017-08-09 03:44:03 +02:00
unsigned *width, unsigned *height)
2017-08-09 03:53:19 +02:00
{
DEVMODE dm;
2018-01-08 23:30:07 +01:00
unsigned i;
bool found = false;
2017-08-09 03:53:19 +02:00
unsigned prev_width = 0;
unsigned prev_height = 0;
unsigned curr_width = 0;
unsigned curr_height = 0;
if (win32_get_video_output(&dm, -1, sizeof(dm)))
{
curr_width = dm.dmPelsWidth;
curr_height = dm.dmPelsHeight;
}
2017-08-09 03:53:19 +02:00
for (i = 0; win32_get_video_output(&dm, i, sizeof(dm)); i++)
2017-08-09 03:53:19 +02:00
{
2018-04-16 04:20:24 +02:00
if ( dm.dmPelsWidth == curr_width
2017-08-09 13:28:31 +02:00
&& dm.dmPelsHeight == curr_height)
2017-08-09 03:53:19 +02:00
{
if ( prev_width != curr_width
2017-08-09 13:28:31 +02:00
&& prev_height != curr_height)
2017-08-09 03:53:19 +02:00
{
found = true;
2017-08-09 03:53:19 +02:00
break;
}
}
prev_width = dm.dmPelsWidth;
prev_height = dm.dmPelsHeight;
}
if (found)
{
*width = prev_width;
*height = prev_height;
}
2017-08-09 03:53:19 +02:00
}
float win32_get_refresh_rate(void *data)
{
float refresh_rate = 0.0f;
#if _WIN32_WINNT >= 0x0601 || _WIN32_WINDOWS >= 0x0601 /* Win 7 */
OSVERSIONINFO version_info;
2018-07-11 16:37:37 -05:00
UINT32 TopologyID;
unsigned int NumPathArrayElements = 0;
unsigned int NumModeInfoArrayElements = 0;
2018-05-02 01:03:25 +02:00
DISPLAYCONFIG_PATH_INFO_CUSTOM *PathInfoArray = NULL;
DISPLAYCONFIG_MODE_INFO_CUSTOM *ModeInfoArray = NULL;
#ifdef HAVE_DYLIB
2018-07-11 16:37:37 -05:00
static QUERYDISPLAYCONFIG pQueryDisplayConfig;
static GETDISPLAYCONFIGBUFFERSIZES pGetDisplayConfigBufferSizes;
if (!pQueryDisplayConfig)
pQueryDisplayConfig = (QUERYDISPLAYCONFIG)GetProcAddress(GetModuleHandle("user32.dll"), "QueryDisplayConfig");
2018-07-11 16:37:37 -05:00
if (!pGetDisplayConfigBufferSizes)
pGetDisplayConfigBufferSizes = (GETDISPLAYCONFIGBUFFERSIZES)GetProcAddress(GetModuleHandle("user32.dll"), "GetDisplayConfigBufferSizes");
#else
2018-07-11 16:37:37 -05:00
static QUERYDISPLAYCONFIG pQueryDisplayConfig = QueryDisplayConfig;
static GETDISPLAYCONFIGBUFFERSIZES pGetDisplayConfigBufferSizes = GetDisplayConfigBufferSizes;
#endif
version_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (!GetVersionEx(&version_info))
return refresh_rate;
if (version_info.dwMajorVersion < 6 ||
(version_info.dwMajorVersion == 6 && version_info.dwMinorVersion < 1))
return refresh_rate;
2022-05-17 13:21:56 +02:00
if (pGetDisplayConfigBufferSizes(
QDC_DATABASE_CURRENT,
&NumPathArrayElements,
&NumModeInfoArrayElements) != ERROR_SUCCESS)
return refresh_rate;
2018-05-02 01:03:25 +02:00
PathInfoArray = (DISPLAYCONFIG_PATH_INFO_CUSTOM *)
malloc(sizeof(DISPLAYCONFIG_PATH_INFO_CUSTOM) * NumPathArrayElements);
ModeInfoArray = (DISPLAYCONFIG_MODE_INFO_CUSTOM *)
malloc(sizeof(DISPLAYCONFIG_MODE_INFO_CUSTOM) * NumModeInfoArrayElements);
if (pQueryDisplayConfig(QDC_DATABASE_CURRENT,
&NumPathArrayElements,
PathInfoArray,
&NumModeInfoArrayElements,
ModeInfoArray,
&TopologyID) == ERROR_SUCCESS
&& NumPathArrayElements >= 1)
refresh_rate = (float) PathInfoArray[0].targetInfo.refreshRate.Numerator /
PathInfoArray[0].targetInfo.refreshRate.Denominator;
free(ModeInfoArray);
free(PathInfoArray);
#endif
return refresh_rate;
}
2017-08-09 04:09:44 +02:00
void win32_get_video_output_next(
unsigned *width, unsigned *height)
{
DEVMODE dm;
2018-01-08 23:30:07 +01:00
int i;
2017-08-09 04:09:44 +02:00
bool found = false;
unsigned curr_width = 0;
unsigned curr_height = 0;
if (win32_get_video_output(&dm, -1, sizeof(dm)))
{
curr_width = dm.dmPelsWidth;
curr_height = dm.dmPelsHeight;
}
2017-08-09 04:09:44 +02:00
for (i = 0; win32_get_video_output(&dm, i, sizeof(dm)); i++)
2017-08-09 04:09:44 +02:00
{
if (found)
{
*width = dm.dmPelsWidth;
*height = dm.dmPelsHeight;
2017-08-09 04:09:44 +02:00
break;
}
2018-04-16 04:20:24 +02:00
if ( dm.dmPelsWidth == curr_width
2017-08-09 13:28:31 +02:00
&& dm.dmPelsHeight == curr_height)
2017-08-09 04:09:44 +02:00
found = true;
}
}
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0500 /* 2K */
2022-05-17 13:21:56 +02:00
#define WIN32_GET_VIDEO_OUTPUT(iModeNum, dm) EnumDisplaySettingsEx(NULL, iModeNum, dm, EDS_ROTATEDMODE)
#else
2022-05-17 13:21:56 +02:00
#define WIN32_GET_VIDEO_OUTPUT(iModeNum, dm) EnumDisplaySettings(NULL, iModeNum, dm)
#endif
2019-12-20 03:41:10 +01:00
bool win32_get_video_output(DEVMODE *dm, int mode, size_t len)
{
memset(dm, 0, len);
dm->dmSize = len;
2022-05-17 13:21:56 +02:00
if (WIN32_GET_VIDEO_OUTPUT((mode == -1)
2020-05-12 14:36:27 +02:00
? ENUM_CURRENT_SETTINGS
: (DWORD)mode,
2019-12-20 03:41:10 +01:00
dm) == 0)
return false;
return true;
}
void win32_get_video_output_size(void *data, unsigned *width, unsigned *height, char *desc, size_t desc_len)
2017-08-09 03:44:03 +02:00
{
DEVMODE dm;
if (win32_get_video_output(&dm, -1, sizeof(dm)))
2017-08-09 03:44:03 +02:00
{
*width = dm.dmPelsWidth;
*height = dm.dmPelsHeight;
}
}
2019-08-28 23:58:15 +02:00
void win32_setup_pixel_format(HDC hdc, bool supports_gl)
{
PIXELFORMATDESCRIPTOR pfd = {0};
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 0;
pfd.cStencilBits = 0;
pfd.iLayerType = PFD_MAIN_PLANE;
if (supports_gl)
pfd.dwFlags |= PFD_SUPPORT_OPENGL;
SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd);
}
#ifndef __WINRT__
unsigned short win32_get_langid_from_retro_lang(enum retro_language lang);
bool win32_window_init(WNDCLASSEX *wndclass,
bool fullscreen, const char *class_name)
{
#if _WIN32_WINNT >= 0x0501
/* Use the language set in the config for the menubar...
* also changes the console language. */
SetThreadUILanguage(win32_get_langid_from_retro_lang(
(enum retro_language)
*msg_hash_get_uint(MSG_HASH_USER_LANGUAGE)));
#endif
wndclass->cbSize = sizeof(WNDCLASSEX);
wndclass->style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wndclass->hInstance = GetModuleHandle(NULL);
wndclass->hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass->lpszClassName = class_name ? class_name : "RetroArch";
wndclass->hIcon = LoadIcon(GetModuleHandle(NULL),
MAKEINTRESOURCE(IDI_ICON));
wndclass->hIconSm = (HICON)LoadImage(GetModuleHandle(NULL),
MAKEINTRESOURCE(IDI_ICON), IMAGE_ICON, 16, 16, 0);
if (GetSystemMetrics(SM_SWAPBUTTON))
g_win32_flags |= WIN32_CMN_FLAG_SWAP_MOUSE_BTNS;
else
g_win32_flags &= ~WIN32_CMN_FLAG_SWAP_MOUSE_BTNS;
if (!fullscreen)
wndclass->hbrBackground = (HBRUSH)COLOR_WINDOW;
if (class_name)
wndclass->style |= CS_CLASSDC;
2022-05-17 13:21:56 +02:00
return RegisterClassEx(wndclass);
}
#endif