Sincronize os locais dos ícones da área de trabalho entre os sistemas operacionais

0

Eu tenho uma configuração de inicialização dupla do Windows 10 / Arch Linux. Eu configurei os dois sistemas para usar o mesmo Desktop (simplesmente link /home/rawing/Desktop to D:/Users/Rawing/Desktop ). Funciona bem, eu tenho acesso a todos os meus arquivos em ambos os sistemas, mas gostaria de sincronizar a localização dos arquivos na área de trabalho. Por exemplo, se eu criar um novo arquivo no linux e movê-lo para o canto inferior direito da área de trabalho, o Windows ainda mostrará o novo arquivo no canto superior esquerdo, forçando-me a realocar o arquivo pela segunda vez.

Existe uma maneira de sincronizar a localização dos arquivos na área de trabalho?

    
por Aran-Fey 29.08.2016 / 20:57

2 respostas

3

Os locais dos ícones seriam armazenados de maneira diferente para cada sistema operacional. Você não pode ter a localização de ícones compartilhados entre janelas e linux.

    
por 29.08.2016 / 22:45
0

Eu fiz alguns progressos que gostaria de compartilhar. Esta não é uma resposta completa e funcional ainda, mas limpei alguns obstáculos.

Script Python3 para Linux:

def get_icon_positions_linux():
    desktop= os.path.join(os.path.expanduser('~'), 'Desktop')
    icons= {}

    #try to find out the screen resolution
    resolution= get_screen_resolution()

    for name in os.listdir(desktop):
        path= os.path.join(desktop, name)
        data= subprocess.getoutput("gvfs-info -a 'metadata::nautilus-icon-position' "+shlex.quote(path))
        if not data:
            continue
        match= re.search(r'(\d+),(\d+)\s*$', data)
        x, y= int(match.group(1)), int(match.group(2))
        if resolution is not None:
            x/= resolution[0]
            y/= resolution[1]
        icons[name]= (x,y)

    return icons

def set_icon_positions_linux(icons):
    desktop= os.path.join(os.path.expanduser('~'), 'Desktop')

    for name,(x,y) in icons.items():
        path= os.path.join(desktop, name)
        pos= ','.join(map(str, (x,y)))
        subprocess.call(['gvfs-set-attribute', '-t', 'string', path, 'metadata::nautilus-icon-position', pos])

    #FIXME: refresh desktop

E o Windows:

