#!/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 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() ui_service.start() 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() 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 is not None and layouts_list is not [] \ and variants_list is not None and variants_list is not []: configrec.set_layouts(layouts_list) configrec.set_variants(variants_list) model = gconf_client.get_string(\ '/desktop/sugar/peripherals/keyboard/model') if model: configrec.set_model(model) options = gconf_client.get_list(\ '/desktop/sugar/peripherals/keyboard/options', gconf.VALUE_STRING) if options is not [] and options is not None: configrec.set_options(options) 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 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', 'disabled') 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) 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) try: gtk.main() except KeyboardInterrupt: print 'Ctrl+C pressed, exiting...' def __window_manager_changed_cb(screen): wm_name = screen.get_window_manager_name() if wm_name is not None: screen.disconnect_by_func(__window_manager_changed_cb) bootstrap() main()