diff --git a/src/model/homemodel.py b/src/model/homemodel.py
index 5538f84..a75adcf 100644
--- a/src/model/homemodel.py
+++ b/src/model/homemodel.py
@@ -42,18 +42,21 @@ class HomeModel(gobject.GObject):
         'activity-added':          (gobject.SIGNAL_RUN_FIRST,
                                     gobject.TYPE_NONE, 
                                    ([gobject.TYPE_PYOBJECT])),
-        'activity-started':         (gobject.SIGNAL_RUN_FIRST,
-                                    gobject.TYPE_NONE, 
-                                   ([gobject.TYPE_PYOBJECT])),
         'activity-removed':        (gobject.SIGNAL_RUN_FIRST,
                                     gobject.TYPE_NONE,
                                    ([gobject.TYPE_PYOBJECT])),
         'active-activity-changed': (gobject.SIGNAL_RUN_FIRST,
                                     gobject.TYPE_NONE,
                                    ([gobject.TYPE_PYOBJECT])),
-        'pending-activity-changed': (gobject.SIGNAL_RUN_FIRST,
-                                     gobject.TYPE_NONE,
-                                     ([gobject.TYPE_PYOBJECT]))
+        'launch-started':          (gobject.SIGNAL_RUN_FIRST,
+                                    gobject.TYPE_NONE, 
+                                   ([gobject.TYPE_PYOBJECT])),
+        'launch-completed':        (gobject.SIGNAL_RUN_FIRST,
+                                    gobject.TYPE_NONE, 
+                                   ([gobject.TYPE_PYOBJECT])),
+        'launch-failed':           (gobject.SIGNAL_RUN_FIRST,
+                                    gobject.TYPE_NONE, 
+                                   ([gobject.TYPE_PYOBJECT]))
     }
     
     def __init__(self):
@@ -61,7 +64,6 @@ class HomeModel(gobject.GObject):
 
         self._activities = []
         self._active_activity = None
-        self._pending_activity = None
 
         screen = wnck.screen_get_default()
         screen.connect('window-opened', self._window_opened_cb)
@@ -78,7 +80,7 @@ class HomeModel(gobject.GObject):
 
     def get_previous_activity(self):
         activities = self._get_activities_with_window()
-        i = activities.index(self._pending_activity)
+        i = activities.index(self._active_activity)
         if len(activities) == 0:
             return None
         elif i - 1 >= 0:
@@ -88,7 +90,7 @@ class HomeModel(gobject.GObject):
 
     def get_next_activity(self):
         activities = self._get_activities_with_window()
-        i = activities.index(self._pending_activity)
+        i = activities.index(self._active_activity)
         if len(activities) == 0:
             return None
         elif i + 1 < len(activities):
@@ -96,34 +98,8 @@ class HomeModel(gobject.GObject):
         else:
             return activities[0]
 
-    def get_pending_activity(self):
-        """Returns the activity that would be seen in the Activity zoom level
-
-        In the Home (or Neighborhood or Groups) zoom level, this
-        indicates the activity that would become active if the user
-        switched to the Activity zoom level. (In the Activity zoom
-        level, this just returns the currently-active activity.)
-        Unlike get_active_activity(), this never returns None as long
-        as there is any activity running.
-        """
-        return self._pending_activity
-
-    def _set_pending_activity(self, home_activity):
-        if self._pending_activity == home_activity:
-            return
-
-        self._pending_activity = home_activity
-        self.emit('pending-activity-changed', self._pending_activity)
-
     def get_active_activity(self):
-        """Returns the activity that the user is currently working in
-
-        In the Activity zoom level, this returns the currently-active
-        activity. In the other zoom levels, it returns the activity
-        that was most-recently active in the Activity zoom level, or
-        None if the most-recently-active activity is no longer
-        running.
-        """
+        """Returns the activity that the user is currently working in"""
         return self._active_activity
 
     def _set_active_activity(self, home_activity):
@@ -181,10 +157,10 @@ class HomeModel(gobject.GObject):
             home_activity.set_window(window)
 
             home_activity.props.launching = False
-            self.emit('activity-started', home_activity)
+            self.emit('launch-completed', home_activity)
 
-            if self._pending_activity is None:
-                self._set_pending_activity(home_activity)
+            if self._active_activity is None:
+                self._set_active_activity(home_activity)
 
     def _window_closed_cb(self, screen, window):
         if window.get_window_type() == wnck.WINDOW_NORMAL:
