(UWP) Style nits/cleanups

This commit is contained in:
LibretroAdmin 2022-10-01 15:46:09 +02:00
parent b93599c7e0
commit 6be8dccd46

View File

@ -59,7 +59,8 @@ char uwp_dir_data[PATH_MAX_LENGTH] = { 0 };
char uwp_device_family[128] = { 0 }; char uwp_device_family[128] = { 0 };
char win32_cpu_model_name[128] = { 0 }; char win32_cpu_model_name[128] = { 0 };
// Some keys are unavailable in the VirtualKey enum (wtf) but the old-style constants work /* Some keys are unavailable in the VirtualKey enum (wtf) but the old-style
* constants work */
const struct rarch_key_map rarch_key_map_uwp[] = { const struct rarch_key_map rarch_key_map_uwp[] = {
{ (unsigned int)VirtualKey::Back, RETROK_BACKSPACE }, { (unsigned int)VirtualKey::Back, RETROK_BACKSPACE },
{ (unsigned int)VirtualKey::Tab, RETROK_TAB }, { (unsigned int)VirtualKey::Tab, RETROK_TAB },
@ -178,10 +179,10 @@ const struct rarch_key_map rarch_key_map_uwp[] = {
struct input_pointer struct input_pointer
{ {
int id; int id;
short x; int16_t x;
short y; int16_t y;
short full_x; int16_t full_x;
short full_y; int16_t full_y;
bool isInContact; bool isInContact;
}; };
@ -189,12 +190,12 @@ struct uwp_input_state_t
{ {
struct input_pointer touch[MAX_TOUCH]; /* int alignment */ struct input_pointer touch[MAX_TOUCH]; /* int alignment */
unsigned touch_count; unsigned touch_count;
short mouse_screen_x; int16_t mouse_screen_x;
short mouse_screen_y; int16_t mouse_screen_y;
short mouse_rel_x; int16_t mouse_rel_x;
short mouse_rel_y; int16_t mouse_rel_y;
short mouse_wheel_left; int16_t mouse_wheel_left;
short mouse_wheel_up; int16_t mouse_wheel_up;
bool mouse_left; bool mouse_left;
bool mouse_right; bool mouse_right;
bool mouse_middle; bool mouse_middle;
@ -204,28 +205,36 @@ struct uwp_input_state_t
struct uwp_input_state_t uwp_current_input, uwp_next_input; struct uwp_input_state_t uwp_current_input, uwp_next_input;
// Taken from DirectX UWP samples - on Xbox, everything is scaled 200% so getting the DPI calculation correct is crucial /* Taken from DirectX UWP samples - on Xbox, everything is scaled 200%,
* so getting the DPI calculation correct is crucial */
static inline float ConvertDipsToPixels(float dips, float dpi) static inline float ConvertDipsToPixels(float dips, float dpi)
{ {
static const float dipsPerInch = 96.0f; static const float dips_per_inch = 96.0f;
return floorf(dips * dpi / dipsPerInch + 0.5f); return floorf(dips * dpi / dips_per_inch + 0.5f);
} }
// The main function is only used to initialize our IFrameworkView class. /* The main function is only used to initialize our IFrameworkView class. */
[Platform::MTAThread] [Platform::MTAThread]
int main(Platform::Array<Platform::String^>^) int main(Platform::Array<Platform::String^>^)
{ {
Platform::String^ install_dir = Windows::ApplicationModel::Package::Current->InstalledLocation->Path + L"\\"; DWORD dwAttrib;
wcstombs(uwp_dir_install, install_dir->Data(), sizeof(uwp_dir_install)); char vfs_cache_dir[MAX_PATH];
Platform::String^ data_dir = Windows::Storage::ApplicationData::Current->LocalFolder->Path + L"\\"; Platform::String^ local_folder =
wcstombs(uwp_dir_data, data_dir->Data(), sizeof(uwp_dir_data)); Windows::Storage::ApplicationData::Current->LocalFolder->Path;
Platform::String^ install_dir = Windows::ApplicationModel::Package::Current->InstalledLocation->Path + L"\\";
Platform::String^ data_dir = local_folder + L"\\";
// delete vfs cache dir, we do this because this allows a far far more consise implementation than manually implementing a function to do this /* Delete VFS cache dir, we do this because this allows a far more
// this may be a little slower but shouldn't really matter as the cache dir should never have more than a few items * concise implementation than manually implementing a function to do this
Platform::String^ vfs_dir = Windows::Storage::ApplicationData::Current->LocalFolder->Path + L"\\VFSCACHE"; * This may be a little slower but shouldn't really matter as the cache dir
char vfs_cache_dir[MAX_PATH]; * should never have more than a few items */
wcstombs(vfs_cache_dir, vfs_dir->Data(), sizeof(vfs_cache_dir)); Platform::String^ vfs_dir = local_folder + L"\\VFSCACHE";
DWORD dwAttrib = GetFileAttributesA(vfs_cache_dir);
wcstombs(uwp_dir_install, install_dir->Data(), sizeof(uwp_dir_install));
wcstombs(uwp_dir_data, data_dir->Data(), sizeof(uwp_dir_data));
wcstombs(vfs_cache_dir, vfs_dir->Data(), sizeof(vfs_cache_dir));
dwAttrib = GetFileAttributesA(vfs_cache_dir);
if ((dwAttrib != INVALID_FILE_ATTRIBUTES) && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) if ((dwAttrib != INVALID_FILE_ATTRIBUTES) && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))
{ {
concurrency::task<StorageFolder^> vfsdirtask = concurrency::create_task(StorageFolder::GetFolderFromPathAsync(vfs_dir)); concurrency::task<StorageFolder^> vfsdirtask = concurrency::create_task(StorageFolder::GetFolderFromPathAsync(vfs_dir));
@ -266,15 +275,16 @@ App::App() :
/* The first method called when the IFrameworkView is being created. */ /* The first method called when the IFrameworkView is being created. */
void App::Initialize(CoreApplicationView^ applicationView) void App::Initialize(CoreApplicationView^ applicationView)
{ {
/* Register event handlers for app lifecycle. This example includes Activated, so that we /* Register event handlers for app lifecycle. This example
* can make the CoreWindow active and start rendering on the window. */ * includes Activated, so that we can make the CoreWindow active and start
applicationView->Activated += * rendering on the window. */
applicationView->Activated +=
ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &App::OnActivated); ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &App::OnActivated);
CoreApplication::Suspending += CoreApplication::Suspending +=
ref new EventHandler<SuspendingEventArgs^>(this, &App::OnSuspending); ref new EventHandler<SuspendingEventArgs^>(this, &App::OnSuspending);
CoreApplication::Resuming += CoreApplication::Resuming +=
ref new EventHandler<Platform::Object^>(this, &App::OnResuming); ref new EventHandler<Platform::Object^>(this, &App::OnResuming);
CoreApplication::EnteredBackground += CoreApplication::EnteredBackground +=
@ -284,31 +294,31 @@ void App::Initialize(CoreApplicationView^ applicationView)
/* Called when the CoreWindow object is created (or re-created). */ /* Called when the CoreWindow object is created (or re-created). */
void App::SetWindow(CoreWindow^ window) void App::SetWindow(CoreWindow^ window)
{ {
window->SizeChanged += window->SizeChanged +=
ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &App::OnWindowSizeChanged); ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &App::OnWindowSizeChanged);
window->VisibilityChanged += window->VisibilityChanged +=
ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &App::OnVisibilityChanged); ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &App::OnVisibilityChanged);
window->Activated += window->Activated +=
ref new TypedEventHandler<CoreWindow^, WindowActivatedEventArgs^>(this, &App::OnWindowActivated); ref new TypedEventHandler<CoreWindow^, WindowActivatedEventArgs^>(this, &App::OnWindowActivated);
window->Closed += window->Closed +=
ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &App::OnWindowClosed); ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &App::OnWindowClosed);
window->KeyDown += window->KeyDown +=
ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &App::OnKey); ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &App::OnKey);
window->KeyUp += window->KeyUp +=
ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &App::OnKey); ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &App::OnKey);
window->PointerPressed += window->PointerPressed +=
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointer); ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointer);
window->PointerReleased += window->PointerReleased +=
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointer); ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointer);
window->PointerMoved += window->PointerMoved +=
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointer); ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointer);
window->PointerWheelChanged += window->PointerWheelChanged +=
@ -316,13 +326,13 @@ void App::SetWindow(CoreWindow^ window)
DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView(); DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView();
currentDisplayInformation->DpiChanged += currentDisplayInformation->DpiChanged +=
ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnDpiChanged); ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnDpiChanged);
DisplayInformation::DisplayContentsInvalidated += DisplayInformation::DisplayContentsInvalidated +=
ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnDisplayContentsInvalidated); ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnDisplayContentsInvalidated);
currentDisplayInformation->OrientationChanged += currentDisplayInformation->OrientationChanged +=
ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnOrientationChanged); ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnOrientationChanged);
Windows::UI::Core::SystemNavigationManager::GetForCurrentView()->BackRequested += Windows::UI::Core::SystemNavigationManager::GetForCurrentView()->BackRequested +=
@ -348,7 +358,6 @@ void App::Run()
return; return;
} }
for (;;) for (;;)
{ {
int ret; int ret;
@ -365,7 +374,7 @@ void App::Run()
* Perhaps PreferredLaunchViewSize is broken and * Perhaps PreferredLaunchViewSize is broken and
* we need to wait until the app starts to call TryResizeView */ * we need to wait until the app starts to call TryResizeView */
m_windowResized = true; m_windowResized = true;
x = true; x = true;
} }
if (ret == -1) if (ret == -1)
@ -381,17 +390,23 @@ void App::Uninitialize()
{ {
main_exit(NULL); main_exit(NULL);
//if this instance of RetroArch was started from another app/frontend and the frontend passed "launchOnExit" parameter: /* If this instance of RetroArch was started from another app/frontend
//1. launch the app specified in "launchOnExit", most likely the same app that started RetroArch * and the frontend passed "launchOnExit" parameter:
//2. RetroArch goes to background and RunAsyncAndCatchErrors doesn't return, because the target app is immediately started. * 1. launch the app specified in "launchOnExit", most likely the
//3. explicitly exit in App::OnEnteredBackground if m_launchOnExitShutdown is set. Otherwise, RetroArch doesn't properly shutdown. * same app that started RetroArch
if (m_launchOnExit != nullptr && m_launchOnExit->IsEmpty() == false) * 2. RetroArch goes to background and RunAsyncAndCatchErrors doesn't
* return, because the target app is immediately started.
* 3. Explicitly exit in App::OnEnteredBackground if
* m_launchOnExitShutdown is set. Otherwise, RetroArch doesn't
* properly shutdown.
*/
if (m_launchOnExit != nullptr && !m_launchOnExit->IsEmpty())
{ {
try try
{ {
//launch the target app /* Launch the target app */
m_launchOnExitShutdown = true; m_launchOnExitShutdown = true;
auto ret = RunAsyncAndCatchErrors<bool>([&]() { auto ret = RunAsyncAndCatchErrors<bool>([&]() {
return create_task(Launcher::LaunchUriAsync(ref new Uri(m_launchOnExit))); return create_task(Launcher::LaunchUriAsync(ref new Uri(m_launchOnExit)));
}, false); }, false);
} }
@ -405,19 +420,20 @@ void App::Uninitialize()
void App::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) void App::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
{ {
int ret;
int argc = NULL; int argc = NULL;
std::vector<char*> argv; std::vector<char*> argv;
std::vector<std::string> argvTmp; //using std::string as temp buf instead of char* array to avoid manual char allocations /* using std::string as temp buf instead of char* array
* to avoid manual char allocations */
std::vector<std::string> argvTmp;
ParseProtocolArgs(args, &argc, &argv, &argvTmp); ParseProtocolArgs(args, &argc, &argv, &argvTmp);
//start only if not already initialized. If there is a game in progress, just return /* Start only if not already initialized.
if (m_initialized == true) * If there is a game in progress, just return */
{ if (m_initialized)
return; return;
}
int ret = rarch_main(argc, argv.data(), NULL); if ((ret = rarch_main(argc, argv.data(), NULL)) != 0)
if (ret != 0)
{ {
RARCH_ERR("Init failed\n"); RARCH_ERR("Init failed\n");
CoreApplication::Exit(); CoreApplication::Exit();
@ -427,41 +443,41 @@ void App::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^
if (is_running_on_xbox()) if (is_running_on_xbox())
{ {
bool reset = false; bool reset = false;
int width = uwp_get_width(); int width = uwp_get_width();
int height = uwp_get_height(); int height = uwp_get_height();
//reset driver to d3d11 if set to opengl on boot as cores can just set to gl when needed and there is no good reason to use gl for the menus /* Reset driver to D3D11 if set to OpenGL on boot as cores can
//do not change the default driver if the content is already initialized through arguments as this would crash RA for cores that use only ANGLE * just set to 'gl' when needed and there is no good reason to
settings_t* settings = config_get_ptr(); * use 'gl' for the menus
content_state_t* p_content = content_state_get_ptr(); * Do not change the default driver if the content is already
char* currentdriver = settings->arrays.video_driver; * initialized through arguments, as this would crash RA for
if (strcmpi(currentdriver, "gl") == 0 && p_content->is_inited == false) * cores that use only ANGLE */
settings_t *settings = config_get_ptr();
content_state_t *p_content = content_state_get_ptr();
char *currentdriver = settings->arrays.video_driver;
if ( strcmpi(currentdriver, "gl") == 0
&& !p_content->is_inited)
{ {
//set driver to default /* Set driver to default */
configuration_set_string(settings, configuration_set_string(settings,
settings->arrays.video_driver, settings->arrays.video_driver,
config_get_default_video()); config_get_default_video());
//reset needed reset = true; /* Reset needed */
reset = true;
} }
if ((settings->uints.video_fullscreen_x != width) || (settings->uints.video_fullscreen_y != height)) if ( (settings->uints.video_fullscreen_x != width)
|| (settings->uints.video_fullscreen_y != height))
{ {
//get width and height from display again /* Get width and height from display again */
configuration_set_int(settings, configuration_set_int(settings,
settings->uints.video_fullscreen_x, settings->uints.video_fullscreen_x,
width); width);
configuration_set_int(settings, configuration_set_int(settings,
settings->uints.video_fullscreen_y, settings->uints.video_fullscreen_y,
height); height);
//reset needed reset = true; /* Reset needed */
reset = true;
} }
if (reset) if (reset) /* Restart driver */
{
//restart driver
command_event(CMD_EVENT_REINIT, NULL); command_event(CMD_EVENT_REINIT, NULL);
}
} }
/* Run() won't start until the CoreWindow is activated. */ /* Run() won't start until the CoreWindow is activated. */
@ -470,16 +486,18 @@ void App::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^
void App::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) void App::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args)
{ {
//This function will ensure that configs saved in case the app sent to background or terminated /* This function will ensure that configs are saved in case the app
//for saving configs on quit now configs will be saved in `retroarch_main_quit` at `retroarch.c` * is sent to background or terminated for saving configs on quit
//if this function called because of app closed by quit the below code must be ignored * for saving configs on quit now configs will be saved in
* `retroarch_main_quit` at `retroarch.c`
* If this function is called because of app closed by quit,
* the below code must be ignored
/* Save app state asynchronously after requesting a deferral.
/* Save app state asynchronously after requesting a deferral. Holding a deferral * Holding a deferral indicates that the application is busy
* indicates that the application is busy performing suspending operations. Be * performing suspending operations. Be aware that a deferral may
* aware that a deferral may not be held indefinitely. After about five seconds, * not be held indefinitely. After about five seconds, the app will
* the app will be forced to exit. * be forced to exit. */
*/
SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral();
auto app = this; auto app = this;
@ -529,11 +547,10 @@ void App::OnResuming(Platform::Object^ sender, Platform::Object^ args)
void App::OnEnteredBackground(Platform::Object^ sender, EnteredBackgroundEventArgs^ args) void App::OnEnteredBackground(Platform::Object^ sender, EnteredBackgroundEventArgs^ args)
{ {
//RetroArch entered background because another app/frontend was launched on exit, so properly quit /* RetroArch entered background because another app/frontend
if (m_launchOnExitShutdown == true) * was launched on exit, so properly quit */
{ if (m_launchOnExitShutdown)
CoreApplication::Exit(); CoreApplication::Exit();
}
} }
void App::OnBackRequested(Platform::Object^ sender, Windows::UI::Core::BackRequestedEventArgs^ args) void App::OnBackRequested(Platform::Object^ sender, Windows::UI::Core::BackRequestedEventArgs^ args)
@ -561,6 +578,7 @@ void App::OnWindowActivated(CoreWindow^ sender, WindowActivatedEventArgs^ args)
void App::OnKey(CoreWindow^ sender, KeyEventArgs^ args) void App::OnKey(CoreWindow^ sender, KeyEventArgs^ args)
{ {
unsigned keycode;
uint16_t mod = 0; uint16_t mod = 0;
if ((sender->GetKeyState(VirtualKey::Shift) & CoreVirtualKeyStates::Locked) == CoreVirtualKeyStates::Locked) if ((sender->GetKeyState(VirtualKey::Shift) & CoreVirtualKeyStates::Locked) == CoreVirtualKeyStates::Locked)
mod |= RETROKMOD_SHIFT; mod |= RETROKMOD_SHIFT;
@ -576,27 +594,26 @@ void App::OnKey(CoreWindow^ sender, KeyEventArgs^ args)
(sender->GetKeyState(VirtualKey::RightWindows) & CoreVirtualKeyStates::Locked) == CoreVirtualKeyStates::Locked) (sender->GetKeyState(VirtualKey::RightWindows) & CoreVirtualKeyStates::Locked) == CoreVirtualKeyStates::Locked)
mod |= RETROKMOD_META; mod |= RETROKMOD_META;
unsigned keycode = input_keymaps_translate_keysym_to_rk((unsigned)args->VirtualKey); keycode = input_keymaps_translate_keysym_to_rk((unsigned)args->VirtualKey);
input_keyboard_event(!args->KeyStatus.IsKeyReleased, keycode, 0, mod, RETRO_DEVICE_KEYBOARD); input_keyboard_event(!args->KeyStatus.IsKeyReleased, keycode, 0, mod, RETRO_DEVICE_KEYBOARD);
} }
void App::OnPointer(CoreWindow^ sender, PointerEventArgs^ args) void App::OnPointer(CoreWindow^ sender, PointerEventArgs^ args)
{ {
float dpi = DisplayInformation::GetForCurrentView()->LogicalDpi; float dpi = DisplayInformation::GetForCurrentView()->LogicalDpi;
if (args->CurrentPoint->PointerDevice->PointerDeviceType == PointerDeviceType::Mouse) if (args->CurrentPoint->PointerDevice->PointerDeviceType == PointerDeviceType::Mouse)
{ {
uwp_next_input.mouse_left = args->CurrentPoint->Properties->IsLeftButtonPressed; uwp_next_input.mouse_left = args->CurrentPoint->Properties->IsLeftButtonPressed;
uwp_next_input.mouse_middle = args->CurrentPoint->Properties->IsMiddleButtonPressed; uwp_next_input.mouse_middle = args->CurrentPoint->Properties->IsMiddleButtonPressed;
uwp_next_input.mouse_right = args->CurrentPoint->Properties->IsRightButtonPressed; uwp_next_input.mouse_right = args->CurrentPoint->Properties->IsRightButtonPressed;
uwp_next_input.mouse_button4 = args->CurrentPoint->Properties->IsXButton1Pressed; uwp_next_input.mouse_button4 = args->CurrentPoint->Properties->IsXButton1Pressed;
uwp_next_input.mouse_button5 = args->CurrentPoint->Properties->IsXButton2Pressed; uwp_next_input.mouse_button5 = args->CurrentPoint->Properties->IsXButton2Pressed;
uwp_next_input.mouse_screen_x = ConvertDipsToPixels(args->CurrentPoint->Position.X, dpi); uwp_next_input.mouse_screen_x = ConvertDipsToPixels(args->CurrentPoint->Position.X, dpi);
uwp_next_input.mouse_screen_y = ConvertDipsToPixels(args->CurrentPoint->Position.Y, dpi); uwp_next_input.mouse_screen_y = ConvertDipsToPixels(args->CurrentPoint->Position.Y, dpi);
uwp_next_input.mouse_rel_x = uwp_next_input.mouse_screen_x - uwp_current_input.mouse_screen_x; uwp_next_input.mouse_rel_x = uwp_next_input.mouse_screen_x - uwp_current_input.mouse_screen_x;
uwp_next_input.mouse_rel_y = uwp_next_input.mouse_screen_y - uwp_current_input.mouse_screen_y; uwp_next_input.mouse_rel_y = uwp_next_input.mouse_screen_y - uwp_current_input.mouse_screen_y;
if (args->CurrentPoint->Properties->IsHorizontalMouseWheel) if (args->CurrentPoint->Properties->IsHorizontalMouseWheel)
uwp_next_input.mouse_wheel_left += args->CurrentPoint->Properties->MouseWheelDelta; uwp_next_input.mouse_wheel_left += args->CurrentPoint->Properties->MouseWheelDelta;
else else
@ -604,6 +621,7 @@ void App::OnPointer(CoreWindow^ sender, PointerEventArgs^ args)
} }
else else
{ {
struct video_viewport vp;
unsigned i, free_index = MAX_TOUCH; bool found = false; unsigned i, free_index = MAX_TOUCH; bool found = false;
int id = args->CurrentPoint->PointerId; int id = args->CurrentPoint->PointerId;
@ -630,8 +648,6 @@ void App::OnPointer(CoreWindow^ sender, PointerEventArgs^ args)
uwp_next_input.touch[i].id = id; uwp_next_input.touch[i].id = id;
struct video_viewport vp;
/* convert from event coordinates to core and screen coordinates */ /* convert from event coordinates to core and screen coordinates */
vp.x = 0; vp.x = 0;
vp.y = 0; vp.y = 0;
@ -661,8 +677,6 @@ void App::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
/* DisplayInformation event handlers. */ /* DisplayInformation event handlers. */
void App::OnDpiChanged(DisplayInformation^ sender, Object^ args) void App::OnDpiChanged(DisplayInformation^ sender, Object^ args)
{ {
m_windowResized = true; m_windowResized = true;
@ -678,7 +692,8 @@ void App::OnDisplayContentsInvalidated(DisplayInformation^ sender, Object^ args)
/* Probably can be ignored? */ /* Probably can be ignored? */
} }
void App::OnPackageInstalling(PackageCatalog^ sender, PackageInstallingEventArgs^ args) void App::OnPackageInstalling(PackageCatalog^ sender,
PackageInstallingEventArgs^ args)
{ {
/* TODO: This doesn't seem to work even though it's exactly the same as in sample app and it works there */ /* TODO: This doesn't seem to work even though it's exactly the same as in sample app and it works there */
if (args->IsComplete) if (args->IsComplete)
@ -694,11 +709,14 @@ void App::ParseProtocolArgs(Windows::ApplicationModel::Activation::IActivatedEve
argvTmp->clear(); argvTmp->clear();
argv->clear(); argv->clear();
// If the app is activated using protocol, it is expected to be in this format: /* If the app is activated using protocol,
// "retroarch:?cmd=<RetroArch CLI arguments>&launchOnExit=<app to launch on exit>" * it is expected to be in this format:
// For example: * "retroarch:?cmd=<RetroArch CLI arguments>&launchOnExit=<app to launch on exit>"
// retroarch:?cmd=retroarch -L cores\core_libretro.dll "c:\mypath\path with spaces\game.rom"&launchOnExit=LaunchApp: * For example:
// "cmd" and "launchOnExit" are optional. If none specified, it will normally launch into menu * retroarch:?cmd=retroarch -L cores\core_libretro.dll "c:\mypath\path with spaces\game.rom"&launchOnExit=LaunchApp:
* "cmd" and "launchOnExit" are optional. If none specified,
* it will normally launch into menu
*/
if (args->Kind == ActivationKind::Protocol) if (args->Kind == ActivationKind::Protocol)
{ {
unsigned i; unsigned i;
@ -709,41 +727,38 @@ void App::ParseProtocolArgs(Windows::ApplicationModel::Activation::IActivatedEve
{ {
IWwwFormUrlDecoderEntry^ arg = query->GetAt(i); IWwwFormUrlDecoderEntry^ arg = query->GetAt(i);
//parse RetroArch command line string /* Parse RetroArch command line string */
/* This allows a frotend to quit RetroArch, which in turn allows it
* to launch a different game. */
if (arg->Name == "forceExit") if (arg->Name == "forceExit")
{
//this allows a frotend to quit RetroArch, which in turn allows it to launch a different game.
CoreApplication::Exit(); CoreApplication::Exit();
} else if (arg->Name == "cmd" && !m_initialized)
else if (arg->Name == "cmd" && m_initialized == false)
{ {
std::wstring wsValue(arg->Value->ToString()->Data()); std::wstring wsValue(arg->Value->ToString()->Data());
std::string strValue(wsValue.begin(), wsValue.end()); std::string strValue(wsValue.begin(), wsValue.end());
std::istringstream iss(strValue); std::istringstream iss(strValue);
std::string s; std::string s;
//set escape character to null char to preserve backslashes in paths which are inside quotes, they get stripped by default /* Set escape character to NULL char to preserve backslashes in
while (iss >> std::quoted(s, '"', (char)0)) { * paths which are inside quotes, they get stripped by default */
while (iss >> std::quoted(s, '"', (char)0))
argvTmp->push_back(s); argvTmp->push_back(s);
}
} }
/* If RetroArch UWP app is started using protocol
* with argument "launchOnExit", this gives an option
* to launch another app on RA exit,
* making it easy to integrate RA with other UWP frontends */
else if (arg->Name == "launchOnExit") else if (arg->Name == "launchOnExit")
{
//if RetroArch UWP app is started using protocol with argument "launchOnExit", this gives an option to launch another app on RA exit,
//making it easy to integrate RA with other UWP frontends
m_launchOnExit = arg->Value; m_launchOnExit = arg->Value;
}
} }
} }
if (m_initialized == false) if (!m_initialized)
{ {
(*argc) = argvTmp->size(); (*argc) = argvTmp->size();
//convert to char* array compatible with argv /* Convert to char* array compatible with argv */
for (int i = 0; i < argvTmp->size(); i++) for (int i = 0; i < argvTmp->size(); i++)
{
argv->push_back((char*)(argvTmp->at(i)).c_str()); argv->push_back((char*)(argvTmp->at(i)).c_str());
}
argv->push_back(nullptr); argv->push_back(nullptr);
} }
} }
@ -766,7 +781,8 @@ extern "C" {
{ {
if (App::GetInstance()->IsInitialized()) if (App::GetInstance()->IsInitialized())
{ {
if (fullscreen != ApplicationView::GetForCurrentView()->IsFullScreenMode) if (fullscreen !=
ApplicationView::GetForCurrentView()->IsFullScreenMode)
{ {
if (fullscreen) if (fullscreen)
ApplicationView::GetForCurrentView()->TryEnterFullScreenMode(); ApplicationView::GetForCurrentView()->TryEnterFullScreenMode();
@ -777,17 +793,21 @@ extern "C" {
} }
else else
{ {
/* In case the window is not activated yet, TryResizeView will fail and we have to set the initial parameters instead */ /* In case the window is not activated yet,
/* Note that these are preserved after restarting the app and used for the UWP splash screen size (!), so they should be set only during init and not changed afterwards */ * TryResizeView will fail and we have to set the
ApplicationView::PreferredLaunchViewSize = Size(width, height); * initial parameters instead
* Note that these are preserved after restarting the app
* and used for the UWP splash screen size (!), so they
* should be set only during init and not changed afterwards */
ApplicationView::PreferredLaunchViewSize = Size(width, height);
ApplicationView::PreferredLaunchWindowingMode = fullscreen ? ApplicationViewWindowingMode::FullScreen : ApplicationViewWindowingMode::PreferredLaunchViewSize; ApplicationView::PreferredLaunchWindowingMode = fullscreen ? ApplicationViewWindowingMode::FullScreen : ApplicationViewWindowingMode::PreferredLaunchViewSize;
} }
/* Setting the window size may sometimes fail "because UWP" /* Setting the window size may sometimes fail "because UWP"
* (i.e. we are on device with no windows, or Windows sandbox decides the window can't be that small) * (i.e. we are on device with no windows, or Windows sandbox decides the window can't be that small)
* so in case resizing fails we just send a resized event back to RetroArch with old size * so in case resizing fails we just send a resized event back to RetroArch with old size
* (and report success because otherwise it bails out hard about failing to set video mode) * (and report success because otherwise it bails out hard about failing
*/ * to set video mode) */
App::GetInstance()->SetWindowResized(); App::GetInstance()->SetWindowResized();
return true; return true;
} }
@ -820,21 +840,21 @@ extern "C" {
return true; return true;
case DISPLAY_METRIC_MM_WIDTH: case DISPLAY_METRIC_MM_WIDTH:
/* 25.4 mm in an inch. */ /* 25.4 mm in an inch. */
{ {
int pixels_x = DisplayInformation::GetForCurrentView()->ScreenWidthInRawPixels; int pixels_x = DisplayInformation::GetForCurrentView()->ScreenWidthInRawPixels;
int raw_dpi_x = DisplayInformation::GetForCurrentView()->RawDpiX; int raw_dpi_x = DisplayInformation::GetForCurrentView()->RawDpiX;
int physical_width = pixels_x / raw_dpi_x; int physical_width = pixels_x / raw_dpi_x;
*value = 254 * physical_width / 10; *value = 254 * physical_width / 10;
} }
return true; return true;
case DISPLAY_METRIC_MM_HEIGHT: case DISPLAY_METRIC_MM_HEIGHT:
/* 25.4 mm in an inch. */ /* 25.4 mm in an inch. */
{ {
int pixels_y = DisplayInformation::GetForCurrentView()->ScreenHeightInRawPixels; int pixels_y = DisplayInformation::GetForCurrentView()->ScreenHeightInRawPixels;
int raw_dpi_y = DisplayInformation::GetForCurrentView()->RawDpiY; int raw_dpi_y = DisplayInformation::GetForCurrentView()->RawDpiY;
int physical_height = pixels_y / raw_dpi_y; int physical_height = pixels_y / raw_dpi_y;
*value = 254 * physical_height / 10; *value = 254 * physical_height / 10;
} }
return true; return true;
case DISPLAY_METRIC_DPI: case DISPLAY_METRIC_DPI:
*value = DisplayInformation::GetForCurrentView()->RawDpiX; *value = DisplayInformation::GetForCurrentView()->RawDpiX;
@ -850,13 +870,13 @@ extern "C" {
void win32_check_window(void *data, void win32_check_window(void *data,
bool *quit, bool *resize, unsigned *width, unsigned *height) bool *quit, bool *resize, unsigned *width, unsigned *height)
{ {
static bool is_xbox = is_running_on_xbox(); static bool is_xbox = is_running_on_xbox();
*quit = App::GetInstance()->IsWindowClosed(); *quit = App::GetInstance()->IsWindowClosed();
if (is_xbox) if (is_xbox)
{ {
settings_t* settings = config_get_ptr(); settings_t* settings = config_get_ptr();
*width = settings->uints.video_fullscreen_x != 0 ? settings->uints.video_fullscreen_x : uwp_get_width(); *width = settings->uints.video_fullscreen_x != 0 ? settings->uints.video_fullscreen_x : uwp_get_width();
*height = settings->uints.video_fullscreen_y != 0 ? settings->uints.video_fullscreen_y : uwp_get_height(); *height = settings->uints.video_fullscreen_y != 0 ? settings->uints.video_fullscreen_y : uwp_get_height();
return; return;
} }
@ -876,45 +896,49 @@ extern "C" {
int uwp_get_height(void) int uwp_get_height(void)
{ {
//This function must be performed within UI thread otherwise it will cause crash in specific cases /* This function must be performed within UI thread,
//https://github.com/libretro/RetroArch/issues/13491 * otherwise it will cause a crash in specific cases
float surface_scale = 0; * https://github.com/libretro/RetroArch/issues/13491 */
int returnValue = -1; float surface_scale = 0;
int ret = -1;
volatile bool finished = false; volatile bool finished = false;
Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync( Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
CoreDispatcherPriority::Normal, CoreDispatcherPriority::Normal,
ref new Windows::UI::Core::DispatchedHandler([&surface_scale, &returnValue, &finished]() ref new Windows::UI::Core::DispatchedHandler([&surface_scale, &ret, &finished]()
{ {
if (is_running_on_xbox()) if (is_running_on_xbox())
{ {
const Windows::Graphics::Display::Core::HdmiDisplayInformation^ hdi = Windows::Graphics::Display::Core::HdmiDisplayInformation::GetForCurrentView(); const Windows::Graphics::Display::Core::HdmiDisplayInformation^ hdi = Windows::Graphics::Display::Core::HdmiDisplayInformation::GetForCurrentView();
if (hdi) if (hdi)
returnValue = Windows::Graphics::Display::Core::HdmiDisplayInformation::GetForCurrentView()->GetCurrentDisplayMode()->ResolutionHeightInRawPixels; ret = Windows::Graphics::Display::Core::HdmiDisplayInformation::GetForCurrentView()->GetCurrentDisplayMode()->ResolutionHeightInRawPixels;
} }
if (returnValue == -1) { if (ret == -1)
const LONG32 resolution_scale = static_cast<LONG32>(Windows::Graphics::Display::DisplayInformation::GetForCurrentView()->ResolutionScale); {
surface_scale = static_cast<float>(resolution_scale) / 100.0f; const LONG32 resolution_scale = static_cast<LONG32>(Windows::Graphics::Display::DisplayInformation::GetForCurrentView()->ResolutionScale);
returnValue = static_cast<LONG32>(CoreWindow::GetForCurrentThread()->Bounds.Height * surface_scale); surface_scale = static_cast<float>(resolution_scale) / 100.0f;
} ret = static_cast<LONG32>(
CoreWindow::GetForCurrentThread()->Bounds.Height
* surface_scale);
}
finished = true; finished = true;
})); }));
Windows::UI::Core::CoreWindow^ corewindow = Windows::UI::Core::CoreWindow::GetForCurrentThread(); Windows::UI::Core::CoreWindow^ corewindow = Windows::UI::Core::CoreWindow::GetForCurrentThread();
while (!finished) while (!finished)
{ {
if (corewindow) { if (corewindow)
corewindow->Dispatcher->ProcessEvents(Windows::UI::Core::CoreProcessEventsOption::ProcessAllIfPresent); corewindow->Dispatcher->ProcessEvents(Windows::UI::Core::CoreProcessEventsOption::ProcessAllIfPresent);
}
} }
return returnValue; return ret;
} }
int uwp_get_width(void) int uwp_get_width(void)
{ {
//This function must be performed within UI thread otherwise it will cause crash in specific cases /* This function must be performed within UI thread,
//https://github.com/libretro/RetroArch/issues/13491 * otherwise it will cause a crash in specific cases
float surface_scale = 0; * https://github.com/libretro/RetroArch/issues/13491 */
int returnValue = -1; float surface_scale = 0;
int returnValue = -1;
volatile bool finished = false; volatile bool finished = false;
Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync( Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
CoreDispatcherPriority::Normal, CoreDispatcherPriority::Normal,
@ -927,19 +951,21 @@ extern "C" {
returnValue = Windows::Graphics::Display::Core::HdmiDisplayInformation::GetForCurrentView()->GetCurrentDisplayMode()->ResolutionWidthInRawPixels; returnValue = Windows::Graphics::Display::Core::HdmiDisplayInformation::GetForCurrentView()->GetCurrentDisplayMode()->ResolutionWidthInRawPixels;
} }
if(returnValue == -1) { if(returnValue == -1)
const LONG32 resolution_scale = static_cast<LONG32>(Windows::Graphics::Display::DisplayInformation::GetForCurrentView()->ResolutionScale); {
surface_scale = static_cast<float>(resolution_scale) / 100.0f; const LONG32 resolution_scale = static_cast<LONG32>(Windows::Graphics::Display::DisplayInformation::GetForCurrentView()->ResolutionScale);
returnValue = static_cast<LONG32>(CoreWindow::GetForCurrentThread()->Bounds.Width * surface_scale); surface_scale = static_cast<float>(resolution_scale) / 100.0f;
} returnValue = static_cast<LONG32>(
CoreWindow::GetForCurrentThread()->Bounds.Width
* surface_scale);
}
finished = true; finished = true;
})); }));
Windows::UI::Core::CoreWindow^ corewindow = Windows::UI::Core::CoreWindow::GetForCurrentThread(); Windows::UI::Core::CoreWindow^ corewindow = Windows::UI::Core::CoreWindow::GetForCurrentThread();
while (!finished) while (!finished)
{ {
if (corewindow) { if (corewindow)
corewindow->Dispatcher->ProcessEvents(Windows::UI::Core::CoreProcessEventsOption::ProcessAllIfPresent); corewindow->Dispatcher->ProcessEvents(Windows::UI::Core::CoreProcessEventsOption::ProcessAllIfPresent);
}
} }
return returnValue; return returnValue;
@ -977,9 +1003,9 @@ extern "C" {
/* At times CoreWindow will return NULL while running Dolphin core /* At times CoreWindow will return NULL while running Dolphin core
* Dolphin core runs on its own CPU thread separate from the UI-thread and so we must do a check for this. */ * Dolphin core runs on its own CPU thread separate from the UI-thread and so we must do a check for this. */
if (!window) if (window)
return false; return (window->GetKeyState(sym) & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down;
return (window->GetKeyState(sym) & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down; return false;
} }
int16_t uwp_mouse_state(unsigned port, unsigned id, bool screen) int16_t uwp_mouse_state(unsigned port, unsigned id, bool screen)
@ -1074,10 +1100,12 @@ extern "C" {
const char* uwp_get_cpu_model_name(void) const char* uwp_get_cpu_model_name(void)
{ {
if (!is_running_on_xbox()) /* TODO/FIXME - Xbox codepath should have a hardcoded CPU model name */
if (is_running_on_xbox()) { }
else
{ {
Platform::String^ cpu_id = nullptr; Platform::String^ cpu_id = nullptr;
Platform::String^ cpu_name = nullptr; Platform::String^ cpu_name = nullptr;
/* GUID_DEVICE_PROCESSOR: {97FADB10-4E33-40AE-359C-8BEF029DBDD0} */ /* GUID_DEVICE_PROCESSOR: {97FADB10-4E33-40AE-359C-8BEF029DBDD0} */
Platform::String^ if_filter = L"System.Devices.InterfaceClassGuid:=\"{97FADB10-4E33-40AE-359C-8BEF029DBDD0}\""; Platform::String^ if_filter = L"System.Devices.InterfaceClassGuid:=\"{97FADB10-4E33-40AE-359C-8BEF029DBDD0}\"";
@ -1109,14 +1137,12 @@ extern "C" {
}, nullptr); }, nullptr);
} }
if (cpu_name)
if (!cpu_name) {
return "Unknown"; wcstombs(win32_cpu_model_name, cpu_name->Data(), sizeof(win32_cpu_model_name));
return win32_cpu_model_name;
wcstombs(win32_cpu_model_name, cpu_name->Data(), sizeof(win32_cpu_model_name)); }
return win32_cpu_model_name;
} }
else return "Unknown";
return "Unknown";
} }
} }