WinRTUtil.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. #include "pch.h"
  2. #include <wrl.h>
  3. #include <string>
  4. #include <map>
  5. #include <list>
  6. #include <DXGI.h>
  7. #include <ppltasks.h>
  8. #include "../SDLPal.Common/AsyncHelper.h"
  9. #include "../SDLPal.Common/StringHelper.h"
  10. #include "input.h"
  11. #include "main.h"
  12. #include "SDL.h"
  13. #include "SDL_endian.h"
  14. static std::string g_configpath;
  15. extern HANDLE g_eventHandle;
  16. extern "C" std::map<std::string, Windows::Storage::StorageFile^>* get_special_files_map();
  17. extern "C" std::map<std::string, Windows::Storage::StorageFolder^>* get_special_folders_map();
  18. extern "C"
  19. LPCSTR UTIL_ConfigPath(VOID)
  20. {
  21. if (g_configpath.empty())
  22. {
  23. auto localfolder = Windows::Storage::ApplicationData::Current->LocalFolder->Path;
  24. if (localfolder->End()[-1] != L'\\') localfolder += "\\";
  25. ConvertString(localfolder, g_configpath);
  26. }
  27. return g_configpath.c_str();
  28. }
  29. extern "C"
  30. LPCSTR UTIL_ScreenShotPath(VOID)
  31. {
  32. return gConfig.pszGamePath;
  33. }
  34. extern "C"
  35. BOOL UTIL_GetScreenSize(DWORD *pdwScreenWidth, DWORD *pdwScreenHeight)
  36. {
  37. DXGI_OUTPUT_DESC desc;
  38. IDXGIFactory1* pFactory = nullptr;
  39. IDXGIAdapter1* pAdapter = nullptr;
  40. IDXGIOutput* pOutput = nullptr;
  41. DWORD retval = FALSE;
  42. #if NTDDI_VERSION >= NTDDI_WIN10
  43. if (Windows::System::Profile::AnalyticsInfo::VersionInfo->DeviceFamily != L"Windows.Mobile") return FALSE;
  44. #endif
  45. if (!pdwScreenWidth || !pdwScreenHeight) return FALSE;
  46. if (FAILED(CreateDXGIFactory1(IID_IDXGIFactory1, (void**)&pFactory))) goto UTIL_WP_GetScreenSize_exit;
  47. if (FAILED(pFactory->EnumAdapters1(0, &pAdapter))) goto UTIL_WP_GetScreenSize_exit;
  48. if (FAILED(pAdapter->EnumOutputs(0, &pOutput))) goto UTIL_WP_GetScreenSize_exit;
  49. if (SUCCEEDED(pOutput->GetDesc(&desc)))
  50. {
  51. #if (NTDDI_VERSION < NTDDI_WIN10) && (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
  52. *pdwScreenWidth = (desc.DesktopCoordinates.right - desc.DesktopCoordinates.left);
  53. *pdwScreenHeight = (desc.DesktopCoordinates.bottom - desc.DesktopCoordinates.top);
  54. #else
  55. *pdwScreenWidth = (desc.DesktopCoordinates.bottom - desc.DesktopCoordinates.top);
  56. *pdwScreenHeight = (desc.DesktopCoordinates.right - desc.DesktopCoordinates.left);
  57. #endif
  58. retval = TRUE;
  59. }
  60. UTIL_WP_GetScreenSize_exit:
  61. if (pOutput) pOutput->Release();
  62. if (pAdapter) pAdapter->Release();
  63. if (pFactory) pFactory->Release();
  64. return retval;
  65. }
  66. extern "C"
  67. BOOL UTIL_IsAbsolutePath(LPCSTR lpszFileName)
  68. {
  69. char szDrive[_MAX_DRIVE], szDir[_MAX_DIR], szFname[_MAX_FNAME], szExt[_MAX_EXT];
  70. if (_splitpath_s(lpszFileName, szDrive, szDir, szFname, szExt) == 0)
  71. return (strlen(szDrive) > 0 && (szDir[0] == '\\' || szDir[0] == '/'));
  72. else
  73. return FALSE;
  74. }
  75. extern "C"
  76. BOOL UTIL_TouchEnabled(VOID)
  77. {
  78. return (ref new Windows::Devices::Input::TouchCapabilities())->TouchPresent;
  79. }
  80. static Windows::Storage::StorageFile^ g_running_file = nullptr;
  81. static void CreateRunningFile()
  82. {
  83. // Create the 'running' file for crash detection.
  84. try { g_running_file = AWait(Windows::Storage::ApplicationData::Current->LocalFolder->CreateFileAsync("running", Windows::Storage::CreationCollisionOption::OpenIfExists), g_eventHandle); }
  85. catch (Platform::Exception^) {}
  86. }
  87. static void DeleteRunningFile()
  88. {
  89. // Delete the 'running' file on normal exit.
  90. try { if (g_running_file) AWait(g_running_file->DeleteAsync()); g_running_file = nullptr; }
  91. catch (Platform::Exception^) {}
  92. }
  93. static int SDLCALL WinRT_EventFilter(void *userdata, SDL_Event * event)
  94. {
  95. switch (event->type)
  96. {
  97. case SDL_APP_DIDENTERFOREGROUND:
  98. CreateRunningFile();
  99. break;
  100. case SDL_APP_DIDENTERBACKGROUND:
  101. case SDL_APP_TERMINATING:
  102. // Enter background or exiting, treat as normal exit
  103. DeleteRunningFile();
  104. break;
  105. }
  106. return 0;
  107. }
  108. static int input_event_filter(const SDL_Event *lpEvent, volatile PALINPUTSTATE *state)
  109. {
  110. if (lpEvent->type == SDL_KEYDOWN &&
  111. lpEvent->key.keysym.sym == SDLK_AC_BACK)
  112. {
  113. if (gpGlobals->fInMainGame)
  114. {
  115. state->dwKeyPress |= kKeyFlee;
  116. }
  117. else
  118. {
  119. PAL_Shutdown(0);
  120. }
  121. }
  122. return 0;
  123. }
  124. extern "C"
  125. INT UTIL_Platform_Init(int argc, char* argv[])
  126. {
  127. // Defaults log to debug output
  128. UTIL_LogAddOutputCallback([](LOGLEVEL, const char* str, const char*)->void {
  129. #if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
  130. OutputDebugStringA(str);
  131. #endif
  132. }, PAL_DEFAULT_LOGLEVEL);
  133. CreateRunningFile();
  134. SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeRight");
  135. SDL_SetHint(SDL_HINT_WINRT_HANDLE_BACK_BUTTON, "1");
  136. SDL_AddEventWatch(WinRT_EventFilter, nullptr);
  137. std::list<Platform::String^> invalid_tokens;
  138. auto& files = *get_special_files_map();
  139. auto& folders = *get_special_folders_map();
  140. auto fal = Windows::Storage::AccessCache::StorageApplicationPermissions::FutureAccessList;
  141. for each (auto entry in fal->Entries)
  142. {
  143. try
  144. {
  145. auto item = AWait(fal->GetItemAsync(entry.Token), g_eventHandle);
  146. if (dynamic_cast<Windows::Storage::StorageFolder^>(item) != nullptr)
  147. {
  148. auto localfolder = entry.Metadata;
  149. if (localfolder->End()[-1] != L'\\') localfolder += "\\";
  150. auto folder = ConvertString(localfolder);
  151. folders[folder] = dynamic_cast<Windows::Storage::StorageFolder^>(item);
  152. PAL_SetConfigItem(PAL_ConfigIndex(ConvertString(entry.Token).c_str()), ConfigValue{ folder.c_str() });
  153. continue;
  154. }
  155. if (dynamic_cast<Windows::Storage::StorageFile^>(item) != nullptr)
  156. {
  157. auto file = ConvertString(entry.Metadata);
  158. files[file] = dynamic_cast<Windows::Storage::StorageFile^>(item);
  159. PAL_SetConfigItem(PAL_ConfigIndex(ConvertString(entry.Token).c_str()), ConfigValue{ file.c_str() });
  160. continue;
  161. }
  162. }
  163. catch (Exception^ e)
  164. {
  165. invalid_tokens.push_back(entry.Token);
  166. }
  167. }
  168. for (auto i = invalid_tokens.begin(); i != invalid_tokens.end(); fal->Remove(*i++));
  169. PAL_RegisterInputFilter(nullptr, input_event_filter, nullptr);
  170. return 0;
  171. }
  172. extern "C"
  173. VOID UTIL_Platform_Quit(VOID)
  174. {
  175. DeleteRunningFile();
  176. }