Rework Deskbar's tray replicant support a bit. Instead of relying on a live query
for be:deskbar_item_status in order to determine which replicants are supposed to be living in the tray, a list of entry refs is now stored. While the former approach was cool, it doesn't really work in either a multiuser or a package-aware world, where executables are generally read-only. Note this means you'll lose your existing replicants the first time you run this new revision, and need to re-add them. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@43004 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1028,6 +1028,13 @@ TBarView::AddItem(BMessage* item, DeskbarShelf, int32* id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
TBarView::AddItem(BEntry* entry, DeskbarShelf, int32* id)
|
||||||
|
{
|
||||||
|
return fReplicantTray->LoadAddOn(entry, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TBarView::RemoveItem(int32 id)
|
TBarView::RemoveItem(int32 id)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ class TBarView : public BView {
|
|||||||
int32 CountItems(DeskbarShelf shelf);
|
int32 CountItems(DeskbarShelf shelf);
|
||||||
|
|
||||||
status_t AddItem(BMessage* archive, DeskbarShelf shelf, int32* id);
|
status_t AddItem(BMessage* archive, DeskbarShelf shelf, int32* id);
|
||||||
|
status_t AddItem(BEntry* entry, DeskbarShelf shelf, int32* id);
|
||||||
|
|
||||||
void RemoveItem(int32 id);
|
void RemoveItem(int32 id);
|
||||||
void RemoveItem(const char* name, DeskbarShelf shelf);
|
void RemoveItem(const char* name, DeskbarShelf shelf);
|
||||||
|
|||||||
@@ -518,7 +518,7 @@ TBarWindow::CountItems(BMessage* message)
|
|||||||
void
|
void
|
||||||
TBarWindow::AddItem(BMessage* message)
|
TBarWindow::AddItem(BMessage* message)
|
||||||
{
|
{
|
||||||
DeskbarShelf shelf;
|
DeskbarShelf shelf = B_DESKBAR_TRAY;
|
||||||
entry_ref ref;
|
entry_ref ref;
|
||||||
int32 id = 999;
|
int32 id = 999;
|
||||||
BMessage reply;
|
BMessage reply;
|
||||||
@@ -527,24 +527,17 @@ TBarWindow::AddItem(BMessage* message)
|
|||||||
BMessage archivedView;
|
BMessage archivedView;
|
||||||
if (message->FindMessage("view", &archivedView) == B_OK) {
|
if (message->FindMessage("view", &archivedView) == B_OK) {
|
||||||
#if SHELF_AWARE
|
#if SHELF_AWARE
|
||||||
if (message->FindInt32("shelf", (int32*)&shelf) != B_OK)
|
message->FindInt32("shelf", &shelf);
|
||||||
#endif
|
#endif
|
||||||
shelf = B_DESKBAR_TRAY;
|
|
||||||
|
|
||||||
BMessage* archive = new BMessage(archivedView);
|
BMessage* archive = new BMessage(archivedView);
|
||||||
err = fBarView->AddItem(archive, shelf, &id);
|
err = fBarView->AddItem(archive, shelf, &id);
|
||||||
if (err < B_OK)
|
if (err < B_OK)
|
||||||
delete archive;
|
delete archive;
|
||||||
} else if (message->FindRef("addon", &ref) == B_OK) {
|
} else if (message->FindRef("addon", &ref) == B_OK) {
|
||||||
// exposing the name of the view here is not so great
|
|
||||||
TReplicantTray* tray
|
|
||||||
= dynamic_cast<TReplicantTray*>(FindView("Status"));
|
|
||||||
if (tray) {
|
|
||||||
// Force this into the deskbar even if the security code is wrong
|
|
||||||
// This is OK because the user specifically asked for this replicant
|
|
||||||
BEntry entry(&ref);
|
BEntry entry(&ref);
|
||||||
err = tray->LoadAddOn(&entry, &id, true);
|
err = entry.InitCheck();
|
||||||
}
|
if (err == B_OK)
|
||||||
|
err = fBarView->AddItem(&entry, shelf, &id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err == B_OK)
|
if (err == B_OK)
|
||||||
|
|||||||
+35
-179
@@ -83,11 +83,8 @@ using std::max;
|
|||||||
|
|
||||||
const char* const kInstantiateItemCFunctionName = "instantiate_deskbar_item";
|
const char* const kInstantiateItemCFunctionName = "instantiate_deskbar_item";
|
||||||
const char* const kInstantiateEntryCFunctionName = "instantiate_deskbar_entry";
|
const char* const kInstantiateEntryCFunctionName = "instantiate_deskbar_entry";
|
||||||
const char* const kDeskbarSecurityCodeFile = "Deskbar_security_code";
|
const char* const kReplicantSettingsFile = "Deskbar_replicants";
|
||||||
const char* const kDeskbarSecurityCodeAttr = "be:deskbar_security_code";
|
const char* const kReplicantRefField = "replicant";
|
||||||
const char* const kStatusPredicate = "be:deskbar_item_status";
|
|
||||||
const char* const kEnabledPredicate = "be:deskbar_item_status = enabled";
|
|
||||||
const char* const kDisabledPredicate = "be:deskbar_item_status = disabled";
|
|
||||||
|
|
||||||
float sMinimumWindowWidth = kGutter + kMinimumTrayWidth + kDragRegionWidth;
|
float sMinimumWindowWidth = kGutter + kMinimumTrayWidth + kDragRegionWidth;
|
||||||
|
|
||||||
@@ -331,7 +328,6 @@ TReplicantTray::MessageReceived(BMessage* message)
|
|||||||
|
|
||||||
#ifdef DB_ADDONS
|
#ifdef DB_ADDONS
|
||||||
case B_NODE_MONITOR:
|
case B_NODE_MONITOR:
|
||||||
case B_QUERY_UPDATE:
|
|
||||||
HandleEntryUpdate(message);
|
HandleEntryUpdate(message);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@@ -410,53 +406,48 @@ TReplicantTray::InitAddOnSupport()
|
|||||||
{
|
{
|
||||||
// list to maintain refs to each rep added/deleted
|
// list to maintain refs to each rep added/deleted
|
||||||
fItemList = new BList();
|
fItemList = new BList();
|
||||||
bool haveKey = false;
|
|
||||||
BPath path;
|
BPath path;
|
||||||
|
|
||||||
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path, true) == B_OK) {
|
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path, true) == B_OK) {
|
||||||
path.Append(kDeskbarSecurityCodeFile);
|
path.Append(kReplicantSettingsFile);
|
||||||
|
|
||||||
BFile file(path.Path(), B_READ_ONLY);
|
BFile file(path.Path(), B_READ_ONLY);
|
||||||
if (file.InitCheck() == B_OK
|
if (file.InitCheck() == B_OK) {
|
||||||
&& file.Read(&fDeskbarSecurityCode, sizeof(fDeskbarSecurityCode))
|
entry_ref ref;
|
||||||
== sizeof(fDeskbarSecurityCode))
|
status_t result;
|
||||||
haveKey = true;
|
BEntry entry;
|
||||||
}
|
int32 id;
|
||||||
if (!haveKey) {
|
if (fAddOnSettings.Unflatten(&file) == B_OK) {
|
||||||
// create the security code
|
for (int32 i = 0; fAddOnSettings.FindRef(kReplicantRefField,
|
||||||
bigtime_t real = real_time_clock_usecs();
|
i, &ref) == B_OK; i++) {
|
||||||
bigtime_t boot = system_time();
|
if (entry.SetTo(&ref) == B_OK && entry.Exists()) {
|
||||||
// two computers would have to have exactly matching clocks, and launch
|
result = LoadAddOn(&entry, &id, false);
|
||||||
// Deskbar at the exact same time into the bootsequence in order for
|
} else
|
||||||
// their security-ID to be identical
|
result = B_ENTRY_NOT_FOUND;
|
||||||
fDeskbarSecurityCode = ((real & 0xffffffffULL) << 32)
|
|
||||||
| (boot & 0xffffffffULL);
|
|
||||||
|
|
||||||
if (find_directory (B_USER_SETTINGS_DIRECTORY, &path, true) == B_OK) {
|
if (result != B_OK) {
|
||||||
path.Append(kDeskbarSecurityCodeFile);
|
fAddOnSettings.RemoveData(kReplicantRefField, i);
|
||||||
BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE
|
--i;
|
||||||
| B_ERASE_FILE);
|
}
|
||||||
if (file.InitCheck() == B_OK)
|
}
|
||||||
file.Write(&fDeskbarSecurityCode, sizeof(fDeskbarSecurityCode));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// for each volume currently mounted index the volume with our indices
|
|
||||||
BVolumeRoster roster;
|
|
||||||
BVolume volume;
|
|
||||||
while (roster.GetNextVolume(&volume) == B_OK) {
|
|
||||||
fs_create_index(volume.Device(), kStatusPredicate, B_STRING_TYPE, 0);
|
|
||||||
RunAddOnQuery(&volume, kEnabledPredicate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// we also watch for volumes mounted and unmounted
|
|
||||||
watch_node(NULL, B_WATCH_MOUNT | B_WATCH_ATTR, this, Window());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TReplicantTray::DeleteAddOnSupport()
|
TReplicantTray::DeleteAddOnSupport()
|
||||||
{
|
{
|
||||||
|
BPath path;
|
||||||
|
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path, true) == B_OK) {
|
||||||
|
path.Append(kReplicantSettingsFile);
|
||||||
|
|
||||||
|
BFile file(path.Path(), B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
|
||||||
|
if (file.InitCheck() == B_OK)
|
||||||
|
fAddOnSettings.Flatten(&file);
|
||||||
|
}
|
||||||
|
|
||||||
for (int32 i = fItemList->CountItems(); i-- > 0 ;) {
|
for (int32 i = fItemList->CountItems(); i-- > 0 ;) {
|
||||||
DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->RemoveItem(i);
|
DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->RemoveItem(i);
|
||||||
if (item) {
|
if (item) {
|
||||||
@@ -473,47 +464,6 @@ TReplicantTray::DeleteAddOnSupport()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
TReplicantTray::RunAddOnQuery(BVolume* volume, const char* predicate)
|
|
||||||
{
|
|
||||||
// Since the new BFS supports querying for attributes without
|
|
||||||
// an index, we only run the query if the index exists (for
|
|
||||||
// newly mounted devices only - the Deskbar will automatically
|
|
||||||
// create an index for every device mounted at startup).
|
|
||||||
index_info info;
|
|
||||||
if (!volume->KnowsQuery()
|
|
||||||
|| fs_stat_index(volume->Device(), kStatusPredicate, &info) != 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// run a new query on a specific volume and make it live
|
|
||||||
BQuery query;
|
|
||||||
query.SetVolume(volume);
|
|
||||||
query.SetPredicate(predicate);
|
|
||||||
query.Fetch();
|
|
||||||
|
|
||||||
int32 id;
|
|
||||||
BEntry entry;
|
|
||||||
while (query.GetNextEntry(&entry) == B_OK) {
|
|
||||||
// scan any entries returned
|
|
||||||
// attempt to load them as add-ons
|
|
||||||
// collisions are handled in LoadAddOn
|
|
||||||
LoadAddOn(&entry, &id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
TReplicantTray::IsAddOn(entry_ref& ref)
|
|
||||||
{
|
|
||||||
BFile file(&ref, B_READ_ONLY);
|
|
||||||
|
|
||||||
char status[64];
|
|
||||||
ssize_t size = file.ReadAttr(kStatusPredicate, B_STRING_TYPE, 0, &status,
|
|
||||||
sizeof(status));
|
|
||||||
return size > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DeskbarItemInfo*
|
DeskbarItemInfo*
|
||||||
TReplicantTray::DeskbarItemFor(node_ref& nodeRef)
|
TReplicantTray::DeskbarItemFor(node_ref& nodeRef)
|
||||||
{
|
{
|
||||||
@@ -565,61 +515,6 @@ TReplicantTray::HandleEntryUpdate(BMessage* message)
|
|||||||
|
|
||||||
BPath path;
|
BPath path;
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case B_ENTRY_CREATED:
|
|
||||||
{
|
|
||||||
// entry was just listed, matches live query
|
|
||||||
const char* name;
|
|
||||||
ino_t directory;
|
|
||||||
dev_t device;
|
|
||||||
// received when an app adds a ref to the
|
|
||||||
// Deskbar add-ons folder
|
|
||||||
if (message->FindString("name", &name) == B_OK
|
|
||||||
&& message->FindInt64("directory", &directory) == B_OK
|
|
||||||
&& message->FindInt32("device", &device) == B_OK) {
|
|
||||||
entry_ref ref(device, directory, name);
|
|
||||||
// see if this item has the attribute
|
|
||||||
// that we expect
|
|
||||||
if (IsAddOn(ref)) {
|
|
||||||
int32 id;
|
|
||||||
BEntry entry(&ref);
|
|
||||||
LoadAddOn(&entry, &id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case B_ATTR_CHANGED:
|
|
||||||
{
|
|
||||||
// from node watch on individual items
|
|
||||||
// (node_watch added in LoadAddOn)
|
|
||||||
node_ref nodeRef;
|
|
||||||
if (message->FindInt32("device", &(nodeRef.device)) == B_OK
|
|
||||||
&& message->FindInt64("node", &(nodeRef.node)) == B_OK) {
|
|
||||||
// get the add-on this is for
|
|
||||||
DeskbarItemInfo* item = DeskbarItemFor(nodeRef);
|
|
||||||
if (item == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
BFile file(&item->entryRef, B_READ_ONLY);
|
|
||||||
|
|
||||||
char status[255];
|
|
||||||
ssize_t size = file.ReadAttr(kStatusPredicate,
|
|
||||||
B_STRING_TYPE, 0, status, sizeof(status) - 1);
|
|
||||||
status[sizeof(status) - 1] = '\0';
|
|
||||||
|
|
||||||
// attribute was removed
|
|
||||||
if (size == B_ENTRY_NOT_FOUND) {
|
|
||||||
// cleans up and removes node_watch
|
|
||||||
UnloadAddOn(&nodeRef, NULL, true, false);
|
|
||||||
} else if (!strcmp(status, "enable")) {
|
|
||||||
int32 id;
|
|
||||||
BEntry entry(&item->entryRef, true);
|
|
||||||
LoadAddOn(&entry, &id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case B_ENTRY_MOVED:
|
case B_ENTRY_MOVED:
|
||||||
{
|
{
|
||||||
entry_ref ref;
|
entry_ref ref;
|
||||||
@@ -663,32 +558,6 @@ TReplicantTray::HandleEntryUpdate(BMessage* message)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case B_DEVICE_MOUNTED:
|
|
||||||
{
|
|
||||||
// run a new query on the new device
|
|
||||||
dev_t device;
|
|
||||||
if (message->FindInt32("new device", &device) != B_OK)
|
|
||||||
break;
|
|
||||||
|
|
||||||
BVolume volume(device);
|
|
||||||
RunAddOnQuery(&volume, kEnabledPredicate);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case B_DEVICE_UNMOUNTED:
|
|
||||||
{
|
|
||||||
// remove all items associated with the device
|
|
||||||
// unmounted
|
|
||||||
// contrary to what the BeBook says, the item is called "device",
|
|
||||||
// not "new device" like it is for B_DEVICE_MOUNTED
|
|
||||||
dev_t device;
|
|
||||||
if (message->FindInt32("device", &device) != B_OK)
|
|
||||||
break;
|
|
||||||
|
|
||||||
UnloadAddOn(NULL, &device, false, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -698,7 +567,7 @@ TReplicantTray::HandleEntryUpdate(BMessage* message)
|
|||||||
primary function is the Instantiate function
|
primary function is the Instantiate function
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
TReplicantTray::LoadAddOn(BEntry* entry, int32* id, bool force)
|
TReplicantTray::LoadAddOn(BEntry* entry, int32* id, bool addToSettings)
|
||||||
{
|
{
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
@@ -710,21 +579,6 @@ TReplicantTray::LoadAddOn(BEntry* entry, int32* id, bool force)
|
|||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
BNode node(entry);
|
BNode node(entry);
|
||||||
if (!force) {
|
|
||||||
status_t error = node.InitCheck();
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
uint64 deskbarID;
|
|
||||||
ssize_t size = node.ReadAttr(kDeskbarSecurityCodeAttr, B_UINT64_TYPE,
|
|
||||||
0, &deskbarID, sizeof(fDeskbarSecurityCode));
|
|
||||||
if (size != sizeof(fDeskbarSecurityCode)
|
|
||||||
|| deskbarID != fDeskbarSecurityCode) {
|
|
||||||
// no code or code doesn't match
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BPath path;
|
BPath path;
|
||||||
status_t status = entry->GetPath(&path);
|
status_t status = entry->GetPath(&path);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
@@ -770,8 +624,11 @@ TReplicantTray::LoadAddOn(BEntry* entry, int32* id, bool force)
|
|||||||
AddIcon(data, id, &ref);
|
AddIcon(data, id, &ref);
|
||||||
// add the rep; adds info to list
|
// add the rep; adds info to list
|
||||||
|
|
||||||
node.WriteAttr(kDeskbarSecurityCodeAttr, B_UINT64_TYPE, 0,
|
if (addToSettings) {
|
||||||
&fDeskbarSecurityCode, sizeof(fDeskbarSecurityCode));
|
entry_ref ref;
|
||||||
|
if (entry->GetRef(&ref) == B_OK)
|
||||||
|
fAddOnSettings.AddRef(kReplicantRefField, &ref);
|
||||||
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -841,7 +698,6 @@ TReplicantTray::RemoveItem(int32 id)
|
|||||||
// attribute was added via Deskbar API (AddItem(entry_ref*, int32*)
|
// attribute was added via Deskbar API (AddItem(entry_ref*, int32*)
|
||||||
if (item->isAddOn) {
|
if (item->isAddOn) {
|
||||||
BNode node(&item->entryRef);
|
BNode node(&item->entryRef);
|
||||||
node.RemoveAttr(kStatusPredicate);
|
|
||||||
watch_node(&item->nodeRef, B_STOP_WATCHING, this, Window());
|
watch_node(&item->nodeRef, B_STOP_WATCHING, this, Window());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ public:
|
|||||||
void DealWithClock(bool);
|
void DealWithClock(bool);
|
||||||
|
|
||||||
#ifdef DB_ADDONS
|
#ifdef DB_ADDONS
|
||||||
status_t LoadAddOn(BEntry* entry, int32* id, bool force = false);
|
status_t LoadAddOn(BEntry* entry, int32* id, bool addToSettings = true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -129,9 +129,7 @@ private:
|
|||||||
#ifdef DB_ADDONS
|
#ifdef DB_ADDONS
|
||||||
void InitAddOnSupport();
|
void InitAddOnSupport();
|
||||||
void DeleteAddOnSupport();
|
void DeleteAddOnSupport();
|
||||||
void RunAddOnQuery(BVolume* volume, const char* predicated);
|
|
||||||
|
|
||||||
bool IsAddOn(entry_ref &ref);
|
|
||||||
DeskbarItemInfo* DeskbarItemFor(node_ref &nodeRef);
|
DeskbarItemInfo* DeskbarItemFor(node_ref &nodeRef);
|
||||||
DeskbarItemInfo* DeskbarItemFor(int32 id);
|
DeskbarItemInfo* DeskbarItemFor(int32 id);
|
||||||
bool NodeExists(node_ref &nodeRef);
|
bool NodeExists(node_ref &nodeRef);
|
||||||
@@ -162,7 +160,7 @@ private:
|
|||||||
bool fAlignmentSupport;
|
bool fAlignmentSupport;
|
||||||
#ifdef DB_ADDONS
|
#ifdef DB_ADDONS
|
||||||
BList* fItemList;
|
BList* fItemList;
|
||||||
uint64 fDeskbarSecurityCode;
|
BMessage fAddOnSettings;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user