2012-02-10 9 views
12

Desidero modificare a livello di programmazione l'icona del volume per un file system impilato implementato utilizzando OSXFUSE (in precedenza MacFUSE). L'icona deve riflettere lo stato di un file system montato.È possibile modificare a livello di programmazione l'icona del volume su un'unità montata su Mac OS X?

L'approccio che ho cercato di ottenere è di mappare le richieste di /.VolumeIcon.icns all'icona appropriata nel pacchetto dell'applicazione. Quindi inviando notifiche di modifica al file system per il percorso effettivo (percorso) e il percorso di montaggio (mountPath).

[[NSWorkspace sharedWorkspace] noteFileSystemChanged: @"/Volumes"]; 
    [[NSWorkspace sharedWorkspace] noteFileSystemChanged: [mountPath stringByDeletingLastPathComponent]]; 
    [[NSWorkspace sharedWorkspace] noteFileSystemChanged: mountPath]; 
    [[NSWorkspace sharedWorkspace] noteFileSystemChanged: [path stringByDeletingLastPathComponent]]; 
    [[NSWorkspace sharedWorkspace] noteFileSystemChanged: path]; 

    FNNotifyByPath([[[mountPath stringByDeletingLastPathComponent] dataUsingEncoding:NSUTF8StringEncoding] bytes], kFNDirectoryModifiedMessage, kNilOptions); 
    FNNotifyByPath([[[path stringByDeletingLastPathComponent] dataUsingEncoding:NSUTF8StringEncoding] bytes], kFNDirectoryModifiedMessage, kNilOptions); 
    FNNotifyByPath([[@"/Volumes" dataUsingEncoding:NSUTF8StringEncoding] bytes], kFNDirectoryModifiedMessage, kNilOptions); 

Facendo un passo attraverso il debugger posso vedere questo codice essere colpito ma il codice per mappare le /.VolumeIcon.icns viene chiamato raramente e mai in risposta a queste notifiche.

+0

Hai provato l'eliminazione di file di .DS_Store nascosto? –

+1

Non sono sicuro che interesserà l'icona. Ma in ogni caso sono riluttante a percorrere questa strada perché significa pulire le impostazioni di visualizzazione della cartella scelte dall'utente. –

+0

@Aditya - Ho provato il tuo suggerimento ma l'eliminazione del file .DS_Store non ha alcun impatto sull'icona del volume visualizzata sul desktop. –

risposta

3

Penso che la risposta breve sia, sei sfortunato. La risposta lunga è mentre il progetto OSXFUSE è diverso rispetto al progetto Fuse4X, sono entrambi derivati ​​dalla stessa fonte, e Fuse4X ha questo da dire circa le icone del volume nella loro FAQ:

Q 4.1. Perché i volumi Fuse4X vengono visualizzati con icone "server" (o "rete ")?

A: Per la precisione, per impostazione predefinita i volumi Fuse4X si presentano come volumi non locali , che il Finder tratta sfortunatamente come "server". È una buona domanda sul perché Fuse4X normalmente tagga i suoi volumi come non locali. Alcune persone pensano che nel caso di sistemi basati su disco , Fuse4X deve taggare il volume come locale. Bene, vediamo.

Affinché un vfs sia locale su Mac OS X, è necessario un dispositivo disco "reale", un nodo stile /dev/disk *. Un tale vero nodo del dispositivo disco nel caso di Fuse4X è problematico: al momento del montaggio, per un volume locale, il kernel dovrebbe aprire il nodo del dispositivo e passarlo a Fuse4X. In tal modo, il kernel dovrebbe assicurarsi che il dispositivo non sia attualmente in uso (per , per disabilitare più supporti dello stesso dispositivo). Questo succede prima che il controllo passi a Fuse4X e il montaggio può procedere. Questo sarebbe andava bene se l'intero file system viveva nel kernel, ma nel caso di Fuse4X, il programma di file system user-space vorrebbe anche (esclusivamente) aprire il dispositivo del disco.

1

Dai uno sguardo allo path finder source code.

- (BOOL)setAsCustomIconForVolume:(NString *)path; 
{ 
    FSref FSRefpath = convertoFsref(path); 
    // filename for custom icon is ".VolumeIcon.icns" 
    NSString *iconPath = [path stringByAppendingPathComponent:@".VolumeIcon.icns"]; 

    // remove any existing file first. 

    [self writeToFile:iconPath]; 
    FSSetHasCustomIcon(FSRefpath); 

    // rebuild volumeList 


    return YES; 
} 
OSErr FSSetHasCustomIcon(
        const FSRef *ref) 
{ 
    return (FSChangeFinderFlags(ref, true, kHasCustomIcon)); 
} 
OSErr FSChangeFinderFlags(
        const FSRef *ref, 
        Boolean setBits, 
        UInt16 flagBits) 
{ 
    OSErr   result; 
    FSCatalogInfo catalogInfo; 
    FSRef   parentRef; 

    /* get the current finderInfo */ 
    result = FSGetCatalogInfo(ref, kFSCatInfoFinderInfo, &catalogInfo, NULL, NULL, &parentRef); 
    require_noerr(result, FSGetCatalogInfo); 

    /* set or clear the appropriate bits in the finderInfo.finderFlags */ 
    if (setBits) 
    { 
     /* OR in the bits */ 
     ((FileInfo *)&catalogInfo.finderInfo)->finderFlags |= flagBits; 
    } 
    else 
    { 
     /* AND out the bits */ 
     ((FileInfo *)&catalogInfo.finderInfo)->finderFlags &= ~flagBits; 
    } 

    /* save the modified finderInfo */ 
    result = FSSetCatalogInfo(ref, kFSCatInfoFinderInfo, &catalogInfo); 
    require_noerr(result, FSSetCatalogInfo); 

FSSetCatalogInfo: 
FSGetCatalogInfo: 

     return (result); 
} 

NTVolumeNotificationMgr
NTIconFamily