- #!/usr/bin/env python
- # Copyright (C) 2006, Red Hat, Inc.
- # Copyright (C) 2009, One Laptop Per Child Association 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 os
- import sys
- import time
- import subprocess
- import shutil
- if os.environ.get('SUGAR_LOGGER_LEVEL', '') == 'debug':
- print '%r STARTUP: Starting the shell' % time.time()
- sys.stdout.flush()
- import gettext
- import logging
- import gconf
- import gtk
- import gobject
- import dbus.glib
- import wnck
- try:
- import xklavier
- except ImportError:
- logging.debug('Could not load xklavier for keyboard configuration')
- gtk.gdk.threads_init()
- dbus.glib.threads_init()
- def cleanup_logs(logs_dir):
- """Clean up the log directory, moving old logs into a numbered backup
- directory. We only keep `_MAX_BACKUP_DIRS` of these backup directories
- around; the rest are removed."""
- if not os.path.isdir(logs_dir):
- os.makedirs(logs_dir)
- backup_logs = []
- backup_dirs = []
- for f in os.listdir(logs_dir):
- path = os.path.join(logs_dir, f)
- if os.path.isfile(path):
- backup_logs.append(f)
- elif os.path.isdir(path):
- backup_dirs.append(path)
- if len(backup_dirs) > 3:
- backup_dirs.sort()
- root = backup_dirs[0]
- for f in os.listdir(root):
- os.remove(os.path.join(root, f))
- os.rmdir(root)
- if len(backup_logs) > 0:
- name = str(int(time.time()))
- backup_dir = os.path.join(logs_dir, name)
- os.mkdir(backup_dir)
- for log in backup_logs:
- source_path = os.path.join(logs_dir, log)
- dest_path = os.path.join(backup_dir, log)
- os.rename(source_path, dest_path)
- def start_ui_service():
- from jarabe.view.service import UIService
- ui_service = UIService()
- def start_session_manager():
- from jarabe.model.session import get_session_manager
- session_manager = get_session_manager()
- session_manager.start()
- def unfreeze_dcon_cb():
- logging.debug('STARTUP: unfreeze_dcon_cb')
- from jarabe.model import screen
- screen.set_dcon_freeze(0)
- def setup_frame_cb():
- logging.debug('STARTUP: setup_frame_cb')
- from jarabe import frame
- frame.get_view()
- def setup_keyhandler_cb():
- logging.debug('STARTUP: setup_keyhandler_cb')
- from jarabe.view import keyhandler
- from jarabe import frame
- keyhandler.setup(frame.get_view())
- def setup_journal_cb():
- logging.debug('STARTUP: setup_journal_cb')
- from jarabe.journal import journalactivity
- journalactivity.start()
- def show_software_updates_cb():
- logging.debug('STARTUP: show_software_updates_cb')
- if os.path.isfile(os.path.expanduser('~/.sugar-update')):
- from jarabe.desktop import homewindow
- home_window = homewindow.get_instance()
- home_window.get_home_box().show_software_updates_alert()
- def setup_notification_service_cb():
- from jarabe.model import notifications
- notifications.init()
- def setup_file_transfer_cb():
- from jarabe.model import filetransfer
- filetransfer.init()
- def setup_keyboard_cb():
- logging.debug('STARTUP: setup_keyboard_cb')
- gconf_client = gconf.client_get_default()
- have_config = False
- try:
- display = gtk.gdk.display_get_default()
- if display is not None:
- engine = xklavier.Engine(display)
- else:
- logging.debug('setup_keyboard_cb: Could not get default display.')
- return
- configrec = xklavier.ConfigRec()
- configrec.get_from_server(engine)
- layouts = gconf_client.get_list(\
- '/desktop/sugar/peripherals/keyboard/layouts', gconf.VALUE_STRING)
- layouts_list = []
- variants_list = []
- for layout in layouts:
- layouts_list.append(layout.split('(')[0])
- variants_list.append(layout.split('(')[1][:-1])
- if layouts_list and variants_list:
- have_config = True
- configrec.set_layouts(layouts_list)
- configrec.set_variants(variants_list)
- model = gconf_client.get_string(\
- '/desktop/sugar/peripherals/keyboard/model')
- if model:
- have_config = True
- configrec.set_model(model)
- options = gconf_client.get_list(\
- '/desktop/sugar/peripherals/keyboard/options', gconf.VALUE_STRING)
- if options:
- have_config = True
- configrec.set_options(options)
- if have_config:
- configrec.activate(engine)
- except Exception:
- logging.exception('Error during keyboard configuration')
- def setup_window_manager():
- logging.debug('STARTUP: window_manager')
- # have to reset cursor(metacity sets it on startup)
- if subprocess.call('echo $DISPLAY; xsetroot -cursor_name left_ptr', shell=True):
- logging.warning('Can not reset cursor')
- if subprocess.call('metacity-message disable-keybindings',
- shell=True):
- logging.warning('Can not disable metacity keybindings')
- def bootstrap():
- setup_window_manager()
- from jarabe.view import launcher
- launcher.setup()
- gobject.idle_add(setup_frame_cb)
- gobject.idle_add(setup_keyhandler_cb)
- gobject.idle_add(setup_journal_cb)
- gobject.idle_add(setup_notification_service_cb)
- gobject.idle_add(setup_file_transfer_cb)
- gobject.idle_add(show_software_updates_cb)
- if sys.modules.has_key('xklavier'):
- gobject.idle_add(setup_keyboard_cb)
- def set_fonts():
- client = gconf.client_get_default()
- face = client.get_string('/desktop/sugar/font/default_face')
- size = client.get_float('/desktop/sugar/font/default_size')
- settings = gtk.settings_get_default()
- settings.set_property("gtk-font-name", "%s %f" % (face, size))
- def main():
- try:
- from sugar import env
- # Remove temporary files. See http://bugs.sugarlabs.org/ticket/1876
- data_dir = os.path.join(env.get_profile_path(), 'data')
- shutil.rmtree(data_dir, ignore_errors=True)
- os.makedirs(data_dir)
- cleanup_logs(env.get_logs_path())
- except OSError, e:
- # logs cleanup is not critical; it should not prevent sugar from
- # starting if (for example) the disk is full or read-only.
- print 'logs cleanup failed: %s' % e
- from sugar import logger
- # NOTE: This needs to happen so early because some modules register translatable
- # strings in the module scope.
- from jarabe import config
- gettext.bindtextdomain('sugar', config.locale_path)
- gettext.bindtextdomain('sugar-toolkit', config.locale_path)
- gettext.textdomain('sugar')
- from jarabe.desktop import homewindow
- from jarabe.model import sound
- from jarabe import intro
- logger.start('shell')
- client = gconf.client_get_default()
- client.set_string('/apps/metacity/general/mouse_button_modifier',
- '<Super>')
- timezone = client.get_string('/desktop/sugar/date/timezone')
- if timezone is not None and timezone:
- os.environ['TZ'] = timezone
- set_fonts()
- # this must be added early, so that it executes and unfreezes the screen
- # even when we initially get blocked on the intro screen
- gobject.idle_add(unfreeze_dcon_cb)
- # make sure we have the correct cursor in the intro screen
- # TODO #3204
- if subprocess.call('echo $DISPLAY; xsetroot -cursor_name left_ptr', shell=True):
- logging.warning('Can not reset cursor')
- intro.check_profile()
- start_ui_service()
- start_session_manager()
- sound.restore()
- sys.path.append(config.ext_path)
- icons_path = os.path.join(config.data_path, 'icons')
- gtk.icon_theme_get_default().append_search_path(icons_path)
- # open homewindow before window_manager to let desktop appear fast
- home_window = homewindow.get_instance()
- home_window.show()
- screen = wnck.screen_get_default()
- screen.connect('window-manager-changed', __window_manager_changed_cb)
- _check_for_window_manager(screen)
- try:
- gtk.main()
- except KeyboardInterrupt:
- print 'Ctrl+C pressed, exiting...'
- def __window_manager_changed_cb(screen):
- _check_for_window_manager(screen)
- def _check_for_window_manager(screen):
- wm_name = screen.get_window_manager_name()
- if wm_name is not None:
- screen.disconnect_by_func(__window_manager_changed_cb)
- bootstrap()
- main()