WindowsBattery.cpp (3723B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "Hal.h" 7 #include "HalImpl.h" 8 #include "mozilla/Preferences.h" 9 #include "mozilla/dom/battery/Constants.h" 10 11 #include <windows.h> 12 13 using namespace mozilla::dom::battery; 14 15 namespace mozilla { 16 namespace hal_impl { 17 18 static HPOWERNOTIFY sPowerHandle = nullptr; 19 static HPOWERNOTIFY sCapacityHandle = nullptr; 20 static HWND sHWnd = nullptr; 21 22 static LRESULT CALLBACK BatteryWindowProc(HWND hwnd, UINT msg, WPARAM wParam, 23 LPARAM lParam) { 24 if (msg != WM_POWERBROADCAST || wParam != PBT_POWERSETTINGCHANGE) { 25 return DefWindowProc(hwnd, msg, wParam, lParam); 26 } 27 28 hal::BatteryInformation currentInfo; 29 30 // Since we need update remainingTime, we cannot use LPARAM. 31 hal_impl::GetCurrentBatteryInformation(¤tInfo); 32 33 hal::NotifyBatteryChange(currentInfo); 34 return TRUE; 35 } 36 37 void EnableBatteryNotifications() { 38 // Create custom window to watch battery event 39 // If we can get Gecko's window handle, this is unnecessary. 40 41 if (sHWnd == nullptr) { 42 WNDCLASSW wc; 43 HMODULE hSelf = GetModuleHandle(nullptr); 44 45 if (!GetClassInfoW(hSelf, L"MozillaBatteryClass", &wc)) { 46 ZeroMemory(&wc, sizeof(WNDCLASSW)); 47 wc.hInstance = hSelf; 48 wc.lpfnWndProc = BatteryWindowProc; 49 wc.lpszClassName = L"MozillaBatteryClass"; 50 RegisterClassW(&wc); 51 } 52 53 sHWnd = CreateWindowW(L"MozillaBatteryClass", L"Battery Watcher", 0, 0, 0, 54 0, 0, nullptr, nullptr, hSelf, nullptr); 55 } 56 57 if (sHWnd == nullptr) { 58 return; 59 } 60 61 sPowerHandle = RegisterPowerSettingNotification( 62 sHWnd, &GUID_ACDC_POWER_SOURCE, DEVICE_NOTIFY_WINDOW_HANDLE); 63 sCapacityHandle = RegisterPowerSettingNotification( 64 sHWnd, &GUID_BATTERY_PERCENTAGE_REMAINING, DEVICE_NOTIFY_WINDOW_HANDLE); 65 } 66 67 void DisableBatteryNotifications() { 68 if (sPowerHandle) { 69 UnregisterPowerSettingNotification(sPowerHandle); 70 sPowerHandle = nullptr; 71 } 72 73 if (sCapacityHandle) { 74 UnregisterPowerSettingNotification(sCapacityHandle); 75 sCapacityHandle = nullptr; 76 } 77 78 if (sHWnd) { 79 DestroyWindow(sHWnd); 80 sHWnd = nullptr; 81 } 82 } 83 84 void GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo) { 85 SYSTEM_POWER_STATUS status; 86 if (!GetSystemPowerStatus(&status)) { 87 aBatteryInfo->level() = kDefaultLevel; 88 aBatteryInfo->charging() = kDefaultCharging; 89 aBatteryInfo->remainingTime() = kDefaultRemainingTime; 90 return; 91 } 92 93 aBatteryInfo->level() = status.BatteryLifePercent == 255 94 ? kDefaultLevel 95 : ((double)status.BatteryLifePercent) / 100.0; 96 aBatteryInfo->charging() = (status.ACLineStatus != 0); 97 if (status.ACLineStatus != 0) { 98 if (aBatteryInfo->level() == 1.0) { 99 // GetSystemPowerStatus API may returns -1 for BatteryFullLifeTime. 100 // So, if battery is 100%, set kDefaultRemainingTime at force. 101 aBatteryInfo->remainingTime() = kDefaultRemainingTime; 102 } else { 103 aBatteryInfo->remainingTime() = status.BatteryFullLifeTime == (DWORD)-1 104 ? kUnknownRemainingTime 105 : status.BatteryFullLifeTime; 106 } 107 } else { 108 aBatteryInfo->remainingTime() = status.BatteryLifeTime == (DWORD)-1 109 ? kUnknownRemainingTime 110 : status.BatteryLifeTime; 111 } 112 } 113 114 } // namespace hal_impl 115 } // namespace mozilla