diff --git a/lutris/runners/wine.py b/lutris/runners/wine.py index 1912bd9a8..4872513bb 100644 --- a/lutris/runners/wine.py +++ b/lutris/runners/wine.py @@ -139,7 +139,7 @@ def create_prefix(prefix, wine_path=None, arch='win32', overrides={}, logger.info('%s Prefix created in %s', arch, prefix) prefix_manager = WinePrefixManager(prefix) prefix_manager.setup_defaults() - + self.sandbox(prefix_manager) def winekill(prefix, arch='win32', wine_path=None, env=None, initial_pids=None): """Kill processes in Wine prefix.""" @@ -323,22 +323,6 @@ def detect_prefix_arch(directory=None): return 'win32' logger.debug("Can't detect prefix arch for %s", directory) - -def disable_desktop_integration(prefix): - """Remove links to user directories in a prefix.""" - if not prefix: - raise ValueError('Missing prefix') - user = os.getenv('USER') - user_dir = os.path.join(prefix, "drive_c/users/", user) - # Replace symlinks - if os.path.exists(user_dir): - for item in os.listdir(user_dir): - path = os.path.join(user_dir, item) - if os.path.islink(path): - os.unlink(path) - os.makedirs(path) - - def set_drive_path(prefix, letter, path): dosdevices_path = os.path.join(prefix, "dosdevices") if not os.path.exists(dosdevices_path): @@ -723,6 +707,21 @@ class wine(Runner): 'advanced': True, 'help': "Sets WINEDLLOVERRIDES when launching the game." }, + { + 'option': 'sandbox', + 'type': 'bool', + 'label': 'Create a sandbox for wine folders', + 'default': True, + 'help': ("Do not use $HOME for desktop integration folders.\n" + "By default, it use the directories in the confined " + "Windows environment.") + }, + { + 'option': 'sandbox_dir', + 'type': 'directory_chooser', + 'label': 'Sandbox directory', + 'help': ("Custom directory for desktop integration folders.") + } ] @property @@ -883,8 +882,8 @@ class wine(Runner): if not os.path.exists(os.path.join(self.prefix_path, 'user.reg')): create_prefix(self.prefix_path, arch=self.wine_arch) prefix_manager = WinePrefixManager(self.prefix_path) - prefix_manager.setup_defaults() prefix_manager.configure_joypads() + self.sandbox(prefix_manager) self.set_regedit_keys() return True @@ -953,6 +952,13 @@ class wine(Runner): x360ce_config.populate_controllers() x360ce_config.write(os.path.join(x360ce_path, 'x360ce.ini')) + def sandbox(self, wine_prefix): + sandbox = self.runner_config.get('sandbox', True) + + if (sandbox): + sandbox_dir = self.runner_config.get('sandbox_dir', None) + wine_prefix.desktop_integration(desktop_dir=sandbox_dir) + def play(self): game_exe = self.game_exe arguments = self.game_config.get('args', '') diff --git a/lutris/util/wineprefix.py b/lutris/util/wineprefix.py index c79e9a723..bf7cb872e 100644 --- a/lutris/util/wineprefix.py +++ b/lutris/util/wineprefix.py @@ -1,8 +1,10 @@ import os +import time from lutris.util.wineregistry import WineRegistry from lutris.util.log import logger from lutris.util import joypad +desktop_folders = ["Desktop", "My Documents", "My Music", "My Videos", "My Pictures"] class WinePrefixManager: """Class to allow modification of Wine prefixes without the use of Wine""" @@ -12,7 +14,6 @@ class WinePrefixManager: self.path = path def setup_defaults(self): - self.sandbox() self.override_dll("winemenubuilder.exe", "") def get_registry_path(self, key): @@ -48,14 +49,44 @@ class WinePrefixManager: return self.set_registry_key(key, dll, mode) - def sandbox(self): + def desktop_integration(self, desktop_dir=None): + """Overwrite desktop integration""" + user = os.getenv('USER') user_dir = os.path.join(self.path, "drive_c/users/", user) - # Replace symlinks + + if (not desktop_dir): + desktop_dir = user_dir + if os.path.exists(user_dir): - for item in os.listdir(user_dir): + # Replace desktop integration symlinks + for item in desktop_folders: path = os.path.join(user_dir, item) - if os.path.islink(path): + old_path = path + ".winecfg" + + if (os.path.islink(path)): + os.unlink(path) + elif (os.path.isdir(path)): + try: + os.rmdir(path) + # We can't delete nonempty dir, so we rename as wine do. + except OSError: + os.rename(path, old_path) + + if (desktop_dir != user_dir): + src_path = os.path.join(desktop_dir, item) + os.makedirs(src_path, exist_ok=True) + os.symlink(src_path, path) + else: + # We use first the renamed dir, otherwise we make it. + if (os.path.isdir(old_path)): + os.rename(old_path, path) + else: + os.makedirs(path, exist_ok=True) + + # Security: Remove other symlinks. + for item in os.listdir(user_dir): + if not item in desktop_folders and os.path.islink(path): os.unlink(path) os.makedirs(path)