1 # Copyright (C) 2008, Vincent Povirk for CodeWeavers
3 # This library is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU Lesser General Public
5 # License as published by the Free Software Foundation; either
6 # version 2 of the License, or (at your option) any later version.
8 # This library is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 # Lesser General Public License for more details.
13 # You should have received a copy of the GNU Lesser General Public
14 # License along with this library; if not, write to the
15 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 # Boston, MA 02111-1307, USA.
18 from sugar
.activity
import activity
28 class WineActivity(activity
.Activity
):
29 def __init__(self
, handle
):
30 activity
.Activity
.__init
__(self
, handle
)
32 self
.bundle_path
= activity
.get_bundle_path()
35 activity_root
= activity
.get_activity_root()
36 wine_prefix
= os
.path
.join(activity_root
, 'data', 'wine')
37 except AttributeError:
39 activity_root
= os
.environ
['SUGAR_ACTIVITY_ROOT']
40 wine_prefix
= os
.path
.join(activity_root
, 'data', 'wine')
43 wine_prefix
= os
.path
.expanduser('~/.wine')
46 f
= open(os
.path
.join(self
.bundle_path
, 'activity', 'wine.info'), 'U')
47 for line
in f
.readlines():
49 key
, value
= line
.rstrip('\n').split('=')
50 self
.settings
[key
] = value
54 self
.desktop_parent
= gtk
.EventBox()
55 self
.desktop_parent
.show()
56 self
.set_canvas(self
.desktop_parent
)
57 except AttributeError:
58 # remove any children of the window that Sugar may have added
59 for widget
in self
.get_children():
62 self
.desktop_parent
= self
64 os
.environ
['LD_LIBRARY_PATH'] = "%s:%s" % (os
.path
.join(self
.bundle_path
, 'lib'), os
.environ
.get('LD_LIBRARY_PATH', ''))
65 os
.environ
['PATH'] = "%s:%s" % (os
.path
.join(self
.bundle_path
, 'bin'), os
.environ
.get('PATH', ''))
66 os
.environ
['WINEPREFIX'] = wine_prefix
67 os
.environ
['WINELOADER'] = os
.path
.join(self
.bundle_path
, 'bin/wine')
68 os
.environ
['WINESERVER'] = os
.path
.join(self
.bundle_path
, 'bin/wineserver')
69 os
.environ
['WINEDLLPATH'] = os
.path
.join(self
.bundle_path
, 'lib/wine')
71 self
.desktop_name
= str(os
.getpid())
72 os
.environ
['WINE_DESKTOP_NAME'] = self
.desktop_name
74 firstrun
= not os
.path
.exists(wine_prefix
)
76 self
.setup_prefix(firstrun
)
78 self
.desktop_parent
.connect('map', self
.on_parent_map
)
85 self
.set_title("Wine")
87 def on_parent_map(self
, widget
):
88 os
.environ
['WINE_DESKTOP_PARENT'] = str(self
.desktop_parent
.window
.xid
)
89 os
.environ
['SUGARED_WINE_TOPLEVEL'] = str(self
.window
.xid
)
93 os
.chdir(self
.get_unix_path('c:\\'))
95 width
= gtk
.gdk
.screen_width()
96 height
= gtk
.gdk
.screen_height()
98 cmdline
= ('wine', 'explorer', '/desktop=%s,%sx%s' % (self
.desktop_name
, width
, height
))
100 args
= self
.settings
['exec'].split(' ')
104 cmdline
+= ('start', '/unix')
105 cmdline
+= (os
.path
.join(self
.bundle_path
, args
[0]),)
106 cmdline
+= tuple(args
[1:])
108 self
.wine_pid
, stdin
, stdout
, stderr
= gobject
.spawn_async(cmdline
,
109 flags
=gobject
.SPAWN_SEARCH_PATH|gobject
.SPAWN_DO_NOT_REAP_CHILD
)
110 gobject
.child_watch_add(self
.wine_pid
, self
.on_wine_quit
, None)
112 for cmdline
in self
.to_run
:
113 self
.start_wine(*cmdline
)
115 def start_wine(self
, *args
):
117 logging
.info("running command line: %s" % ' '.join(str(x
) for x
in args
))
119 ['wine', 'explorer', '/desktop=%s' % self
.desktop_name
] + [str(x
) for x
in args
],
120 flags
=gobject
.SPAWN_SEARCH_PATH
)
122 self
.to_run
.append(args
)
124 def run_cmd(self
, *args
):
125 pid
, stdin
, stdout
, stderr
= gobject
.spawn_async(
127 flags
=gobject
.SPAWN_SEARCH_PATH
,
128 standard_output
=True)
131 s
= os
.read(stdout
, 4096)
134 s
= os
.read(stdout
, 4096)
136 result
= ''.join(result
)
140 def get_unix_path(self
, windowspath
):
141 return self
.run_cmd('winepath', '--unix', windowspath
).rstrip('\n')
143 def setup_prefix(self
, firstrun
):
145 f
= open(os
.path
.join(os
.environ
['WINEPREFIX'], '.update-timestamp'), 'r')
147 timestamp
= int(f
.read().strip())
151 expected_timestamp
= os
.stat(os
.path
.join(self
.bundle_path
, 'share/wine/wine.inf')).st_mtime
152 if timestamp
== expected_timestamp
:
159 self
.run_cmd('wine', 'start', '/unix', os
.path
.join(self
.bundle_path
, self
.settings
['init']))
161 self
.run_cmd('wineboot', '--update')
163 self
.run_cmd('wineserver', '-w')
167 background_file
= os
.path
.join(self
.bundle_path
, self
.settings
['background'])
171 #set up desktop background
172 winini
= self
.get_unix_path(r
'c:\windows\win.ini')
174 f
= open(winini
, 'w')
175 f
.write("\r\n\r\n[desktop]\r\nWallPaper=c:\\windows\\background.bmp")
178 landscapebmp
= self
.get_unix_path(r
'c:\windows\background.bmp')
179 os
.symlink(background_file
, landscapebmp
)
181 def on_wine_quit(self
, pid
, condition
, data
):
184 def read_file(self
, file_path
):
185 #the file is read-only and will be deleted so make a copy
187 fd
, filename
= filenames
.create_dsobject_file(self
.metadata
)
188 os
.chmod(filename
, int('0770', 8))
189 shutil
.copyfile(file_path
, filename
)
191 atexit
.register(os
.unlink
, filename
)
192 self
.start_wine('start', '/unix', filename
)