2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "WinEventsWin10.h"
11 #include "GUIUserMessages.h"
12 #include "ServiceBroker.h"
13 #include "application/AppInboundProtocol.h"
14 #include "application/Application.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"
32 #include "platform/win10/input/RemoteControlXbox.h"
34 #include <winrt/Windows.Devices.Input.h>
38 using namespace Windows::Foundation
;
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
;
49 using namespace PERIPHERALS
;
51 static winrt::Point
GetScreenPoint(winrt::Point point
)
53 auto dpi
= DX::DeviceResources::Get()->GetDpi();
54 return winrt::Point(DX::ConvertDipsToPixels(point
.X
, dpi
), DX::ConvertDipsToPixels(point
.Y
, dpi
));
57 CWinEventsWin10::CWinEventsWin10() = default;
58 CWinEventsWin10::~CWinEventsWin10() = default;
60 void CWinEventsWin10::InitOSKeymap(void)
62 KODI::WINDOWING::WINDOWS::DIB_InitOSKeymap();
65 void CWinEventsWin10::MessagePush(XBMC_Event
*newEvent
)
67 // push input events in the queue they may init modal dialog which init
68 // deeper message loop and call the deeper MessagePump from there.
69 if ( newEvent
->type
== XBMC_KEYDOWN
70 || newEvent
->type
== XBMC_KEYUP
71 || newEvent
->type
== XBMC_MOUSEMOTION
72 || newEvent
->type
== XBMC_MOUSEBUTTONDOWN
73 || newEvent
->type
== XBMC_MOUSEBUTTONUP
74 || newEvent
->type
== XBMC_TOUCH
)
76 m_events
.push(*newEvent
);
80 std::shared_ptr
<CAppInboundProtocol
> appPort
= CServiceBroker::GetAppPort();
82 appPort
->OnEvent(*newEvent
);
86 bool CWinEventsWin10::MessagePump()
89 std::shared_ptr
<CAppInboundProtocol
> appPort
= CServiceBroker::GetAppPort();
91 // processes all pending events and exits immediately
92 CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent
);
95 while (m_events
.try_pop(pumpEvent
))
98 ret
|= appPort
->OnEvent(pumpEvent
);
100 if (pumpEvent
.type
== XBMC_MOUSEBUTTONUP
)
101 CServiceBroker::GetGUI()->GetWindowManager().SendMessage(GUI_MSG_UNFOCUS_ALL
, 0, 0, 0, 0);
106 size_t CWinEventsWin10::GetQueueSize()
108 return m_events
.unsafe_size();
111 void CWinEventsWin10::InitEventHandlers(const CoreWindow
& window
)
113 CWinEventsWin10::InitOSKeymap();
115 //window->SetPointerCapture();
118 window
.SizeChanged({ this, &CWinEventsWin10::OnWindowSizeChanged
});
119 window
.ResizeStarted({ this, &CWinEventsWin10::OnWindowResizeStarted
});
120 window
.ResizeCompleted({ this, &CWinEventsWin10::OnWindowResizeCompleted
});
121 window
.Closed({ this, &CWinEventsWin10::OnWindowClosed
});
122 window
.VisibilityChanged(CWinEventsWin10::OnVisibilityChanged
);
123 window
.Activated(CWinEventsWin10::OnWindowActivationChanged
);
124 // mouse, touch and pen
125 window
.PointerPressed({ this, &CWinEventsWin10::OnPointerPressed
});
126 window
.PointerMoved({ this, &CWinEventsWin10::OnPointerMoved
});
127 window
.PointerReleased({ this, &CWinEventsWin10::OnPointerReleased
});
128 window
.PointerExited({ this, &CWinEventsWin10::OnPointerExited
});
129 window
.PointerWheelChanged({ this, &CWinEventsWin10::OnPointerWheelChanged
});
131 window
.Dispatcher().AcceleratorKeyActivated({ this, &CWinEventsWin10::OnAcceleratorKeyActivated
});
133 DisplayInformation currentDisplayInformation
= DisplayInformation::GetForCurrentView();
134 currentDisplayInformation
.DpiChanged(CWinEventsWin10::OnDpiChanged
);
135 currentDisplayInformation
.OrientationChanged(CWinEventsWin10::OnOrientationChanged
);
136 DisplayInformation::DisplayContentsInvalidated(CWinEventsWin10::OnDisplayContentsInvalidated
);
138 SystemNavigationManager sysNavManager
= SystemNavigationManager::GetForCurrentView();
139 sysNavManager
.BackRequested(CWinEventsWin10::OnBackRequested
);
141 // requirement for backgroup playback
142 m_smtc
= SystemMediaTransportControls::GetForCurrentView();
145 m_smtc
.IsPlayEnabled(true);
146 m_smtc
.IsPauseEnabled(true);
147 m_smtc
.IsStopEnabled(true);
148 m_smtc
.IsRecordEnabled(true);
149 m_smtc
.IsNextEnabled(true);
150 m_smtc
.IsPreviousEnabled(true);
151 m_smtc
.IsFastForwardEnabled(true);
152 m_smtc
.IsRewindEnabled(true);
153 m_smtc
.IsChannelUpEnabled(true);
154 m_smtc
.IsChannelDownEnabled(true);
155 if (CSysInfo::GetWindowsDeviceFamily() != CSysInfo::WindowsDeviceFamily::Xbox
)
157 m_smtc
.ButtonPressed(CWinEventsWin10::OnSystemMediaButtonPressed
);
159 m_smtc
.IsEnabled(true);;
160 CServiceBroker::GetAnnouncementManager()->AddAnnouncer(this);
162 if (CSysInfo::GetWindowsDeviceFamily() == CSysInfo::WindowsDeviceFamily::Xbox
)
164 m_remote
= std::make_unique
<CRemoteControlXbox
>();
165 m_remote
->Initialize();
169 void CWinEventsWin10::UpdateWindowSize()
171 auto size
= DX::DeviceResources::Get()->GetOutputSize();
173 CLog::Log(LOGDEBUG
, __FUNCTION__
": window resize event {:f} x {:f} (as:{})", size
.Width
,
175 CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_fullScreen
? "true"
178 auto appView
= ApplicationView::GetForCurrentView();
179 appView
.SetDesiredBoundsMode(ApplicationViewBoundsMode::UseCoreWindow
);
181 // seems app has lost FS mode it may occurs if an user use core window's button
182 if (CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_fullScreen
&& !appView
.IsFullScreenMode())
183 CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_fullScreen
= false;
185 XBMC_Event newEvent
= {};
186 newEvent
.type
= XBMC_VIDEORESIZE
;
187 newEvent
.resize
.w
= size
.Width
;
188 newEvent
.resize
.h
= size
.Height
;
189 if (g_application
.GetRenderGUI() && !DX::Windowing()->IsAlteringWindow() && newEvent
.resize
.w
> 0 && newEvent
.resize
.h
> 0)
190 MessagePush(&newEvent
);
193 void CWinEventsWin10::OnResize(float width
, float height
)
195 CLog::Log(LOGDEBUG
, __FUNCTION__
": window size changed.");
196 m_logicalWidth
= width
;
197 m_logicalHeight
= height
;
203 HandleWindowSizeChanged();
206 // Window event handlers.
207 void CWinEventsWin10::OnWindowSizeChanged(const CoreWindow
&, const WindowSizeChangedEventArgs
& args
)
209 OnResize(args
.Size().Width
, args
.Size().Height
);
212 void CWinEventsWin10::OnWindowResizeStarted(const CoreWindow
& sender
, const winrt::IInspectable
&)
214 CLog::Log(LOGDEBUG
, __FUNCTION__
": window resize started.");
215 m_logicalPosX
= sender
.Bounds().X
;
216 m_logicalPosY
= sender
.Bounds().Y
;
217 m_sizeChanging
= true;
220 void CWinEventsWin10::OnWindowResizeCompleted(const CoreWindow
& sender
, const winrt::IInspectable
&)
222 CLog::Log(LOGDEBUG
, __FUNCTION__
": window resize completed.");
223 m_sizeChanging
= false;
225 if (m_logicalPosX
!= sender
.Bounds().X
|| m_logicalPosY
!= sender
.Bounds().Y
)
228 HandleWindowSizeChanged();
231 void CWinEventsWin10::HandleWindowSizeChanged()
233 CLog::Log(LOGDEBUG
, __FUNCTION__
": window size/move handled.");
236 // it will get position from CoreWindow
237 DX::Windowing()->OnMove(0, 0);
241 DX::Windowing()->OnResize(m_logicalWidth
, m_logicalHeight
);
248 void CWinEventsWin10::OnVisibilityChanged(const CoreWindow
& sender
, const VisibilityChangedEventArgs
& args
)
250 bool active
= g_application
.GetRenderGUI();
251 std::shared_ptr
<CAppInboundProtocol
> appPort
= CServiceBroker::GetAppPort();
253 appPort
->SetRenderGUI(args
.Visible());
255 if (g_application
.GetRenderGUI() != active
)
256 DX::Windowing()->NotifyAppActiveChange(g_application
.GetRenderGUI());
257 CLog::Log(LOGDEBUG
, __FUNCTION__
": window is {}",
258 g_application
.GetRenderGUI() ? "shown" : "hidden");
261 void CWinEventsWin10::OnWindowActivationChanged(const CoreWindow
& sender
, const WindowActivatedEventArgs
& args
)
263 bool active
= g_application
.GetRenderGUI();
264 if (args
.WindowActivationState() == CoreWindowActivationState::Deactivated
)
266 std::shared_ptr
<CAppInboundProtocol
> appPort
= CServiceBroker::GetAppPort();
268 appPort
->SetRenderGUI(DX::Windowing()->WindowedMode());
270 else if (args
.WindowActivationState() == CoreWindowActivationState::PointerActivated
271 || args
.WindowActivationState() == CoreWindowActivationState::CodeActivated
)
273 std::shared_ptr
<CAppInboundProtocol
> appPort
= CServiceBroker::GetAppPort();
275 appPort
->SetRenderGUI(true);
277 if (g_application
.GetRenderGUI() != active
)
278 DX::Windowing()->NotifyAppActiveChange(g_application
.GetRenderGUI());
280 if (CServiceBroker::IsLoggingUp())
281 CLog::Log(LOGDEBUG
, __FUNCTION__
": window is {}",
282 g_application
.GetRenderGUI() ? "active" : "inactive");
285 void CWinEventsWin10::OnWindowClosed(const CoreWindow
& sender
, const CoreWindowEventArgs
& args
)
287 // send quit command to the application if it's still running
288 if (!g_application
.m_bStop
)
290 XBMC_Event newEvent
= {};
291 newEvent
.type
= XBMC_QUIT
;
292 MessagePush(&newEvent
);
296 void CWinEventsWin10::OnPointerPressed(const CoreWindow
&, const PointerEventArgs
& args
)
298 XBMC_Event newEvent
= {};
300 PointerPoint point
= args
.CurrentPoint();
301 auto position
= GetScreenPoint(point
.Position());
303 if (point
.PointerDevice().PointerDeviceType() == PointerDeviceType::Touch
)
305 CGenericTouchInputHandler::GetInstance().HandleTouchInput(TouchInputDown
, position
.X
, position
.Y
, point
.Timestamp(), 0, 10);
310 newEvent
.type
= XBMC_MOUSEBUTTONDOWN
;
311 newEvent
.button
.x
= position
.X
;
312 newEvent
.button
.y
= position
.Y
;
313 if (point
.PointerDevice().PointerDeviceType() == PointerDeviceType::Mouse
)
315 if (point
.Properties().IsLeftButtonPressed())
316 newEvent
.button
.button
= XBMC_BUTTON_LEFT
;
317 else if (point
.Properties().IsMiddleButtonPressed())
318 newEvent
.button
.button
= XBMC_BUTTON_MIDDLE
;
319 else if (point
.Properties().IsRightButtonPressed())
320 newEvent
.button
.button
= XBMC_BUTTON_RIGHT
;
322 else if (point
.PointerDevice().PointerDeviceType() == PointerDeviceType::Pen
)
328 MessagePush(&newEvent
);
331 void CWinEventsWin10::OnPointerMoved(const CoreWindow
&, const PointerEventArgs
& args
)
333 PointerPoint point
= args
.CurrentPoint();
334 auto position
= GetScreenPoint(point
.Position());
336 if (point
.PointerDevice().PointerDeviceType() == PointerDeviceType::Touch
)
338 if (point
.IsInContact())
340 CGenericTouchInputHandler::GetInstance().UpdateTouchPointer(0, position
.X
, position
.Y
, point
.Timestamp(), 10.f
);
341 CGenericTouchInputHandler::GetInstance().HandleTouchInput(TouchInputMove
, position
.X
, position
.Y
, point
.Timestamp(), 0, 10.f
);
346 XBMC_Event newEvent
= {};
347 newEvent
.type
= XBMC_MOUSEMOTION
;
348 newEvent
.motion
.x
= position
.X
;
349 newEvent
.motion
.y
= position
.Y
;
350 MessagePush(&newEvent
);
353 void CWinEventsWin10::OnPointerReleased(const CoreWindow
&, const PointerEventArgs
& args
)
355 PointerPoint point
= args
.CurrentPoint();
356 auto position
= GetScreenPoint(point
.Position());
358 if (point
.PointerDevice().PointerDeviceType() == PointerDeviceType::Touch
)
360 CGenericTouchInputHandler::GetInstance().HandleTouchInput(TouchInputUp
, position
.X
, position
.Y
, point
.Timestamp(), 0, 10);
364 XBMC_Event newEvent
= {};
365 newEvent
.type
= XBMC_MOUSEBUTTONUP
;
366 newEvent
.button
.x
= position
.X
;
367 newEvent
.button
.y
= position
.Y
;
369 if (point
.Properties().PointerUpdateKind() == PointerUpdateKind::LeftButtonReleased
)
370 newEvent
.button
.button
= XBMC_BUTTON_LEFT
;
371 else if (point
.Properties().PointerUpdateKind() == PointerUpdateKind::MiddleButtonReleased
)
372 newEvent
.button
.button
= XBMC_BUTTON_MIDDLE
;
373 else if (point
.Properties().PointerUpdateKind() == PointerUpdateKind::RightButtonReleased
)
374 newEvent
.button
.button
= XBMC_BUTTON_RIGHT
;
376 MessagePush(&newEvent
);
379 void CWinEventsWin10::OnPointerExited(const CoreWindow
&, const PointerEventArgs
& args
)
381 const PointerPoint
& point
= args
.CurrentPoint();
382 auto position
= GetScreenPoint(point
.Position());
384 if (point
.PointerDevice().PointerDeviceType() == PointerDeviceType::Touch
)
386 CGenericTouchInputHandler::GetInstance().HandleTouchInput(TouchInputAbort
, position
.X
, position
.Y
, point
.Timestamp(), 0, 10);
390 void CWinEventsWin10::OnPointerWheelChanged(const CoreWindow
&, const PointerEventArgs
& args
)
392 XBMC_Event 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
);
402 void CWinEventsWin10::Kodi_KeyEvent(unsigned int vkey
, unsigned scancode
, unsigned keycode
, bool isDown
)
404 using State
= CoreVirtualKeyStates
;
406 XBMC_keysym keysym
= {};
407 keysym
.scancode
= scancode
;
408 keysym
.sym
= KODI::WINDOWING::WINDOWS::VK_keymap
[vkey
];
409 keysym
.unicode
= keycode
;
411 auto window
= CoreWindow::GetForCurrentThread();
413 uint16_t mod
= (uint16_t)XBMCKMOD_NONE
;
414 // If left control and right alt are down this usually means that AltGr is down
415 if ((window
.GetKeyState(VirtualKey::LeftControl
) & State::Down
) == State::Down
416 && (window
.GetKeyState(VirtualKey::RightMenu
) & State::Down
) == State::Down
)
418 mod
|= XBMCKMOD_MODE
;
419 mod
|= XBMCKMOD_MODE
;
423 if ((window
.GetKeyState(VirtualKey::LeftControl
) & State::Down
) == State::Down
)
424 mod
|= XBMCKMOD_LCTRL
;
425 if ((window
.GetKeyState(VirtualKey::RightMenu
) & State::Down
) == State::Down
)
426 mod
|= XBMCKMOD_RALT
;
429 // Check the remaining modifiers
430 if ((window
.GetKeyState(VirtualKey::LeftShift
) & State::Down
) == State::Down
)
431 mod
|= XBMCKMOD_LSHIFT
;
432 if ((window
.GetKeyState(VirtualKey::RightShift
) & State::Down
) == State::Down
)
433 mod
|= XBMCKMOD_RSHIFT
;
434 if ((window
.GetKeyState(VirtualKey::RightControl
) & State::Down
) == State::Down
)
435 mod
|= XBMCKMOD_RCTRL
;
436 if ((window
.GetKeyState(VirtualKey::LeftMenu
) & State::Down
) == State::Down
)
437 mod
|= XBMCKMOD_LALT
;
438 if ((window
.GetKeyState(VirtualKey::LeftWindows
) & State::Down
) == State::Down
)
439 mod
|= XBMCKMOD_LSUPER
;
440 if ((window
.GetKeyState(VirtualKey::RightWindows
) & State::Down
) == State::Down
)
441 mod
|= XBMCKMOD_LSUPER
;
443 keysym
.mod
= static_cast<XBMCMod
>(mod
);
445 XBMC_Event newEvent
= {};
446 newEvent
.type
= isDown
? XBMC_KEYDOWN
: XBMC_KEYUP
;
447 newEvent
.key
.keysym
= keysym
;
448 MessagePush(&newEvent
);
451 void CWinEventsWin10::OnAcceleratorKeyActivated(const CoreDispatcher
&, const AcceleratorKeyEventArgs
& args
)
453 static auto lockedState
= CoreVirtualKeyStates::Locked
;
454 static VirtualKey keyStore
= VirtualKey::None
;
456 // skip if device is remote control
457 if (m_remote
&& m_remote
->IsRemoteDevice(args
.DeviceId().c_str()))
461 unsigned keyCode
= 0;
462 unsigned vk
= static_cast<unsigned>(args
.VirtualKey());
464 auto window
= CoreWindow::GetForCurrentThread();
465 bool numLockLocked
= ((window
.GetKeyState(VirtualKey::NumberKeyLock
) & lockedState
) == lockedState
);
467 switch (args
.EventType())
469 case CoreAcceleratorKeyEventType::KeyDown
:
470 case CoreAcceleratorKeyEventType::SystemKeyDown
:
472 if ( (vk
== 0x08) // VK_BACK
473 || (vk
== 0x09) // VK_TAB
474 || (vk
== 0x0C) // VK_CLEAR
475 || (vk
== 0x0D) // VK_RETURN
476 || (vk
== 0x1B) // VK_ESCAPE
477 || (vk
== 0x20) // VK_SPACE
478 || (vk
>= 0x30 && vk
<= 0x39) // numeric keys
479 || (vk
>= 0x41 && vk
<= 0x5A) // alphabetic keys
480 || (vk
>= 0x60 && vk
<= 0x69 && numLockLocked
) // keypad numeric (if numlock is on)
481 || (vk
>= 0x6A && vk
<= 0x6F) // keypad keys except numeric
482 || (vk
>= 0x92 && vk
<= 0x96) // OEM specific
483 || (vk
>= 0xBA && vk
<= 0xC0) // OEM specific
484 || (vk
>= 0xDB && vk
<= 0xDF) // OEM specific
485 || (vk
>= 0xE1 && vk
<= 0xF5 && vk
!= 0xE5 && vk
!= 0xE7 && vk
!= 0xE8) // OEM specific
488 // store this for character events, because VirtualKey is key code on character event.
489 keyStore
= args
.VirtualKey();
495 case CoreAcceleratorKeyEventType::KeyUp
:
496 case CoreAcceleratorKeyEventType::SystemKeyUp
:
498 case CoreAcceleratorKeyEventType::Character
:
499 case CoreAcceleratorKeyEventType::SystemCharacter
:
500 case CoreAcceleratorKeyEventType::UnicodeCharacter
:
501 case CoreAcceleratorKeyEventType::DeadCharacter
:
502 case CoreAcceleratorKeyEventType::SystemDeadCharacter
:
504 // VirtualKey is KeyCode
505 keyCode
= static_cast<unsigned>(args
.VirtualKey());
506 // rewrite vk with stored value
507 vk
= static_cast<unsigned>(keyStore
);
508 // reset stored value
509 keyStore
= VirtualKey::None
;
516 Kodi_KeyEvent(vk
, args
.KeyStatus().ScanCode
, keyCode
, isDown
);
520 // DisplayInformation event handlers.
521 void CWinEventsWin10::OnDpiChanged(const DisplayInformation
& sender
, const winrt::IInspectable
&)
523 // Note: The value for LogicalDpi retrieved here may not match the effective DPI of the app
524 // if it is being scaled for high resolution devices. Once the DPI is set on DeviceResources,
525 // you should always retrieve it using the GetDpi method.
526 // See DeviceResources.cpp for more details.
527 //critical_section::scoped_lock lock(m_deviceResources->GetCriticalSection());
528 RECT resizeRect
= { 0,0,0,0 };
529 DX::Windowing()->DPIChanged(sender
.LogicalDpi(), resizeRect
);
530 CGenericTouchInputHandler::GetInstance().SetScreenDPI(DX::DisplayMetrics::Dpi100
);
533 void CWinEventsWin10::OnOrientationChanged(const DisplayInformation
&, const winrt::IInspectable
&)
535 //critical_section::scoped_lock lock(m_deviceResources->GetCriticalSection());
536 //m_deviceResources->SetCurrentOrientation(sender->CurrentOrientation);
538 //auto size = DX::DeviceResources::Get()->GetOutputSize();
539 //UpdateWindowSize(size.Width, size.Height);
542 void CWinEventsWin10::OnDisplayContentsInvalidated(const DisplayInformation
&, const winrt::IInspectable
&)
544 CLog::Log(LOGDEBUG
, __FUNCTION__
": onevent.");
545 DX::DeviceResources::Get()->ValidateDevice();
548 void CWinEventsWin10::OnBackRequested(const winrt::IInspectable
&, const BackRequestedEventArgs
& args
)
550 // handle this only on windows mobile
551 if (CSysInfo::GetWindowsDeviceFamily() == CSysInfo::WindowsDeviceFamily::Mobile
)
553 CServiceBroker::GetAppMessenger()->PostMsg(TMSG_GUI_ACTION
, WINDOW_INVALID
, -1,
554 static_cast<void*>(new CAction(ACTION_NAV_BACK
)));
559 void CWinEventsWin10::OnSystemMediaButtonPressed(const SystemMediaTransportControls
&, const SystemMediaTransportControlsButtonPressedEventArgs
& args
)
561 int action
= ACTION_NONE
;
562 switch (args
.Button())
564 case SystemMediaTransportControlsButton::ChannelDown
:
565 action
= ACTION_CHANNEL_DOWN
;
567 case SystemMediaTransportControlsButton::ChannelUp
:
568 action
= ACTION_CHANNEL_UP
;
570 case SystemMediaTransportControlsButton::FastForward
:
571 action
= ACTION_PLAYER_FORWARD
;
573 case SystemMediaTransportControlsButton::Rewind
:
574 action
= ACTION_PLAYER_REWIND
;
576 case SystemMediaTransportControlsButton::Next
:
577 action
= ACTION_NEXT_ITEM
;
579 case SystemMediaTransportControlsButton::Previous
:
580 action
= ACTION_PREV_ITEM
;
582 case SystemMediaTransportControlsButton::Pause
:
583 case SystemMediaTransportControlsButton::Play
:
584 action
= ACTION_PLAYER_PLAYPAUSE
;
586 case SystemMediaTransportControlsButton::Stop
:
587 action
= ACTION_STOP
;
589 case SystemMediaTransportControlsButton::Record
:
590 action
= ACTION_RECORD
;
595 if (action
!= ACTION_NONE
)
597 CServiceBroker::GetAppMessenger()->PostMsg(TMSG_GUI_ACTION
, WINDOW_INVALID
, -1,
598 static_cast<void*>(new CAction(action
)));
602 void CWinEventsWin10::Announce(ANNOUNCEMENT::AnnouncementFlag flag
,
603 const std::string
& sender
,
604 const std::string
& message
,
605 const CVariant
& data
)
607 if (flag
& ANNOUNCEMENT::Player
)
610 if (data
.isMember("player") && data
["player"].isMember("speed"))
611 speed
= data
["player"]["speed"].asDouble(1.0);
613 bool changed
= false;
614 MediaPlaybackStatus status
= MediaPlaybackStatus::Changing
;
616 if (message
== "OnPlay" || message
== "OnResume")
619 status
= MediaPlaybackStatus::Playing
;
621 else if (message
== "OnStop")
624 status
= MediaPlaybackStatus::Stopped
;
626 else if (message
== "OnPause")
629 status
= MediaPlaybackStatus::Paused
;
631 else if (message
== "OnSpeedChanged")
634 status
= speed
!= 0.0 ? MediaPlaybackStatus::Playing
: MediaPlaybackStatus::Paused
;
641 auto dispatcher
= CoreApplication::MainView().Dispatcher();
644 dispatcher
.RunAsync(CoreDispatcherPriority::Normal
, DispatchedHandler([status
, speed
]
646 auto smtc
= SystemMediaTransportControls::GetForCurrentView();
650 smtc
.PlaybackStatus(status
);
651 smtc
.PlaybackRate(speed
);
655 catch (const winrt::hresult_error
&)