void TTracker::RefsReceived(BMessage *message) { OpenSelector selector = kOpen; if (message->HasInt32("launchUsingSelector")) selector = kRunOpenWithWindow; entry_ref handlingApp; if (message->FindRef("handler", &handlingApp) == B_OK) selector = kOpenWith; int32 count; uint32 type; message->GetInfo("refs", &type, &count); switch (selector) { case kRunOpenWithWindow: OpenContainerWindow(0, message, selector); // window adopts model break; case kOpenWith: { // Open With resulted in passing refs and a handler, open the files // with the handling app message->RemoveName("handler"); // have to find out if handling app is the Tracker // if it is, just pass it to the active Tracker, no matter which Tracker // was chosen to handle the refs char signature[B_MIME_TYPE_LENGTH]; signature[0] = '\0'; { BFile handlingNode(&handlingApp, O_RDONLY); BAppFileInfo appInfo(&handlingNode); appInfo.GetSignature(signature); } if (strcasecmp(signature, kTrackerSignature) != 0) { // handling app not Tracker, pass entries to the apps RefsReceived TrackerLaunch(&handlingApp, message, true); break; } // fall thru, opening refs by the Tracker, as if they were double clicked } case kOpen: { // copy over "Poses" messenger so that refs received recipients know // where the open came from BMessage *bundleThis = NULL; BMessenger messenger; if (message->FindMessenger("TrackerViewToken", &messenger) == B_OK) { bundleThis = new BMessage(); bundleThis->AddMessenger("TrackerViewToken", messenger); } for (int32 index = 0; index < count; index++) { entry_ref ref; message->FindRef("refs", index, &ref); const node_ref *nodeToClose = NULL; const node_ref *nodeToSelect = NULL; ssize_t numBytes; message->FindData("nodeRefsToClose", B_RAW_TYPE, index, (const void **)&nodeToClose, &numBytes); message->FindData("nodeRefToSelect", B_RAW_TYPE, index, (const void **)&nodeToSelect, &numBytes); OpenRef(&ref, nodeToClose, nodeToSelect, selector, bundleThis); } delete bundleThis; break; } } }
status_t TTracker::OpenRef(const entry_ref *ref, const node_ref *nodeToClose, const node_ref *nodeToSelect, OpenSelector selector, const BMessage *messageToBundle) { Model *model = NULL; BEntry entry(ref, true); status_t result = entry.InitCheck(); bool brokenLinkWithSpecificHandler = false; BString brokenLinkPreferredApp; if (result != B_OK) { model = new Model(ref, false); if (model->IsSymLink() && !model->LinkTo()) { model->GetPreferredAppForBrokenSymLink(brokenLinkPreferredApp); if (brokenLinkPreferredApp.Length() && brokenLinkPreferredApp != kTrackerSignature) brokenLinkWithSpecificHandler = true; } if (!brokenLinkWithSpecificHandler) { delete model; (new BAlert("", "There was an error resolving the link.", "Cancel", 0, 0, B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go(); return result; } } else model = new Model(&entry); result = model->InitCheck(); if (result != B_OK) { delete model; return result; } bool openAsContainer = model->IsContainer(); if (openAsContainer && selector != kOpenWith) { // if folder or query has a preferred handler and it's not the // Tracker, open it by sending refs to the handling app // if we are responding to the final open of OpenWith, just // skip this and proceed to opening the container with Tracker model->OpenNode(); BNodeInfo nodeInfo(model->Node()); char preferredApp[B_MIME_TYPE_LENGTH]; if (nodeInfo.GetPreferredApp(preferredApp) == B_OK && strcasecmp(preferredApp, kTrackerSignature) != 0) openAsContainer = false; model->CloseNode(); } if (openAsContainer || selector == kRunOpenWithWindow) { // special case opening plain folders, queries or using open with OpenContainerWindow(model, 0, selector); // window adopts model if (nodeToClose) CloseParentWaitingForChildSoon(ref, nodeToClose); } else if (model->IsQueryTemplate()) { // query template - open new find window (new FindWindow(model->EntryRef()))->Show(); if (nodeToClose) CloseParentWaitingForChildSoon(ref, nodeToClose); } else { delete model; // run Launch in a separate thread // and close parent if successfull if (nodeToClose) Thread::Launch(new EntryAndNodeDoSoonWithMessageFunctor<TTracker, bool (TTracker::*)(const entry_ref *, const node_ref *, const BMessage *)>(&TTracker::LaunchAndCloseParentIfOK, this, ref, nodeToClose, messageToBundle)); else { BMessage refsReceived(B_REFS_RECEIVED); if (messageToBundle) { refsReceived = *messageToBundle; refsReceived.what = B_REFS_RECEIVED; } refsReceived.AddRef("refs", ref); if (brokenLinkWithSpecificHandler) // This cruft is to support a hacky workaround for double-clicking // broken refs for cifs; should get fixed in R5 LaunchBrokenLink(brokenLinkPreferredApp.String(), &refsReceived); else TrackerLaunch(&refsReceived, true); } } if (nodeToSelect) SelectChildInParentSoon(ref, nodeToSelect); return B_OK; }
void TTracker::_OpenPreviouslyOpenedWindows(const char* pathFilter) { size_t filterLength = 0; if (pathFilter != NULL) filterLength = strlen(pathFilter); BDirectory deskDir; attr_info attrInfo; if (FSGetDeskDir(&deskDir) != B_OK || deskDir.GetAttrInfo(kAttrOpenWindows, &attrInfo) != B_OK) return; char *buffer = (char *)malloc((size_t)attrInfo.size); BMessage message; if (deskDir.ReadAttr(kAttrOpenWindows, B_MESSAGE_TYPE, 0, buffer, (size_t)attrInfo.size) != attrInfo.size || message.Unflatten(buffer) != B_OK) { free(buffer); return; } free(buffer); node_ref nodeRef; deskDir.GetNodeRef(&nodeRef); int32 stateMessageCounter = 0; const char *path; for (int32 i = 0; message.FindString("paths", i, &path) == B_OK; i++) { if (strncmp(path, pathFilter, filterLength)) continue; BEntry entry(path, true); if (entry.InitCheck() != B_OK) continue; int8 flags = 0; for (int32 j = 0; message.FindInt8(path, j, &flags) == B_OK; j++) { Model *model = new Model(&entry); if (model->InitCheck() == B_OK && model->IsContainer()) { BMessage state; bool restoreStateFromMessage = false; if ((flags & kOpenWindowHasState) != 0 && message.FindMessage("window state", stateMessageCounter++, &state) == B_OK) restoreStateFromMessage = true; if (restoreStateFromMessage) { OpenContainerWindow(model, 0, kOpen, kRestoreWorkspace | (flags & kOpenWindowMinimized ? kIsHidden : 0U) | kRestoreDecor, false, &state); } else { OpenContainerWindow(model, 0, kOpen, kRestoreWorkspace | (flags & kOpenWindowMinimized ? kIsHidden : 0U) | kRestoreDecor); } } else delete model; } } // Open disks window if needed if (pathFilter == NULL && TrackerSettings().ShowDisksIcon() && message.HasBool("open_disks_window")) { BEntry entry("/"); Model* model = new Model(&entry); if (model->InitCheck() == B_OK) OpenContainerWindow(model, 0, kOpen, kRestoreWorkspace); else delete model; } }
void TTracker::ReadyToRun() { gStatusWindow = new BStatusWindow(); InitMimeTypes(); InstallDefaultTemplates(); InstallIndices(); HideVarDir(); fTrashWatcher = new BTrashWatcher(); fTrashWatcher->Run(); fClipboardRefsWatcher = new BClipboardRefsWatcher(); fClipboardRefsWatcher->Run(); fAutoMounter = new AutoMounter(); fAutoMounter->Run(); fTaskLoop = new StandAloneTaskLoop(true); bool openDisksWindow = false; // open desktop window BContainerWindow *deskWindow = NULL; BVolume bootVol; BVolumeRoster().GetBootVolume(&bootVol); BDirectory deskDir; if (FSGetDeskDir(&deskDir, bootVol.Device()) == B_OK) { // create desktop BEntry entry; deskDir.GetEntry(&entry); Model *model = new Model(&entry); if (model->InitCheck() == B_OK) { AutoLock<WindowList> lock(&fWindowList); deskWindow = new BDeskWindow(&fWindowList); AutoLock<BWindow> windowLock(deskWindow); deskWindow->CreatePoseView(model); deskWindow->Init(); } else delete model; // open previously open windows attr_info attrInfo; if (!BootedInSafeMode() && deskDir.GetAttrInfo(kAttrOpenWindows, &attrInfo) == B_OK) { char *buffer = (char *)malloc((size_t)attrInfo.size); BMessage message; if (deskDir.ReadAttr(kAttrOpenWindows, B_MESSAGE_TYPE, 0, buffer, (size_t)attrInfo.size) == attrInfo.size && message.Unflatten(buffer) == B_OK) { node_ref nodeRef; deskDir.GetNodeRef(&nodeRef); int32 stateMessageCounter = 0; const char *path; for (int32 outer = 0;message.FindString("paths", outer, &path) == B_OK;outer++) { int8 flags = 0; for (int32 inner = 0;message.FindInt8(path, inner, &flags) == B_OK;inner++) { BEntry entry(path, true); if (entry.InitCheck() == B_OK) { Model *model = new Model(&entry); if (model->InitCheck() == B_OK && model->IsContainer()) { BMessage state; bool restoreStateFromMessage = false; if ((flags & kOpenWindowHasState) != 0 && message.FindMessage("window state", stateMessageCounter++, &state) == B_OK) restoreStateFromMessage = true; if (restoreStateFromMessage) OpenContainerWindow(model, 0, kOpen, kRestoreWorkspace | (flags & kOpenWindowMinimized ? kIsHidden : 0U), false, &state); else OpenContainerWindow(model, 0, kOpen, kRestoreWorkspace | (flags & kOpenWindowMinimized ? kIsHidden : 0U)); } else delete model; } } } if (message.HasBool("open_disks_window")) openDisksWindow = true; } free(buffer); } } // create model for root of everything if (deskWindow) { BEntry entry("/"); Model model(&entry); if (model.InitCheck() == B_OK) { if (TrackerSettings().ShowDisksIcon()) { // add the root icon to desktop window BMessage message; message.what = B_NODE_MONITOR; message.AddInt32("opcode", B_ENTRY_CREATED); message.AddInt32("device", model.NodeRef()->device); message.AddInt64("node", model.NodeRef()->node); message.AddInt64("directory", model.EntryRef()->directory); message.AddString("name", model.EntryRef()->name); deskWindow->PostMessage(&message, deskWindow->PoseView()); } if (openDisksWindow) OpenContainerWindow(new Model(model), 0, kOpen, kRestoreWorkspace); } } // kick off building the mime type list for find panels, etc. fMimeTypeList = new MimeTypeList(); if (!BootedInSafeMode()) // kick of transient query killer DeleteTransientQueriesTask::StartUpTransientQueryCleaner(); }
void TTracker::RefsReceived(BMessage* message) { OpenSelector selector = kOpen; if (message->HasInt32("launchUsingSelector")) selector = kRunOpenWithWindow; entry_ref handlingApp; if (message->FindRef("handler", &handlingApp) == B_OK) selector = kOpenWith; int32 count; uint32 type; message->GetInfo("refs", &type, &count); switch (selector) { case kRunOpenWithWindow: OpenContainerWindow(0, message, selector); // window adopts model break; case kOpenWith: { // Open With resulted in passing refs and a handler, // open the files with the handling app message->RemoveName("handler"); // have to find out if handling app is the Tracker // if it is, just pass it to the active Tracker, // no matter which Tracker was chosen to handle the refs char signature[B_MIME_TYPE_LENGTH]; signature[0] = '\0'; { BFile handlingNode(&handlingApp, O_RDONLY); BAppFileInfo appInfo(&handlingNode); appInfo.GetSignature(signature); } if (strcasecmp(signature, kTrackerSignature) != 0) { // handling app not Tracker, pass entries to the apps // RefsReceived TrackerLaunch(&handlingApp, message, true); break; } } // fall thru, opening refs by the Tracker as if they were // double-clicked case kOpen: { // copy over "Poses" messenger so that refs received // recipients know where the open came from BMessage* bundleThis = NULL; BMessage stackBundleThis; BMessenger messenger; if (message->FindMessenger("TrackerViewToken", &messenger) == B_OK) { bundleThis = &stackBundleThis; bundleThis->AddMessenger("TrackerViewToken", messenger); } else { // copy over any "be:*" fields -- e.g. /bin/open may include // "be:line" and "be:column" for (int32 i = 0;; i++) { char* name; type_code type; int32 count; status_t error = message->GetInfo(B_ANY_TYPE, i, &name, &type, &count); if (error != B_OK) break; if (strncmp(name, "be:", 3) != 0) continue; for (int32 k = 0; k < count; k++) { const void* data; ssize_t size; if (message->FindData(name, type, k, &data, &size) != B_OK) { break; } if (stackBundleThis.AddData(name, type, data, size) != B_OK) { break; } bundleThis = &stackBundleThis; } } } for (int32 index = 0; index < count; index++) { entry_ref ref; message->FindRef("refs", index, &ref); const node_ref* nodeToClose = NULL; const node_ref* nodeToSelect = NULL; ssize_t numBytes; message->FindData("nodeRefsToClose", B_RAW_TYPE, index, (const void**)&nodeToClose, &numBytes); message->FindData("nodeRefToSelect", B_RAW_TYPE, index, (const void**)&nodeToSelect, &numBytes); OpenRef(&ref, nodeToClose, nodeToSelect, selector, bundleThis); } break; } } }