1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
8
9 #include "WinEventsWin10.h"
10
11 #include "AppInboundProtocol.h"
12 #include "Application.h"
13 #include "GUIUserMessages.h"
14 #include "ServiceBroker.h"
15 #include "guilib/GUIComponent.h"
16 #include "guilib/GUIWindowManager.h"
17 #include "input/actions/Action.h"
18 #include "input/actions/ActionIDs.h"
19 #include "input/mouse/MouseStat.h"
20 #include "input/touch/generic/GenericTouchInputHandler.h"
21 #include "interfaces/AnnouncementManager.h"
22 #include "messaging/ApplicationMessenger.h"
23 #include "rendering/dx/DeviceResources.h"
24 #include "rendering/dx/RenderContext.h"
25 #include "settings/AdvancedSettings.h"
26 #include "settings/SettingsComponent.h"
27 #include "utils/SystemInfo.h"
28 #include "utils/Variant.h"
29 #include "utils/log.h"
30 #include "windowing/windows/WinKeyMap.h"
31
32 #include "platform/win10/input/RemoteControlXbox.h"
33
34 #include <winrt/Windows.Devices.Input.h>
35
36 namespace winrt
37 {
38 using namespace Windows::Foundation;
39 }
40 using namespace winrt::Windows::ApplicationModel::Core;
41 using namespace winrt::Windows::Devices::Input;
42 using namespace winrt::Windows::Graphics::Display;
43 using namespace winrt::Windows::Media;
44 using namespace winrt::Windows::System;
45 using namespace winrt::Windows::UI::Core;
46 using namespace winrt::Windows::UI::Input;
47 using namespace winrt::Windows::UI::ViewManagement;
48
49 using namespace PERIPHERALS;
50 using namespace KODI::MESSAGING;
51
GetScreenPoint(winrt::Point point)52 static winrt::Point GetScreenPoint(winrt::Point point)
53 {
54 auto dpi = DX::DeviceResources::Get()->GetDpi();
55 return winrt::Point(DX::ConvertDipsToPixels(point.X, dpi), DX::ConvertDipsToPixels(point.Y, dpi));
56 }
57
58 CWinEventsWin10::CWinEventsWin10() = default;
59 CWinEventsWin10::~CWinEventsWin10() = default;
60
InitOSKeymap(void)61 void CWinEventsWin10::InitOSKeymap(void)
62 {
63 KODI::WINDOWING::WINDOWS::DIB_InitOSKeymap();
64 }
65
MessagePush(XBMC_Event * newEvent)66 void CWinEventsWin10::MessagePush(XBMC_Event *newEvent)
67 {
68 // push input events in the queue they may init modal dialog which init
69 // deeper message loop and call the deeper MessagePump from there.
70 if ( newEvent->type == XBMC_KEYDOWN
71 || newEvent->type == XBMC_KEYUP
72 || newEvent->type == XBMC_MOUSEMOTION
73 || newEvent->type == XBMC_MOUSEBUTTONDOWN
74 || newEvent->type == XBMC_MOUSEBUTTONUP
75 || newEvent->type == XBMC_TOUCH)
76 {
77 m_events.push(*newEvent);
78 }
79 else
80 {
81 std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort();
82 if (appPort)
83 appPort->OnEvent(*newEvent);
84 }
85 }
86
MessagePump()87 bool CWinEventsWin10::MessagePump()
88 {
89 bool ret = false;
90 std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort();
91
92 // processes all pending events and exits immediately
93 CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
94
95 XBMC_Event pumpEvent;
96 while (m_events.try_pop(pumpEvent))
97 {
98 if (appPort)
99 ret |= appPort->OnEvent(pumpEvent);
100
101 if (pumpEvent.type == XBMC_MOUSEBUTTONUP)
102 CServiceBroker::GetGUI()->GetWindowManager().SendMessage(GUI_MSG_UNFOCUS_ALL, 0, 0, 0, 0);
103 }
104 return ret;
105 }
106
GetQueueSize()107 size_t CWinEventsWin10::GetQueueSize()
108 {
109 return m_events.unsafe_size();
110 }
111
InitEventHandlers(const CoreWindow & window)112 void CWinEventsWin10::InitEventHandlers(const CoreWindow& window)
113 {
114 CWinEventsWin10::InitOSKeymap();
115
116 //window->SetPointerCapture();
117
118 // window
119 window.SizeChanged({ this, &CWinEventsWin10::OnWindowSizeChanged });
120 window.ResizeStarted({ this, &CWinEventsWin10::OnWindowResizeStarted });
121 window.ResizeCompleted({ this, &CWinEventsWin10::OnWindowResizeCompleted });
122 window.Closed({ this, &CWinEventsWin10::OnWindowClosed});
123 window.VisibilityChanged(CWinEventsWin10::OnVisibilityChanged);
124 window.Activated(CWinEventsWin10::OnWindowActivationChanged);
125 // mouse, touch and pen
126 window.PointerPressed({ this, &CWinEventsWin10::OnPointerPressed });
127 window.PointerMoved({ this, &CWinEventsWin10::OnPointerMoved });
128 window.PointerReleased({ this, &CWinEventsWin10::OnPointerReleased });
129 window.PointerExited({ this, &CWinEventsWin10::OnPointerExited });
130 window.PointerWheelChanged({ this, &CWinEventsWin10::OnPointerWheelChanged });
131 // keyboard
132 window.Dispatcher().AcceleratorKeyActivated({ this, &CWinEventsWin10::OnAcceleratorKeyActivated });
133 // display
134 DisplayInformation currentDisplayInformation = DisplayInformation::GetForCurrentView();
135 currentDisplayInformation.DpiChanged(CWinEventsWin10::OnDpiChanged);
136 currentDisplayInformation.OrientationChanged(CWinEventsWin10::OnOrientationChanged);
137 DisplayInformation::DisplayContentsInvalidated(CWinEventsWin10::OnDisplayContentsInvalidated);
138 // system
139 SystemNavigationManager sysNavManager = SystemNavigationManager::GetForCurrentView();
140 sysNavManager.BackRequested(CWinEventsWin10::OnBackRequested);
141
142 // requirement for backgroup playback
143 m_smtc = SystemMediaTransportControls::GetForCurrentView();
144 if (m_smtc)
145 {
146 m_smtc.IsPlayEnabled(true);
147 m_smtc.IsPauseEnabled(true);
148 m_smtc.IsStopEnabled(true);
149 m_smtc.IsRecordEnabled(true);
150 m_smtc.IsNextEnabled(true);
151 m_smtc.IsPreviousEnabled(true);
152 m_smtc.IsFastForwardEnabled(true);
153 m_smtc.IsRewindEnabled(true);
154 m_smtc.IsChannelUpEnabled(true);
155 m_smtc.IsChannelDownEnabled(true);
156 if (CSysInfo::GetWindowsDeviceFamily() != CSysInfo::WindowsDeviceFamily::Xbox)
157 {
158 m_smtc.ButtonPressed(CWinEventsWin10::OnSystemMediaButtonPressed);
159 }
160 m_smtc.IsEnabled(true);;
161 CServiceBroker::GetAnnouncementManager()->AddAnnouncer(this);
162 }
163 if (CSysInfo::GetWindowsDeviceFamily() == CSysInfo::WindowsDeviceFamily::Xbox)
164 {
165 m_remote = std::make_unique<CRemoteControlXbox>();
166 m_remote->Initialize();
167 }
168 }
169
UpdateWindowSize()170 void CWinEventsWin10::UpdateWindowSize()
171 {
172 auto size = DX::DeviceResources::Get()->GetOutputSize();
173
174 CLog::Log(LOGDEBUG, __FUNCTION__": window resize event %f x %f (as:%s)", size.Width, size.Height, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_fullScreen ? "true" : "false");
175
176 auto appView = ApplicationView::GetForCurrentView();
177 appView.SetDesiredBoundsMode(ApplicationViewBoundsMode::UseCoreWindow);
178
179 // seems app has lost FS mode it may occurs if an user use core window's button
180 if (CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_fullScreen && !appView.IsFullScreenMode())
181 CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_fullScreen = false;
182
183 XBMC_Event newEvent;
184 memset(&newEvent, 0, sizeof(newEvent));
185 newEvent.type = XBMC_VIDEORESIZE;
186 newEvent.resize.w = size.Width;
187 newEvent.resize.h = size.Height;
188 if (g_application.GetRenderGUI() && !DX::Windowing()->IsAlteringWindow() && newEvent.resize.w > 0 && newEvent.resize.h > 0)
189 MessagePush(&newEvent);
190 }
191
OnResize(float width,float height)192 void CWinEventsWin10::OnResize(float width, float height)
193 {
194 CLog::Log(LOGDEBUG, __FUNCTION__": window size changed.");
195 m_logicalWidth = width;
196 m_logicalHeight = height;
197 m_bResized = true;
198
199 if (m_sizeChanging)
200 return;
201
202 HandleWindowSizeChanged();
203 }
204
205 // Window event handlers.
OnWindowSizeChanged(const CoreWindow &,const WindowSizeChangedEventArgs & args)206 void CWinEventsWin10::OnWindowSizeChanged(const CoreWindow&, const WindowSizeChangedEventArgs& args)
207 {
208 OnResize(args.Size().Width, args.Size().Height);
209 }
210
OnWindowResizeStarted(const CoreWindow & sender,const winrt::IInspectable &)211 void CWinEventsWin10::OnWindowResizeStarted(const CoreWindow& sender, const winrt::IInspectable&)
212 {
213 CLog::Log(LOGDEBUG, __FUNCTION__": window resize started.");
214 m_logicalPosX = sender.Bounds().X;
215 m_logicalPosY = sender.Bounds().Y;
216 m_sizeChanging = true;
217 }
218
OnWindowResizeCompleted(const CoreWindow & sender,const winrt::IInspectable &)219 void CWinEventsWin10::OnWindowResizeCompleted(const CoreWindow& sender, const winrt::IInspectable&)
220 {
221 CLog::Log(LOGDEBUG, __FUNCTION__": window resize completed.");
222 m_sizeChanging = false;
223
224 if (m_logicalPosX != sender.Bounds().X || m_logicalPosY != sender.Bounds().Y)
225 m_bMoved = true;
226
227 HandleWindowSizeChanged();
228 }
229
HandleWindowSizeChanged()230 void CWinEventsWin10::HandleWindowSizeChanged()
231 {
232 CLog::Log(LOGDEBUG, __FUNCTION__": window size/move handled.");
233 if (m_bMoved)
234 {
235 // it will get position from CoreWindow
236 DX::Windowing()->OnMove(0, 0);
237 }
238 if (m_bResized)
239 {
240 DX::Windowing()->OnResize(m_logicalWidth, m_logicalHeight);
241 UpdateWindowSize();
242 }
243 m_bResized = false;
244 m_bMoved = false;
245 }
246
OnVisibilityChanged(const CoreWindow & sender,const VisibilityChangedEventArgs & args)247 void CWinEventsWin10::OnVisibilityChanged(const CoreWindow& sender, const VisibilityChangedEventArgs& args)
248 {
249 bool active = g_application.GetRenderGUI();
250 std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort();
251 if (appPort)
252 appPort->SetRenderGUI(args.Visible());
253
254 if (g_application.GetRenderGUI() != active)
255 DX::Windowing()->NotifyAppActiveChange(g_application.GetRenderGUI());
256 CLog::Log(LOGDEBUG, __FUNCTION__": window is %s", g_application.GetRenderGUI() ? "shown" : "hidden");
257 }
258
OnWindowActivationChanged(const CoreWindow & sender,const WindowActivatedEventArgs & args)259 void CWinEventsWin10::OnWindowActivationChanged(const CoreWindow& sender, const WindowActivatedEventArgs& args)
260 {
261 bool active = g_application.GetRenderGUI();
262 if (args.WindowActivationState() == CoreWindowActivationState::Deactivated)
263 {
264 std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort();
265 if (appPort)
266 appPort->SetRenderGUI(DX::Windowing()->WindowedMode());
267 }
268 else if (args.WindowActivationState() == CoreWindowActivationState::PointerActivated
269 || args.WindowActivationState() == CoreWindowActivationState::CodeActivated)
270 {
271 std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort();
272 if (appPort)
273 appPort->SetRenderGUI(true);
274 }
275 if (g_application.GetRenderGUI() != active)
276 DX::Windowing()->NotifyAppActiveChange(g_application.GetRenderGUI());
277 CLog::Log(LOGDEBUG, __FUNCTION__": window is %s", g_application.GetRenderGUI() ? "active" : "inactive");
278 }
279
OnWindowClosed(const CoreWindow & sender,const CoreWindowEventArgs & args)280 void CWinEventsWin10::OnWindowClosed(const CoreWindow& sender, const CoreWindowEventArgs& args)
281 {
282 // send quit command to the application if it's still running
283 if (!g_application.m_bStop)
284 {
285 XBMC_Event newEvent;
286 memset(&newEvent, 0, sizeof(newEvent));
287 newEvent.type = XBMC_QUIT;
288 MessagePush(&newEvent);
289 }
290 }
291
OnPointerPressed(const CoreWindow &,const PointerEventArgs & args)292 void CWinEventsWin10::OnPointerPressed(const CoreWindow&, const PointerEventArgs& args)
293 {
294 XBMC_Event newEvent;
295 memset(&newEvent, 0, sizeof(newEvent));
296
297 PointerPoint point = args.CurrentPoint();
298 auto position = GetScreenPoint(point.Position());
299
300 if (point.PointerDevice().PointerDeviceType() == PointerDeviceType::Touch)
301 {
302 CGenericTouchInputHandler::GetInstance().HandleTouchInput(TouchInputDown, position.X, position.Y, point.Timestamp(), 0, 10);
303 return;
304 }
305 else
306 {
307 newEvent.type = XBMC_MOUSEBUTTONDOWN;
308 newEvent.button.x = position.X;
309 newEvent.button.y = position.Y;
310 if (point.PointerDevice().PointerDeviceType() == PointerDeviceType::Mouse)
311 {
312 if (point.Properties().IsLeftButtonPressed())
313 newEvent.button.button = XBMC_BUTTON_LEFT;
314 else if (point.Properties().IsMiddleButtonPressed())
315 newEvent.button.button = XBMC_BUTTON_MIDDLE;
316 else if (point.Properties().IsRightButtonPressed())
317 newEvent.button.button = XBMC_BUTTON_RIGHT;
318 }
319 else if (point.PointerDevice().PointerDeviceType() == PointerDeviceType::Pen)
320 {
321 // pen
322 // TODO
323 }
324 }
325 MessagePush(&newEvent);
326 }
327
OnPointerMoved(const CoreWindow &,const PointerEventArgs & args)328 void CWinEventsWin10::OnPointerMoved(const CoreWindow&, const PointerEventArgs& args)
329 {
330 PointerPoint point = args.CurrentPoint();
331 auto position = GetScreenPoint(point.Position());
332
333 if (point.PointerDevice().PointerDeviceType() == PointerDeviceType::Touch)
334 {
335 if (point.IsInContact())
336 {
337 CGenericTouchInputHandler::GetInstance().UpdateTouchPointer(0, position.X, position.Y, point.Timestamp(), 10.f);
338 CGenericTouchInputHandler::GetInstance().HandleTouchInput(TouchInputMove, position.X, position.Y, point.Timestamp(), 0, 10.f);
339 }
340 return;
341 }
342
343 XBMC_Event newEvent;
344 memset(&newEvent, 0, sizeof(newEvent));
345 newEvent.type = XBMC_MOUSEMOTION;
346 newEvent.motion.x = position.X;
347 newEvent.motion.y = position.Y;
348 MessagePush(&newEvent);
349 }
350
OnPointerReleased(const CoreWindow &,const PointerEventArgs & args)351 void CWinEventsWin10::OnPointerReleased(const CoreWindow&, const PointerEventArgs& args)
352 {
353 PointerPoint point = args.CurrentPoint();
354 auto position = GetScreenPoint(point.Position());
355
356 if (point.PointerDevice().PointerDeviceType() == PointerDeviceType::Touch)
357 {
358 CGenericTouchInputHandler::GetInstance().HandleTouchInput(TouchInputUp, position.X, position.Y, point.Timestamp(), 0, 10);
359 return;
360 }
361
362 XBMC_Event newEvent;
363 memset(&newEvent, 0, sizeof(newEvent));
364 newEvent.type = XBMC_MOUSEBUTTONUP;
365 newEvent.button.x = position.X;
366 newEvent.button.y = position.Y;
367
368 if (point.Properties().PointerUpdateKind() == PointerUpdateKind::LeftButtonReleased)
369 newEvent.button.button = XBMC_BUTTON_LEFT;
370 else if (point.Properties().PointerUpdateKind() == PointerUpdateKind::MiddleButtonReleased)
371 newEvent.button.button = XBMC_BUTTON_MIDDLE;
372 else if (point.Properties().PointerUpdateKind() == PointerUpdateKind::RightButtonReleased)
373 newEvent.button.button = XBMC_BUTTON_RIGHT;
374
375 MessagePush(&newEvent);
376 }
377
OnPointerExited(const CoreWindow &,const PointerEventArgs & args)378 void CWinEventsWin10::OnPointerExited(const CoreWindow&, const PointerEventArgs& args)
379 {
380 const PointerPoint& point = args.CurrentPoint();
381 auto position = GetScreenPoint(point.Position());
382
383 if (point.PointerDevice().PointerDeviceType() == PointerDeviceType::Touch)
384 {
385 CGenericTouchInputHandler::GetInstance().HandleTouchInput(TouchInputAbort, position.X, position.Y, point.Timestamp(), 0, 10);
386 }
387 }
388
OnPointerWheelChanged(const CoreWindow &,const PointerEventArgs & args)389 void CWinEventsWin10::OnPointerWheelChanged(const CoreWindow&, const PointerEventArgs& args)
390 {
391 XBMC_Event newEvent;
392 memset(&newEvent, 0, sizeof(newEvent));
393 newEvent.type = XBMC_MOUSEBUTTONDOWN;
394 newEvent.button.x = args.CurrentPoint().Position().X;
395 newEvent.button.y = args.CurrentPoint().Position().Y;
396 newEvent.button.button = args.CurrentPoint().Properties().MouseWheelDelta() > 0 ? XBMC_BUTTON_WHEELUP : XBMC_BUTTON_WHEELDOWN;
397 MessagePush(&newEvent);
398 newEvent.type = XBMC_MOUSEBUTTONUP;
399 MessagePush(&newEvent);
400 }
401
Kodi_KeyEvent(unsigned int vkey,unsigned scancode,unsigned keycode,bool isDown)402 void CWinEventsWin10::Kodi_KeyEvent(unsigned int vkey, unsigned scancode, unsigned keycode, bool isDown)
403 {
404 using State = CoreVirtualKeyStates;
405
406 XBMC_keysym keysym;
407 memset(&keysym, 0, sizeof(keysym));
408 keysym.scancode = scancode;
409 keysym.sym = KODI::WINDOWING::WINDOWS::VK_keymap[vkey];
410 keysym.unicode = keycode;
411
412 auto window = CoreWindow::GetForCurrentThread();
413
414 uint16_t mod = (uint16_t)XBMCKMOD_NONE;
415 // If left control and right alt are down this usually means that AltGr is down
416 if ((window.GetKeyState(VirtualKey::LeftControl) & State::Down) == State::Down
417 && (window.GetKeyState(VirtualKey::RightMenu) & State::Down) == State::Down)
418 {
419 mod |= XBMCKMOD_MODE;
420 mod |= XBMCKMOD_MODE;
421 }
422 else
423 {
424 if ((window.GetKeyState(VirtualKey::LeftControl) & State::Down) == State::Down)
425 mod |= XBMCKMOD_LCTRL;
426 if ((window.GetKeyState(VirtualKey::RightMenu) & State::Down) == State::Down)
427 mod |= XBMCKMOD_RALT;
428 }
429
430 // Check the remaining modifiers
431 if ((window.GetKeyState(VirtualKey::LeftShift) & State::Down) == State::Down)
432 mod |= XBMCKMOD_LSHIFT;
433 if ((window.GetKeyState(VirtualKey::RightShift) & State::Down) == State::Down)
434 mod |= XBMCKMOD_RSHIFT;
435 if ((window.GetKeyState(VirtualKey::RightControl) & State::Down) == State::Down)
436 mod |= XBMCKMOD_RCTRL;
437 if ((window.GetKeyState(VirtualKey::LeftMenu) & State::Down) == State::Down)
438 mod |= XBMCKMOD_LALT;
439 if ((window.GetKeyState(VirtualKey::LeftWindows) & State::Down) == State::Down)
440 mod |= XBMCKMOD_LSUPER;
441 if ((window.GetKeyState(VirtualKey::RightWindows) & State::Down) == State::Down)
442 mod |= XBMCKMOD_LSUPER;
443
444 keysym.mod = static_cast<XBMCMod>(mod);
445
446 XBMC_Event newEvent;
447 memset(&newEvent, 0, sizeof(newEvent));
448 newEvent.type = isDown ? XBMC_KEYDOWN : XBMC_KEYUP;
449 newEvent.key.keysym = keysym;
450 MessagePush(&newEvent);
451 }
452
OnAcceleratorKeyActivated(const CoreDispatcher &,const AcceleratorKeyEventArgs & args)453 void CWinEventsWin10::OnAcceleratorKeyActivated(const CoreDispatcher&, const AcceleratorKeyEventArgs& args)
454 {
455 static auto lockedState = CoreVirtualKeyStates::Locked;
456 static VirtualKey keyStore = VirtualKey::None;
457
458 // skip if device is remote control
459 if (m_remote && m_remote->IsRemoteDevice(args.DeviceId().c_str()))
460 return;
461
462 bool isDown = false;
463 unsigned keyCode = 0;
464 unsigned vk = static_cast<unsigned>(args.VirtualKey());
465
466 auto window = CoreWindow::GetForCurrentThread();
467 bool numLockLocked = ((window.GetKeyState(VirtualKey::NumberKeyLock) & lockedState) == lockedState);
468
469 switch (args.EventType())
470 {
471 case CoreAcceleratorKeyEventType::KeyDown:
472 case CoreAcceleratorKeyEventType::SystemKeyDown:
473 {
474 if ( (vk == 0x08) // VK_BACK
475 || (vk == 0x09) // VK_TAB
476 || (vk == 0x0C) // VK_CLEAR
477 || (vk == 0x0D) // VK_RETURN
478 || (vk == 0x1B) // VK_ESCAPE
479 || (vk == 0x20) // VK_SPACE
480 || (vk >= 0x30 && vk <= 0x39) // numeric keys
481 || (vk >= 0x41 && vk <= 0x5A) // alphabetic keys
482 || (vk >= 0x60 && vk <= 0x69 && numLockLocked) // keypad numeric (if numlock is on)
483 || (vk >= 0x6A && vk <= 0x6F) // keypad keys except numeric
484 || (vk >= 0x92 && vk <= 0x96) // OEM specific
485 || (vk >= 0xBA && vk <= 0xC0) // OEM specific
486 || (vk >= 0xDB && vk <= 0xDF) // OEM specific
487 || (vk >= 0xE1 && vk <= 0xF5 && vk != 0xE5 && vk != 0xE7 && vk != 0xE8) // OEM specific
488 )
489 {
490 // store this for character events, because VirtualKey is key code on character event.
491 keyStore = args.VirtualKey();
492 return;
493 }
494 isDown = true;
495 break;
496 }
497 case CoreAcceleratorKeyEventType::KeyUp:
498 case CoreAcceleratorKeyEventType::SystemKeyUp:
499 break;
500 case CoreAcceleratorKeyEventType::Character:
501 case CoreAcceleratorKeyEventType::SystemCharacter:
502 case CoreAcceleratorKeyEventType::UnicodeCharacter:
503 case CoreAcceleratorKeyEventType::DeadCharacter:
504 case CoreAcceleratorKeyEventType::SystemDeadCharacter:
505 {
506 // VirtualKey is KeyCode
507 keyCode = static_cast<unsigned>(args.VirtualKey());
508 // rewrite vk with stored value
509 vk = static_cast<unsigned>(keyStore);
510 // reset stored value
511 keyStore = VirtualKey::None;
512 isDown = true;
513 }
514 default:
515 break;
516 }
517
518 Kodi_KeyEvent(vk, args.KeyStatus().ScanCode, keyCode, isDown);
519 args.Handled(true);
520 }
521
522 // DisplayInformation event handlers.
OnDpiChanged(const DisplayInformation & sender,const winrt::IInspectable &)523 void CWinEventsWin10::OnDpiChanged(const DisplayInformation& sender, const winrt::IInspectable&)
524 {
525 // Note: The value for LogicalDpi retrieved here may not match the effective DPI of the app
526 // if it is being scaled for high resolution devices. Once the DPI is set on DeviceResources,
527 // you should always retrieve it using the GetDpi method.
528 // See DeviceResources.cpp for more details.
529 //critical_section::scoped_lock lock(m_deviceResources->GetCriticalSection());
530 RECT resizeRect = { 0,0,0,0 };
531 DX::Windowing()->DPIChanged(sender.LogicalDpi(), resizeRect);
532 CGenericTouchInputHandler::GetInstance().SetScreenDPI(DX::DisplayMetrics::Dpi100);
533 }
534
OnOrientationChanged(const DisplayInformation &,const winrt::IInspectable &)535 void CWinEventsWin10::OnOrientationChanged(const DisplayInformation&, const winrt::IInspectable&)
536 {
537 //critical_section::scoped_lock lock(m_deviceResources->GetCriticalSection());
538 //m_deviceResources->SetCurrentOrientation(sender->CurrentOrientation);
539
540 //auto size = DX::DeviceResources::Get()->GetOutputSize();
541 //UpdateWindowSize(size.Width, size.Height);
542 }
543
OnDisplayContentsInvalidated(const DisplayInformation &,const winrt::IInspectable &)544 void CWinEventsWin10::OnDisplayContentsInvalidated(const DisplayInformation&, const winrt::IInspectable&)
545 {
546 CLog::Log(LOGDEBUG, __FUNCTION__": onevent.");
547 DX::DeviceResources::Get()->ValidateDevice();
548 }
549
OnBackRequested(const winrt::IInspectable &,const BackRequestedEventArgs & args)550 void CWinEventsWin10::OnBackRequested(const winrt::IInspectable&, const BackRequestedEventArgs& args)
551 {
552 // handle this only on windows mobile
553 if (CSysInfo::GetWindowsDeviceFamily() == CSysInfo::WindowsDeviceFamily::Mobile)
554 {
555 CApplicationMessenger::GetInstance().PostMsg(TMSG_GUI_ACTION, WINDOW_INVALID, -1, static_cast<void*>(new CAction(ACTION_NAV_BACK)));
556 }
557 args.Handled(true);
558 }
559
OnSystemMediaButtonPressed(const SystemMediaTransportControls &,const SystemMediaTransportControlsButtonPressedEventArgs & args)560 void CWinEventsWin10::OnSystemMediaButtonPressed(const SystemMediaTransportControls&, const SystemMediaTransportControlsButtonPressedEventArgs& args)
561 {
562 int action = ACTION_NONE;
563 switch (args.Button())
564 {
565 case SystemMediaTransportControlsButton::ChannelDown:
566 action = ACTION_CHANNEL_DOWN;
567 break;
568 case SystemMediaTransportControlsButton::ChannelUp:
569 action = ACTION_CHANNEL_UP;
570 break;
571 case SystemMediaTransportControlsButton::FastForward:
572 action = ACTION_PLAYER_FORWARD;
573 break;
574 case SystemMediaTransportControlsButton::Rewind:
575 action = ACTION_PLAYER_REWIND;
576 break;
577 case SystemMediaTransportControlsButton::Next:
578 action = ACTION_NEXT_ITEM;
579 break;
580 case SystemMediaTransportControlsButton::Previous:
581 action = ACTION_PREV_ITEM;
582 break;
583 case SystemMediaTransportControlsButton::Pause:
584 case SystemMediaTransportControlsButton::Play:
585 action = ACTION_PLAYER_PLAYPAUSE;
586 break;
587 case SystemMediaTransportControlsButton::Stop:
588 action = ACTION_STOP;
589 break;
590 case SystemMediaTransportControlsButton::Record:
591 action = ACTION_RECORD;
592 break;
593 default:
594 break;
595 }
596 if (action != ACTION_NONE)
597 {
598 CApplicationMessenger::GetInstance().PostMsg(TMSG_GUI_ACTION, WINDOW_INVALID, -1, static_cast<void*>(new CAction(action)));
599 }
600 }
601
Announce(ANNOUNCEMENT::AnnouncementFlag flag,const std::string & sender,const std::string & message,const CVariant & data)602 void CWinEventsWin10::Announce(ANNOUNCEMENT::AnnouncementFlag flag,
603 const std::string& sender,
604 const std::string& message,
605 const CVariant& data)
606 {
607 if (flag & ANNOUNCEMENT::Player)
608 {
609 double speed = 1.0;
610 if (data.isMember("player") && data["player"].isMember("speed"))
611 speed = data["player"]["speed"].asDouble(1.0);
612
613 bool changed = false;
614 MediaPlaybackStatus status = MediaPlaybackStatus::Changing;
615
616 if (message == "OnPlay" || message == "OnResume")
617 {
618 changed = true;
619 status = MediaPlaybackStatus::Playing;
620 }
621 else if (message == "OnStop")
622 {
623 changed = true;
624 status = MediaPlaybackStatus::Stopped;
625 }
626 else if (message == "OnPause")
627 {
628 changed = true;
629 status = MediaPlaybackStatus::Paused;
630 }
631 else if (message == "OnSpeedChanged")
632 {
633 changed = true;
634 status = speed != 0.0 ? MediaPlaybackStatus::Playing : MediaPlaybackStatus::Paused;
635 }
636
637 if (changed)
638 {
639 try
640 {
641 auto dispatcher = CoreApplication::MainView().Dispatcher();
642 if (dispatcher)
643 {
644 dispatcher.RunAsync(CoreDispatcherPriority::Normal, DispatchedHandler([status, speed]
645 {
646 auto smtc = SystemMediaTransportControls::GetForCurrentView();
647 if (!smtc)
648 return;
649
650 smtc.PlaybackStatus(status);
651 smtc.PlaybackRate(speed);
652 }));
653 }
654 }
655 catch (const winrt::hresult_error&)
656 {
657 }
658 }
659 }
660 }
661