def get_icon_positions_windows():
    # retrieves icon locations from the Windows registry. More info can be found here:
    #    https://superuser.com/questions/625854/where-does-windows-store-icon-positions

    #FIXME: before doing anything, make explorer save the current positions

    import winreg

    icons= {}

    key= winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'Software\Microsoft\Windows\Shell\Bags\Desktop')

    #find the key with the current screen resolution
    resolution= get_screen_resolution()

    valuename= 'ItemPos'+ 'x'.join(map(str, resolution))
    for index in range(1024):
        value= winreg.EnumValue(key, index)
        if value[0].startswith(valuename):
            break

    #parse the icon locations
    data= value[1]
    #first 16 bytes are junk
    data= data[0x10:]

    format= 'HHIHHH'
    name_offset= struct.calcsize(format)
    while True:
        # What they call "unknown padding" is exactly what we're looking for.
        x, y= struct.unpack_from('II', data) # (x,y) in pixels on the Desktop from the top left corner.
        data= data[8:]

        if len(data)<name_offset:
            break

        size, flags, filesize, date, time, fileattrs= struct.unpack_from(format, data)
        if size==0:
            break

        chunk= data[:size]
        data= data[size:]
        if size>=0x15:
            chunk= chunk[name_offset:]
            name= chunk[:chunk.find(b'
def get_icon_positions_linux():
    desktop= os.path.join(os.path.expanduser('~'), 'Desktop')
    icons= {}

    #try to find out the screen resolution
    resolution= get_screen_resolution()

    for name in os.listdir(desktop):
        path= os.path.join(desktop, name)
        data= subprocess.getoutput("gvfs-info -a 'metadata::nautilus-icon-position' "+shlex.quote(path))
        if not data:
            continue
        match= re.search(r'(\d+),(\d+)\s*$', data)
        x, y= int(match.group(1)), int(match.group(2))
        if resolution is not None:
            x/= resolution[0]
            y/= resolution[1]
        icons[name]= (x,y)

    return icons

def set_icon_positions_linux(icons):
    desktop= os.path.join(os.path.expanduser('~'), 'Desktop')

    for name,(x,y) in icons.items():
        path= os.path.join(desktop, name)
        pos= ','.join(map(str, (x,y)))
        subprocess.call(['gvfs-set-attribute', '-t', 'string', path, 'metadata::nautilus-icon-position', pos])

    #FIXME: refresh desktop
')].decode() icons[name]= (x/resolution[0], y/resolution[1]) return icons def set_icon_positions_windows(icons): """ WARNING: This will kill and restart the explorer.exe process! """ import winreg key= winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'Software\Microsoft\Windows\Shell\Bags\Desktop', 0, winreg.KEY_ALL_ACCESS) #find the key with the current screen resolution resolution= get_screen_resolution() valuename= 'ItemPos'+ 'x'.join(map(str, resolution)) for index in range(1024): value= winreg.EnumValue(key, index) if value[0].startswith(valuename): valuename= value[0] break old_data= value[1] #first 16 bytes are junk new_data= old_data[:0x10] old_data= old_data[0x10:] format= 'HHIHHH' name_offset= struct.calcsize(format) while True: if len(old_data)<8+name_offset: break size, flags, filesize, date, time, fileattrs= struct.unpack_from(format, old_data[8:]) if size==0: break chunk= old_data[8:8+size] if size>=0x15: chunk= chunk[name_offset:] name= chunk[:chunk.find(b'
def get_icon_positions_windows():
    # retrieves icon locations from the Windows registry. More info can be found here:
    #    https://superuser.com/questions/625854/where-does-windows-store-icon-positions

    #FIXME: before doing anything, make explorer save the current positions

    import winreg

    icons= {}

    key= winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'Software\Microsoft\Windows\Shell\Bags\Desktop')

    #find the key with the current screen resolution
    resolution= get_screen_resolution()

    valuename= 'ItemPos'+ 'x'.join(map(str, resolution))
    for index in range(1024):
        value= winreg.EnumValue(key, index)
        if value[0].startswith(valuename):
            break

    #parse the icon locations
    data= value[1]
    #first 16 bytes are junk
    data= data[0x10:]

    format= 'HHIHHH'
    name_offset= struct.calcsize(format)
    while True:
        # What they call "unknown padding" is exactly what we're looking for.
        x, y= struct.unpack_from('II', data) # (x,y) in pixels on the Desktop from the top left corner.
        data= data[8:]

        if len(data)<name_offset:
            break

        size, flags, filesize, date, time, fileattrs= struct.unpack_from(format, data)
        if size==0:
            break

        chunk= data[:size]
        data= data[size:]
        if size>=0x15:
            chunk= chunk[name_offset:]
            name= chunk[:chunk.find(b'%pre%')].decode()

            icons[name]= (x/resolution[0], y/resolution[1])
    return icons

def set_icon_positions_windows(icons):
    """
    WARNING: This will kill and restart the explorer.exe process!
    """
    import winreg

    key= winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'Software\Microsoft\Windows\Shell\Bags\Desktop', 0, winreg.KEY_ALL_ACCESS)

    #find the key with the current screen resolution
    resolution= get_screen_resolution()

    valuename= 'ItemPos'+ 'x'.join(map(str, resolution))
    for index in range(1024):
        value= winreg.EnumValue(key, index)
        if value[0].startswith(valuename):
            valuename= value[0]
            break

    old_data= value[1]
    #first 16 bytes are junk
    new_data= old_data[:0x10]
    old_data= old_data[0x10:]

    format= 'HHIHHH'
    name_offset= struct.calcsize(format)
    while True:
        if len(old_data)<8+name_offset:
            break

        size, flags, filesize, date, time, fileattrs= struct.unpack_from(format, old_data[8:])
        if size==0:
            break

        chunk= old_data[8:8+size]
        if size>=0x15:
            chunk= chunk[name_offset:]
            name= chunk[:chunk.find(b'%pre%')].decode()

            if name in icons:
                #update the position
                x, y= icons.pop(name)
                new_data+= struct.pack('II', x, y)
                #copy everything else
                new_data+= old_data[8:8+size]
                old_data= old_data[8+size:]
                continue

        #if it's an invalid struct (size<0x15) or we're not supposed to change this file's position, copy the old value
        new_data+= old_data[:8+size]
        old_data= old_data[8+size:]

    #if there are still icons remaining, we must construct their data from scratch
    for name,(x,y) in icons.items():
        name= name.encode()
        if len(name)%2:
            name+= b'%pre%'
        size= name_offset + len(name) + 4
        chunk= struct.pack('II', x, y)
        chunk+= struct.pack(format, size, 0, 0, 0, 0, 0) #FIXME: set sensible values
        chunk+= name
        chunk+= struct.pack('HH', 0, 0) #FIXME: set sensible values
        new_data+= chunk

    #whatever data remained, add it.
    new_data+= old_data

    winreg.SetValueEx(key, valuename, 0, winreg.REG_BINARY, new_data)

    #restart explorer for changes to take effect
    subprocess.call(['taskkill', '/f', '/im', 'explorer.exe'])
    subprocess.Popen(r'start %WINDIR%\explorer.exe"', shell=True)
')].decode() if name in icons: #update the position x, y= icons.pop(name) new_data+= struct.pack('II', x, y) #copy everything else new_data+= old_data[8:8+size] old_data= old_data[8+size:] continue #if it's an invalid struct (size<0x15) or we're not supposed to change this file's position, copy the old value new_data+= old_data[:8+size] old_data= old_data[8+size:] #if there are still icons remaining, we must construct their data from scratch for name,(x,y) in icons.items(): name= name.encode() if len(name)%2: name+= b'%pre%' size= name_offset + len(name) + 4 chunk= struct.pack('II', x, y) chunk+= struct.pack(format, size, 0, 0, 0, 0, 0) #FIXME: set sensible values chunk+= name chunk+= struct.pack('HH', 0, 0) #FIXME: set sensible values new_data+= chunk #whatever data remained, add it. new_data+= old_data winreg.SetValueEx(key, valuename, 0, winreg.REG_BINARY, new_data) #restart explorer for changes to take effect subprocess.call(['taskkill', '/f', '/im', 'explorer.exe']) subprocess.Popen(r'start %WINDIR%\explorer.exe"', shell=True)

O código atualmente tem os seguintes problemas:

  1. get_icon_positions_windows não força o Windows Explorer a salvar os locais dos ícones atuais. Cria um instantâneo dos últimos locais salvos.
  2. set_icon_positions_linux não atualiza a área de trabalho. Você pode ter que pressionar F5 para que as alterações entrem em vigor.

A idéia é usar este código para gravar / carregar as posições dos ícones de / para um arquivo sempre que o usuário fizer log-on ou off. Infelizmente, ainda não descobri uma maneira de executar um comando no logout no Windows. (Veja minha outra pergunta )

    
por 31.08.2016 / 18:49