Rework NetworkStatus's status tracking a bit.

NetworkStatus now tracks the status of each interface separately, and
uses that information to make correct comparisons for notifications.
Previously, it would only send notifications using whatever interface
was last in the enumeration list, and if an earlier interface had a higher
configuration level than that, the notification would incorrectly be sent
as occurring on the last interface. We now send notifications for each
interface separately. The status shown by the deskbar icon remains that
of the most highly configured detected interface. Fixes #8468.
This commit is contained in:
Rene Gollent
2012-04-14 08:46:48 -04:00
parent d57a764108
commit 5c46b17139
2 changed files with 65 additions and 51 deletions
+57 -48
View File
@@ -1,11 +1,12 @@
/*
* Copyright 2006-2009, Haiku, Inc. All rights reserved.
* Copyright 2006-2012, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, [email protected]
* Hugo Santos, [email protected]
* Dario Casalinuovo
* Rene Gollent, [email protected]
*/
@@ -105,8 +106,7 @@ NetworkStatusView::NetworkStatusView(BRect frame, int32 resizingMode,
bool inDeskbar)
: BView(frame, kDeskbarItemName, resizingMode,
B_WILL_DRAW | B_FRAME_EVENTS),
fInDeskbar(inDeskbar),
fStatus(kStatusUnknown)
fInDeskbar(inDeskbar)
{
_Init();
@@ -326,11 +326,18 @@ NetworkStatusView::FrameResized(float width, float height)
void
NetworkStatusView::Draw(BRect updateRect)
{
if (fTrayIcons[fStatus] == NULL)
int32 status = kStatusUnknown;
for (std::map<BString, int32>::const_iterator it
= fInterfaceStatuses.begin(); it != fInterfaceStatuses.end(); ++it) {
if (it->second > status)
status = it->second;
}
if (fTrayIcons[status] == NULL)
return;
SetDrawingMode(B_OP_ALPHA);
DrawBitmap(fTrayIcons[fStatus]);
DrawBitmap(fTrayIcons[status]);
SetDrawingMode(B_OP_COPY);
}
@@ -409,11 +416,14 @@ NetworkStatusView::MouseDown(BPoint point)
BPopUpMenu* menu = new BPopUpMenu(B_EMPTY_STRING, false, false);
menu->SetAsyncAutoDestruct(true);
menu->SetFont(be_plain_font);
BString wifiInterface;
BNetworkDevice wifiDevice;
// Add interfaces
for (int32 i = 0; i < fInterfaces.CountItems(); i++) {
BString& name = *fInterfaces.ItemAt(i);
for (std::map<BString, int32>::const_iterator it
= fInterfaceStatuses.begin(); it != fInterfaceStatuses.end(); ++it) {
const BString& name = it->first;
BString label = name;
label += ": ";
@@ -423,30 +433,33 @@ NetworkStatusView::MouseDown(BPoint point)
BMessage* info = new BMessage(kMsgShowConfiguration);
info->AddString("interface", name.String());
menu->AddItem(new BMenuItem(label.String(), info));
// We only show the networks of the first wireless device we find.
if (wifiInterface.IsEmpty()) {
wifiDevice.SetTo(name);
if (wifiDevice.IsWireless())
wifiInterface = name;
}
}
if (!fInterfaces.IsEmpty())
if (!fInterfaceStatuses.empty())
menu->AddSeparatorItem();
// Add wireless networks, if any
for (int32 i = 0; i < fInterfaces.CountItems(); i++) {
BNetworkDevice device(fInterfaces.ItemAt(i)->String());
if (!device.IsWireless())
continue;
if (!wifiInterface.IsEmpty()) {
std::set<BNetworkAddress> associated;
BNetworkAddress address;
uint32 cookie = 0;
while (device.GetNextAssociatedNetwork(cookie, address) == B_OK)
while (wifiDevice.GetNextAssociatedNetwork(cookie, address) == B_OK)
associated.insert(address);
wireless_network network;
int32 count = 0;
cookie = 0;
while (device.GetNextNetwork(cookie, network) == B_OK) {
while (wifiDevice.GetNextNetwork(cookie, network) == B_OK) {
BMessage* message = new BMessage(kMsgJoinNetwork);
message->AddString("device", device.Name());
message->AddString("device", wifiInterface);
message->AddString("name", network.name);
BMenuItem* item = new WirelessNetworkMenuItem(network.name,
@@ -465,9 +478,6 @@ NetworkStatusView::MouseDown(BPoint point)
menu->AddItem(item);
}
menu->AddSeparatorItem();
// We only show the networks of the first wireless device we find.
break;
}
menu->AddItem(new BMenuItem(B_TRANSLATE(
@@ -522,9 +532,9 @@ NetworkStatusView::_PrepareRequest(struct ifreq& request, const char* name)
int32
NetworkStatusView::_DetermineInterfaceStatus(const char* name)
NetworkStatusView::_DetermineInterfaceStatus(
const BNetworkInterface& interface)
{
BNetworkInterface interface(name);
uint32 flags = interface.Flags();
int32 status = kStatusNoLink;
@@ -542,41 +552,40 @@ NetworkStatusView::_DetermineInterfaceStatus(const char* name)
void
NetworkStatusView::_Update(bool force)
{
int32 oldStatus = fStatus;
fStatus = kStatusUnknown;
fInterfaces.MakeEmpty();
BNetworkRoster& roster = BNetworkRoster::Default();
BNetworkInterface interface;
uint32 cookie = 0;
while (roster.GetNextInterface(&cookie, interface) == B_OK) {
if ((interface.Flags() & IFF_LOOPBACK) == 0) {
fInterfaces.AddItem(new BString(interface.Name()));
int32 status = _DetermineInterfaceStatus(interface.Name());
if (status > fStatus)
fStatus = status;
int32 oldStatus = kStatusUnknown;
if (fInterfaceStatuses.find(interface.Name())
!= fInterfaceStatuses.end()) {
oldStatus = fInterfaceStatuses[interface.Name()];
}
int32 status = _DetermineInterfaceStatus(interface);
if (oldStatus != status) {
BNotification notification(B_INFORMATION_NOTIFICATION);
notification.SetGroup(B_TRANSLATE("Network Status"));
notification.SetTitle(interface.Name());
notification.SetMessageID(interface.Name());
notification.SetIcon(fNotifyIcons[status]);
if (status == kStatusConnecting
|| (status == kStatusReady
&& oldStatus == kStatusConnecting)
|| (status == kStatusNoLink
&& oldStatus == kStatusReady)
|| (status == kStatusNoLink
&& oldStatus == kStatusConnecting)) {
// A significant state change, raise notification.
notification.SetContent(kStatusDescriptions[status]);
notification.Send();
}
Invalidate();
}
fInterfaceStatuses[interface.Name()] = status;
}
}
if (fStatus != oldStatus) {
// A little notification on major status changes for primary interface
BNotification notification(B_INFORMATION_NOTIFICATION);
notification.SetGroup(B_TRANSLATE("Network Status"));
notification.SetTitle(interface.Name());
notification.SetMessageID(interface.Name());
notification.SetIcon(fNotifyIcons[fStatus]);
if (fStatus == kStatusConnecting
|| (fStatus == kStatusReady && oldStatus == kStatusConnecting)
|| (fStatus == kStatusNoLink && oldStatus == kStatusReady)
|| (fStatus == kStatusNoLink && oldStatus == kStatusConnecting)) {
// A significant state change, raise notification.
notification.SetContent(kStatusDescriptions[fStatus]);
notification.Send();
}
Invalidate();
}
}
+8 -3
View File
@@ -14,7 +14,10 @@
#include <ObjectList.h>
#include <View.h>
#include <map>
class BMessageRunner;
class BNetworkInterface;
enum {
@@ -27,6 +30,7 @@ enum {
kStatusCount
};
class NetworkStatusView : public BView {
public:
NetworkStatusView(BRect frame, int32 resizingMode,
@@ -53,15 +57,16 @@ class NetworkStatusView : public BView {
void _ShowConfiguration(BMessage* message);
bool _PrepareRequest(struct ifreq& request,
const char* name);
int32 _DetermineInterfaceStatus(const char* name);
int32 _DetermineInterfaceStatus(
const BNetworkInterface& interface);
void _Update(bool force = false);
void _OpenNetworksPreferences();
BObjectList<BString> fInterfaces;
std::map<BString, int32>
fInterfaceStatuses;
bool fInDeskbar;
BBitmap* fTrayIcons[kStatusCount];
BBitmap* fNotifyIcons[kStatusCount];
int32 fStatus;
};
#endif // NETWORK_STATUS_VIEW_H