bug 921565 - look for WM_DEVICECHANGE in Windows gamepad backend and rescan for devices. r=jimm

This commit is contained in:
Ted Mielczarek 2013-10-24 15:06:19 -04:00
Родитель beb74c06a8
Коммит 817ac2fa3a
1 изменённых файлов: 64 добавлений и 15 удалений

Просмотреть файл

@ -232,7 +232,6 @@ public:
mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
observerService->AddObserver(this, "devices-changed", false);
observerService->AddObserver(this,
NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID,
false);
@ -245,7 +244,6 @@ public:
if (mObserving) {
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
observerService->RemoveObserver(this, "devices-changed");
observerService->RemoveObserver(this, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID);
mObserving = false;
}
@ -255,6 +253,15 @@ public:
Stop();
}
void SetDeviceChangeTimer() {
// set stable timer, since we will get multiple devices-changed
// notifications at once
if (mTimer) {
mTimer->Cancel();
mTimer->Init(this, kDevicesChangedStableDelay, nsITimer::TYPE_ONE_SHOT);
}
}
private:
// Gamepad service owns us, we just hold a reference back to it.
WindowsGamepadService& mSvc;
@ -277,7 +284,11 @@ public:
}
}
void DevicesChanged();
enum DeviceChangeType {
DeviceChangeNotification,
DeviceChangeStable
};
void DevicesChanged(DeviceChangeType type);
void Startup();
void Shutdown();
@ -589,8 +600,12 @@ WindowsGamepadService::CleanupGamepad(Gamepad& gamepad) {
}
void
WindowsGamepadService::DevicesChanged() {
SetEvent(mThreadRescanEvent);
WindowsGamepadService::DevicesChanged(DeviceChangeType type) {
if (type == DeviceChangeNotification) {
mObserver->SetDeviceChangeTimer();
} else if (type == DeviceChangeStable) {
SetEvent(mThreadRescanEvent);
}
}
NS_IMETHODIMP
@ -598,27 +613,39 @@ Observer::Observe(nsISupports* aSubject,
const char* aTopic,
const PRUnichar* aData) {
if (strcmp(aTopic, "timer-callback") == 0) {
mSvc.DevicesChanged();
mSvc.DevicesChanged(WindowsGamepadService::DeviceChangeStable);
} else if (strcmp(aTopic, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID) == 0) {
Stop();
} else if (strcmp(aTopic, "devices-changed")) {
// set stable timer, since we will get multiple devices-changed
// notifications at once
if (mTimer) {
mTimer->Cancel();
mTimer->Init(this, kDevicesChangedStableDelay, nsITimer::TYPE_ONE_SHOT);
}
}
return NS_OK;
}
WindowsGamepadService* gService = nullptr;
HWND sHWnd = nullptr;
static
LRESULT CALLBACK
GamepadWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
const unsigned int DBT_DEVICEARRIVAL = 0x8000;
const unsigned int DBT_DEVICEREMOVECOMPLETE = 0x8004;
const unsigned int DBT_DEVNODES_CHANGED = 0x7;
if (msg == WM_DEVICECHANGE &&
(wParam == DBT_DEVICEARRIVAL ||
wParam == DBT_DEVICEREMOVECOMPLETE ||
wParam == DBT_DEVNODES_CHANGED)) {
if (gService) {
gService->DevicesChanged(WindowsGamepadService::DeviceChangeNotification);
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
} // namespace
namespace mozilla {
namespace hal_impl {
WindowsGamepadService* gService = nullptr;
void StartMonitoringGamepadStatus()
{
if (gService)
@ -626,6 +653,23 @@ void StartMonitoringGamepadStatus()
gService = new WindowsGamepadService();
gService->Startup();
if (sHWnd == nullptr) {
WNDCLASSW wc;
HMODULE hSelf = GetModuleHandle(nullptr);
if (!GetClassInfoW(hSelf, L"MozillaGamepadClass", &wc)) {
ZeroMemory(&wc, sizeof(WNDCLASSW));
wc.hInstance = hSelf;
wc.lpfnWndProc = GamepadWindowProc;
wc.lpszClassName = L"MozillaGamepadClass";
RegisterClassW(&wc);
}
sHWnd = CreateWindowW(L"MozillaGamepadClass", L"Gamepad Watcher",
0, 0, 0, 0, 0,
nullptr, nullptr, hSelf, nullptr);
}
}
void StopMonitoringGamepadStatus()
@ -633,6 +677,11 @@ void StopMonitoringGamepadStatus()
if (!gService)
return;
if (sHWnd) {
DestroyWindow(sHWnd);
sHWnd = nullptr;
}
gService->Shutdown();
delete gService;
gService = nullptr;