More Tracker refactoring:

* relocated Trash dirs to volume roots by modifying find_directory() to report the trash location as volume/Trash.
 * FSUtils no longer creates /home/Desktop on every volume.
 * TrashWatcher now keeps icons in sync on all volumes.
 * Simplified FSGetDeskDir since it no longer has to worry about getting the desk directory on any volume other than the root.
 * Relocated trash context menu logic to BContainerWindow so it can also be used at the volume roots.
 * DesktopPoseView now creates a virtual Trash pose representing the trash contents as before.
 * Corrected typo: Model::WriteAttrKillForegin() -> Model::WriteAttrKillForeign().

Closes ticket #5245.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35085 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Rene Gollent 2010-01-15 05:12:45 +00:00
parent bb7cffd0d1
commit 01dffd8edd
18 changed files with 264 additions and 262 deletions

View File

@ -94,6 +94,8 @@ namespace BPrivate {
#define kAttrPoseInfo_le "_trk/pinfo_le"
#define kAttrDisksPoseInfo_be "_trk/d_pinfo"
#define kAttrDisksPoseInfo_le "_trk/d_pinfo_le"
#define kAttrTrashPoseInfo_be "_trk/t_pinfo"
#define kAttrTrashPoseInfo_le "_trk/t_pinfo_le"
#define kAttrColumns_be "_trk/columns"
#define kAttrColumns_le "_trk/columns_le"
#define kAttrViewState_be "_trk/viewstate"
@ -117,6 +119,9 @@ namespace BPrivate {
#define kAttrDisksPoseInfo kAttrDisksPoseInfo_le
#define kAttrDisksPoseInfoForeign kAttrDisksPoseInfo_be
#define kAttrTrashPoseInfo kAttrTrashPoseInfo_le
#define kAttrTrashPoseInfoForeign kAttrTrashPoseInfo_be
#define kAttrPoseInfo kAttrPoseInfo_le
#define kAttrPoseInfoForeign kAttrPoseInfo_be
@ -149,6 +154,9 @@ namespace BPrivate {
#define kAttrDisksPoseInfo kAttrDisksPoseInfo_be
#define kAttrDisksPoseInfoForeign kAttrDisksPoseInfo_le
#define kAttrTrashPoseInfo kAttrTrashPoseInfo_be
#define kAttrTrashPoseInfoForeign kAttrTrashPoseInfo_le
#define kAttrPoseInfo kAttrPoseInfo_be
#define kAttrPoseInfoForeign kAttrPoseInfo_le

View File

@ -804,7 +804,11 @@ BContainerWindow::AddContextMenus()
AddDropContextMenus(fDropContextMenu);
fDragContextMenu = new BSlowContextMenu("DragContext");
// will get added and built dynamically in ShowContextMenu
// will get added and built dynamically in ShowContextMenu
fTrashContextMenu = new BPopUpMenu("TrashContext", false, false);
fTrashContextMenu->SetFont(be_plain_font);
AddTrashContextMenus(fTrashContextMenu);
}
@ -2482,101 +2486,124 @@ BContainerWindow::ShowContextMenu(BPoint loc, const entry_ref *ref, BView *)
if (ref) {
// clicked on a pose, show file or volume context menu
Model model(ref);
BEntry entry;
if (entry.SetTo(ref) == B_OK && FSIsTrashDir(&entry)) {
bool showAsVolume = false;
bool filePanel = PoseView()->IsFilePanel();
if (Dragging()) {
fContextMenu = NULL;
BEntry entry;
model.GetEntry(&entry);
// only show for directories (directory, volume, root)
//
// don't show a popup for the trash or printers
// trash is handled in DeskWindow
//
// since this menu is opened asynchronously
// we need to make sure we don't open it more
// than once, the IsShowing flag is set in
// SlowContextPopup::AttachedToWindow and
// reset in DetachedFromWindow
// see the notes in SlowContextPopup::AttachedToWindow
if (!FSIsPrintersDir(&entry) && !fDragContextMenu->IsShowing()) {
// printf("ShowContextMenu - target is %s %i\n", ref->name, IsShowing(ref));
fDragContextMenu->ClearMenu();
// in case the ref is a symlink, resolve it
// only pop open for directories
BEntry resolvedEntry(ref, true);
if (!resolvedEntry.IsDirectory())
return;
entry_ref resolvedRef;
resolvedEntry.GetRef(&resolvedRef);
// use the resolved ref for the menu
fDragContextMenu->SetNavDir(&resolvedRef);
fDragContextMenu->SetTypesList(fCachedTypesList);
fDragContextMenu->SetTarget(BMessenger(this));
BPoseView *poseView = PoseView();
if (poseView) {
BMessenger tmpTarget(poseView);
fDragContextMenu->InitTrackingHook(
&BPoseView::MenuTrackingHook, &tmpTarget, fDragMessage);
}
// this is now asynchronous so that we don't
// deadlock in Window::Quit,
fDragContextMenu->Go(global, true, false, true);
}
return;
} else if (TargetModel()->IsRoot() || model.IsVolume()) {
fContextMenu = fVolumeContextMenu;
showAsVolume = true;
} else
fContextMenu = fFileContextMenu;
// clean up items from last context menu
if (fContextMenu) {
if (fContextMenu->Window())
if (fTrashContextMenu->Window() || Dragging())
return;
else
MenusEnded();
if (model.InitCheck() == B_OK) { // ??? Do I need this ???
if (showAsVolume) {
// non-volume enable/disable copy, move, identify
EnableNamedMenuItem(fContextMenu, kDuplicateSelection, false);
EnableNamedMenuItem(fContextMenu, kMoveToTrash, false);
EnableNamedMenuItem(fContextMenu, kIdentifyEntry, false);
// volume model, enable/disable the Unmount item
bool ejectableVolumeSelected = false;
BVolume boot;
BVolumeRoster().GetBootVolume(&boot);
BVolume volume;
volume.SetTo(model.NodeRef()->device);
if (volume != boot)
ejectableVolumeSelected = true;
EnableNamedMenuItem(fContextMenu, "Unmount", ejectableVolumeSelected);
DeleteSubmenu(fNavigationItem);
// selected item was trash, show the trash context menu instead
BPoint global(loc);
PoseView()->ConvertToScreen(&global);
PoseView()->CommitActivePose();
BRect mouse_rect(global.x, global.y, global.x, global.y);
mouse_rect.InsetBy(-5, -5);
EnableNamedMenuItem(fTrashContextMenu, kEmptyTrash,
static_cast<TTracker *>(be_app)->TrashFull());
SetupNavigationMenu(ref, fTrashContextMenu);
fTrashContextMenu->Go(global, true, false, mouse_rect, true);
} else {
bool showAsVolume = false;
bool filePanel = PoseView()->IsFilePanel();
if (Dragging()) {
fContextMenu = NULL;
BEntry entry;
model.GetEntry(&entry);
// only show for directories (directory, volume, root)
//
// don't show a popup for the trash or printers
// trash is handled in DeskWindow
//
// since this menu is opened asynchronously
// we need to make sure we don't open it more
// than once, the IsShowing flag is set in
// SlowContextPopup::AttachedToWindow and
// reset in DetachedFromWindow
// see the notes in SlowContextPopup::AttachedToWindow
if (!FSIsPrintersDir(&entry) && !fDragContextMenu->IsShowing()) {
// printf("ShowContextMenu - target is %s %i\n", ref->name, IsShowing(ref));
fDragContextMenu->ClearMenu();
// in case the ref is a symlink, resolve it
// only pop open for directories
BEntry resolvedEntry(ref, true);
if (!resolvedEntry.IsDirectory())
return;
entry_ref resolvedRef;
resolvedEntry.GetRef(&resolvedRef);
// use the resolved ref for the menu
fDragContextMenu->SetNavDir(&resolvedRef);
fDragContextMenu->SetTypesList(fCachedTypesList);
fDragContextMenu->SetTarget(BMessenger(this));
BPoseView *poseView = PoseView();
if (poseView) {
BMessenger tmpTarget(poseView);
fDragContextMenu->InitTrackingHook(
&BPoseView::MenuTrackingHook, &tmpTarget, fDragMessage);
}
// this is now asynchronous so that we don't
// deadlock in Window::Quit,
fDragContextMenu->Go(global, true, false, true);
}
return;
} else if (TargetModel()->IsRoot() || model.IsVolume()) {
fContextMenu = fVolumeContextMenu;
showAsVolume = true;
} else
fContextMenu = fFileContextMenu;
// clean up items from last context menu
if (fContextMenu) {
if (fContextMenu->Window())
return;
else
MenusEnded();
if (model.InitCheck() == B_OK) { // ??? Do I need this ???
if (showAsVolume) {
// non-volume enable/disable copy, move, identify
EnableNamedMenuItem(fContextMenu, kDuplicateSelection, false);
EnableNamedMenuItem(fContextMenu, kMoveToTrash, false);
EnableNamedMenuItem(fContextMenu, kIdentifyEntry, false);
// volume model, enable/disable the Unmount item
bool ejectableVolumeSelected = false;
BVolume boot;
BVolumeRoster().GetBootVolume(&boot);
BVolume volume;
volume.SetTo(model.NodeRef()->device);
if (volume != boot)
ejectableVolumeSelected = true;
EnableNamedMenuItem(fContextMenu, "Unmount", ejectableVolumeSelected);
}
}
SetupNavigationMenu(ref, fContextMenu);
if (!showAsVolume && !filePanel) {
SetupMoveCopyMenus(ref, fContextMenu);
SetupOpenWithMenu(fContextMenu);
}
UpdateMenu(fContextMenu, kPosePopUpContext);
fContextMenu->Go(global, true, false, mouseRect, true);
}
SetupNavigationMenu(ref, fContextMenu);
if (!showAsVolume && !filePanel) {
SetupMoveCopyMenus(ref, fContextMenu);
SetupOpenWithMenu(fContextMenu);
}
UpdateMenu(fContextMenu, kPosePopUpContext);
fContextMenu->Go(global, true, false, mouseRect, true);
}
} else if (fWindowContextMenu) {
if (fWindowContextMenu->Window())
@ -2728,6 +2755,20 @@ BContainerWindow::AddDropContextMenus(BMenu *menu)
}
void
BContainerWindow::AddTrashContextMenus(BMenu *menu)
{
// setup special trash context menu
menu->AddItem(new BMenuItem("Empty Trash",
new BMessage(kEmptyTrash)));
menu->AddItem(new BMenuItem("Open",
new BMessage(kOpenSelection), 'O'));
menu->AddItem(new BMenuItem("Get info",
new BMessage(kGetInfo), 'I'));
menu->SetTargetForItems(PoseView());
}
void
BContainerWindow::EachAddon(bool (*eachAddon)(const Model *, const char *,
uint32 shortcut, bool primary, void *context), void *passThru)
@ -3475,7 +3516,7 @@ BContainerWindow::SetUpDefaultState()
if (!TargetModel()->IsRoot()) {
BDirectory desktop;
FSGetDeskDir(&desktop, TargetModel()->EntryRef()->device);
FSGetDeskDir(&desktop);
// try copying state from our parent directory, unless it is the desktop folder
BEntry entry(TargetModel()->EntryRef());
@ -3902,10 +3943,8 @@ WindowStateNodeOpener::WindowStateNodeOpener(BContainerWindow *window, bool forW
fStreamNode(NULL)
{
if (window->TargetModel() && window->TargetModel()->IsRoot()) {
BVolume bootVol;
BVolumeRoster().GetBootVolume(&bootVol);
BDirectory dir;
if (FSGetDeskDir(&dir, bootVol.Device()) == B_OK) {
if (FSGetDeskDir(&dir) == B_OK) {
fNode = new BDirectory(dir);
fStreamNode = new AttributeStreamFileNode(fNode);
}

View File

@ -213,6 +213,7 @@ class BContainerWindow : public BWindow {
virtual void AddWindowContextMenus(BMenu *);
virtual void AddVolumeContextMenus(BMenu *);
virtual void AddDropContextMenus(BMenu *);
virtual void AddTrashContextMenus(BMenu *);
virtual void RepopulateMenus();
@ -253,6 +254,7 @@ class BContainerWindow : public BWindow {
BPopUpMenu *fWindowContextMenu;
BPopUpMenu *fDropContextMenu;
BPopUpMenu *fVolumeContextMenu;
BPopUpMenu *fTrashContextMenu;
BSlowContextMenu *fDragContextMenu;
BMenuItem *fMoveToItem;
BMenuItem *fCopyToItem;

View File

@ -147,7 +147,6 @@ BDeskWindow::~BDeskWindow()
void
BDeskWindow::Init(const BMessage *)
{
AddTrashContextMenu();
//
// Set the size of the screen before calling the container window's
// Init() because it will add volume poses to this window and
@ -356,52 +355,6 @@ BDeskWindow::AddWindowContextMenus(BMenu *menu)
}
void
BDeskWindow::AddTrashContextMenu()
{
// setup special trash context menu
fTrashContextMenu = new BPopUpMenu("TrashContext", false, false);
fTrashContextMenu->SetFont(be_plain_font);
fTrashContextMenu->AddItem(new BMenuItem("Empty Trash",
new BMessage(kEmptyTrash)));
fTrashContextMenu->AddItem(new BMenuItem("Open",
new BMessage(kOpenSelection), 'O'));
fTrashContextMenu->AddItem(new BMenuItem("Get info",
new BMessage(kGetInfo), 'I'));
fTrashContextMenu->SetTargetForItems(PoseView());
}
void
BDeskWindow::ShowContextMenu(BPoint loc, const entry_ref *ref, BView *view)
{
BEntry entry;
// cleanup previous entries
DeleteSubmenu(fNavigationItem);
if (ref && entry.SetTo(ref) == B_OK && FSIsTrashDir(&entry)) {
if (fTrashContextMenu->Window() || Dragging())
return;
// selected item was trash, show the trash context menu instead
BPoint global(loc);
PoseView()->ConvertToScreen(&global);
PoseView()->CommitActivePose();
BRect mouse_rect(global.x, global.y, global.x, global.y);
mouse_rect.InsetBy(-5, -5);
EnableNamedMenuItem(fTrashContextMenu, kEmptyTrash,
static_cast<TTracker *>(be_app)->TrashFull());
SetupNavigationMenu(ref, fTrashContextMenu);
fTrashContextMenu->Go(global, true, false, mouse_rect, true);
} else
_inherited::ShowContextMenu(loc, ref, view);
}
void
BDeskWindow::WorkspaceActivated(int32 workspace, bool state)
{

View File

@ -56,7 +56,6 @@ public:
virtual void Quit();
virtual void ScreenChanged(BRect, color_space);
virtual void ShowContextMenu(BPoint, const entry_ref *, BView *);
virtual void CreatePoseView(Model *);
virtual bool ShouldAddMenus() const;
@ -72,7 +71,6 @@ public:
protected:
virtual void AddWindowContextMenus(BMenu *);
void AddTrashContextMenu();
virtual BPoseView *NewPoseView(Model *, BRect, uint32);
virtual void WorkspaceActivated(int32, bool);

View File

@ -73,11 +73,6 @@ ShouldShowDesktopPose(dev_t device, const Model *model, const PoseInfo *)
} // namespace BPrivate
DesktopEntryListCollection::DesktopEntryListCollection()
{
}
// #pragma mark -
@ -101,7 +96,7 @@ DesktopPoseView::InitDesktopDirentIterator(BPoseView *nodeMonitoringTarget,
if (sourceModel.InitCheck() != B_OK)
return NULL;
CachedEntryIteratorList *result = new DesktopEntryListCollection();
CachedEntryIteratorList *result = new CachedEntryIteratorList();
ASSERT(!sourceModel.IsQuery());
ASSERT(sourceModel.Node());
@ -176,6 +171,13 @@ DesktopPoseView::AddPosesThreadValid(const entry_ref *) const
}
void
DesktopPoseView::AddPosesCompleted()
{
_inherited::AddPosesCompleted();
AddTrashPose();
}
bool
DesktopPoseView::ShouldShowPose(const Model *model, const PoseInfo *poseInfo)
{
@ -212,7 +214,7 @@ DesktopPoseView::ShowVolumes(bool visible, bool showShared)
{
if (LockLooper()) {
SavePoseLocations();
if (!visible)
if (!visible)
RemoveRootPoses();
else
AddRootPoses(true, showShared);
@ -221,6 +223,26 @@ DesktopPoseView::ShowVolumes(bool visible, bool showShared)
}
void
DesktopPoseView::AddTrashPose()
{
BVolume volume;
if (BVolumeRoster().GetBootVolume(&volume) == B_OK) {
BDirectory trash;
BEntry entry;
node_ref ref;
if (FSGetTrashDir(&trash, volume.Device()) == B_OK
&& trash.GetEntry(&entry) == B_OK && entry.GetNodeRef(&ref) == B_OK) {
WatchNewNode(&ref);
Model *model = new Model(&entry);
PoseInfo info;
ReadPoseInfo(model, &info);
CreatePose(model, &info, false, NULL, NULL, true);
}
}
}
void
DesktopPoseView::StartSettingsWatch()
{

View File

@ -58,6 +58,7 @@ public:
void StopSettingsWatch();
virtual bool AddPosesThreadValid(const entry_ref *) const;
virtual void AddPosesCompleted();
protected:
virtual EntryListBase *InitDirentIterator(const entry_ref *);
@ -77,11 +78,8 @@ private:
friend bool ShouldShowDesktopPose(dev_t device, const Model *,
const PoseInfo *);
};
class DesktopEntryListCollection : public CachedEntryIteratorList {
public:
DesktopEntryListCollection();
void AddTrashPose();
};

View File

@ -109,10 +109,8 @@ BDirMenu::Populate(const BEntry *startEntry, BWindow *originatingWindow,
parent.GetEntry(&entry);
}
BVolume bootVol;
BVolumeRoster().GetBootVolume(&bootVol);
BDirectory desktopDir;
FSGetDeskDir(&desktopDir, bootVol.Device());
FSGetDeskDir(&desktopDir);
BEntry desktopEntry;
desktopDir.GetEntry(&desktopEntry);

View File

@ -1881,7 +1881,8 @@ CheckName(uint32 moveMode, const BEntry *sourceEntry, const BDirectory *destDir,
}
}
if (FSIsTrashDir(sourceEntry)) {
if (FSIsTrashDir(sourceEntry) && moveMode != kCreateLink
&& moveMode != kCreateRelativeLink) {
(new BAlert("", "You can't move or copy the trash.",
"OK", 0, 0, B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go();
return B_ERROR;
@ -2291,15 +2292,10 @@ FSGetTrashDir(BDirectory *trash_dir, dev_t dev)
status_t
FSGetDeskDir(BDirectory *deskDir, dev_t dev)
FSGetDeskDir(BDirectory *deskDir)
{
BVolume volume(dev);
status_t result = volume.InitCheck();
if (result != B_OK)
return result;
BPath path;
result = find_directory(B_DESKTOP_DIRECTORY, &path, true, &volume);
status_t result = find_directory(B_DESKTOP_DIRECTORY, &path, true);
if (result != B_OK)
return result;
@ -2383,7 +2379,7 @@ FSIsTrashDir(const BEntry *entry)
bool
FSIsDeskDir(const BEntry *entry, dev_t device)
FSIsDeskDir(const BEntry *entry)
{
BPath path;
status_t result = find_directory(B_DESKTOP_DIRECTORY, &path, true);
@ -2395,17 +2391,6 @@ FSIsDeskDir(const BEntry *entry, dev_t device)
}
bool
FSIsDeskDir(const BEntry *entry)
{
entry_ref ref;
if (entry->GetRef(&ref) != B_OK)
return false;
return FSIsDeskDir(entry, ref.device);
}
bool
FSIsHomeDir(const BEntry *entry)
{
@ -2778,9 +2763,6 @@ FSCreateTrashDirs()
continue;
BPath path;
// TODO: relocate Trash directory such that a Desktop dir on
// every volume is no longer needed
find_directory(B_DESKTOP_DIRECTORY, &path, true, &volume);
find_directory(B_TRASH_DIRECTORY, &path, true, &volume);
BDirectory trashDir;

View File

@ -190,7 +190,7 @@ _IMPEXP_TRACKER status_t FSCreateNewFolderIn(const node_ref *destDir, entry_ref
node_ref *new_node);
_IMPEXP_TRACKER void FSCreateTrashDirs();
_IMPEXP_TRACKER status_t FSGetTrashDir(BDirectory *trashDir, dev_t volume);
_IMPEXP_TRACKER status_t FSGetDeskDir(BDirectory *deskDir, dev_t volume);
_IMPEXP_TRACKER status_t FSGetDeskDir(BDirectory *deskDir);
_IMPEXP_TRACKER status_t FSRecursiveCalcSize(BInfoWindow *, BDirectory *,
off_t *runningSize, int32 *fileCount, int32 *dirCount);
@ -233,7 +233,7 @@ status_t LaunchBrokenLink(const char *, const BMessage *);
status_t FSFindTrackerSettingsDir(BPath *, bool autoCreate = true);
bool FSIsDeskDir(const BEntry *, dev_t);
bool FSIsDeskDir(const BEntry *);
bool ConfirmChangeIfWellKnownDirectory(const BEntry *entry, const char *action,
bool dontAsk = false, int32 *confirmedAlready = NULL);

View File

@ -1252,7 +1252,7 @@ TFilePanel::CanOpenParent() const
if (TrackerSettings().DesktopFilePanelRoot()) {
// don't allow opening Desktop folder's parent
BEntry entry(TargetModel()->EntryRef());
if (FSIsDeskDir(&entry, TargetModel()->NodeRef()->device))
if (FSIsDeskDir(&entry))
return false;
}
@ -1280,11 +1280,8 @@ TFilePanel::SwitchDirToDesktopIfNeeded(entry_ref &ref)
BEntry root("/");
BDirectory desktopDir;
BVolume bootVol;
BVolumeRoster().GetBootVolume(&bootVol);
FSGetDeskDir(&desktopDir, bootVol.Device());
if ((bootVol.Device() != ref.device && FSIsDeskDir(&entry, ref.device))
FSGetDeskDir(&desktopDir);
if (FSIsDeskDir(&entry)
// navigated into non-boot desktop, switch to boot desktop
|| (entry == root && !settings.ShowDisksIcon())) {
// hit "/" level, map to desktop
@ -1293,7 +1290,7 @@ TFilePanel::SwitchDirToDesktopIfNeeded(entry_ref &ref)
entry.GetRef(&ref);
return true;
}
return FSIsDeskDir(&entry, ref.device);
return FSIsDeskDir(&entry);
}

View File

@ -1156,7 +1156,7 @@ Model::WriteAttr(const char *attr, type_code type, off_t offset,
ssize_t
Model::WriteAttrKillForegin(const char *attr, const char *foreignAttr,
Model::WriteAttrKillForeign(const char *attr, const char *foreignAttr,
type_code type, off_t offset, const void *buffer, size_t length)
{
BModelWriteOpener opener(this);

View File

@ -196,7 +196,7 @@ class Model {
const void *buffer, size_t );
// cover call, creates a writable node and writes out attributes
// into it; work around for file nodes not being writeable
ssize_t WriteAttrKillForegin(const char *attr, const char *foreignAttr,
ssize_t WriteAttrKillForeign(const char *attr, const char *foreignAttr,
type_code type, off_t, const void *buffer, size_t);
bool Mimeset(bool force);

View File

@ -757,17 +757,24 @@ BPoseView::SavePoseLocations(BRect *frameIfDesktop)
ASSERT(model);
ASSERT(model->InitCheck() == B_OK);
// special handling for "root" disks icon
if (model->IsRoot()) {
BVolume bootVol;
// and trash pose on desktop dir
BEntry entry;
model->GetEntry(&entry);
bool isTrash = FSIsTrashDir(&entry) && IsDesktopView();
if (model->IsRoot() || isTrash) {
BDirectory dir;
BVolumeRoster().GetBootVolume(&bootVol);
if (FSGetDeskDir(&dir, bootVol.Device()) == B_OK) {
if (dir.WriteAttr(kAttrDisksPoseInfo, B_RAW_TYPE, 0,
if (FSGetDeskDir(&dir) == B_OK) {
const char *poseInfoAttr = (isTrash) ? kAttrTrashPoseInfo
: kAttrDisksPoseInfo;
const char *poseInfoAttrForeign = (isTrash)
? kAttrTrashPoseInfoForeign
: kAttrDisksPoseInfoForeign;
if (dir.WriteAttr(poseInfoAttr, B_RAW_TYPE, 0,
&poseInfo, sizeof(poseInfo)) == sizeof(poseInfo))
// nuke opposite endianness
dir.RemoveAttr(kAttrDisksPoseInfoForeign);
dir.RemoveAttr(poseInfoAttrForeign);
if (desktop && dir.WriteAttr(kAttrExtendedDisksPoseInfo,
if (!isTrash && desktop && dir.WriteAttr(kAttrExtendedDisksPoseInfo,
B_RAW_TYPE, 0,
extendedPoseInfo, extendedPoseInfoSize)
== (ssize_t)extendedPoseInfoSize)
@ -775,11 +782,11 @@ BPoseView::SavePoseLocations(BRect *frameIfDesktop)
dir.RemoveAttr(kAttrExtendedDisksPoseInfoForegin);
}
} else {
model->WriteAttrKillForegin(kAttrPoseInfo, kAttrPoseInfoForeign,
model->WriteAttrKillForeign(kAttrPoseInfo, kAttrPoseInfoForeign,
B_RAW_TYPE, 0, &poseInfo, sizeof(poseInfo));
if (desktop) {
model->WriteAttrKillForegin(kAttrExtendedPoseInfo,
model->WriteAttrKillForeign(kAttrExtendedPoseInfo,
kAttrExtendedPoseInfoForegin,
B_RAW_TYPE, 0, extendedPoseInfo, extendedPoseInfoSize);
}
@ -2634,17 +2641,22 @@ BPoseView::ReadPoseInfo(Model *model, PoseInfo *poseInfo)
BModelOpener opener(model);
if (!model->Node())
return;
ReadAttrResult result = kReadAttrFailed;
BEntry entry;
model->GetEntry(&entry);
bool isTrash = FSIsTrashDir(&entry) && IsDesktopView();
// special case the "root" disks icon
if (model->IsRoot()) {
BVolume bootVol;
// as well as the trash on desktop
if (model->IsRoot() || isTrash) {
BDirectory dir;
BVolumeRoster().GetBootVolume(&bootVol);
if (FSGetDeskDir(&dir, bootVol.Device()) == B_OK) {
result = ReadAttr(&dir, kAttrDisksPoseInfo, kAttrDisksPoseInfoForeign,
if (FSGetDeskDir(&dir) == B_OK) {
const char *poseInfoAttr = (isTrash) ? kAttrTrashPoseInfo
: kAttrDisksPoseInfo;
const char *poseInfoAttrForeign = (isTrash) ? kAttrTrashPoseInfoForeign
: kAttrDisksPoseInfoForeign;
result = ReadAttr(&dir, poseInfoAttr, poseInfoAttrForeign,
B_RAW_TYPE, 0, poseInfo, sizeof(*poseInfo), &PoseInfo::EndianSwap);
}
} else {
@ -2710,11 +2722,8 @@ BPoseView::ReadExtendedPoseInfo(Model *model)
// special case the "root" disks icon
if (model->IsRoot()) {
BVolume bootVol;
BDirectory dir;
BVolumeRoster().GetBootVolume(&bootVol);
if (FSGetDeskDir(&dir, bootVol.Device()) == B_OK) {
if (FSGetDeskDir(&dir) == B_OK) {
extendedPoseInfoAttrName = kAttrExtendedDisksPoseInfo;
extendedPoseInfoAttrForeignName = kAttrExtendedDisksPoseInfoForegin;
} else

View File

@ -459,7 +459,8 @@ class BPoseView : public BView {
virtual void AddPoses(Model *model = NULL);
// if <model> is zero, PoseView has other means of iterating through all
// the entries that it adds
// the entries thaat it adds
virtual void AddRootPoses(bool watchIndividually, bool mountShared);
// watchIndividually is used when placing a volume pose onto the Desktop
// where unlike in the Root window it will not be watched by the folder

View File

@ -237,9 +237,6 @@ TTracker::QuitRequested()
gStatusWindow->AttemptToQuit();
// try quitting the copy/move/empty trash threads
BVolume bootVolume;
DEBUG_ONLY(status_t err =) BVolumeRoster().GetBootVolume(&bootVolume);
ASSERT(err == B_OK);
BMessage message;
AutoLock<WindowList> lock(&fWindowList);
// save open windows in a message inside an attribute of the desktop
@ -294,7 +291,7 @@ TTracker::QuitRequested()
// write windows to open on disk
BDirectory deskDir;
if (!BootedInSafeMode() && FSGetDeskDir(&deskDir, bootVolume.Device()) == B_OK) {
if (!BootedInSafeMode() && FSGetDeskDir(&deskDir) == B_OK) {
// if message is empty, delete the corresponding attribute
if (message.CountNames(B_ANY_TYPE)) {
size_t size = (size_t)message.FlattenedSize();
@ -1189,11 +1186,9 @@ TTracker::_OpenPreviouslyOpenedWindows(const char* pathFilter)
if (pathFilter != NULL)
filterLength = strlen(pathFilter);
BVolume bootVolume;
BVolumeRoster().GetBootVolume(&bootVolume);
BDirectory deskDir;
attr_info attrInfo;
if (FSGetDeskDir(&deskDir, bootVolume.Device()) != B_OK
if (FSGetDeskDir(&deskDir) != B_OK
|| deskDir.GetAttrInfo(kAttrOpenWindows, &attrInfo) != B_OK)
return;
@ -1279,10 +1274,8 @@ TTracker::ReadyToRun()
// open desktop window
BContainerWindow *deskWindow = NULL;
BVolume bootVolume;
BVolumeRoster().GetBootVolume(&bootVolume);
BDirectory deskDir;
if (FSGetDeskDir(&deskDir, bootVolume.Device()) == B_OK) {
if (FSGetDeskDir(&deskDir) == B_OK) {
// create desktop
BEntry entry;
deskDir.GetEntry(&entry);

View File

@ -152,46 +152,48 @@ BTrashWatcher::MessageReceived(BMessage *message)
void
BTrashWatcher::UpdateTrashIcons()
{
BVolume boot;
if (BVolumeRoster().GetBootVolume(&boot) != B_OK)
return;
BVolumeRoster roster;
BVolume volume;
roster.Rewind();
BDirectory trashDir;
if (FSGetTrashDir(&trashDir, boot.Device()) == B_OK) {
// pull out the icons for the current trash state from resources and
// apply them onto the trash directory node
size_t largeSize = 0;
size_t smallSize = 0;
const void *largeData = GetTrackerResources()->LoadResource('ICON',
fTrashFull ? kResTrashFullIcon : kResTrashIcon, &largeSize);
const void *smallData = GetTrackerResources()->LoadResource('MICN',
fTrashFull ? kResTrashFullIcon : kResTrashIcon, &smallSize);
while (roster.GetNextVolume(&volume) == B_OK) {
if (FSGetTrashDir(&trashDir, volume.Device()) == B_OK) {
// pull out the icons for the current trash state from resources and
// apply them onto the trash directory node
size_t largeSize = 0;
size_t smallSize = 0;
const void *largeData = GetTrackerResources()->LoadResource('ICON',
fTrashFull ? kResTrashFullIcon : kResTrashIcon, &largeSize);
const void *smallData = GetTrackerResources()->LoadResource('MICN',
fTrashFull ? kResTrashFullIcon : kResTrashIcon, &smallSize);
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
size_t vectorSize = 0;
const void *vectorData = GetTrackerResources()->LoadResource(
B_VECTOR_ICON_TYPE, fTrashFull ? kResTrashFullIcon : kResTrashIcon,
&vectorSize);
if (vectorData)
trashDir.WriteAttr(kAttrIcon, B_VECTOR_ICON_TYPE, 0,
vectorData, vectorSize);
else
TRESPASS();
size_t vectorSize = 0;
const void *vectorData = GetTrackerResources()->LoadResource(
B_VECTOR_ICON_TYPE, fTrashFull ? kResTrashFullIcon : kResTrashIcon,
&vectorSize);
if (vectorData)
trashDir.WriteAttr(kAttrIcon, B_VECTOR_ICON_TYPE, 0,
vectorData, vectorSize);
else
TRESPASS();
#endif
if (largeData)
trashDir.WriteAttr(kAttrLargeIcon, 'ICON', 0,
largeData, largeSize);
else
TRESPASS();
if (smallData)
trashDir.WriteAttr(kAttrMiniIcon, 'MICN', 0,
smallData, smallSize);
else
TRESPASS();
if (largeData)
trashDir.WriteAttr(kAttrLargeIcon, 'ICON', 0,
largeData, largeSize);
else
TRESPASS();
if (smallData)
trashDir.WriteAttr(kAttrMiniIcon, 'MICN', 0,
smallData, smallSize);
else
TRESPASS();
}
}
}

View File

@ -201,7 +201,7 @@ find_directory(directory_which which, dev_t device, bool createIt,
case B_TRASH_DIRECTORY:
// TODO: eventually put that into the file system API?
if (device == bootDevice || !strcmp(fsInfo.fsh_name, "bfs"))
template = "$h/Desktop/Trash";
template = "Trash"; // TODO: add suffix for current user
else if (!strcmp(fsInfo.fsh_name, "dos"))
template = "RECYCLED/_BEOS_";
break;