From c686b865ce98875cdded7402688d2e5ec8926456 Mon Sep 17 00:00:00 2001
From: Aleksey Lim <alsroot@member.fsf.org>
Date: Wed, 12 May 2010 12:21:35 +0000
Subject: resume journal entry race may duplicate resumed activity id #1719
diff --git a/src/jarabe/frame/activitiestray.py b/src/jarabe/frame/activitiestray.py
index b5762ee..c275679 100644
a
|
b
|
class ActivityButton(RadioToolButton): |
59 | 59 | self.set_palette_invoker(FrameWidgetInvoker(self)) |
60 | 60 | |
61 | 61 | self._home_activity = home_activity |
| 62 | self._notify_launch_hid = None |
62 | 63 | |
63 | 64 | self._icon = PulsingIcon() |
64 | 65 | self._icon.props.base_color = home_activity.get_icon_color() |
… |
… |
class ActivityButton(RadioToolButton): |
72 | 73 | self.set_icon_widget(self._icon) |
73 | 74 | self._icon.show() |
74 | 75 | |
75 | | if home_activity.props.launching: |
| 76 | if home_activity.props.launch_status == home_activity.LAUNCHING: |
76 | 77 | self._icon.props.pulsing = True |
77 | | self._notify_launching_hid = home_activity.connect( \ |
78 | | 'notify::launching', self.__notify_launching_cb) |
79 | | else: |
80 | | self._notify_launching_hid = None |
81 | | self._notif_icon = None |
| 78 | self._notify_launch_hid = home_activity.connect( \ |
| 79 | 'notify::launch-status', self.__notify_launch_status_cb) |
| 80 | elif home_activity.props.launch_status == home_activity.LAUNCH_FAILED: |
| 81 | self._on_failed_launch() |
82 | 82 | |
83 | 83 | def create_palette(self): |
84 | 84 | if self._home_activity.is_journal(): |
… |
… |
class ActivityButton(RadioToolButton): |
88 | 88 | palette.set_group_id('frame') |
89 | 89 | self.set_palette(palette) |
90 | 90 | |
91 | | def __notify_launching_cb(self, home_activity, pspec): |
92 | | if not home_activity.props.launching: |
| 91 | def _on_failed_launch(self): |
| 92 | # TODO |
| 93 | pass |
| 94 | |
| 95 | def __notify_launch_status_cb(self, home_activity, pspec): |
| 96 | home_activity.disconnect(self._notify_launch_hid) |
| 97 | self._notify_launch_hid = None |
| 98 | if home_activity.props.launch_status == home_activity.LAUNCH_FAILED: |
| 99 | self._on_failed_launch() |
| 100 | else: |
93 | 101 | self._icon.props.pulsing = False |
94 | | home_activity.disconnect(self._notify_launching_hid) |
| 102 | |
95 | 103 | |
96 | 104 | class BaseInviteButton(ToolButton): |
97 | 105 | def __init__(self, invite): |
diff --git a/src/jarabe/model/shell.py b/src/jarabe/model/shell.py
index e03e0f7..c09107c 100644
a
|
b
|
_SERVICE_NAME = "org.laptop.Activity" |
35 | 35 | _SERVICE_PATH = "/org/laptop/Activity" |
36 | 36 | _SERVICE_INTERFACE = "org.laptop.Activity" |
37 | 37 | |
| 38 | |
38 | 39 | class Activity(gobject.GObject): |
39 | 40 | """Activity which appears in the "Home View" of the Sugar shell |
40 | 41 | |
… |
… |
class Activity(gobject.GObject): |
46 | 47 | |
47 | 48 | __gtype_name__ = 'SugarHomeActivity' |
48 | 49 | |
49 | | __gproperties__ = { |
50 | | 'launching' : (bool, None, None, False, |
51 | | gobject.PARAM_READWRITE), |
52 | | } |
| 50 | LAUNCHING = 0 |
| 51 | LAUNCH_FAILED = 1 |
| 52 | LAUNCHED = 2 |
53 | 53 | |
54 | 54 | def __init__(self, activity_info, activity_id, window=None): |
55 | 55 | """Initialise the HomeActivity |
… |
… |
class Activity(gobject.GObject): |
69 | 69 | self._activity_id = activity_id |
70 | 70 | self._activity_info = activity_info |
71 | 71 | self._launch_time = time.time() |
72 | | self._launching = True |
| 72 | self._launch = self.LAUNCHING |
73 | 73 | |
74 | 74 | if window is not None: |
75 | 75 | self.set_window(window) |
… |
… |
class Activity(gobject.GObject): |
84 | 84 | signal_name="NameOwnerChanged", |
85 | 85 | dbus_interface="org.freedesktop.DBus") |
86 | 86 | |
| 87 | self._launch_completed_hid = get_model().connect('launch-completed', |
| 88 | self.__launch_completed_cb) |
| 89 | self._launch_failed_hid = get_model().connect('launch-failed', |
| 90 | self.__launch_failed_cb) |
| 91 | |
| 92 | def get_launch_status(self): |
| 93 | return self._launch |
| 94 | |
| 95 | launch_status = gobject.property(getter=get_launch_status) |
| 96 | |
87 | 97 | def set_window(self, window): |
88 | 98 | """Set the window for the activity |
89 | 99 | |
… |
… |
class Activity(gobject.GObject): |
224 | 234 | return self._window.get_xid() == activity.get_xid() |
225 | 235 | return False |
226 | 236 | |
227 | | def do_set_property(self, pspec, value): |
228 | | if pspec.name == 'launching': |
229 | | self._launching = value |
230 | | |
231 | | def do_get_property(self, pspec): |
232 | | if pspec.name == 'launching': |
233 | | return self._launching |
234 | | |
235 | 237 | def _get_service_name(self): |
236 | 238 | if self._activity_id: |
237 | 239 | return _SERVICE_NAME + self._activity_id |
… |
… |
class Activity(gobject.GObject): |
270 | 272 | def _set_active_error(self, err): |
271 | 273 | logging.error("set_active() failed: %s", err) |
272 | 274 | |
| 275 | def _set_launch_status(self, value): |
| 276 | get_model().disconnect(self._launch_completed_hid) |
| 277 | get_model().disconnect(self._launch_failed_hid) |
| 278 | self._launch_completed_hid = None |
| 279 | self._launch_failed_hid = None |
| 280 | self._launch = value |
| 281 | self.notify('launch_status') |
| 282 | |
| 283 | def __launch_completed_cb(self, model, home_activity): |
| 284 | if home_activity is self: |
| 285 | self._set_launch_status(self.LAUNCHED) |
| 286 | |
| 287 | def __launch_failed_cb(self, model, home_activity): |
| 288 | if home_activity is self: |
| 289 | self._set_launch_status(self.LAUNCH_FAILED) |
| 290 | |
| 291 | |
273 | 292 | class ShellModel(gobject.GObject): |
274 | 293 | """Model of the shell (activity management) |
275 | 294 | |
… |
… |
class ShellModel(gobject.GObject): |
332 | 351 | self._active_activity = None |
333 | 352 | self._tabbing_activity = None |
334 | 353 | self._pservice = presenceservice.get_instance() |
| 354 | self._launchers = {} |
335 | 355 | |
336 | 356 | self._screen.toggle_showing_desktop(True) |
337 | 357 | |
| 358 | def get_launcher(self, activity_id): |
| 359 | return self._launchers.get(str(activity_id)) |
| 360 | |
| 361 | def push_launcher(self, activity_id, launcher): |
| 362 | self._launchers[str(activity_id)] = launcher |
| 363 | |
| 364 | def pop_launcher(self, activity_id): |
| 365 | if str(activity_id) not in self._launchers: |
| 366 | return None |
| 367 | else: |
| 368 | return self._launchers.pop(str(activity_id)) |
| 369 | |
338 | 370 | def _update_zoom_level(self, window): |
339 | 371 | if window.get_window_type() == wnck.WINDOW_DIALOG: |
340 | 372 | return |
… |
… |
class ShellModel(gobject.GObject): |
482 | 514 | home_activity.set_window(window) |
483 | 515 | |
484 | 516 | if wm.get_sugar_window_type(window) != 'launcher': |
485 | | home_activity.props.launching = False |
486 | | if not home_activity.is_journal(): |
487 | | self.emit('launch-completed', home_activity) |
| 517 | self.emit('launch-completed', home_activity) |
488 | 518 | |
489 | 519 | startup_time = time.time() - home_activity.get_launch_time() |
490 | 520 | logging.debug('%s launched in %f seconds.', |
… |
… |
class ShellModel(gobject.GObject): |
560 | 590 | " was not found in the bundle registry." |
561 | 591 | % service_name) |
562 | 592 | home_activity = Activity(activity_info, activity_id) |
563 | | home_activity.props.launching = True |
564 | 593 | self._add_activity(home_activity) |
565 | 594 | |
566 | 595 | self._set_active_activity(home_activity) |
… |
… |
class ShellModel(gobject.GObject): |
577 | 606 | if home_activity: |
578 | 607 | logging.debug("Activity %s (%s) launch failed", activity_id, |
579 | 608 | home_activity.get_type()) |
580 | | if home_activity.props.launching: |
| 609 | if self.get_launcher(activity_id) is not None: |
581 | 610 | self.emit('launch-failed', home_activity) |
582 | 611 | else: |
| 612 | # activity sent failure notification after closing launcher |
583 | 613 | self._remove_activity(home_activity) |
584 | 614 | else: |
585 | 615 | logging.error('Model for activity id %s does not exist.', |
… |
… |
class ShellModel(gobject.GObject): |
592 | 622 | logging.debug('Activity %s has been closed already.', activity_id) |
593 | 623 | return False |
594 | 624 | |
595 | | if home_activity.props.launching: |
| 625 | if self.get_launcher(activity_id) is not None: |
596 | 626 | logging.debug('Activity %s still launching, assuming it failed.', |
597 | 627 | activity_id) |
598 | 628 | self.notify_launch_failed(activity_id) |
diff --git a/src/jarabe/view/launcher.py b/src/jarabe/view/launcher.py
index 422a49a..15554bf 100644
a
|
b
|
class _Animation(animator.Animation): |
156 | 156 | self._icon.props.size = int(self.start_size + d) |
157 | 157 | |
158 | 158 | |
159 | | _launchers = {} |
160 | | |
161 | | |
162 | 159 | def setup(): |
163 | 160 | model = shell.get_model() |
164 | 161 | model.connect('launch-started', __launch_started_cb) |
… |
… |
def setup(): |
167 | 164 | |
168 | 165 | |
169 | 166 | def add_launcher(activity_id, icon_path, icon_color): |
| 167 | model = shell.get_model() |
170 | 168 | |
171 | | if activity_id in _launchers: |
| 169 | if model.get_launcher(activity_id) is not None: |
172 | 170 | return |
173 | 171 | |
174 | 172 | launch_window = LaunchWindow(activity_id, icon_path, icon_color) |
175 | 173 | launch_window.show() |
176 | 174 | |
177 | | _launchers[activity_id] = launch_window |
| 175 | model.push_launcher(activity_id, launch_window) |
178 | 176 | |
179 | 177 | |
180 | 178 | def __launch_started_cb(home_model, home_activity): |
… |
… |
def __launch_started_cb(home_model, home_activity): |
184 | 182 | |
185 | 183 | def __launch_failed_cb(home_model, home_activity): |
186 | 184 | activity_id = home_activity.get_activity_id() |
187 | | launcher = _launchers.get(activity_id) |
| 185 | launcher = shell.get_model().get_launcher(activity_id) |
188 | 186 | |
189 | 187 | if launcher is None: |
190 | 188 | logging.error('Launcher for %s is missing', activity_id) |
… |
… |
def __launch_completed_cb(home_model, home_activity): |
208 | 206 | |
209 | 207 | def _destroy_launcher(home_activity): |
210 | 208 | activity_id = home_activity.get_activity_id() |
| 209 | launcher = shell.get_model().pop_launcher(activity_id) |
211 | 210 | |
212 | | if activity_id in _launchers: |
213 | | _launchers[activity_id].destroy() |
214 | | del _launchers[activity_id] |
215 | | else: |
| 211 | if launcher is not None: |
| 212 | launcher.destroy() |
| 213 | elif not home_activity.is_journal(): |
216 | 214 | logging.error('Launcher for %s is missing', activity_id) |
diff --git a/src/jarabe/view/palettes.py b/src/jarabe/view/palettes.py
index 2beceff..14d2707 100644
a
|
b
|
class BasePalette(Palette): |
39 | 39 | def __init__(self, home_activity): |
40 | 40 | Palette.__init__(self) |
41 | 41 | |
42 | | if home_activity.props.launching: |
43 | | home_activity.connect('notify::launching', |
44 | | self._launching_changed_cb) |
| 42 | self._notify_launch_hid = None |
| 43 | |
| 44 | if home_activity.props.launch_status == home_activity.LAUNCHING: |
| 45 | self._notify_launch_hid = home_activity.connect( \ |
| 46 | 'notify::launch-status', self.__notify_launch_status_cb) |
45 | 47 | self.set_primary_text(_('Starting...')) |
| 48 | elif home_activity.props.launch_status == home_activity.LAUNCH_FAILED: |
| 49 | self._on_failed_launch() |
46 | 50 | else: |
47 | 51 | self.setup_palette() |
48 | 52 | |
49 | | def _launching_changed_cb(self, home_activity, pspec): |
50 | | if not home_activity.props.launching: |
51 | | self.setup_palette() |
52 | | |
53 | 53 | def setup_palette(self): |
54 | 54 | raise NotImplementedError |
55 | 55 | |
| 56 | def _on_failed_launch(self): |
| 57 | self.set_primary_text(_('Activity failed to start')) |
| 58 | |
| 59 | def __notify_launch_status_cb(self, home_activity, pspec): |
| 60 | home_activity.disconnect(self._notify_launch_hid) |
| 61 | self._notify_launch_hid = None |
| 62 | if home_activity.props.launch_status == home_activity.LAUNCH_FAILED: |
| 63 | self._on_failed_launch() |
| 64 | else: |
| 65 | self.setup_palette() |
| 66 | |
| 67 | |
56 | 68 | class CurrentActivityPalette(BasePalette): |
57 | 69 | def __init__(self, home_activity): |
58 | 70 | self._home_activity = home_activity |
diff --git a/src/jarabe/view/service.py b/src/jarabe/view/service.py
index fbcc961..bb71694 100644
a
|
b
|
class UIService(dbus.service.Object): |
83 | 83 | |
84 | 84 | if activity is not None and activity.get_window() is not None: |
85 | 85 | activity.get_window().activate(gtk.get_current_event_time()) |
86 | | return not activity.props.launching |
| 86 | return self._shell_model.get_launcher(activity_id) is None |
87 | 87 | |
88 | 88 | return False |
89 | 89 | |