Ticket #3776: sugar-session

File sugar-session, 10.2 KB (added by dsd, 12 years ago)

replacement /usr/bin/sugar-session

Line 
1#!/usr/bin/env python
2# Copyright (C) 2006, Red Hat, Inc.
3# Copyright (C) 2009, One Laptop Per Child Association Inc
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
19import os
20import sys
21import time
22import subprocess
23import shutil
24
25if os.environ.get('SUGAR_LOGGER_LEVEL', '') == 'debug':
26    print '%r STARTUP: Starting the shell' % time.time()
27    sys.stdout.flush()
28
29import gettext
30import logging
31
32import gconf
33import gtk
34import gobject
35import dbus.glib
36import wnck
37import dbus
38
39try:
40    import xklavier
41except ImportError:
42    logging.debug('Could not load xklavier for keyboard configuration')
43
44gtk.gdk.threads_init()
45dbus.glib.threads_init()
46
47def cleanup_logs(logs_dir):
48    """Clean up the log directory, moving old logs into a numbered backup
49    directory.  We only keep `_MAX_BACKUP_DIRS` of these backup directories
50    around; the rest are removed."""
51    if not os.path.isdir(logs_dir):
52        os.makedirs(logs_dir)
53
54    backup_logs = []
55    backup_dirs = []
56    for f in os.listdir(logs_dir):
57        path = os.path.join(logs_dir, f)
58        if os.path.isfile(path):
59            backup_logs.append(f)
60        elif os.path.isdir(path):
61            backup_dirs.append(path)
62
63    if len(backup_dirs) > 3:
64        backup_dirs.sort()
65        root = backup_dirs[0]
66        for f in os.listdir(root):
67            os.remove(os.path.join(root, f))
68        os.rmdir(root)
69
70    if len(backup_logs) > 0:
71        name = str(int(time.time()))
72        backup_dir = os.path.join(logs_dir, name)
73        os.mkdir(backup_dir)
74        for log in backup_logs:
75            source_path = os.path.join(logs_dir, log)
76            dest_path = os.path.join(backup_dir, log)
77            os.rename(source_path, dest_path)
78
79def show_welcome_screen():
80    path = os.path.expanduser('~/.welcome_screen')
81    if os.path.exists(path):
82        welcome_file_flag = open(path, 'r')
83        welcome_file_command = welcome_file_flag.read()
84        welcome_file_flag.close()
85        os.remove(path)
86        if subprocess.call(welcome_file_command.split()):
87            logging.warning('Can not display welcome screen.')
88
89def start_ui_service():
90    from jarabe.view.service import UIService
91
92    ui_service = UIService()
93
94def start_session_manager():
95    from jarabe.model.session import get_session_manager
96
97    session_manager = get_session_manager()
98    session_manager.start()
99
100def unfreeze_dcon_cb():
101    logging.debug('STARTUP: unfreeze_dcon_cb')
102    from jarabe.model import screen
103
104    screen.set_dcon_freeze(0)
105
106def setup_frame_cb():
107    logging.debug('STARTUP: setup_frame_cb')
108    from jarabe import frame
109    frame.get_view()
110
111def setup_keyhandler_cb():
112    logging.debug('STARTUP: setup_keyhandler_cb')
113    from jarabe.view import keyhandler
114    from jarabe import frame
115    keyhandler.setup(frame.get_view())
116
117def setup_journal_cb():
118    logging.debug('STARTUP: setup_journal_cb')
119    from jarabe.journal import journalactivity
120    journalactivity.start()
121
122def show_software_updates_cb():
123    logging.debug('STARTUP: show_software_updates_cb')
124    if os.path.isfile(os.path.expanduser('~/.sugar-update')):
125        from jarabe.desktop import homewindow
126        home_window = homewindow.get_instance()
127        home_window.get_home_box().show_software_updates_alert()
128
129browse_p = None
130
131def browse_check():
132    logging.warning("checking for browse")
133    rc = browse_p.poll()
134    if rc is None:
135        logging.warning("browse still running")
136        bus = dbus.SystemBus()
137        proxy = bus.get_object('org.freedesktop.login1', '/org/freedesktop/login1')
138        pm = dbus.Interface(proxy, 'org.freedesktop.login1.Manager')
139        pm.Reboot(True)
140    else:
141        logging.warning("browse exited with code %s", rc)
142
143def start_browse():
144    logging.warning("starting browse")
145    global browse_p
146    browse_p = subprocess.Popen("/usr/bin/sugar-launch org.laptop.WebActivity", shell=True)
147    gobject.timeout_add(18000, browse_check)
148    return False
149
150def setup_notification_service_cb():
151    from jarabe.model import notifications
152    notifications.init()
153
154def setup_file_transfer_cb():
155    from jarabe.model import filetransfer
156    filetransfer.init()
157
158def setup_keyboard_cb():
159    logging.debug('STARTUP: setup_keyboard_cb')
160
161    gconf_client = gconf.client_get_default()
162    have_config = False
163
164    try:
165        display = gtk.gdk.display_get_default()
166        if display is not None:
167            engine = xklavier.Engine(display)
168        else:
169            logging.debug('setup_keyboard_cb: Could not get default display.')
170            return
171
172        configrec = xklavier.ConfigRec()
173        configrec.get_from_server(engine)
174
175        layouts = gconf_client.get_list(\
176            '/desktop/sugar/peripherals/keyboard/layouts', gconf.VALUE_STRING)
177        layouts_list = []
178        variants_list = []
179        for layout in layouts:
180            layouts_list.append(layout.split('(')[0])
181            variants_list.append(layout.split('(')[1][:-1])
182
183        if layouts_list and variants_list:
184            have_config = True
185            configrec.set_layouts(layouts_list)
186            configrec.set_variants(variants_list)
187
188        model = gconf_client.get_string(\
189            '/desktop/sugar/peripherals/keyboard/model')
190        if model:
191            have_config = True
192            configrec.set_model(model)
193
194        options = gconf_client.get_list(\
195            '/desktop/sugar/peripherals/keyboard/options', gconf.VALUE_STRING)
196        if options:
197            have_config = True
198            configrec.set_options(options)
199
200        if have_config:
201            configrec.activate(engine)
202    except Exception:
203        logging.exception('Error during keyboard configuration')
204
205def setup_window_manager():
206    logging.debug('STARTUP: window_manager')
207
208    # have to reset cursor(metacity sets it on startup)
209    if subprocess.call('echo $DISPLAY; xsetroot -cursor_name left_ptr', shell=True):
210        logging.warning('Can not reset cursor')
211
212    if subprocess.call('metacity-message disable-keybindings',
213            shell=True):
214        logging.warning('Can not disable metacity keybindings')
215
216    if subprocess.call('metacity-message disable-mouse-button-modifiers',
217            shell=True):
218        logging.warning('Can not disable metacity mouse button modifiers')
219
220def bootstrap():
221    setup_window_manager()
222
223    from jarabe.view import launcher
224    launcher.setup()
225
226    gobject.idle_add(setup_frame_cb)
227    gobject.idle_add(setup_keyhandler_cb)
228    gobject.idle_add(setup_journal_cb)
229    gobject.idle_add(setup_notification_service_cb)
230    gobject.idle_add(setup_file_transfer_cb)
231    gobject.idle_add(show_software_updates_cb)
232    gobject.timeout_add(10000, start_browse)
233
234    if sys.modules.has_key('xklavier'):
235        gobject.idle_add(setup_keyboard_cb)
236
237def set_fonts():
238    client = gconf.client_get_default()
239    face = client.get_string('/desktop/sugar/font/default_face')
240    size = client.get_float('/desktop/sugar/font/default_size')
241    settings = gtk.settings_get_default()
242    settings.set_property("gtk-font-name", "%s %f" % (face, size))
243
244def main():
245    try:
246        from sugar import env
247        # Remove temporary files. See http://bugs.sugarlabs.org/ticket/1876
248        data_dir = os.path.join(env.get_profile_path(), 'data')
249        shutil.rmtree(data_dir, ignore_errors=True)
250        os.makedirs(data_dir)
251        cleanup_logs(env.get_logs_path())
252    except OSError, e:
253        # logs cleanup is not critical; it should not prevent sugar from
254        # starting if (for example) the disk is full or read-only.
255        print 'logs cleanup failed: %s' % e
256
257    from sugar import logger
258    # NOTE: This needs to happen so early because some modules register translatable
259    # strings in the module scope.
260    from jarabe import config
261    gettext.bindtextdomain('sugar', config.locale_path)
262    gettext.bindtextdomain('sugar-toolkit', config.locale_path)
263    gettext.textdomain('sugar')
264
265    from jarabe.desktop import homewindow
266    from jarabe.model import sound
267    from jarabe import intro
268
269    logger.start('shell')
270
271    client = gconf.client_get_default()
272    client.set_string('/apps/metacity/general/mouse_button_modifier',
273                      '<Super>')
274
275    timezone = client.get_string('/desktop/sugar/date/timezone')
276    if timezone is not None and timezone:
277        os.environ['TZ'] = timezone
278
279    set_fonts()
280
281    # this must be added early, so that it executes and unfreezes the screen
282    # even when we initially get blocked on the intro screen
283    gobject.idle_add(unfreeze_dcon_cb)
284
285    # make sure we have the correct cursor in the intro screen
286    # TODO #3204
287    if subprocess.call('echo $DISPLAY; xsetroot -cursor_name left_ptr', shell=True):
288        logging.warning('Can not reset cursor')
289
290    # open welcome screen if booted for the first time
291    show_welcome_screen()
292
293    intro.check_profile()
294
295    start_ui_service()
296    start_session_manager()
297
298    sound.restore()
299
300    sys.path.append(config.ext_path)
301
302    icons_path = os.path.join(config.data_path, 'icons')
303    gtk.icon_theme_get_default().append_search_path(icons_path)
304
305    # open homewindow before window_manager to let desktop appear fast
306    home_window = homewindow.get_instance()
307    home_window.show()
308
309    screen = wnck.screen_get_default()
310    screen.connect('window-manager-changed', __window_manager_changed_cb)
311    _check_for_window_manager(screen)
312
313    try:
314        gtk.main()
315    except KeyboardInterrupt:
316        print 'Ctrl+C pressed, exiting...'
317
318
319def __window_manager_changed_cb(screen):
320    _check_for_window_manager(screen)
321
322
323def _check_for_window_manager(screen):
324    wm_name = screen.get_window_manager_name()
325    if wm_name is not None:
326        screen.disconnect_by_func(__window_manager_changed_cb)
327        bootstrap()
328
329
330main()