@@ -219,7 +195,6 @@ class HomeModel(gobject.GObject):
 
         act = self._get_activity_by_xid(window.get_xid())
         if act is not None:
-            self._set_pending_activity(act)
             self._set_active_activity(act)
 
     def _add_activity(self, home_activity):
@@ -228,20 +203,16 @@ class HomeModel(gobject.GObject):
 
     def _remove_activity(self, home_activity):
         if home_activity == self._active_activity:
-            self._set_active_activity(None)
-
-        if home_activity == self._pending_activity:
-            # Figure out the new _pending_activity
             windows = wnck.screen_get_default().get_windows_stacked()
             windows.reverse()
             for window in windows:
                 new_activity = self._get_activity_by_xid(window.get_xid())
                 if new_activity is not None:
-                    self._set_pending_activity(new_activity)
+                    self._set_active_activity(new_activity)
                     break
             else:
                 logging.error('No activities are running')
-                self._set_pending_activity(None)
+                self._set_active_activity(None)
 
         self.emit('activity-removed', home_activity)
         self._activities.remove(home_activity)
@@ -253,7 +224,7 @@ class HomeModel(gobject.GObject):
         else:
             logging.error('Model for window %d does not exist.' % xid)
 
-    def notify_activity_launch(self, activity_id, service_name):
+    def notify_launch(self, activity_id, service_name):
         registry = activity.get_registry()
         activity_info = registry.get_activity(service_name)
         if not activity_info:
@@ -264,11 +235,15 @@ class HomeModel(gobject.GObject):
         home_activity.props.launching = True
         self._add_activity(home_activity)
 
+        self._set_active_activity(home_activity)
+
+        self.emit('launch-started', home_activity)
+
         # FIXME: better learn about finishing processes by receiving a signal.
         # Now just check whether an activity has a window after ~90sec
         gobject.timeout_add(90000, self._check_activity_launched, activity_id)
 
