BaseApp.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. /**********************************************************************************************
  2. *
  3. * raylib.BaseApp - UWP App generic code for managing interface between C and C++
  4. *
  5. * LICENSE: zlib/libpng
  6. *
  7. * CONFIGURATION:
  8. *
  9. * #define PCH
  10. * This defines what header is the PCH and needs to be included
  11. *
  12. * #define HOLDHACK
  13. * This enables a hack to fix flickering key presses (Temporary)
  14. *
  15. * Copyright (c) 2013-2020 Ramon Santamaria (@raysan5)
  16. *
  17. * This software is provided "as-is", without any express or implied warranty. In no event
  18. * will the authors be held liable for any damages arising from the use of this software.
  19. *
  20. * Permission is granted to anyone to use this software for any purpose, including commercial
  21. * applications, and to alter it and redistribute it freely, subject to the following restrictions:
  22. *
  23. * 1. The origin of this software must not be misrepresented; you must not claim that you
  24. * wrote the original software. If you use this software in a product, an acknowledgment
  25. * in the product documentation would be appreciated but is not required.
  26. *
  27. * 2. Altered source versions must be plainly marked as such, and must not be misrepresented
  28. * as being the original software.
  29. *
  30. * 3. This notice may not be removed or altered from any source distribution.
  31. *
  32. **********************************************************************************************/
  33. #pragma once
  34. #if defined(PCH)
  35. #include PCH
  36. #endif
  37. #include <chrono>
  38. #include <memory>
  39. #include <wrl.h>
  40. //EGL
  41. #include <EGL/eglplatform.h>
  42. #include "raylib.h"
  43. #include "utils.h"
  44. using namespace Windows::ApplicationModel::Core;
  45. using namespace Windows::ApplicationModel::Activation;
  46. using namespace Windows::UI::Core;
  47. using namespace Windows::UI::Input;
  48. using namespace Windows::Devices::Input;
  49. using namespace Windows::Foundation;
  50. using namespace Windows::Foundation::Collections;
  51. using namespace Windows::Gaming::Input;
  52. using namespace Windows::Graphics::Display;
  53. using namespace Microsoft::WRL;
  54. using namespace Platform;
  55. extern "C" { EGLNativeWindowType handle; };
  56. /*
  57. TODO list:
  58. - Cache reference to our CoreWindow?
  59. - Implement gestures support
  60. */
  61. // Stand-ins for "core.c" variables
  62. #define MAX_GAMEPADS 4 // Max number of gamepads supported
  63. #define MAX_GAMEPAD_BUTTONS 32 // Max bumber of buttons supported (per gamepad)
  64. #define MAX_GAMEPAD_AXIS 8 // Max number of axis supported (per gamepad)
  65. //Mouse cursor locking
  66. bool cursorLocked = false;
  67. Vector2 mouseDelta = {0, 0};
  68. //Our mouse cursor
  69. CoreCursor ^regularCursor = ref new CoreCursor(CoreCursorType::Arrow, 0); // The "visible arrow" cursor type
  70. //Base app implementation
  71. ref class BaseApp : public Windows::ApplicationModel::Core::IFrameworkView
  72. {
  73. public:
  74. // IFrameworkView Methods.
  75. virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView)
  76. {
  77. // Register event handlers for app lifecycle. This example includes Activated, so that we
  78. // can make the CoreWindow active and start rendering on the window.
  79. applicationView->Activated += ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &BaseApp::OnActivated);
  80. // Logic for other event handlers could go here.
  81. // Information about the Suspending and Resuming event handlers can be found here:
  82. // http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh994930.aspx
  83. CoreApplication::Resuming += ref new EventHandler<Platform::Object^>(this, &BaseApp::OnResuming);
  84. }
  85. virtual void SetWindow(Windows::UI::Core::CoreWindow^ window)
  86. {
  87. window->SizeChanged += ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &BaseApp::OnWindowSizeChanged);
  88. window->VisibilityChanged += ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &BaseApp::OnVisibilityChanged);
  89. window->Closed += ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &BaseApp::OnWindowClosed);
  90. window->PointerPressed += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &BaseApp::PointerPressed);
  91. window->PointerWheelChanged += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &BaseApp::PointerWheelChanged);
  92. window->KeyDown += ref new TypedEventHandler<CoreWindow ^, KeyEventArgs ^>(this, &BaseApp::OnKeyDown);
  93. window->KeyUp += ref new TypedEventHandler<CoreWindow ^, KeyEventArgs ^>(this, &BaseApp::OnKeyUp);
  94. Windows::Devices::Input::MouseDevice::GetForCurrentView()->MouseMoved += ref new TypedEventHandler<MouseDevice^, MouseEventArgs^>(this, &BaseApp::MouseMoved);
  95. DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView();
  96. currentDisplayInformation->DpiChanged += ref new TypedEventHandler<DisplayInformation^, Object^>(this, &BaseApp::OnDpiChanged);
  97. currentDisplayInformation->OrientationChanged += ref new TypedEventHandler<DisplayInformation^, Object^>(this, &BaseApp::OnOrientationChanged);
  98. // The CoreWindow has been created, so EGL can be initialized.
  99. handle = (EGLNativeWindowType)window;
  100. InitWindow(width, height, NULL);
  101. }
  102. virtual void Load(Platform::String^ entryPoint) {}
  103. void Setup(int width, int height)
  104. {
  105. // Set dimensions
  106. this->width = width;
  107. this->height = height;
  108. }
  109. virtual void Run()
  110. {
  111. // Get display dimensions
  112. DisplayInformation^ dInfo = DisplayInformation::GetForCurrentView();
  113. Vector2 screenSize = { dInfo->ScreenWidthInRawPixels, dInfo->ScreenHeightInRawPixels };
  114. // Send display dimensions
  115. UWPMessage *msg = CreateUWPMessage();
  116. msg->type = UWP_MSG_SET_DISPLAY_DIMS;
  117. msg->paramVector0 = screenSize;
  118. UWPSendMessage(msg);
  119. // Send the time to the core
  120. using clock = std::chrono::high_resolution_clock;
  121. auto timeStart = clock::now();
  122. // Set fps if 0
  123. if (GetFPS() <= 0) SetTargetFPS(60);
  124. while (!mWindowClosed)
  125. {
  126. if (mWindowVisible)
  127. {
  128. // Send time
  129. auto delta = clock::now() - timeStart;
  130. UWPMessage *timeMsg = CreateUWPMessage();
  131. timeMsg->type = UWP_MSG_SET_GAME_TIME;
  132. timeMsg->paramDouble0 = std::chrono::duration_cast<std::chrono::seconds>(delta).count();
  133. UWPSendMessage(timeMsg);
  134. // Call update function
  135. Update();
  136. PollInput();
  137. CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
  138. }
  139. else
  140. {
  141. CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
  142. }
  143. }
  144. CloseWindow();
  145. }
  146. //Called every frame (Maybe add draw)
  147. virtual void Update() {}
  148. virtual void Uninitialize() {}
  149. protected:
  150. // Input polling
  151. void PollInput()
  152. {
  153. // Process Messages
  154. {
  155. // Loop over pending messages
  156. while (UWPHasMessages())
  157. {
  158. // Get the message
  159. auto msg = UWPGetMessage();
  160. // Carry out the command
  161. switch(msg->type)
  162. {
  163. case UWP_MSG_SHOW_MOUSE: // Do the same thing because of how UWP works...
  164. case UWP_MSG_UNLOCK_MOUSE:
  165. {
  166. CoreWindow::GetForCurrentThread()->PointerCursor = regularCursor;
  167. cursorLocked = false;
  168. MoveMouse(GetMousePosition());
  169. break;
  170. }
  171. case UWP_MSG_HIDE_MOUSE: // Do the same thing because of how UWP works...
  172. case UWP_MSG_LOCK_MOUSE:
  173. {
  174. CoreWindow::GetForCurrentThread()->PointerCursor = nullptr;
  175. cursorLocked = true;
  176. break;
  177. }
  178. case UWP_MSG_SET_MOUSE_LOCATION:
  179. {
  180. MoveMouse(msg->paramVector0);
  181. break;
  182. }
  183. }
  184. // Delete the message
  185. DeleteUWPMessage(msg);
  186. }
  187. }
  188. // Process Keyboard
  189. {
  190. for (int k = 0x08; k < 0xA6; k++) {
  191. auto state = CoreWindow::GetForCurrentThread()->GetKeyState((Windows::System::VirtualKey) k);
  192. #ifdef HOLDHACK
  193. // Super hacky way of waiting three frames to see if we are ready to register the key as deregistered
  194. // This will wait an entire 4 frames before deregistering the key, this makes sure that the key is not flickering
  195. if (KeyboardStateHack[k] == 2)
  196. {
  197. if ((state & CoreVirtualKeyStates::None) == CoreVirtualKeyStates::None)
  198. {
  199. KeyboardStateHack[k] = 3;
  200. }
  201. }
  202. else if (KeyboardStateHack[k] == 3)
  203. {
  204. if ((state & CoreVirtualKeyStates::None) == CoreVirtualKeyStates::None)
  205. {
  206. KeyboardStateHack[k] = 4;
  207. }
  208. }
  209. else if (KeyboardStateHack[k] == 4)
  210. {
  211. if ((state & CoreVirtualKeyStates::None) == CoreVirtualKeyStates::None)
  212. {
  213. //Reset key...
  214. KeyboardStateHack[k] = 0;
  215. //Tell core
  216. RegisterKey(k, 0);
  217. }
  218. }
  219. #endif
  220. // Left and right alt, KeyUp and KeyDown are not called for it
  221. // No need to hack because this is not a character
  222. // TODO: Maybe do all other key registrations like this, no more key events?
  223. if (k == 0xA4 || k == 0xA5)
  224. {
  225. if ((state & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down)
  226. {
  227. RegisterKey(k, 1);
  228. }
  229. else
  230. {
  231. RegisterKey(k, 0);
  232. }
  233. }
  234. }
  235. }
  236. // Process Mouse
  237. {
  238. if (CurrentPointerID > -1)
  239. {
  240. auto point = PointerPoint::GetCurrentPoint(CurrentPointerID);
  241. auto props = point->Properties;
  242. if (props->IsLeftButtonPressed)
  243. {
  244. RegisterClick(MOUSE_LEFT_BUTTON, 1);
  245. }
  246. else
  247. {
  248. RegisterClick(MOUSE_LEFT_BUTTON, 0);
  249. }
  250. if (props->IsRightButtonPressed)
  251. {
  252. RegisterClick(MOUSE_RIGHT_BUTTON, 1);
  253. }
  254. else
  255. {
  256. RegisterClick(MOUSE_RIGHT_BUTTON, 0);
  257. }
  258. if (props->IsMiddleButtonPressed)
  259. {
  260. RegisterClick(MOUSE_MIDDLE_BUTTON, 1);
  261. }
  262. else
  263. {
  264. RegisterClick(MOUSE_MIDDLE_BUTTON, 0);
  265. }
  266. }
  267. CoreWindow ^window = CoreWindow::GetForCurrentThread();
  268. if (cursorLocked)
  269. {
  270. // Track cursor movement delta, recenter it on the client
  271. auto curMousePos = GetMousePosition();
  272. auto x = curMousePos.x + mouseDelta.x;
  273. auto y = curMousePos.y + mouseDelta.y;
  274. UpdateMousePosition({ x, y });
  275. // Why we're not using UWPSetMousePosition here...
  276. // UWPSetMousePosition changes the "mousePosition" variable to match where the cursor actually is.
  277. // Our cursor is locked to the middle of screen, and we don't want that reflected in "mousePosition"
  278. Vector2 centerClient = { (float)(GetScreenWidth() / 2), (float)(GetScreenHeight() / 2) };
  279. window->PointerPosition = Point(centerClient.x + window->Bounds.X, centerClient.y + window->Bounds.Y);
  280. }
  281. else
  282. {
  283. // Record the cursor's position relative to the client
  284. auto x = window->PointerPosition.X - window->Bounds.X;
  285. auto y = window->PointerPosition.Y - window->Bounds.Y;
  286. UpdateMousePosition({ x, y });
  287. }
  288. mouseDelta = { 0 ,0 };
  289. }
  290. // Process Gamepads
  291. {
  292. // Check if gamepads are ready
  293. for (int i = 0; i < MAX_GAMEPADS; i++)
  294. {
  295. // HACK: UWP keeps a contiguous list of gamepads. For the interest of time I'm just doing a 1:1 mapping of
  296. // connected gamepads with their spot in the list, but this has serious robustness problems
  297. // e.g. player 1, 2, and 3 are playing a game - if player2 disconnects, p3's controller would now be mapped to p2's character since p3 is now second in the list.
  298. UWPMessage* msg = CreateUWPMessage();
  299. msg->type = UWP_MSG_SET_GAMEPAD_ACTIVE;
  300. msg->paramInt0 = i;
  301. msg->paramBool0 = i < Gamepad::Gamepads->Size;
  302. UWPSendMessage(msg);
  303. }
  304. // Get current gamepad state
  305. for (int i = 0; i < MAX_GAMEPADS; i++)
  306. {
  307. if (IsGamepadAvailable(i))
  308. {
  309. // Get current gamepad state
  310. auto gamepad = Gamepad::Gamepads->GetAt(i);
  311. GamepadReading reading = gamepad->GetCurrentReading();
  312. // NOTE: Maybe it would be wiser to redefine the gamepad button mappings in "raylib.h" for the UWP platform instead of remapping them manually
  313. RegisterGamepadButton(i, GAMEPAD_BUTTON_RIGHT_FACE_DOWN, ((reading.Buttons & GamepadButtons::A) == GamepadButtons::A));
  314. RegisterGamepadButton(i, GAMEPAD_BUTTON_RIGHT_FACE_RIGHT, ((reading.Buttons & GamepadButtons::B) == GamepadButtons::B));
  315. RegisterGamepadButton(i, GAMEPAD_BUTTON_RIGHT_FACE_LEFT, ((reading.Buttons & GamepadButtons::X) == GamepadButtons::X));
  316. RegisterGamepadButton(i, GAMEPAD_BUTTON_RIGHT_FACE_UP, ((reading.Buttons & GamepadButtons::Y) == GamepadButtons::Y));
  317. RegisterGamepadButton(i, GAMEPAD_BUTTON_LEFT_TRIGGER_1, ((reading.Buttons & GamepadButtons::LeftShoulder) == GamepadButtons::LeftShoulder));
  318. RegisterGamepadButton(i, GAMEPAD_BUTTON_RIGHT_TRIGGER_1, ((reading.Buttons & GamepadButtons::RightShoulder) == GamepadButtons::RightShoulder));
  319. RegisterGamepadButton(i, GAMEPAD_BUTTON_MIDDLE_LEFT, ((reading.Buttons & GamepadButtons::View) == GamepadButtons::View)); // Changed for XB1 Controller
  320. RegisterGamepadButton(i, GAMEPAD_BUTTON_MIDDLE_RIGHT, ((reading.Buttons & GamepadButtons::Menu) == GamepadButtons::Menu)); // Changed for XB1 Controller
  321. RegisterGamepadButton(i, GAMEPAD_BUTTON_LEFT_FACE_UP, ((reading.Buttons & GamepadButtons::DPadUp) == GamepadButtons::DPadUp));
  322. RegisterGamepadButton(i, GAMEPAD_BUTTON_LEFT_FACE_RIGHT, ((reading.Buttons & GamepadButtons::DPadRight) == GamepadButtons::DPadRight));
  323. RegisterGamepadButton(i, GAMEPAD_BUTTON_LEFT_FACE_DOWN, ((reading.Buttons & GamepadButtons::DPadDown) == GamepadButtons::DPadDown));
  324. RegisterGamepadButton(i, GAMEPAD_BUTTON_LEFT_FACE_LEFT, ((reading.Buttons & GamepadButtons::DPadLeft) == GamepadButtons::DPadLeft));
  325. RegisterGamepadButton(i, GAMEPAD_BUTTON_MIDDLE, false); // Home button not supported by UWP
  326. // Get current axis state
  327. RegisterGamepadAxis(i, GAMEPAD_AXIS_LEFT_X, (float)reading.LeftThumbstickX);
  328. RegisterGamepadAxis(i, GAMEPAD_AXIS_LEFT_Y, (float)reading.LeftThumbstickY);
  329. RegisterGamepadAxis(i, GAMEPAD_AXIS_RIGHT_X, (float)reading.RightThumbstickX);
  330. RegisterGamepadAxis(i, GAMEPAD_AXIS_RIGHT_Y, (float)reading.RightThumbstickY);
  331. RegisterGamepadAxis(i, GAMEPAD_AXIS_LEFT_TRIGGER, (float)reading.LeftTrigger);
  332. RegisterGamepadAxis(i, GAMEPAD_AXIS_RIGHT_TRIGGER, (float)reading.RightTrigger);
  333. }
  334. }
  335. }
  336. }
  337. // Application lifecycle event handlers.
  338. void OnActivated(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args)
  339. {
  340. // Run() won't start until the CoreWindow is activated.
  341. CoreWindow::GetForCurrentThread()->Activate();
  342. }
  343. void OnResuming(Platform::Object^ sender, Platform::Object^ args) {}
  344. // Window event handlers.
  345. void OnWindowSizeChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ args)
  346. {
  347. UWPMessage* msg = CreateUWPMessage();
  348. msg->type = UWP_MSG_HANDLE_RESIZE;
  349. UWPSendMessage(msg);
  350. }
  351. void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args)
  352. {
  353. mWindowVisible = args->Visible;
  354. }
  355. void OnWindowClosed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CoreWindowEventArgs^ args)
  356. {
  357. mWindowClosed = true;
  358. }
  359. // DisplayInformation event handlers.
  360. void OnDpiChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args) {}
  361. void OnOrientationChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args) {}
  362. // Input event handlers
  363. void PointerPressed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args)
  364. {
  365. //Get the current active pointer ID for our loop
  366. CurrentPointerID = args->CurrentPoint->PointerId;
  367. args->Handled = true;
  368. }
  369. void PointerWheelChanged(Windows::UI::Core::CoreWindow ^sender, Windows::UI::Core::PointerEventArgs^ args)
  370. {
  371. UWPMessage* msg = CreateUWPMessage();
  372. msg->type = UWP_MSG_SCROLL_WHEEL_UPDATE;
  373. msg->paramFloat0 = args->CurrentPoint->Properties->MouseWheelDelta;
  374. UWPSendMessage(msg);
  375. }
  376. void MouseMoved(Windows::Devices::Input::MouseDevice^ mouseDevice, Windows::Devices::Input::MouseEventArgs^ args)
  377. {
  378. mouseDelta.x += args->MouseDelta.X;
  379. mouseDelta.y += args->MouseDelta.Y;
  380. }
  381. void OnKeyDown(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::KeyEventArgs ^ args)
  382. {
  383. #ifdef HOLDHACK
  384. // Start the hack
  385. KeyboardStateHack[(int)args->VirtualKey] = 1;
  386. #endif
  387. RegisterKey((int)args->VirtualKey, 1);
  388. }
  389. void OnKeyUp(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::KeyEventArgs ^ args)
  390. {
  391. #ifdef HOLDHACK
  392. // The same hack
  393. if (KeyboardStateHack[(int)args->VirtualKey] == 1)
  394. {
  395. KeyboardStateHack[(int)args->VirtualKey] = 2;
  396. }
  397. else if (KeyboardStateHack[(int)args->VirtualKey] == 2)
  398. {
  399. KeyboardStateHack[(int)args->VirtualKey] = 3;
  400. }
  401. else if (KeyboardStateHack[(int)args->VirtualKey] == 3)
  402. {
  403. KeyboardStateHack[(int)args->VirtualKey] = 4;
  404. }
  405. else if (KeyboardStateHack[(int)args->VirtualKey] == 4)
  406. {
  407. RegisterKey((int)args->VirtualKey, 0);
  408. KeyboardStateHack[(int)args->VirtualKey] = 0;
  409. }
  410. #else
  411. // No hack, allow flickers
  412. RegisterKey((int)args->VirtualKey, 0);
  413. #endif
  414. }
  415. private:
  416. void RegisterKey(int key, char status)
  417. {
  418. UWPMessage* msg = CreateUWPMessage();
  419. msg->type = UWPMessageType::UWP_MSG_REGISTER_KEY;
  420. msg->paramInt0 = key;
  421. msg->paramChar0 = status;
  422. UWPSendMessage(msg);
  423. }
  424. void MoveMouse(Vector2 pos)
  425. {
  426. CoreWindow ^window = CoreWindow::GetForCurrentThread();
  427. Point mousePosScreen = Point(pos.x + window->Bounds.X, pos.y + window->Bounds.Y);
  428. window->PointerPosition = mousePosScreen;
  429. }
  430. void RegisterGamepadButton(int gamepad, int button, char status)
  431. {
  432. UWPMessage* msg = CreateUWPMessage();
  433. msg->type = UWP_MSG_SET_GAMEPAD_BUTTON;
  434. msg->paramInt0 = gamepad;
  435. msg->paramInt1 = button;
  436. msg->paramChar0 = status;
  437. UWPSendMessage(msg);
  438. }
  439. void RegisterGamepadAxis(int gamepad, int axis, float value)
  440. {
  441. UWPMessage* msg = CreateUWPMessage();
  442. msg->type = UWP_MSG_SET_GAMEPAD_AXIS;
  443. msg->paramInt0 = gamepad;
  444. msg->paramInt1 = axis;
  445. msg->paramFloat0 = value;
  446. UWPSendMessage(msg);
  447. }
  448. void UpdateMousePosition(Vector2 pos)
  449. {
  450. UWPMessage* msg = CreateUWPMessage();
  451. msg->type = UWP_MSG_UPDATE_MOUSE_LOCATION;
  452. msg->paramVector0 = pos;
  453. UWPSendMessage(msg);
  454. }
  455. void RegisterClick(int button, char status)
  456. {
  457. UWPMessage* msg = CreateUWPMessage();
  458. msg->type = UWPMessageType::UWP_MSG_REGISTER_CLICK;
  459. msg->paramInt0 = button;
  460. msg->paramChar0 = status;
  461. UWPSendMessage(msg);
  462. }
  463. bool mWindowClosed = false;
  464. bool mWindowVisible = true;
  465. int width = 640;
  466. int height = 480;
  467. int CurrentPointerID = -1;
  468. #ifdef HOLDHACK
  469. char KeyboardStateHack[0xA6]; // 0xA6 because the highest key we compare against is 0xA5
  470. #endif
  471. };
  472. // Application source for creating the program
  473. template<typename AppType>
  474. ref class ApplicationSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource
  475. {
  476. public:
  477. virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView()
  478. {
  479. return ref new AppType();
  480. }
  481. };