зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1584501: Draft Implementation of the Windows SystemMediaTransportControl WinRT Interface r=alwu
Differential Revision: https://phabricator.services.mozilla.com/D47546 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
0954bfbeae
Коммит
8f47daac4b
|
@ -3,13 +3,17 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MediaKeysEventSourceFactory.h"
|
||||
#include "WindowsSMTCProvider.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
mozilla::dom::MediaControlKeysEventSource* CreateMediaControlKeysEventSource() {
|
||||
// TODO : will implement this in bug 1584501.
|
||||
return nullptr;
|
||||
#ifndef __MINGW32__
|
||||
return new WindowsSMTCProvider();
|
||||
#else
|
||||
return nullptr; // MinGW doesn't support the required Windows 8.1+ APIs
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
|
|
|
@ -0,0 +1,391 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* mingw currently doesn't support windows.media.h, so we disable
|
||||
* the whole related class until this is fixed.
|
||||
* @TODO: Maybe contact MinGW Team for inclusion?*/
|
||||
#ifndef __MINGW32__
|
||||
|
||||
# include "WindowsSMTCProvider.h"
|
||||
|
||||
# include <windows.h>
|
||||
# include <windows.media.h>
|
||||
# include <winsdkver.h>
|
||||
# include <wrl.h>
|
||||
|
||||
# include "mozilla/Assertions.h"
|
||||
# include "mozilla/Logging.h"
|
||||
# include "mozilla/WidgetUtils.h"
|
||||
# include "mozilla/WindowsVersion.h"
|
||||
|
||||
# pragma comment(lib, "runtimeobject.lib")
|
||||
|
||||
using namespace ABI::Windows::Foundation;
|
||||
using namespace ABI::Windows::Media;
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace Microsoft::WRL::Wrappers;
|
||||
using namespace mozilla;
|
||||
|
||||
# ifndef RuntimeClass_Windows_Media_SystemMediaTransportControls
|
||||
# define RuntimeClass_Windows_Media_SystemMediaTransportControls \
|
||||
L"Windows.Media.SystemMediaTransportControls"
|
||||
# endif
|
||||
|
||||
# ifndef RuntimeClass_Windows_Storage_Streams_RandomAccessStreamReference
|
||||
# define RuntimeClass_Windows_Storage_Streams_RandomAccessStreamReference \
|
||||
L"Windows.Storage.Streams.RandomAccessStreamReference"
|
||||
# endif
|
||||
|
||||
# ifndef ISystemMediaTransportControlsInterop
|
||||
EXTERN_C const IID IID_ISystemMediaTransportControlsInterop;
|
||||
MIDL_INTERFACE("ddb0472d-c911-4a1f-86d9-dc3d71a95f5a")
|
||||
ISystemMediaTransportControlsInterop : public IInspectable {
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE GetForWindow(
|
||||
/* [in] */ __RPC__in HWND appWindow,
|
||||
/* [in] */ __RPC__in REFIID riid,
|
||||
/* [iid_is][retval][out] */
|
||||
__RPC__deref_out_opt void** mediaTransportControl) = 0;
|
||||
};
|
||||
# endif /* __ISystemMediaTransportControlsInterop_INTERFACE_DEFINED__ */
|
||||
|
||||
extern mozilla::LazyLogModule gMediaControlLog;
|
||||
|
||||
# undef LOG
|
||||
# define LOG(msg, ...) \
|
||||
MOZ_LOG(gMediaControlLog, LogLevel::Debug, \
|
||||
("WindowSMTCProvider=%p, " msg, this, ##__VA_ARGS__))
|
||||
|
||||
WindowsSMTCProvider::WindowsSMTCProvider() {
|
||||
LOG("Creating an empty and invisible window");
|
||||
|
||||
// In order to create a SMTC-Provider, we need a hWnd, which shall be created
|
||||
// dynamically from an invisible window. This leads to the following
|
||||
// boilerplate code.
|
||||
WNDCLASS wnd{};
|
||||
wnd.lpszClassName = L"Firefox-MediaKeys";
|
||||
wnd.hInstance = nullptr;
|
||||
wnd.lpfnWndProc = DefWindowProc;
|
||||
GetLastError(); // Clear the error
|
||||
RegisterClass(&wnd);
|
||||
MOZ_ASSERT(!GetLastError());
|
||||
|
||||
mWindow = CreateWindowExW(0, L"Firefox-MediaKeys", L"Firefox Media Keys", 0,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, nullptr,
|
||||
nullptr, nullptr, nullptr);
|
||||
MOZ_ASSERT(mWindow);
|
||||
MOZ_ASSERT(!GetLastError());
|
||||
}
|
||||
|
||||
WindowsSMTCProvider::~WindowsSMTCProvider() {
|
||||
// Dispose the window
|
||||
MOZ_ASSERT(mWindow);
|
||||
if (!DestroyWindow(mWindow)) {
|
||||
LOG("Failed to destroy the hidden window. Error Code: %d", GetLastError());
|
||||
}
|
||||
if (!UnregisterClass(L"Firefox-MediaKeys", nullptr)) {
|
||||
// Note that this is logged when the class wasn't even registered.
|
||||
LOG("Failed to unregister the class. Error Code: %d", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
static inline Maybe<mozilla::dom::MediaControlKeysEvent> TranslateKeycode(
|
||||
SystemMediaTransportControlsButton keycode) {
|
||||
switch (keycode) {
|
||||
case SystemMediaTransportControlsButton_Play:
|
||||
return Some(mozilla::dom::MediaControlKeysEvent::ePlay);
|
||||
case SystemMediaTransportControlsButton_Pause:
|
||||
return Some(mozilla::dom::MediaControlKeysEvent::ePause);
|
||||
case SystemMediaTransportControlsButton_Next:
|
||||
return Some(mozilla::dom::MediaControlKeysEvent::eNextTrack);
|
||||
case SystemMediaTransportControlsButton_Previous:
|
||||
return Some(mozilla::dom::MediaControlKeysEvent::ePrevTrack);
|
||||
case SystemMediaTransportControlsButton_Stop:
|
||||
return Some(mozilla::dom::MediaControlKeysEvent::eStop);
|
||||
case SystemMediaTransportControlsButton_FastForward:
|
||||
return Some(mozilla::dom::MediaControlKeysEvent::eSeekForward);
|
||||
case SystemMediaTransportControlsButton_Rewind:
|
||||
return Some(mozilla::dom::MediaControlKeysEvent::eSeekBackward);
|
||||
default:
|
||||
return Nothing(); // Not supported Button
|
||||
}
|
||||
}
|
||||
|
||||
bool WindowsSMTCProvider::RegisterEvents() {
|
||||
MOZ_ASSERT(mControls);
|
||||
auto self = RefPtr<WindowsSMTCProvider>(this);
|
||||
auto callbackbtnPressed = Callback<
|
||||
ITypedEventHandler<SystemMediaTransportControls*,
|
||||
SystemMediaTransportControlsButtonPressedEventArgs*>>(
|
||||
[this, self](ISystemMediaTransportControls*,
|
||||
ISystemMediaTransportControlsButtonPressedEventArgs* pArgs)
|
||||
-> HRESULT {
|
||||
MOZ_ASSERT(pArgs);
|
||||
SystemMediaTransportControlsButton btn;
|
||||
|
||||
if (FAILED(pArgs->get_Button(&btn))) {
|
||||
LOG("SystemMediaTransportControls: ButtonPressedEvent - Could "
|
||||
"not get Button.");
|
||||
return S_OK; // Propagating the error probably wouldn't help.
|
||||
}
|
||||
|
||||
Maybe<mozilla::dom::MediaControlKeysEvent> keyCode =
|
||||
TranslateKeycode(btn);
|
||||
if (keyCode.isSome() && IsOpened()) {
|
||||
OnButtonPressed(keyCode.value());
|
||||
}
|
||||
return S_OK;
|
||||
});
|
||||
|
||||
if (FAILED(mControls->add_ButtonPressed(callbackbtnPressed.Get(),
|
||||
&mButtonPressedToken))) {
|
||||
LOG("SystemMediaTransportControls: Failed at "
|
||||
"registerEvents().add_ButtonPressed()");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WindowsSMTCProvider::UnregisterEvents() {
|
||||
if (mControls && mButtonPressedToken.value != 0) {
|
||||
mControls->remove_ButtonPressed(mButtonPressedToken);
|
||||
}
|
||||
}
|
||||
|
||||
bool WindowsSMTCProvider::InitDisplayAndControls() {
|
||||
// As Open() might be called multiple times, "cache" the results of the COM
|
||||
// API
|
||||
if (mControls && mDisplay) {
|
||||
return true;
|
||||
}
|
||||
ComPtr<ISystemMediaTransportControlsInterop> interop;
|
||||
HRESULT hr = GetActivationFactory(
|
||||
HStringReference(RuntimeClass_Windows_Media_SystemMediaTransportControls)
|
||||
.Get(),
|
||||
interop.GetAddressOf());
|
||||
if (FAILED(hr)) {
|
||||
LOG("SystemMediaTransportControls: Failed at instantiating the "
|
||||
"Interop object");
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(interop);
|
||||
|
||||
if (!mControls && FAILED(interop->GetForWindow(
|
||||
mWindow, IID_PPV_ARGS(mControls.GetAddressOf())))) {
|
||||
LOG("SystemMediaTransportControls: Failed at GetForWindow()");
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(mControls);
|
||||
|
||||
if (!mDisplay &&
|
||||
FAILED(mControls->get_DisplayUpdater(mDisplay.GetAddressOf()))) {
|
||||
LOG("SystemMediaTransportControls: Failed at get_DisplayUpdater()");
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mDisplay);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WindowsSMTCProvider::Open() {
|
||||
LOG("Opening Source");
|
||||
MOZ_ASSERT(!mInitialized);
|
||||
|
||||
if (!IsWin8Point1OrLater()) {
|
||||
LOG("Windows 8.1 or later is required for Media Key Support");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!InitDisplayAndControls()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Note: SetControlAttributes has to assert mInitialized, because it can be
|
||||
// called after this is open, thus we temporarly set mInit = true
|
||||
mInitialized = RegisterEvents();
|
||||
|
||||
// We set some "default" metadata, until we have a dedicated API for that.
|
||||
if (mInitialized) {
|
||||
bool controlAttribs =
|
||||
SetControlAttributes(SMTCControlAttributes::EnableAll());
|
||||
SetPlaybackState(mozilla::dom::PlaybackState::eStopped);
|
||||
bool metadata = SetMusicMetadata(Nothing(), L"Mozilla Firefox", Nothing());
|
||||
bool update = Update();
|
||||
LOG("Initialization - Enabling All Control Attributes: %s, Setting "
|
||||
"Metadata: %s, Update: %s",
|
||||
controlAttribs ? "true" : "false", metadata ? "true" : "false",
|
||||
update ? "true" : "false");
|
||||
mInitialized = controlAttribs && metadata && update;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mInitialized); // Assert that we could successfully Open
|
||||
|
||||
return mInitialized;
|
||||
}
|
||||
|
||||
bool WindowsSMTCProvider::IsOpened() const { return mInitialized; }
|
||||
|
||||
void WindowsSMTCProvider::Close() {
|
||||
MediaControlKeysEventSource::Close();
|
||||
if (mInitialized) { // Prevent calling Set methods when init failed
|
||||
SetPlaybackState(mozilla::dom::PlaybackState::eStopped);
|
||||
SetControlAttributes(SMTCControlAttributes::DisableAll());
|
||||
mInitialized = false;
|
||||
}
|
||||
|
||||
UnregisterEvents();
|
||||
}
|
||||
|
||||
void WindowsSMTCProvider::SetPlaybackState(mozilla::dom::PlaybackState aState) {
|
||||
MOZ_ASSERT(mInitialized);
|
||||
MediaControlKeysEventSource::SetPlaybackState(aState);
|
||||
|
||||
// Note: we can't return the status of put_PlaybackStatus, but we can at least
|
||||
// assert it.
|
||||
switch (aState) {
|
||||
case mozilla::dom::PlaybackState::ePaused:
|
||||
MOZ_ASSERT(!FAILED(mControls->put_PlaybackStatus(
|
||||
ABI::Windows::Media::MediaPlaybackStatus_Paused)));
|
||||
break;
|
||||
case mozilla::dom::PlaybackState::ePlaying:
|
||||
MOZ_ASSERT(!FAILED(mControls->put_PlaybackStatus(
|
||||
ABI::Windows::Media::MediaPlaybackStatus_Playing)));
|
||||
break;
|
||||
case mozilla::dom::PlaybackState::eStopped:
|
||||
MOZ_ASSERT(!FAILED(mControls->put_PlaybackStatus(
|
||||
ABI::Windows::Media::MediaPlaybackStatus_Stopped)));
|
||||
break;
|
||||
// MediaPlaybackStatus still supports Closed and Changing, which we don't
|
||||
// use (yet)
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"Enum Inconsitency between PlaybackState and WindowsSMTCProvider");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool WindowsSMTCProvider::SetControlAttributes(
|
||||
SMTCControlAttributes aAttributes) {
|
||||
MOZ_ASSERT(mInitialized);
|
||||
|
||||
if (FAILED(mControls->put_IsEnabled(aAttributes.mEnabled))) {
|
||||
return false;
|
||||
}
|
||||
if (FAILED(mControls->put_IsPauseEnabled(aAttributes.mPlayPauseEnabled))) {
|
||||
return false;
|
||||
}
|
||||
if (FAILED(mControls->put_IsPlayEnabled(aAttributes.mPlayPauseEnabled))) {
|
||||
return false;
|
||||
}
|
||||
if (FAILED(mControls->put_IsNextEnabled(aAttributes.mNextEnabled))) {
|
||||
return false;
|
||||
}
|
||||
if (FAILED(mControls->put_IsPreviousEnabled(aAttributes.mPreviousEnabled))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WindowsSMTCProvider::SetThumbnail(const wchar_t* aUrl) {
|
||||
MOZ_ASSERT(mInitialized);
|
||||
ComPtr<IActivationFactory> streamRefFactory;
|
||||
HRESULT hr = GetActivationFactory(
|
||||
HStringReference(
|
||||
RuntimeClass_Windows_Storage_Streams_RandomAccessStreamReference)
|
||||
.Get(),
|
||||
&streamRefFactory);
|
||||
if (FAILED(hr)) {
|
||||
LOG("SystemMediaTransportControls: Failed at "
|
||||
"setThumbnail.GetActivationFactory(&StreamRefFactory)");
|
||||
return false;
|
||||
}
|
||||
|
||||
ComPtr<ABI::Windows::Storage::Streams::IRandomAccessStreamReferenceStatics>
|
||||
streamRefStatic;
|
||||
hr = streamRefFactory.As(&streamRefStatic);
|
||||
if (FAILED(hr)) {
|
||||
LOG("SystemMediaTransportControls: Failed at "
|
||||
"setThumbnail.StreamRefFactory.As()");
|
||||
return false;
|
||||
}
|
||||
|
||||
ComPtr<IUriRuntimeClass> uri;
|
||||
ComPtr<IUriRuntimeClassFactory> uriFactory;
|
||||
hr = GetActivationFactory(
|
||||
HStringReference(RuntimeClass_Windows_Foundation_Uri).Get(), &uriFactory);
|
||||
if (FAILED(hr)) {
|
||||
LOG("SystemMediaTransportControls: Failed at "
|
||||
"setThumbnail.GetActivationFactory(&uriFactory)");
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = uriFactory->CreateUri(HStringReference(aUrl).Get(), uri.GetAddressOf());
|
||||
if (FAILED(hr)) {
|
||||
LOG("SystemMediaTransportControls: Failed at setThumbnail.CreateUri()");
|
||||
return false;
|
||||
}
|
||||
|
||||
ComPtr<ABI::Windows::Storage::Streams::IRandomAccessStreamReference>
|
||||
thumbnail;
|
||||
// When Thumbnail would be a local file: CreateFromFile(file.Get(),
|
||||
// &streamRef);
|
||||
hr = streamRefStatic->CreateFromUri(uri.Get(), thumbnail.GetAddressOf());
|
||||
if (FAILED(hr)) {
|
||||
LOG("SystemMediaTransportControls: Failed at "
|
||||
"setThumbnail.CreateFromUri()");
|
||||
return false;
|
||||
}
|
||||
|
||||
return SUCCEEDED(mDisplay->put_Thumbnail(thumbnail.Get()));
|
||||
}
|
||||
|
||||
bool WindowsSMTCProvider::SetMusicMetadata(
|
||||
mozilla::Maybe<const wchar_t*> aArtist, const wchar_t* aTitle,
|
||||
mozilla::Maybe<const wchar_t*> aAlbumArtist) {
|
||||
MOZ_ASSERT(mInitialized);
|
||||
MOZ_ASSERT(aTitle);
|
||||
ComPtr<IMusicDisplayProperties> musicProps;
|
||||
HRESULT hr = mDisplay->put_Type(MediaPlaybackType::MediaPlaybackType_Music);
|
||||
MOZ_ASSERT(SUCCEEDED(hr));
|
||||
hr = mDisplay->get_MusicProperties(musicProps.GetAddressOf());
|
||||
if (FAILED(hr)) {
|
||||
LOG("SystemMediaTransportControls: Failed at get_MusicProperties()");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aArtist.isSome()) {
|
||||
MOZ_ASSERT(SUCCEEDED(
|
||||
musicProps->put_Artist(HStringReference(aArtist.value()).Get())));
|
||||
} else {
|
||||
MOZ_ASSERT(SUCCEEDED(musicProps->put_Artist(
|
||||
nullptr))); // clearing the previously stored value
|
||||
}
|
||||
|
||||
musicProps->put_Title(HStringReference(aTitle).Get());
|
||||
if (aAlbumArtist.isSome()) {
|
||||
MOZ_ASSERT(SUCCEEDED(musicProps->put_AlbumArtist(
|
||||
HStringReference(aAlbumArtist.value()).Get())));
|
||||
} else {
|
||||
MOZ_ASSERT(SUCCEEDED(musicProps->put_AlbumArtist(
|
||||
nullptr))); // clearing the previously stored value
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WindowsSMTCProvider::OnButtonPressed(
|
||||
mozilla::dom::MediaControlKeysEvent aEvent) {
|
||||
for (auto& listener : mListeners) {
|
||||
listener->OnKeyPressed(aEvent);
|
||||
}
|
||||
}
|
||||
|
||||
bool WindowsSMTCProvider::Update() {
|
||||
MOZ_ASSERT(mInitialized);
|
||||
return SUCCEEDED(mDisplay->Update());
|
||||
}
|
||||
|
||||
#endif // __MINGW32__
|
|
@ -0,0 +1,87 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef WIDGET_WINDOWS_WINDOWSSTMCPROVIDER_H_
|
||||
#define WIDGET_WINDOWS_WINDOWSSTMCPROVIDER_H_
|
||||
|
||||
#ifndef __MINGW32__
|
||||
|
||||
# include <functional>
|
||||
# include <Windows.Media.h>
|
||||
# include <wrl.h>
|
||||
|
||||
# include "mozilla\dom\MediaController.h"
|
||||
# include "mozilla\dom\MediaControlKeysEvent.h"
|
||||
# include "mozilla\Maybe.h"
|
||||
|
||||
using ISMTC = ABI::Windows::Media::ISystemMediaTransportControls;
|
||||
using SMTCProperty = ABI::Windows::Media::SystemMediaTransportControlsProperty;
|
||||
using IMSTCDisplayUpdater =
|
||||
ABI::Windows::Media::ISystemMediaTransportControlsDisplayUpdater;
|
||||
|
||||
struct SMTCControlAttributes {
|
||||
bool mEnabled;
|
||||
bool mPlayPauseEnabled;
|
||||
bool mNextEnabled;
|
||||
bool mPreviousEnabled;
|
||||
|
||||
static constexpr SMTCControlAttributes EnableAll() {
|
||||
return {true, true, true, true};
|
||||
}
|
||||
static constexpr SMTCControlAttributes DisableAll() {
|
||||
return {false, false, false, false};
|
||||
}
|
||||
};
|
||||
|
||||
class WindowsSMTCProvider final
|
||||
: public mozilla::dom::MediaControlKeysEventSource {
|
||||
NS_INLINE_DECL_REFCOUNTING(WindowsSMTCProvider, override)
|
||||
|
||||
public:
|
||||
WindowsSMTCProvider();
|
||||
|
||||
bool IsOpened() const override;
|
||||
bool Open() override;
|
||||
void Close() override;
|
||||
|
||||
// Sets the state of the UI Panel (enabled, can use PlayPause, Next, Previous
|
||||
// Buttons)
|
||||
bool SetControlAttributes(SMTCControlAttributes aAttributes);
|
||||
|
||||
void SetPlaybackState(mozilla::dom::PlaybackState aState) override;
|
||||
|
||||
// Sets the Thumbnail for the currently playing media to the given URL.
|
||||
// Note: This method does not call update(), you need to do that manually.
|
||||
bool SetThumbnail(const wchar_t* aUrl);
|
||||
|
||||
// Sets the Metadata for the currently playing media and sets the playback
|
||||
// type to "MUSIC" Note: This method does not call update(), you need to do
|
||||
// that manually.
|
||||
bool SetMusicMetadata(mozilla::Maybe<const wchar_t*> aArtist,
|
||||
const wchar_t* aTitle,
|
||||
mozilla::Maybe<const wchar_t*> aAlbumArtist);
|
||||
|
||||
private:
|
||||
~WindowsSMTCProvider();
|
||||
void UnregisterEvents();
|
||||
bool RegisterEvents();
|
||||
bool InitDisplayAndControls();
|
||||
void OnButtonPressed(mozilla::dom::MediaControlKeysEvent aEvent);
|
||||
|
||||
// This method flushes the changed Media Metadata to the OS.
|
||||
bool Update();
|
||||
|
||||
bool mInitialized = false;
|
||||
Microsoft::WRL::ComPtr<ISMTC> mControls;
|
||||
Microsoft::WRL::ComPtr<IMSTCDisplayUpdater> mDisplay;
|
||||
HWND mWindow; // handle to the invisible window
|
||||
|
||||
// EventRegistrationTokens are used to have a handle on a callback (to remove
|
||||
// it again)
|
||||
EventRegistrationToken mButtonPressedToken;
|
||||
};
|
||||
|
||||
#endif // __MINGW32__
|
||||
#endif // WIDGET_WINDOWS_WINDOWSSTMCPROVIDER_H_
|
|
@ -33,6 +33,7 @@ EXPORTS.mozilla.widget += [
|
|||
'WinCompositorWidget.h',
|
||||
'WinCompositorWindowThread.h',
|
||||
'WindowsEMF.h',
|
||||
'WindowsSMTCProvider.h',
|
||||
'WinMessages.h',
|
||||
'WinModifierKeyState.h',
|
||||
'WinNativeEventData.h',
|
||||
|
@ -96,6 +97,7 @@ SOURCES += [
|
|||
'nsSharePicker.cpp',
|
||||
'nsWidgetFactory.cpp',
|
||||
'WinCompositorWidget.cpp',
|
||||
'WindowsSMTCProvider.cpp',
|
||||
'WindowsUIUtils.cpp',
|
||||
'WinMouseScrollHandler.cpp',
|
||||
]
|
||||
|
|
Загрузка…
Ссылка в новой задаче