-    def notify_activity_launch_failed(self, activity_id):
+    def notify_launch_failed(self, activity_id):
         home_activity = self._get_activity_by_id(activity_id)
         if home_activity:
             logging.debug("Activity %s (%s) launch failed" % \
@@ -279,10 +254,12 @@ class HomeModel(gobject.GObject):
             logging.error('Model for activity id %s does not exist.'
                           % activity_id)
 
+        self.emit('launch-failed', home_activity)
+
     def _check_activity_launched(self, activity_id):
         home_activity = self._get_activity_by_id(activity_id)
         if home_activity and home_activity.props.launching:
             logging.debug('Activity %s still launching, assuming it failed...'
                           % activity_id)
-            self.notify_activity_launch_failed(activity_id)
+            self.notify_launch_failed(activity_id)
         return False
diff --git a/src/shellservice.py b/src/shellservice.py
index 3d90779..706f2f2 100644
--- a/src/shellservice.py
+++ b/src/shellservice.py
@@ -79,12 +79,14 @@ class ShellService(dbus.service.Object):
     @dbus.service.method(_DBUS_SHELL_IFACE,
                          in_signature="ss", out_signature="")
     def NotifyLaunch(self, bundle_id, activity_id):
-        self._shell.notify_launch(bundle_id, activity_id)
+        home = self._shell.get_model().get_home()
+        home.notify_launch(activity_id, bundle_id)
 
     @dbus.service.method(_DBUS_SHELL_IFACE,
                          in_signature="s", out_signature="")
     def NotifyLaunchFailure(self, activity_id):
-        self._shell.notify_launch_failure(activity_id)
+        home = self._shell.get_model().get_home()
+        home.notify_launch_failed(activity_id)
 
     @dbus.service.signal(_DBUS_OWNER_IFACE, signature="s")
     def ColorChanged(self, color):
diff --git a/src/view/Shell.py b/src/view/Shell.py
index 875e9a5..1095878 100644
--- a/src/view/Shell.py
+++ b/src/view/Shell.py
@@ -56,7 +56,6 @@ class Shell(gobject.GObject):
         self._hosts = {}
         self._screen = wnck.screen_get_default()
         self._current_host = None
-        self._pending_host = None
         self._screen_rotation = 0
 
         self._key_handler = KeyHandler()
@@ -67,12 +66,12 @@ class Shell(gobject.GObject):
         self._home_window.show()
 
         home_model = self._model.get_home()
-        home_model.connect('activity-started', self._activity_started_cb)
+        home_model.connect('launch-started', self.__launch_started_cb)
+        home_model.connect('launch-failed', self.__launch_failed_cb)
+        home_model.connect('launch-completed', self.__launch_completed_cb)
         home_model.connect('activity-removed', self._activity_removed_cb)
         home_model.connect('active-activity-changed',
                            self._active_activity_changed_cb)
-        home_model.connect('pending-activity-changed',
-                           self._pending_activity_changed_cb)
 
         gobject.idle_add(self._start_journal_idle)
 
@@ -95,7 +94,19 @@ class Shell(gobject.GObject):
         if registry.get_activity('org.laptop.JournalActivity'):
             self.start_activity('org.laptop.JournalActivity')
 
-    def _activity_started_cb(self, home_model, home_activity):
+    def __launch_started_cb(self, home_model, home_activity):
+        if home_activity.get_type() == 'org.laptop.JournalActivity':
+            return
+
+        self._screen.toggle_showing_desktop(True)
+        self._home_window.set_zoom_level(shellmodel.ShellModel.ZOOM_ACTIVITY)
+        self._home_window.launch_box.zoom_in()
+
+    def __launch_failed_cb(self, home_model, home_activity):
+        if self._screen.get_showing_desktop():
+            self._home_window.set_zoom_level(shellmodel.ShellModel.ZOOM_HOME)
+
+    def __launch_completed_cb(self, home_model, home_activity):
         activity_host = ActivityHost(home_activity)
         self._hosts[activity_host.get_xid()] = activity_host
         if home_activity.get_type() in self._activities_starting:
@@ -110,22 +121,17 @@ class Shell(gobject.GObject):
             del self._hosts[xid]
 
     def _active_activity_changed_cb(self, home_model, home_activity):
+        host = None
         if home_activity:
-            host = self._hosts[home_activity.get_xid()]
-        else:
-            host = None
+            xid = home_activity.get_xid()
+            if xid:
+                host = self._hosts[home_activity.get_xid()]
 
         if self._current_host:
             self._current_host.set_active(False)
 
         self._current_host = host
 
-    def _pending_activity_changed_cb(self, home_model, home_activity):
-        if home_activity:
-            self._pending_host = self._hosts[home_activity.get_xid()]
-        else:
-            self._pending_host = None
-
     def get_model(self):
         return self._model
 
@@ -150,17 +156,6 @@ class Shell(gobject.GObject):
         handle = ActivityHandle(activity_id)
         activityfactory.create(bundle_id, handle)
 
-    def notify_launch(self, bundle_id, activity_id):
-        # Zoom to Home for launch feedback
-        self.set_zoom_level(shellmodel.ShellModel.ZOOM_HOME)
-
-        home_model = self._model.get_home()
-        home_model.notify_activity_launch(activity_id, bundle_id)
-
-    def notify_launch_failure(self, activity_id):
-        home_model = self._model.get_home()
-        home_model.notify_activity_launch_failed(activity_id)
-
     def start_activity(self, activity_type):
         if activity_type in self._activities_starting:
             logging.debug("This activity is still launching.")
@@ -192,8 +187,8 @@ class Shell(gobject.GObject):
         self.take_activity_screenshot()
 
         if level == shellmodel.ShellModel.ZOOM_ACTIVITY:
-            if self._pending_host is not None:
-                self._pending_host.present()
+            if self._current_host is not None:
+                self._current_host.present()
             self._screen.toggle_showing_desktop(False)
         else:
             self._model.set_zoom_level(level)
diff --git a/src/view/frame/activitiestray.py b/src/view/frame/activitiestray.py
index 020cb68..90be6e9 100644
--- a/src/view/frame/activitiestray.py
+++ b/src/view/frame/activitiestray.py
@@ -191,7 +191,7 @@ class ActivitiesTray(HTray):
         self._home_model = shellmodel.get_instance().get_home()
         self._home_model.connect('activity-added', self.__activity_added_cb)
         self._home_model.connect('activity-removed', self.__activity_removed_cb)
-        self._home_model.connect('pending-activity-changed',
+        self._home_model.connect('active-activity-changed',
                                  self.__activity_changed_cb)
 
         self._invites = shellmodel.get_instance().get_invites()
@@ -227,7 +227,9 @@ class ActivitiesTray(HTray):
     def __activity_clicked_cb(self, button, home_activity):
         if button.props.active:
             logging.debug('ActivitiesTray.__activity_clicked_cb')
-            home_activity.get_window().activate(gtk.get_current_event_time())
+            window = home_activity.get_window()
+            if window:
+                window.activate(gtk.get_current_event_time())
 
     def __invite_clicked_cb(self, icon, invite):
         self._invites.remove_invite(invite)
diff --git a/src/view/frame/friendstray.py b/src/view/frame/friendstray.py
index 86decaa..b9d8c07 100644
--- a/src/view/frame/friendstray.py
+++ b/src/view/frame/friendstray.py
@@ -54,8 +54,8 @@ class FriendsTray(VTray):
                 reply_handler=self._get_activities_cb)
 
         home_model = shellmodel.get_instance().get_home()
-        home_model.connect('pending-activity-changed',
-                           self._pending_activity_changed_cb)
+        home_model.connect('active-activity-changed',
+                           self._active_activity_changed_cb)
 
     def _get_activities_cb(self, activities_list):
         for act in activities_list:
@@ -117,7 +117,7 @@ class FriendsTray(VTray):
             self._left_hid = activity_ps.connect(
                             'buddy-left', self.__buddy_left_cb)
             
-    def _pending_activity_changed_cb(self, home_model, home_activity):
+    def _active_activity_changed_cb(self, home_model, home_activity):
         if home_activity is None:        
             return
 
diff --git a/src/view/home/HomeWindow.py b/src/view/home/HomeWindow.py
index 7e0a0c5..9151d46 100644
--- a/src/view/home/HomeWindow.py
+++ b/src/view/home/HomeWindow.py
@@ -24,12 +24,14 @@ from view.home.MeshBox import MeshBox
 from view.home.HomeBox import HomeBox
 from view.home.FriendsBox import FriendsBox
 from view.home.transitionbox import TransitionBox
+from view.home.launchbox import LaunchBox
 from model.shellmodel import ShellModel
 
 _HOME_PAGE       = 0
 _FRIENDS_PAGE    = 1
 _MESH_PAGE       = 2
 _TRANSITION_PAGE = 3
+_LAUNCH_PAGE     = 4
 
 class HomeWindow(gtk.Window):
     def __init__(self):
@@ -65,6 +67,7 @@ class HomeWindow(gtk.Window):
         self._friends_box = FriendsBox()
         self._mesh_box = MeshBox()
         self._transition_box = TransitionBox()
+        self.launch_box = LaunchBox()
 
         self._activate_view()
         self._canvas.set_root(self._home_box)
@@ -98,12 +101,16 @@ class HomeWindow(gtk.Window):
             self._home_box.suspend()
         elif self._level == ShellModel.ZOOM_MESH:
             self._mesh_box.suspend()
+        elif self._level == ShellModel.ZOOM_ACTIVITY:
+            self.launch_box.suspend()
 
     def _activate_view(self):
         if self._level == ShellModel.ZOOM_HOME:
             self._home_box.resume()
         elif self._level == ShellModel.ZOOM_MESH:
             self._mesh_box.resume()
+        elif self._level == ShellModel.ZOOM_ACTIVITY:
+            self.launch_box.resume()
 
     def _visibility_notify_event_cb(self, window, event):
         if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:
@@ -124,6 +131,8 @@ class HomeWindow(gtk.Window):
             size = style.LARGE_ICON_SIZE
         elif level == ShellModel.ZOOM_MESH:
             size = style.STANDARD_ICON_SIZE
+        elif level == ShellModel.ZOOM_ACTIVITY:
+            size = style.XLARGE_ICON_SIZE
             
         self._transition_box.set_size(size)
     
@@ -135,6 +144,8 @@ class HomeWindow(gtk.Window):
         elif self._level == ShellModel.ZOOM_MESH:
             self._canvas.set_root(self._mesh_box)
             self._mesh_box.focus_search_entry()
+        elif self._level == ShellModel.ZOOM_ACTIVITY:
+            self._canvas.set_root(self.launch_box)
 
     def get_home_box(self):
         return self._home_box   
diff --git a/src/view/home/Makefile.am b/src/view/home/Makefile.am
index 4ae3410..5306e2b 100644
--- a/src/view/home/Makefile.am
+++ b/src/view/home/Makefile.am
@@ -5,6 +5,7 @@ sugar_PYTHON =			\
 	activitiesring.py	\
 	FriendView.py		\
 	FriendsBox.py		\
+	launchbox.py		\
 	HomeBox.py		\
 	HomeWindow.py		\
 	MeshBox.py		\
diff --git a/src/view/home/activitiesring.py b/src/view/home/activitiesring.py
index 4432279..394d31a 100644
--- a/src/view/home/activitiesring.py
+++ b/src/view/home/activitiesring.py
@@ -176,16 +176,16 @@ class CurrentActivityIcon(CanvasIcon, hippo.CanvasItem):
         CanvasIcon.__init__(self, cache=True)
         self._home_model = shellmodel.get_instance().get_home()
 
-        if self._home_model.get_pending_activity() is not None:
-            self._update(self._home_model.get_pending_activity())
+        if self._home_model.get_active_activity() is not None:
+            self._update(self._home_model.get_active_activity())
 
-        self._home_model.connect('pending-activity-changed',
-                self.__pending_activity_changed_cb)
+        self._home_model.connect('active-activity-changed',
+                                 self.__active_activity_changed_cb)
 
         self.connect('button-release-event', self.__button_release_event_cb)
 
     def __button_release_event_cb(self, icon, event):
-        self._home_model.get_pending_activity().get_window().activate(1)
+        self._home_model.get_active_activity().get_window().activate(1)
 
     def _update(self, home_activity):
         _logger.debug('CurrentActivityIcon._update')
@@ -199,7 +199,7 @@ class CurrentActivityIcon(CanvasIcon, hippo.CanvasItem):
             palette = CurrentActivityPalette(home_activity)
         self.set_palette(palette)
 
-    def __pending_activity_changed_cb(self, home_model, home_activity):
+    def __active_activity_changed_cb(self, home_model, home_activity):
         self._update(home_activity)
 
 class RingLayout(gobject.GObject, hippo.CanvasLayout):
diff --git a/src/view/home/launchbox.py b/src/view/home/launchbox.py
new file mode 100644
index 0000000..a70cb61
--- /dev/null
+++ b/src/view/home/launchbox.py
@@ -0,0 +1,94 @@
+# Copyright (C) 2008, Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+import hippo
+import gobject
+import logging
+
+from sugar.graphics import style
+from sugar.graphics import animator
+from sugar.graphics.xocolor import XoColor
+
+from model import shellmodel
+from view.pulsingicon import CanvasPulsingIcon
+
+class LaunchBox(hippo.CanvasBox):
+    def __init__(self):
+        gobject.GObject.__init__(
+                self, background_color=style.COLOR_WHITE.get_int())
+
+        self._activity_icon = CanvasPulsingIcon()
+
+        # FIXME support non-xo colors in CanvasPulsingIcon
+        self._activity_icon.props.base_color = \
+            XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(),
+                               style.COLOR_TRANSPARENT.get_svg()))
+
+        vbox = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL)
+        vbox.append(self._activity_icon, hippo.PACK_EXPAND)
+        self.append(vbox, hippo.PACK_EXPAND)
+
+        self._animator = animator.Animator(1.0)
+
+        self._home = shellmodel.get_instance().get_home()
+        self._home.connect('active-activity-changed',
+                           self.__active_activity_changed_cb)
+
+        self._update_icon()
+
+    def zoom_in(self):
+        logging.debug('zooming in to activity')
+
+        self._activity_icon.props.size = style.STANDARD_ICON_SIZE
+
+        self._animator.remove_all()
+        self._animator.add(_Animation(self._activity_icon,
+                                      style.STANDARD_ICON_SIZE,
+                                      style.XLARGE_ICON_SIZE))
+        self._animator.start()
+
+        logging.debug('starting pulse')
+
+        self._activity_icon.props.pulsing = True
+
+    def suspend(self):
+        self._activity_icon.props.paused = True
+
+    def resume(self):
+        self._activity_icon.props.paused = False
+
+    def _update_icon(self):
+        activity = self._home.get_active_activity()
+        if activity:
+            self._activity_icon.props.file_name = activity.get_icon_path()
+            self._activity_icon.props.pulse_color = activity.get_icon_color()
+        else:
+            self._activity_icon.props.file_name = None
+
+    def __active_activity_changed_cb(self, model, activity):
+        self._update_icon()
+
+class _Animation(animator.Animation):
+    def __init__(self, icon, start_size, end_size):
+        animator.Animation.__init__(self, 0.0, 1.0)
+
+        self._icon = icon
+        self.start_size = start_size
+        self.end_size = end_size
+
+    def next_frame(self, current):
+        d = (self.end_size - self.start_size) * current
+        self._icon.props.size = self.start_size + d
