From 6aed176c0988537d716a89e11130b4253179f607 Mon Sep 17 00:00:00 2001 From: Clemens Zeidler Date: Thu, 9 Jul 2009 17:16:31 +0000 Subject: [PATCH] Add a ACPI battery driver interface to the PowerStatus app. If there is anyone with a working APM please test if its still working! TODO: - Get along with the Layout engine, the extended info window looks "no very nice". - Reading the battery status takes too long so put it into a thread or cache it. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31484 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/powerstatus/ACPIDriverInterface.cpp | 240 +++++++++ src/apps/powerstatus/ACPIDriverInterface.h | 80 +++ src/apps/powerstatus/APMDriverInterface.cpp | 140 ++++++ src/apps/powerstatus/APMDriverInterface.h | 35 ++ src/apps/powerstatus/DriverInterface.cpp | 132 +++++ src/apps/powerstatus/DriverInterface.h | 80 +++ src/apps/powerstatus/ExtendedInfoWindow.cpp | 306 ++++++++++++ src/apps/powerstatus/ExtendedInfoWindow.h | 84 ++++ src/apps/powerstatus/Jamfile | 4 + src/apps/powerstatus/PowerStatus.h | 1 + src/apps/powerstatus/PowerStatusView.cpp | 497 +++++++++++-------- src/apps/powerstatus/PowerStatusView.h | 71 ++- src/apps/powerstatus/PowerStatusWindow.cpp | 2 +- 13 files changed, 1445 insertions(+), 227 deletions(-) create mode 100644 src/apps/powerstatus/ACPIDriverInterface.cpp create mode 100644 src/apps/powerstatus/ACPIDriverInterface.h create mode 100644 src/apps/powerstatus/APMDriverInterface.cpp create mode 100644 src/apps/powerstatus/APMDriverInterface.h create mode 100644 src/apps/powerstatus/DriverInterface.cpp create mode 100644 src/apps/powerstatus/DriverInterface.h create mode 100644 src/apps/powerstatus/ExtendedInfoWindow.cpp create mode 100644 src/apps/powerstatus/ExtendedInfoWindow.h diff --git a/src/apps/powerstatus/ACPIDriverInterface.cpp b/src/apps/powerstatus/ACPIDriverInterface.cpp new file mode 100644 index 0000000000..527ac732f0 --- /dev/null +++ b/src/apps/powerstatus/ACPIDriverInterface.cpp @@ -0,0 +1,240 @@ +/* + * Copyright 2009, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Clemens Zeidler, haiku@clemens-zeidler.de + */ + +#include "ACPIDriverInterface.h" + +#include + +#include +#include +#include +#include + + +RateBuffer::RateBuffer() + : + fPosition(0), + fSize(kRateBufferSize), + fCurrentSize(0) +{ + +} + + +void +RateBuffer::AddRate(int32 rate) +{ + fRateBuffer[fPosition] = rate; + fPosition ++; + if (fPosition >= fSize) + fPosition = 0; + + if (fCurrentSize < fSize) + fCurrentSize ++; +} + + +int32 +RateBuffer::GetMeanRate() +{ + int mean = 0; + for (int i = 0; i < fCurrentSize; i++) { + mean += fRateBuffer[i]; + } + + if (fCurrentSize == 0) + return -1; + + return mean / fCurrentSize; +} + + +Battery::Battery(int driverHandler) + : + fDriverHandler(driverHandler) +{ + _Init(); +} + + +Battery::~Battery() +{ + close(fDriverHandler); +} + + +status_t +Battery::InitCheck() +{ + return fInitStatus; +} + + +status_t +Battery::GetBatteryInfo(battery_info* info) +{ + acpi_battery_info acpiInfo; + status_t status; + status = ioctl(fDriverHandler, GET_BATTERY_INFO, &acpiInfo, + sizeof(acpi_battery_info)); + + if (status != B_OK) + return status; + + info->state = acpiInfo.state; + info->current_rate = acpiInfo.current_rate; + info->capacity = acpiInfo.capacity; + info->full_capacity = fExtendedBatteryInfo.last_full_charge; + fRateBuffer.AddRate(acpiInfo.current_rate); + if (acpiInfo.current_rate > 0) + info->time_left = 3600 * acpiInfo.capacity / fRateBuffer.GetMeanRate(); + else + info->time_left = -1; + + return B_OK; +} + + +status_t +Battery::GetExtendedBatteryInfo(acpi_extended_battery_info* info) +{ + status_t status; + status = ioctl(fDriverHandler, GET_EXTENDED_BATTERY_INFO, info, + sizeof(acpi_extended_battery_info)); + + return status; +} + + +void +Battery::_Init() +{ + uint32 magicId = 0; + fInitStatus = ioctl(fDriverHandler, IDENTIFY_DEVICE, &magicId, + sizeof(uint32)); + if (fInitStatus != B_OK) + return; + + fInitStatus = ioctl(fDriverHandler, GET_EXTENDED_BATTERY_INFO, + &fExtendedBatteryInfo, sizeof(acpi_extended_battery_info)); + if (fInitStatus != B_OK) + return; + + acpi_battery_info info; + fInitStatus = ioctl(fDriverHandler, GET_BATTERY_INFO, &info, + sizeof(acpi_battery_info)); + if (fInitStatus != B_OK) + return; + + printf("ACPI driver found\n"); + +} + + +ACPIDriverInterface::~ACPIDriverInterface() +{ + for (int i = 0; i < fDriverList.CountItems(); i++) + delete fDriverList.ItemAt(i); + +} + + +const char* kDriverDir = "/dev/power"; + + +status_t +ACPIDriverInterface::Connect() +{ + printf("ACPI connect\n"); + return _FindDrivers(kDriverDir); +} + + +status_t +ACPIDriverInterface::GetBatteryInfo(battery_info* info, int32 index) +{ + BAutolock autolock(fBatteryStatusLock); + if (index < 0 || index >= fDriverList.CountItems()) + return B_ERROR; + + status_t status; + status = fDriverList.ItemAt(index)->GetBatteryInfo(info); + return status; +} + + +status_t +ACPIDriverInterface::GetExtendedBatteryInfo(acpi_extended_battery_info* info, + int32 index) +{ + BAutolock autolock(fBatteryStatusLock); + if (index < 0 || index >= fDriverList.CountItems()) + return B_ERROR; + + status_t status; + status = fDriverList.ItemAt(index)->GetExtendedBatteryInfo(info); + + return status; +} + + +int32 +ACPIDriverInterface::GetBatteryCount() +{ + return fDriverList.CountItems(); +} + + +void +ACPIDriverInterface::_WatchPowerStatus() +{ + const bigtime_t kUpdateInterval = 2000000; + // every two seconds + + while (atomic_get(&fIsWatching) > 0) { + Broadcast(kMsgUpdate); + snooze(kUpdateInterval); + } +} + + +status_t +ACPIDriverInterface::_FindDrivers(const char* path) +{ + BDirectory dir(path); + BEntry entry; + + status_t status = B_ERROR; + + while (dir.GetNextEntry(&entry) == B_OK) { + BPath path; + entry.GetPath(&path); + + if (entry.IsDirectory()) { + if (_FindDrivers(path.Path()) == B_OK) + return B_OK; + } + else { + int32 handler = open(path.Path(), O_RDWR); + if (handler >= 0) { + printf("try %s\n", path.Path()); + Battery* battery = new Battery(handler); + if (battery->InitCheck() == B_OK) { + fDriverList.AddItem(battery); + status = B_OK; + } + else + delete battery; + } + } + + } + return status; +} + + diff --git a/src/apps/powerstatus/ACPIDriverInterface.h b/src/apps/powerstatus/ACPIDriverInterface.h new file mode 100644 index 0000000000..b8a5c52e69 --- /dev/null +++ b/src/apps/powerstatus/ACPIDriverInterface.h @@ -0,0 +1,80 @@ +/* + * Copyright 2009, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Clemens Zeidler, haiku@clemens-zeidler.de + */ + +#ifndef ACPI_DRIVER_INTERFACE_H +#define ACPI_DRIVER_INTERFACE_H + +#include "DriverInterface.h" + +#include +#include + +const int8 kRateBufferSize = 10; + +class RateBuffer +{ +public: + RateBuffer(); + void AddRate(int32 rate); + int32 GetMeanRate(); + +private: + int32 fRateBuffer[kRateBufferSize]; + int8 fPosition; + int8 fSize; + int8 fCurrentSize; +}; + + +class Battery +{ +public: + Battery(int driverHandler); + ~Battery(); + + status_t InitCheck(); + + status_t GetBatteryInfo(battery_info* info); + status_t GetExtendedBatteryInfo( + acpi_extended_battery_info* info); + +private: + void _Init(); + + + int fDriverHandler; + status_t fInitStatus; + + acpi_extended_battery_info fExtendedBatteryInfo; + + RateBuffer fRateBuffer; +}; + + +class ACPIDriverInterface : public PowerStatusDriverInterface +{ +public: + virtual ~ACPIDriverInterface(); + + virtual status_t Connect(); + virtual status_t GetBatteryInfo(battery_info* info, int32 index); + virtual status_t GetExtendedBatteryInfo( + acpi_extended_battery_info* info, int32 index); + + virtual int32 GetBatteryCount(); + +protected: + virtual void _WatchPowerStatus(); + virtual status_t _FindDrivers(const char* path); + + BObjectList fDriverList; + + BLocker fBatteryStatusLock; +}; + +#endif diff --git a/src/apps/powerstatus/APMDriverInterface.cpp b/src/apps/powerstatus/APMDriverInterface.cpp new file mode 100644 index 0000000000..f6033e7e86 --- /dev/null +++ b/src/apps/powerstatus/APMDriverInterface.cpp @@ -0,0 +1,140 @@ +/* + * Copyright 2009, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Clemens Zeidler, haiku@clemens-zeidler.de + */ + +#include "APMDriverInterface.h" + +#ifdef HAIKU_TARGET_PLATFORM_HAIKU +# include +# include +# include + // temporary, as long as there is no real power state API +#endif + + +const bigtime_t kUpdateInterval = 2000000; + // every two seconds + + +#ifndef HAIKU_TARGET_PLATFORM_HAIKU +// definitions for the APM driver available for BeOS +enum { + APM_CONTROL = B_DEVICE_OP_CODES_END + 1, + APM_DUMP_POWER_STATUS, + APM_BIOS_CALL, + APM_SET_SAFETY +}; + +#define BIOS_APM_GET_POWER_STATUS 0x530a +#endif + + +APMDriverInterface::~APMDriverInterface() +{ +#ifndef HAIKU_TARGET_PLATFORM_HAIKU + close(fDevice); +#endif +} + + +status_t +APMDriverInterface::Connect() +{ +#ifdef HAIKU_TARGET_PLATFORM_HAIKU + uint32 version = 0; + status_t status = _kern_generic_syscall(APM_SYSCALLS, B_SYSCALL_INFO, + &version, sizeof(version)); + if (status == B_OK) { + battery_info info; + status = _kern_generic_syscall(APM_SYSCALLS, APM_GET_BATTERY_INFO, + &info, sizeof(battery_info)); + } + + return status; + +#else + fDevice = open("/dev/misc/apm", O_RDONLY); + if (fDevice < 0) { + return B_ERROR; + } + + return B_OK; +#endif +} + + +status_t +APMDriverInterface::GetBatteryInfo(battery_info* info, int32 index) +{ + if (index != 0) + return B_BAD_VALUE; + + info->current_rate = -1; + +#ifdef HAIKU_TARGET_PLATFORM_HAIKU + // TODO: retrieve data from APM kernel interface + apm_battery_info apmInfo; + status_t status = _kern_generic_syscall(APM_SYSCALLS, APM_GET_BATTERY_INFO, + &apmInfo, sizeof(apm_battery_info)); + if (status == B_OK) { + info->state = apmInfo.online ? BATTERY_CHARGING : BATTERY_DISCHARGING; + info->capacity = apmInfo.percent; + info->full_capacity = 100; + info->time_left = apmInfo.time_left; + } + + return status; +#else + if (fDevice < 0) + return B_ERROR; + + uint16 regs[6] = {0, 0, 0, 0, 0, 0}; + regs[0] = BIOS_APM_GET_POWER_STATUS; + regs[1] = 0x1; + if (ioctl(fDevice, APM_BIOS_CALL, regs) == 0) { + bool online = (regs[1] >> 8) != 0 && (regs[1] >> 8) != 2; + info->state = online ? BATTERY_CHARGING : BATTERY_DISCHARGING; + info->capacity = regs[2] & 255; + if (info->capacity > 100) + info->capacity = -1; + info->full_capacity = 100; + info->time_left = info->capacity >= 0 ? regs[3] : -1; + if (info->time_left > 0xffff) + info->time_left = -1; + else if (info->time_left & 0x8000) + info->time_left = (info->time_left & 0x7fff) * 60; + } + + return B_OK; +#endif +} + + +status_t +APMDriverInterface::GetExtendedBatteryInfo(acpi_extended_battery_info* info, + int32 index) +{ + return B_ERROR; +} + + +int32 +APMDriverInterface::GetBatteryCount() +{ + return 1; +} + + +void +APMDriverInterface::_WatchPowerStatus() +{ + while (atomic_get(&fIsWatching) > 0) { + Broadcast(kMsgUpdate); + snooze(kUpdateInterval); + } +} + diff --git a/src/apps/powerstatus/APMDriverInterface.h b/src/apps/powerstatus/APMDriverInterface.h new file mode 100644 index 0000000000..ecdb48618f --- /dev/null +++ b/src/apps/powerstatus/APMDriverInterface.h @@ -0,0 +1,35 @@ +/* + * Copyright 2009, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Clemens Zeidler, haiku@clemens-zeidler.de + */ + +#ifndef APM_DRIVER_INTERFACE_H +#define APM_DRIVER_INTERFACE_H + +#include "DriverInterface.h" + + +class APMDriverInterface : public PowerStatusDriverInterface +{ +public: + virtual ~APMDriverInterface(); + + virtual status_t Connect(); + virtual status_t GetBatteryInfo(battery_info* info, int32 index); + virtual status_t GetExtendedBatteryInfo(acpi_extended_battery_info* info, + int32 index); + virtual int32 GetBatteryCount(); + +protected: + virtual void _WatchPowerStatus(); + +private: +#ifndef HAIKU_TARGET_PLATFORM_HAIKU + int fDevice; +#endif +}; + +#endif diff --git a/src/apps/powerstatus/DriverInterface.cpp b/src/apps/powerstatus/DriverInterface.cpp new file mode 100644 index 0000000000..c8b2b46451 --- /dev/null +++ b/src/apps/powerstatus/DriverInterface.cpp @@ -0,0 +1,132 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Clemens Zeidler, haiku@Clemens-Zeidler.de + */ + +#include "DriverInterface.h" + +#include +#include + + +Monitor::~Monitor() +{ + +} + + +status_t +Monitor::StartWatching(BHandler* target) +{ + if (fWatcherList.HasItem(target)) + return B_ERROR; + + fWatcherList.AddItem(target); + return B_OK; +} + + +status_t +Monitor::StopWatching(BHandler* target) +{ + return fWatcherList.RemoveItem(target); +} + + +void +Monitor::Broadcast(uint32 message) +{ + for (int i = 0; i < fWatcherList.CountItems(); i++) + { + BMessenger messenger(fWatcherList.ItemAt(i)); + messenger.SendMessage(message); + } +} + + +PowerStatusDriverInterface::PowerStatusDriverInterface() + : + fIsWatching(0), + fThreadId(-1) +{ + +} + +PowerStatusDriverInterface::~PowerStatusDriverInterface() +{ + +} + +#include +status_t +PowerStatusDriverInterface::StartWatching(BHandler* target) +{ + BAutolock autolock(fListLocker); + + status_t status = Monitor::StartWatching(target); + + if (status != B_OK) + return status; + + if (fThreadId > 0) + return B_OK; + + printf("spawn\n"); + fThreadId = spawn_thread(&_ThreadWatchPowerFunction, "PowerStatusThread", + B_LOW_PRIORITY, this); + if (fThreadId >= 0) { + atomic_set(&fIsWatching, 1); + status = resume_thread(fThreadId); + } + else + return fThreadId; + + if (status != B_OK && fWatcherList.CountItems() == 0) { + atomic_set(&fIsWatching, 0); + } + return status; + +} + + +status_t +PowerStatusDriverInterface::StopWatching(BHandler* target) +{ + BAutolock autolock(fListLocker); + + if (fThreadId < 0) + return B_BAD_VALUE; + + status_t status; + if (fWatcherList.CountItems() == 1) { + atomic_set(&fIsWatching, 0); + + status = wait_for_thread(fThreadId, &status); + fThreadId = -1; + } + + return Monitor::StopWatching(target); +} + + +void +PowerStatusDriverInterface::Disconnect() +{ + atomic_set(&fIsWatching, 0); + status_t status; + wait_for_thread(fThreadId, &status); + fThreadId = -1; +} + + +int32 +PowerStatusDriverInterface::_ThreadWatchPowerFunction(void* data) +{ + PowerStatusDriverInterface* that = (PowerStatusDriverInterface*)data; + that->_WatchPowerStatus(); + return 0; +} + diff --git a/src/apps/powerstatus/DriverInterface.h b/src/apps/powerstatus/DriverInterface.h new file mode 100644 index 0000000000..5d271b9731 --- /dev/null +++ b/src/apps/powerstatus/DriverInterface.h @@ -0,0 +1,80 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Clemens Zeidler, haiku@Clemens-Zeidler.de + */ + +#ifndef DRIVER_INTERFACE_H +#define DRIVER_INTERFACE_H + +#include +#include +#include + +#include "device/power_managment.h" + +typedef BObjectList WatcherList; + +const uint32 kMsgUpdate = 'updt'; + + +struct battery_info +{ + int8 state; + int32 capacity; + int32 full_capacity; + time_t time_left; + int32 current_rate; +}; + + +/*! Handle a list of watcher and broadcast a messages to them. */ +class Monitor +{ +public: + virtual ~Monitor(); + + virtual status_t StartWatching(BHandler* target); + virtual status_t StopWatching(BHandler* target); + + virtual void Broadcast(uint32 message); + +protected: + WatcherList fWatcherList; + +}; + + +class PowerStatusDriverInterface : public Monitor +{ +public: + PowerStatusDriverInterface(); + ~PowerStatusDriverInterface(); + virtual status_t StartWatching(BHandler* target); + virtual status_t StopWatching(BHandler* target); + + virtual status_t Connect() = 0; + virtual void Disconnect(); + + virtual status_t GetBatteryInfo(battery_info* status, int32 index) = 0; + virtual status_t GetExtendedBatteryInfo(acpi_extended_battery_info* info, + int32 index) = 0; + + virtual int32 GetBatteryCount() = 0; + +protected: + virtual void _WatchPowerStatus() = 0; + + vint32 fIsWatching; +private: + static int32 _ThreadWatchPowerFunction(void* data); + + thread_id fThreadId; + + BLocker fListLocker; +}; + + +#endif diff --git a/src/apps/powerstatus/ExtendedInfoWindow.cpp b/src/apps/powerstatus/ExtendedInfoWindow.cpp new file mode 100644 index 0000000000..1990bcdb15 --- /dev/null +++ b/src/apps/powerstatus/ExtendedInfoWindow.cpp @@ -0,0 +1,306 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Clemens Zeidler, haiku@Clemens-Zeidler.de + */ + +#include "ExtendedInfoWindow.h" + +#include +#include +#include +#include +#include + + +BatteryInfoView::BatteryInfoView(BRect frame, int32 resizingMode) + : + BView(frame, "battery info view", resizingMode, B_WILL_DRAW | + B_FULL_UPDATE_ON_RESIZE) +{ + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); +} + + +void +BatteryInfoView::Update(battery_info& info, acpi_extended_battery_info& extInfo) +{ + fBatteryInfo = info; + fBatteryExtendedInfo = extInfo; +} + + +void +BatteryInfoView::Draw(BRect updateRect) +{ + SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + BString powerUnit; + BString rateUnit; + switch (fBatteryExtendedInfo.power_unit) { + case 0: + powerUnit = " mWh"; + rateUnit = " mW"; + break; + + case 1: + powerUnit = " mAh"; + rateUnit = " mA"; + break; + } + + BString text; + if (fBatteryInfo.state & BATTERY_CHARGING) + text = "Battery charging"; + else if (fBatteryInfo.state & BATTERY_DISCHARGING) + text = "Battery discharging"; + else if (fBatteryInfo.state & BATTERY_CRITICAL_STATE) + text = "Empty Battery Slot"; + else + text = "Battery unused"; + BPoint point(10, 10); + int textHeight = 15; + int space = textHeight + 5; + DrawString(text.String(), point); + point.y += space; + + text = "Capacity: "; + text << fBatteryInfo.capacity; + text << powerUnit; + DrawString(text.String(), point); + point.y += space; + + text = "Last full Charge: "; + text << fBatteryInfo.full_capacity; + text << powerUnit; + DrawString(text.String(), point); + point.y += space; + + text = "Current Rate: "; + text << fBatteryInfo.current_rate; + text << rateUnit; + DrawString(text.String(), point); + point.y += space; + + point.y += space; + + text = "Design Capacity: "; + text << fBatteryExtendedInfo.design_capacity; + text << powerUnit; + DrawString(text.String(), point); + point.y += space; + + text = "Technology: "; + text << fBatteryExtendedInfo.technology; + DrawString(text.String(), point); + point.y += space; + + text = "Design Voltage: "; + text << fBatteryExtendedInfo.design_voltage; + text << " mV"; + DrawString(text.String(), point); + point.y += space; + + text = "Design Capacity Warning: "; + text << fBatteryExtendedInfo.design_capacity_warning; + text << powerUnit; + DrawString(text.String(), point); + point.y += space; + + text = "Design Capacity low Warning: "; + text << fBatteryExtendedInfo.design_capacity_low; + text << powerUnit; + DrawString(text.String(), point); + point.y += space; + + text = "Capacity Granularity 1: "; + text << fBatteryExtendedInfo.capacity_granularity_1; + DrawString(text.String(), point); + point.y += space; + + text = "Capacity Granularity 2: "; + text << fBatteryExtendedInfo.capacity_granularity_2; + DrawString(text.String(), point); + point.y += space; + + text = "Model Number: "; + text << fBatteryExtendedInfo.model_number; + DrawString(text.String(), point); + point.y += space; + + text = "Serial number: "; + text << fBatteryExtendedInfo.serial_number; + DrawString(text.String(), point); + point.y += space; + + text = "Type: "; + text += fBatteryExtendedInfo.type; + DrawString(text.String(), point); + point.y += space; + + text = "OEM Info: "; + text += fBatteryExtendedInfo.oem_info; + DrawString(text.String(), point); + point.y += space; + +} + + +ExtPowerStatusView::ExtPowerStatusView(PowerStatusDriverInterface* interface, + BRect frame, int32 resizingMode, int batteryId, + ExtendedInfoWindow* window) + : + PowerStatusView(interface, frame, resizingMode, batteryId), + fExtendedInfoWindow(window), + fBatteryInfoView(window->GetExtendedBatteryInfoView()), + fSelected(false) +{ + +} + + +void +ExtPowerStatusView::Draw(BRect updateRect) +{ + if (fSelected) { + SetLowColor(102, 152, 203); + SetHighColor(102, 152, 203); + FillRect(updateRect); + } + else { + SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + FillRect(updateRect); + } + + PowerStatusView::Draw(updateRect); +} + + +void +ExtPowerStatusView::MouseDown(BPoint where) +{ + if (!fSelected) { + fSelected = true; + _Update(true); + fExtendedInfoWindow->BatterySelected(this); + } +} + + +void +ExtPowerStatusView::Select(bool select) +{ + fSelected = select; + _Update(true); +} + + +bool +ExtPowerStatusView::IsValid() +{ + if (fBatteryInfo.state & BATTERY_CRITICAL_STATE) + return false; + return true; +} + + +void +ExtPowerStatusView::_Update(bool force) +{ + PowerStatusView::_Update(force); + if (!fSelected) + return; + + acpi_extended_battery_info extInfo; + fDriverInterface->GetExtendedBatteryInfo(&extInfo, fBatteryId); + + fBatteryInfoView->Update(fBatteryInfo, extInfo); + fBatteryInfoView->Invalidate(); +} + + +ExtendedInfoWindow::ExtendedInfoWindow(PowerStatusDriverInterface* interface) + : + BWindow(BRect(100, 150, 500, 500), "Extended Battery Info", B_TITLED_WINDOW, + B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS), + fDriverInterface(interface), + fSelectedView(NULL) +{ + BView *view = new BView(Bounds(), "view", B_FOLLOW_ALL, 0); + view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + AddChild(view); + + BGroupLayout* mainLayout = new BGroupLayout(B_VERTICAL); + mainLayout->SetSpacing(10); + mainLayout->SetInsets(10, 10, 10, 10); + view->SetLayout(mainLayout); + + BRect rect = Bounds(); + rect.InsetBy(5, 5); + BBox *infoBox = new BBox(rect, "Power Status Box"); + infoBox->SetLabel("Battery Info"); + BGroupLayout* infoLayout = new BGroupLayout(B_HORIZONTAL); + infoLayout->SetInsets(10, infoBox->TopBorderOffset() * 2 + 10, 10, 10); + infoLayout->SetSpacing(10); + infoBox->SetLayout(infoLayout); + mainLayout->AddView(infoBox); + + BGroupView* batteryView = new BGroupView(B_VERTICAL); + batteryView->GroupLayout()->SetSpacing(10); + infoLayout->AddView(batteryView); + + fBatteryInfoView = new BatteryInfoView(BRect(0, 0, 270, 310), B_FOLLOW_ALL); + + BGroupLayout* batteryLayout = batteryView->GroupLayout(); + BRect batteryRect(0, 0, 50, 30); + for (int i = 0; i < interface->GetBatteryCount(); i++) { + ExtPowerStatusView* view = new ExtPowerStatusView(interface, + batteryRect, B_FOLLOW_ALL, i, this); + batteryLayout->AddView(view); + fBatteryViewList.AddItem(view); + fDriverInterface->StartWatching(view); + if (view->IsValid()) + fSelectedView = view; + } + + batteryLayout->AddItem(BSpaceLayoutItem::CreateGlue()); + + infoLayout->AddView(fBatteryInfoView, 20); + + if (!fSelectedView && fBatteryViewList.CountItems() > 0) + fSelectedView = fBatteryViewList.ItemAt(0); + fSelectedView->Select(); + + BSize size = mainLayout->PreferredSize(); + ResizeTo(size.width, size.height); +} + + +ExtendedInfoWindow::~ExtendedInfoWindow() +{ + for (int i = 0; i < fBatteryViewList.CountItems(); i++) { + fDriverInterface->StopWatching(fBatteryViewList.ItemAt(i)); + } +} + + +BatteryInfoView* +ExtendedInfoWindow::GetExtendedBatteryInfoView() +{ + return fBatteryInfoView; +} + + +void +ExtendedInfoWindow::BatterySelected(ExtPowerStatusView* view) +{ + if (fSelectedView) { + fSelectedView->Select(false); + fSelectedView->Invalidate(); + } + + fSelectedView = view; +} diff --git a/src/apps/powerstatus/ExtendedInfoWindow.h b/src/apps/powerstatus/ExtendedInfoWindow.h new file mode 100644 index 0000000000..671262cc82 --- /dev/null +++ b/src/apps/powerstatus/ExtendedInfoWindow.h @@ -0,0 +1,84 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Clemens Zeidler, haiku@Clemens-Zeidler.de + */ + +#ifndef EXTENDED_INFO_WINDOW_H +#define EXTENDED_INFO_WINDOW_H + +#include +#include +#include +#include + +#include "DriverInterface.h" +#include "PowerStatusView.h" + + +class BatteryInfoView : public BView +{ + public: + BatteryInfoView(BRect frame, int32 resizingMode); + + virtual void Update(battery_info& info, + acpi_extended_battery_info& extInfo); + virtual void Draw(BRect updateRect); + + private: + battery_info fBatteryInfo; + acpi_extended_battery_info fBatteryExtendedInfo; +}; + + +class ExtendedInfoWindow; + +class ExtPowerStatusView : public PowerStatusView +{ + public: + ExtPowerStatusView(PowerStatusDriverInterface* interface, + BRect frame, int32 resizingMode, int batteryId, + ExtendedInfoWindow* window); + + virtual void Draw(BRect updateRect); + virtual void MouseDown(BPoint where); + + virtual void Select(bool select = true); + + // return true if it battery is in a none critical state + virtual bool IsValid(); + + protected: + virtual void _Update(bool force = false); + + private: + ExtendedInfoWindow* fExtendedInfoWindow; + BatteryInfoView* fBatteryInfoView; + + bool fSelected; +}; + + +class ExtendedInfoWindow : public BWindow +{ +public: + ExtendedInfoWindow(PowerStatusDriverInterface* interface); + ~ExtendedInfoWindow(); + + BatteryInfoView* GetExtendedBatteryInfoView(); + + void BatterySelected(ExtPowerStatusView* view); + +private: + PowerStatusDriverInterface* fDriverInterface; + BObjectList fBatteryViewList; + + BatteryInfoView* fBatteryInfoView; + + ExtPowerStatusView* fSelectedView; +}; + + +#endif diff --git a/src/apps/powerstatus/Jamfile b/src/apps/powerstatus/Jamfile index bb77ec3993..e336f49e5f 100644 --- a/src/apps/powerstatus/Jamfile +++ b/src/apps/powerstatus/Jamfile @@ -6,6 +6,10 @@ UsePrivateHeaders shared ; UsePrivateSystemHeaders ; Application PowerStatus : + ACPIDriverInterface.cpp + APMDriverInterface.cpp + DriverInterface.cpp + ExtendedInfoWindow.cpp PowerStatusWindow.cpp PowerStatusView.cpp PowerStatus.cpp diff --git a/src/apps/powerstatus/PowerStatus.h b/src/apps/powerstatus/PowerStatus.h index 6c4527dda7..71473ea120 100644 --- a/src/apps/powerstatus/PowerStatus.h +++ b/src/apps/powerstatus/PowerStatus.h @@ -12,4 +12,5 @@ extern const char* kSignature; extern const char* kDeskbarItemName; + #endif // POWER_STATUS_H diff --git a/src/apps/powerstatus/PowerStatusView.cpp b/src/apps/powerstatus/PowerStatusView.cpp index 1aa1086097..17658069a4 100644 --- a/src/apps/powerstatus/PowerStatusView.cpp +++ b/src/apps/powerstatus/PowerStatusView.cpp @@ -4,19 +4,13 @@ * * Authors: * Axel Dörfler, axeld@pinc-software.de + * Clemens Zeidler, haiku@Clemens-Zeidler.de */ #include "PowerStatusView.h" #include "PowerStatus.h" -#ifdef HAIKU_TARGET_PLATFORM_HAIKU -# include -# include -# include - // temporary, as long as there is no real power state API -#endif - #include #include #include @@ -32,52 +26,34 @@ #include #include +#include "ACPIDriverInterface.h" +#include "APMDriverInterface.h" +#include "ExtendedInfoWindow.h" + extern "C" _EXPORT BView *instantiate_deskbar_item(void); - -const uint32 kMsgUpdate = 'updt'; const uint32 kMsgToggleLabel = 'tglb'; const uint32 kMsgToggleTime = 'tgtm'; const uint32 kMsgToggleStatusIcon = 'tgsi'; +const uint32 kMsgToggleExtInfo = 'texi'; const uint32 kMinIconWidth = 16; const uint32 kMinIconHeight = 16; -const bigtime_t kUpdateInterval = 2000000; - // every two seconds - -#ifndef HAIKU_TARGET_PLATFORM_HAIKU -// definitions for the APM driver available for BeOS -enum { - APM_CONTROL = B_DEVICE_OP_CODES_END + 1, - APM_DUMP_POWER_STATUS, - APM_BIOS_CALL, - APM_SET_SAFETY -}; - -#define BIOS_APM_GET_POWER_STATUS 0x530a -#endif - - -PowerStatusView::PowerStatusView(BRect frame, int32 resizingMode, bool inDeskbar) - : BView(frame, kDeskbarItemName, resizingMode, +PowerStatusView::PowerStatusView(PowerStatusDriverInterface* interface, + BRect frame, int32 resizingMode, int batteryId, bool inDeskbar) + : + BView(frame, kDeskbarItemName, resizingMode, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE), + fDriverInterface(interface), + fBatteryId(batteryId), fInDeskbar(inDeskbar) { + fPreferredSize.width = frame.Width(); + fPreferredSize.height = frame.Height(); _Init(); - - if (!inDeskbar) { - // we were obviously added to a standard window - let's add a dragger - frame.OffsetTo(B_ORIGIN); - frame.top = frame.bottom - 7; - frame.left = frame.right - 7; - BDragger* dragger = new BDragger(frame, this, - B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); - AddChild(dragger); - } else - _Update(); } @@ -93,14 +69,33 @@ PowerStatusView::PowerStatusView(BMessage* archive) fShowStatusIcon = value; if (archive->FindBool("show time", &value) == B_OK) fShowTime = value; + int32 intValue; + if (archive->FindInt32("battery id", &intValue) == B_OK) + fBatteryId = intValue; + } PowerStatusView::~PowerStatusView() { -#ifndef HAIKU_TARGET_PLATFORM_HAIKU - close(fDevice); -#endif + +} + + +status_t +PowerStatusView::Archive(BMessage* archive, bool deep) const +{ + status_t status = BView::Archive(archive, deep); + if (status == B_OK) + status = archive->AddBool("show label", fShowLabel); + if (status == B_OK) + status = archive->AddBool("show icon", fShowStatusIcon); + if (status == B_OK) + status = archive->AddBool("show time", fShowTime); + if (status == B_OK) + status = archive->AddInt32("battery id", fBatteryId); + + return status; } @@ -111,72 +106,10 @@ PowerStatusView::_Init() fShowTime = false; fShowStatusIcon = true; - fMessageRunner = NULL; fPercent = -1; fOnline = true; fTimeLeft = 0; -#ifdef HAIKU_TARGET_PLATFORM_HAIKU - uint32 version = 0; - status_t status = _kern_generic_syscall(APM_SYSCALLS, B_SYSCALL_INFO, - &version, sizeof(version)); - if (status == B_OK) { - battery_info info; - status = _kern_generic_syscall(APM_SYSCALLS, APM_GET_BATTERY_INFO, &info, - sizeof(battery_info)); - } - - if (status != B_OK) { - fprintf(stderr, "No power interface found.\n"); - _Quit(); - } -#else - fDevice = open("/dev/misc/apm", O_RDONLY); - if (fDevice < 0) { - fprintf(stderr, "No power interface found.\n"); - _Quit(); - } -#endif -} - - -void -PowerStatusView::_Quit() -{ - if (fInDeskbar) { - BDeskbar deskbar; - deskbar.RemoveItem(kDeskbarItemName); - } else - be_app->PostMessage(B_QUIT_REQUESTED); -} - - -PowerStatusView * -PowerStatusView::Instantiate(BMessage* archive) -{ - if (!validate_instantiation(archive, "PowerStatusView")) - return NULL; - - return new PowerStatusView(archive); -} - - -status_t -PowerStatusView::Archive(BMessage* archive, bool deep) const -{ - status_t status = BView::Archive(archive, deep); - if (status == B_OK) - status = archive->AddString("add_on", kSignature); - if (status == B_OK) - status = archive->AddString("class", "PowerStatusView"); - if (status == B_OK) - status = archive->AddBool("show label", fShowLabel); - if (status == B_OK) - status = archive->AddBool("show icon", fShowStatusIcon); - if (status == B_OK) - status = archive->AddBool("show time", fShowTime); - - return status; } @@ -191,9 +124,6 @@ PowerStatusView::AttachedToWindow() SetLowColor(ViewColor()); - BMessage update(kMsgUpdate); - fMessageRunner = new BMessageRunner(this, &update, kUpdateInterval); - _Update(); } @@ -201,7 +131,7 @@ PowerStatusView::AttachedToWindow() void PowerStatusView::DetachedFromWindow() { - delete fMessageRunner; + } @@ -213,35 +143,20 @@ PowerStatusView::MessageReceived(BMessage *message) _Update(); break; - case kMsgToggleLabel: - fShowLabel = !fShowLabel; - _Update(true); - break; - - case kMsgToggleTime: - fShowTime = !fShowTime; - _Update(true); - break; - - case kMsgToggleStatusIcon: - fShowStatusIcon = !fShowStatusIcon; - _Update(true); - break; - - case B_ABOUT_REQUESTED: - _AboutRequested(); - break; - - case B_QUIT_REQUESTED: - _Quit(); - break; - default: BView::MessageReceived(message); } } +void +PowerStatusView::GetPreferredSize(float *width, float *height) +{ + *width = fPreferredSize.width; + *height = fPreferredSize.height; +} + + void PowerStatusView::_DrawBattery(BRect rect) { @@ -261,8 +176,7 @@ PowerStatusView::_DrawBattery(BRect rect) gap = 2; } - if (fOnline) - SetHighColor(92, 92, 92); + SetHighColor(92, 92, 92); StrokeRect(rect); @@ -277,6 +191,8 @@ PowerStatusView::_DrawBattery(BRect rect) if (percent > 0) { if (percent < 16) SetHighColor(180, 0, 0); + else + SetHighColor(20, 180, 0); rect.InsetBy(gap + 1, gap + 1); if (gap > 1) { @@ -358,53 +274,6 @@ PowerStatusView::Draw(BRect updateRect) } -void -PowerStatusView::MouseDown(BPoint point) -{ - BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING, false, false); - menu->SetFont(be_plain_font); - - BMenuItem* item; - menu->AddItem(item = new BMenuItem("Show Text Label", new BMessage(kMsgToggleLabel))); - if (fShowLabel) - item->SetMarked(true); - menu->AddItem(item = new BMenuItem("Show Status Icon", - new BMessage(kMsgToggleStatusIcon))); - if (fShowStatusIcon) - item->SetMarked(true); - menu->AddItem(new BMenuItem(!fShowTime ? "Show Time" : "Show Percent", - new BMessage(kMsgToggleTime))); - - menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("About" B_UTF8_ELLIPSIS, new BMessage(B_ABOUT_REQUESTED))); - menu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED))); - menu->SetTargetForItems(this); - - ConvertToScreen(&point); - menu->Go(point, true, false, true); -} - - -void -PowerStatusView::_AboutRequested() -{ - BAlert *alert = new BAlert("about", "PowerStatus\n" - "\twritten by Axel Dörfler\n" - "\tCopyright 2006, Haiku, Inc.\n", "Ok"); - BTextView *view = alert->TextView(); - BFont font; - - view->SetStylable(true); - - view->GetFont(&font); - font.SetSize(18); - font.SetFace(B_BOLD_FACE); - view->SetFontAndColor(0, 11, &font); - - alert->Go(); -} - - void PowerStatusView::_SetLabel(char* buffer, size_t bufferLength) { @@ -432,6 +301,7 @@ PowerStatusView::_SetLabel(char* buffer, size_t bufferLength) } + void PowerStatusView::_Update(bool force) { @@ -439,36 +309,15 @@ PowerStatusView::_Update(bool force) bool previousTimeLeft = fTimeLeft; bool wasOnline = fOnline; -#ifdef HAIKU_TARGET_PLATFORM_HAIKU - // TODO: retrieve data from APM/ACPI kernel interface - battery_info info; - status_t status = _kern_generic_syscall(APM_SYSCALLS, APM_GET_BATTERY_INFO, &info, - sizeof(battery_info)); - if (status == B_OK) { - fPercent = info.percent; - fTimeLeft = info.time_left; - fOnline = info.online; - } -#else - if (fDevice < 0) - return; - - uint16 regs[6] = {0, 0, 0, 0, 0, 0}; - regs[0] = BIOS_APM_GET_POWER_STATUS; - regs[1] = 0x1; - if (ioctl(fDevice, APM_BIOS_CALL, regs) == 0) { - fOnline = (regs[1] >> 8) != 0 && (regs[1] >> 8) != 2; - fPercent = regs[2] & 255; - if (fPercent > 100) - fPercent = -1; - fTimeLeft = fPercent >= 0 ? regs[3] : -1; - if (fTimeLeft > 0xffff) - fTimeLeft = -1; - else if (fTimeLeft & 0x8000) - fTimeLeft = (fTimeLeft & 0x7fff) * 60; - } -#endif + _GetBatteryInfo(&fBatteryInfo, fBatteryId); + fPercent = (100 * fBatteryInfo.capacity) / fBatteryInfo.full_capacity; + fTimeLeft = fBatteryInfo.time_left; + if (fBatteryInfo.state & BATTERY_CHARGING) + fOnline = true; + else + fOnline = false; + if (fInDeskbar) { // make sure the tray icon is large enough float width = fShowStatusIcon ? kMinIconWidth + 2 : 0; @@ -496,12 +345,242 @@ PowerStatusView::_Update(bool force) } +void +PowerStatusView::_GetBatteryInfo(battery_info* batteryInfo, int batteryId) +{ + if (batteryId >= 0) { + fDriverInterface->GetBatteryInfo(batteryInfo, batteryId); + } + else for (int i = 0; i < fDriverInterface->GetBatteryCount(); i++) { + battery_info tmpInfo; + fDriverInterface->GetBatteryInfo(&tmpInfo, i); + + if (i == 0) + *batteryInfo = tmpInfo; + else { + batteryInfo->state &= tmpInfo.state; + batteryInfo->capacity += tmpInfo.capacity; + batteryInfo->full_capacity += tmpInfo.full_capacity; + batteryInfo->time_left += tmpInfo.time_left; + } + } +} + + +// #pragma mark - + + +PowerStatusReplicant::PowerStatusReplicant(BRect frame, int32 resizingMode, + bool inDeskbar) + : + PowerStatusView(NULL, frame, resizingMode, -1, inDeskbar) +{ + _Init(); + + if (!inDeskbar) { + // we were obviously added to a standard window - let's add a dragger + frame.OffsetTo(B_ORIGIN); + frame.top = frame.bottom - 7; + frame.left = frame.right - 7; + BDragger* dragger = new BDragger(frame, this, + B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + AddChild(dragger); + } else + _Update(); +} + + +PowerStatusReplicant::PowerStatusReplicant(BMessage* archive) + : + PowerStatusView(archive) +{ + _Init(); +} + + +PowerStatusReplicant::~PowerStatusReplicant() +{ + if (fExtWindowMessenger) + delete fExtWindowMessenger; + + fDriverInterface->StopWatching(this); + fDriverInterface->Disconnect(); + delete fDriverInterface; +} + + +PowerStatusReplicant* +PowerStatusReplicant::Instantiate(BMessage* archive) +{ + if (!validate_instantiation(archive, "PowerStatusReplicant")) + return NULL; + + return new PowerStatusReplicant(archive); +} + + +status_t +PowerStatusReplicant::Archive(BMessage* archive, bool deep) const +{ + status_t status = PowerStatusView::Archive(archive, deep); + if (status == B_OK) + status = archive->AddString("add_on", kSignature); + if (status == B_OK) + status = archive->AddString("class", "PowerStatusReplicant"); + + return status; +} + + +void +PowerStatusReplicant::MessageReceived(BMessage *message) +{ + switch (message->what) { + case kMsgToggleLabel: + fShowLabel = !fShowLabel; + _Update(true); + break; + + case kMsgToggleTime: + fShowTime = !fShowTime; + _Update(true); + break; + + case kMsgToggleStatusIcon: + fShowStatusIcon = !fShowStatusIcon; + _Update(true); + break; + + case kMsgToggleExtInfo: + _OpenExtendedWindow(); + break; + + case B_ABOUT_REQUESTED: + _AboutRequested(); + break; + + case B_QUIT_REQUESTED: + _Quit(); + break; + + default: + PowerStatusView::MessageReceived(message); + } +} + + +void +PowerStatusReplicant::MouseDown(BPoint point) +{ + BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING, false, false); + menu->SetFont(be_plain_font); + + BMenuItem* item; + menu->AddItem(item = new BMenuItem("Show Text Label", + new BMessage(kMsgToggleLabel))); + if (fShowLabel) + item->SetMarked(true); + menu->AddItem(item = new BMenuItem("Show Status Icon", + new BMessage(kMsgToggleStatusIcon))); + if (fShowStatusIcon) + item->SetMarked(true); + menu->AddItem(new BMenuItem(!fShowTime ? "Show Time" : "Show Percent", + new BMessage(kMsgToggleTime))); + + menu->AddItem(new BMenuItem("Battery Info", + new BMessage(kMsgToggleExtInfo))); + + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("About" B_UTF8_ELLIPSIS, + new BMessage(B_ABOUT_REQUESTED))); + menu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED))); + menu->SetTargetForItems(this); + + ConvertToScreen(&point); + menu->Go(point, true, false, true); +} + + +void +PowerStatusReplicant::_AboutRequested() +{ + BAlert *alert = new BAlert("about", "PowerStatus\n" + "written by Axel Dörfler,\n" + "\tClemens Zeidler\n" + "\tCopyright 2006, Haiku, Inc.\n", "Ok"); + BTextView *view = alert->TextView(); + BFont font; + + view->SetStylable(true); + + view->GetFont(&font); + font.SetSize(18); + font.SetFace(B_BOLD_FACE); + view->SetFontAndColor(0, 11, &font); + + alert->Go(); +} + + +void +PowerStatusReplicant::_Init() +{ + fDriverInterface = new ACPIDriverInterface; + if (fDriverInterface->Connect() != B_OK) { + delete fDriverInterface; + fDriverInterface = new APMDriverInterface; + if (fDriverInterface->Connect() != B_OK) { + fprintf(stderr, "No power interface found.\n"); + _Quit(); + } + } + + fExtendedWindow = NULL; + fExtWindowMessenger = NULL; + + fDriverInterface->StartWatching(this); +} + + +void +PowerStatusReplicant::_Quit() +{ + if (fInDeskbar) { + BDeskbar deskbar; + deskbar.RemoveItem(kDeskbarItemName); + } else + be_app->PostMessage(B_QUIT_REQUESTED); +} + + +void +PowerStatusReplicant::_OpenExtendedWindow() +{ + if (!fExtendedWindow) { + fExtendedWindow = new ExtendedInfoWindow(fDriverInterface); + fExtWindowMessenger = new BMessenger(NULL, fExtendedWindow); + fExtendedWindow->Show(); + return; + } + BMessage msg(B_SET_PROPERTY); + msg.AddSpecifier("Hidden", int32(0)); + if (fExtWindowMessenger->SendMessage(&msg) == B_BAD_PORT_ID) { + fExtendedWindow = new ExtendedInfoWindow(fDriverInterface); + fExtWindowMessenger = new BMessenger(NULL, fExtendedWindow); + fExtendedWindow->Show(); + } + else + fExtendedWindow->Activate(); + +} + + // #pragma mark - extern "C" _EXPORT BView * instantiate_deskbar_item(void) { - return new PowerStatusView(BRect(0, 0, 15, 15), B_FOLLOW_NONE, true); + return new PowerStatusReplicant(BRect(0, 0, 15, 15), B_FOLLOW_NONE, true); } diff --git a/src/apps/powerstatus/PowerStatusView.h b/src/apps/powerstatus/PowerStatusView.h index 3c6e5491ed..e4ebc7a85f 100644 --- a/src/apps/powerstatus/PowerStatusView.h +++ b/src/apps/powerstatus/PowerStatusView.h @@ -4,53 +4,90 @@ * * Authors: * Axel Dörfler, axeld@pinc-software.de + * Clemens Zeidler, haiku@Clemens-Zeidler.de */ + #ifndef POWER_STATUS_VIEW_H #define POWER_STATUS_VIEW_H #include -class BMessageRunner; +#include "DriverInterface.h" class PowerStatusView : public BView { public: - PowerStatusView(BRect frame, int32 resizingMode, bool inDeskbar = false); - PowerStatusView(BMessage* archive); + PowerStatusView(PowerStatusDriverInterface* interface, + BRect frame, int32 resizingMode, int batteryId = -1, + bool inDeskbar = false); + virtual ~PowerStatusView(); - static PowerStatusView* Instantiate(BMessage* archive); virtual status_t Archive(BMessage* archive, bool deep = true) const; virtual void AttachedToWindow(); virtual void DetachedFromWindow(); virtual void MessageReceived(BMessage* message); - virtual void MouseDown(BPoint where); virtual void Draw(BRect updateRect); + virtual void GetPreferredSize(float *width, float *height); + + protected: + PowerStatusView(BMessage* archive); + + virtual void _Update(bool force = false); + virtual void _GetBatteryInfo(battery_info* info, int batteryId); - private: - void _AboutRequested(); - void _Quit(); - void _Init(); - void _SetLabel(char* buffer, size_t bufferLength); - void _Update(bool force = false); - void _DrawBattery(BRect rect); + PowerStatusDriverInterface* fDriverInterface; - BMessageRunner* fMessageRunner; - bool fInDeskbar; bool fShowLabel; bool fShowTime; bool fShowStatusIcon; + + int fBatteryId; + bool fInDeskbar; + + battery_info fBatteryInfo; + + private: + void _Init(); + void _SetLabel(char* buffer, size_t bufferLength); + void _DrawBattery(BRect rect); int32 fPercent; time_t fTimeLeft; bool fOnline; -#ifndef HAIKU_TARGET_PLATFORM_HAIKU - int fDevice; -#endif + BSize fPreferredSize; }; + +class PowerStatusReplicant : public PowerStatusView +{ + public: + PowerStatusReplicant(BRect frame, int32 resizingMode, + bool inDeskbar = false); + PowerStatusReplicant(BMessage* archive); + + virtual ~PowerStatusReplicant(); + + static PowerStatusReplicant* Instantiate(BMessage* archive); + virtual status_t Archive(BMessage* archive, bool deep = true) const; + + virtual void MessageReceived(BMessage* message); + virtual void MouseDown(BPoint where); + + private: + void _AboutRequested(); + void _Init(); + void _Quit(); + + void _OpenExtendedWindow(); + + BWindow* fExtendedWindow; + BMessenger* fExtWindowMessenger; +}; + + #endif // POWER_STATUS_VIEW_H diff --git a/src/apps/powerstatus/PowerStatusWindow.cpp b/src/apps/powerstatus/PowerStatusWindow.cpp index fc97156dcd..7463fbb9e2 100644 --- a/src/apps/powerstatus/PowerStatusWindow.cpp +++ b/src/apps/powerstatus/PowerStatusWindow.cpp @@ -21,7 +21,7 @@ PowerStatusWindow::PowerStatusWindow() topView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); AddChild(topView); - topView->AddChild(new PowerStatusView(Bounds(), B_FOLLOW_ALL)); + topView->AddChild(new PowerStatusReplicant(Bounds(), B_FOLLOW_ALL)); }