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.
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?
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.
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:
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. 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 )
Tags windows linux desktop multi-boot