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. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* Axel Dörfler, [email protected] * Axel Dörfler, [email protected]
* Hugo Santos, [email protected] * Hugo Santos, [email protected]
* Dario Casalinuovo * Dario Casalinuovo
* Rene Gollent, [email protected]
*/ */
@@ -105,8 +106,7 @@ NetworkStatusView::NetworkStatusView(BRect frame, int32 resizingMode,
bool inDeskbar) bool inDeskbar)
: BView(frame, kDeskbarItemName, resizingMode, : BView(frame, kDeskbarItemName, resizingMode,
B_WILL_DRAW | B_FRAME_EVENTS), B_WILL_DRAW | B_FRAME_EVENTS),
fInDeskbar(inDeskbar), fInDeskbar(inDeskbar)
fStatus(kStatusUnknown)
{ {
_Init(); _Init();
@@ -326,11 +326,18 @@ NetworkStatusView::FrameResized(float width, float height)
void void
NetworkStatusView::Draw(BRect updateRect) 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; return;
SetDrawingMode(B_OP_ALPHA); SetDrawingMode(B_OP_ALPHA);
DrawBitmap(fTrayIcons[fStatus]); DrawBitmap(fTrayIcons[status]);
SetDrawingMode(B_OP_COPY); SetDrawingMode(B_OP_COPY);
} }
@@ -409,11 +416,14 @@ NetworkStatusView::MouseDown(BPoint point)
BPopUpMenu* menu = new BPopUpMenu(B_EMPTY_STRING, false, false); BPopUpMenu* menu = new BPopUpMenu(B_EMPTY_STRING, false, false);
menu->SetAsyncAutoDestruct(true); menu->SetAsyncAutoDestruct(true);
menu->SetFont(be_plain_font); menu->SetFont(be_plain_font);
BString wifiInterface;
BNetworkDevice wifiDevice;
// Add interfaces // Add interfaces
for (int32 i = 0; i < fInterfaces.CountItems(); i++) { for (std::map<BString, int32>::const_iterator it
BString& name = *fInterfaces.ItemAt(i); = fInterfaceStatuses.begin(); it != fInterfaceStatuses.end(); ++it) {
const BString& name = it->first;
BString label = name; BString label = name;
label += ": "; label += ": ";
@@ -423,30 +433,33 @@ NetworkStatusView::MouseDown(BPoint point)
BMessage* info = new BMessage(kMsgShowConfiguration); BMessage* info = new BMessage(kMsgShowConfiguration);
info->AddString("interface", name.String()); info->AddString("interface", name.String());
menu->AddItem(new BMenuItem(label.String(), info)); 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(); menu->AddSeparatorItem();
// Add wireless networks, if any // Add wireless networks, if any
for (int32 i = 0; i < fInterfaces.CountItems(); i++) { if (!wifiInterface.IsEmpty()) {
BNetworkDevice device(fInterfaces.ItemAt(i)->String());
if (!device.IsWireless())
continue;
std::set<BNetworkAddress> associated; std::set<BNetworkAddress> associated;
BNetworkAddress address; BNetworkAddress address;
uint32 cookie = 0; uint32 cookie = 0;
while (device.GetNextAssociatedNetwork(cookie, address) == B_OK) while (wifiDevice.GetNextAssociatedNetwork(cookie, address) == B_OK)
associated.insert(address); associated.insert(address);
wireless_network network; wireless_network network;
int32 count = 0; int32 count = 0;
cookie = 0; cookie = 0;
while (device.GetNextNetwork(cookie, network) == B_OK) { while (wifiDevice.GetNextNetwork(cookie, network) == B_OK) {
BMessage* message = new BMessage(kMsgJoinNetwork); BMessage* message = new BMessage(kMsgJoinNetwork);
message->AddString("device", device.Name()); message->AddString("device", wifiInterface);
message->AddString("name", network.name); message->AddString("name", network.name);
BMenuItem* item = new WirelessNetworkMenuItem(network.name, BMenuItem* item = new WirelessNetworkMenuItem(network.name,
@@ -465,9 +478,6 @@ NetworkStatusView::MouseDown(BPoint point)
menu->AddItem(item); menu->AddItem(item);
} }
menu->AddSeparatorItem(); menu->AddSeparatorItem();
// We only show the networks of the first wireless device we find.
break;
} }
menu->AddItem(new BMenuItem(B_TRANSLATE( menu->AddItem(new BMenuItem(B_TRANSLATE(
@@ -522,9 +532,9 @@ NetworkStatusView::_PrepareRequest(struct ifreq& request, const char* name)
int32 int32
NetworkStatusView::_DetermineInterfaceStatus(const char* name) NetworkStatusView::_DetermineInterfaceStatus(
const BNetworkInterface& interface)
{ {
BNetworkInterface interface(name);
uint32 flags = interface.Flags(); uint32 flags = interface.Flags();
int32 status = kStatusNoLink; int32 status = kStatusNoLink;
@@ -542,41 +552,40 @@ NetworkStatusView::_DetermineInterfaceStatus(const char* name)
void void
NetworkStatusView::_Update(bool force) NetworkStatusView::_Update(bool force)
{ {
int32 oldStatus = fStatus;
fStatus = kStatusUnknown;
fInterfaces.MakeEmpty();
BNetworkRoster& roster = BNetworkRoster::Default(); BNetworkRoster& roster = BNetworkRoster::Default();
BNetworkInterface interface; BNetworkInterface interface;
uint32 cookie = 0; uint32 cookie = 0;
while (roster.GetNextInterface(&cookie, interface) == B_OK) { while (roster.GetNextInterface(&cookie, interface) == B_OK) {
if ((interface.Flags() & IFF_LOOPBACK) == 0) { if ((interface.Flags() & IFF_LOOPBACK) == 0) {
fInterfaces.AddItem(new BString(interface.Name())); int32 oldStatus = kStatusUnknown;
int32 status = _DetermineInterfaceStatus(interface.Name()); if (fInterfaceStatuses.find(interface.Name())
if (status > fStatus) != fInterfaceStatuses.end()) {
fStatus = status; 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 <ObjectList.h>
#include <View.h> #include <View.h>
#include <map>
class BMessageRunner; class BMessageRunner;
class BNetworkInterface;
enum { enum {
@@ -27,6 +30,7 @@ enum {
kStatusCount kStatusCount
}; };
class NetworkStatusView : public BView { class NetworkStatusView : public BView {
public: public:
NetworkStatusView(BRect frame, int32 resizingMode, NetworkStatusView(BRect frame, int32 resizingMode,
@@ -53,15 +57,16 @@ class NetworkStatusView : public BView {
void _ShowConfiguration(BMessage* message); void _ShowConfiguration(BMessage* message);
bool _PrepareRequest(struct ifreq& request, bool _PrepareRequest(struct ifreq& request,
const char* name); const char* name);
int32 _DetermineInterfaceStatus(const char* name); int32 _DetermineInterfaceStatus(
const BNetworkInterface& interface);
void _Update(bool force = false); void _Update(bool force = false);
void _OpenNetworksPreferences(); void _OpenNetworksPreferences();
BObjectList<BString> fInterfaces; std::map<BString, int32>
fInterfaceStatuses;
bool fInDeskbar; bool fInDeskbar;
BBitmap* fTrayIcons[kStatusCount]; BBitmap* fTrayIcons[kStatusCount];
BBitmap* fNotifyIcons[kStatusCount]; BBitmap* fNotifyIcons[kStatusCount];
int32 fStatus;
}; };
#endif // NETWORK_STATUS_VIEW_H #endif // NETWORK_STATUS_VIEW_H