Beispiel #1
0
    def __init__(self):
        self._last_ignore_configure_time = None
        self._last_configures = []


        Gtk.Window.__init__(self,
                            urgency_hint = False)
        WindowRectTracker.__init__(self)

        self.restore_window_rect(startup = True)

        self.icp = IconPalette()
        self.icp.connect("activated", self._on_icon_palette_acticated)

        self.connect("delete-event", self._on_delete_event)
        self.connect("configure-event", self._on_configure_event)

        KbdWindowBase.__init__(self)

        once = CallOnce(100).enqueue  # call at most once per 100ms
        rect_changed = lambda x: once(self._on_config_rect_changed)
        config.window.position_notify_add(rect_changed)
        config.window.size_notify_add(rect_changed)
Beispiel #2
0
    def __init__(self):
        gtk.Window.__init__(self)
        _logger.debug("Entered in __init__")
        self.keyboard = None
        self.set_accept_focus(False)
        self.grab_remove()
        self.set_keep_above(True)

        gtk.window_set_default_icon_name("onboard")
        self.set_title(_("Onboard"))

        config.geometry_notify_add(self.resize)
        self.set_default_size(config.keyboard_width, config.keyboard_height)
        config.position_notify_add(self.move)
        self.move(config.x_position, config.y_position)

        self.connect("window-state-event", self.cb_state_change)

        self.icp = IconPalette()
        self.icp.connect_object("activated", gtk.Window.deiconify, self)

        self.show_all()
        if config.start_minimized: self.iconify()
        _logger.debug("Leaving __init__")
Beispiel #3
0
    def _init_delayed(self):

        # Release pressed keys when onboard is killed.
        # Don't keep enter key stuck when being killed by lightdm.
        self._osk_util = osk.Util()
        self._osk_util.set_unix_signal_handler(signal.SIGTERM, self.on_sigterm)
        self._osk_util.set_unix_signal_handler(signal.SIGINT, self.on_sigint)

        sys.path.append(os.path.join(config.install_dir, 'scripts'))

        # Create the central keyboard model
        self.keyboard = Keyboard(self)

        # Create the initial keyboard widget
        # Care for toolkit independence only once there is another
        # supported one besides GTK.
        self.keyboard_widget = KeyboardWidget(self.keyboard)

        # create the main window
        if config.xid_mode:    # XEmbed mode for gnome-screensaver?
            # no icp, don't flash the icon palette in lightdm

            self._window = KbdPlugWindow(self.keyboard_widget)

            # write xid to stdout
            sys.stdout.write('%d\n' % self._window.get_id())
            sys.stdout.flush()
        else:
            icp = IconPalette(self.keyboard)
            icp.set_layout_view(self.keyboard_widget)
            icp.connect("activated", self._on_icon_palette_acticated)
            self.do_connect(icp.get_menu(), "quit-onboard",
                        lambda x: self.do_quit_onboard())

            self._window = KbdWindow(self.keyboard_widget, icp)
            self.do_connect(self._window, "quit-onboard",
                            lambda x: self.do_quit_onboard())

        # config.xid_mode = True
        self._window.application = self
        # need this to access screen properties
        config.main_window = self._window

        # load the initial layout
        _logger.info("Loading initial layout")
        self.reload_layout()

        # Handle command line options x, y, size after window creation
        # because the rotation code needs the window's screen.
        if not config.xid_mode:
            rect = self._window.get_rect().copy()
            options = config.options
            if options.size:
                size = options.size.split("x")
                rect.w = int(size[0])
                rect.h = int(size[1])
            if options.x is not None:
                rect.x = options.x
            if options.y is not None:
                rect.y = options.y

            # Make sure the keyboard fits on screen
            rect = self._window.limit_size(rect)

            if not rect.is_empty() and \
               rect != self._window.get_rect():
                _logger.debug("limiting window size: {} to {}"
                            .format(self._window.get_rect(), rect))
                orientation = self._window.get_screen_orientation()
                self._window.write_window_rect(orientation, rect)
                self._window.restore_window_rect()  # move/resize early
            else:
                _logger.debug("not limiting window size: {} to {}"
                            .format(self._window.get_rect(), rect))


        # export dbus service
        if not config.xid_mode and \
           has_dbus:
            self.service_keyboard = ServiceOnboardKeyboard(self)

        # show/hide the window
        self.keyboard_widget.set_startup_visibility()

        # keep keyboard window and icon palette on top of dash
        self._keep_windows_on_top()

        # connect notifications for keyboard map and group changes
        self.keymap = Gdk.Keymap.get_default()
        # map changes
        self.do_connect(self.keymap, "keys-changed", self.cb_keys_changed)
        self.do_connect(self.keymap, "state-changed", self.cb_state_changed)
        # group changes
        Gdk.event_handler_set(cb_any_event, self)

        # connect config notifications here to keep config from holding
        # references to keyboard objects.
        once = CallOnce(50).enqueue  # delay callbacks by 50ms
        reload_layout       = lambda x: once(self.reload_layout_and_present)
        update_ui           = lambda x: once(self._update_ui)
        update_ui_no_resize = lambda x: once(self._update_ui_no_resize)
        update_transparency = \
            lambda x: once(self.keyboard_widget.update_transparency)
        update_inactive_transparency = \
            lambda x: once(self.keyboard_widget.update_inactive_transparency)

        # general

        # keyboard
        config.keyboard.key_synth_notify_add(reload_layout)
        config.keyboard.input_event_source_notify_add(lambda x:
                                    self.keyboard.update_input_event_source())
        config.keyboard.touch_input_notify_add(lambda x:
                                    self.keyboard.update_touch_input_mode())
        config.keyboard.show_secondary_labels_notify_add(update_ui)

        # window
        config.window.window_state_sticky_notify_add(
            lambda x: self._window.update_sticky_state())
        config.window.window_decoration_notify_add(
            self._on_window_options_changed)
        config.window.force_to_top_notify_add(self._on_window_options_changed)
        config.window.keep_aspect_ratio_notify_add(update_ui)

        config.window.transparency_notify_add(update_transparency)
        config.window.background_transparency_notify_add(update_transparency)
        config.window.transparent_background_notify_add(update_ui)
        config.window.enable_inactive_transparency_notify_add(update_transparency)
        config.window.inactive_transparency_notify_add(update_inactive_transparency)
        config.window.docking_notify_add(self._update_docking)
        config.window.docking_aspect_change_range_notify_add(
            lambda x: self.keyboard_widget
            .update_docking_aspect_change_range())

        # layout
        config.layout_filename_notify_add(reload_layout)

        # theme
        # config.gdi.gtk_theme_notify_add(self.on_gtk_theme_changed)
        config.theme_notify_add(self.on_theme_changed)
        config.key_label_font_notify_add(reload_layout)
        config.key_label_overrides_notify_add(reload_layout)
        config.theme_settings.color_scheme_filename_notify_add(reload_layout)
        config.theme_settings.key_label_font_notify_add(reload_layout)
        config.theme_settings.key_label_overrides_notify_add(reload_layout)
        config.theme_settings.theme_attributes_notify_add(update_ui)

        # snippets
        config.snippets_notify_add(reload_layout)

        # auto-show
        config.auto_show.enabled_notify_add(
            lambda x: self.keyboard.update_auto_show())
        config.auto_show.hide_on_key_press_notify_add(
            lambda x: self.keyboard.update_auto_hide())
        config.auto_show.tablet_mode_detection_notify_add(
            lambda x: self.keyboard.update_tablet_mode_detection())
        config.auto_show.keyboard_device_detection_enabled_notify_add(
            lambda x: self.keyboard.update_keyboard_device_detection())

        # word suggestions
        config.word_suggestions.show_context_line_notify_add(update_ui)
        config.word_suggestions.enabled_notify_add(lambda x:
                                 self.keyboard.on_word_suggestions_enabled(x))
        config.word_suggestions.auto_learn_notify_add(
                                 update_ui_no_resize)
        config.typing_assistance.active_language_notify_add(lambda x: \
                                 self.keyboard.on_active_lang_id_changed())
        config.typing_assistance.spell_check_backend_notify_add(lambda x: \
                                 self.keyboard.on_spell_checker_changed())
        config.typing_assistance.auto_capitalization_notify_add(lambda x: \
                                 self.keyboard.on_word_suggestions_enabled(x))
        config.word_suggestions.spelling_suggestions_enabled_notify_add(lambda x: \
                                 self.keyboard.on_spell_checker_changed())
        config.word_suggestions.delayed_word_separators_enabled_notify_add(lambda x: \
                                 self.keyboard.on_punctuator_changed())
        config.word_suggestions.wordlist_buttons_notify_add(
                                 update_ui_no_resize)

        # universal access
        config.scanner.enabled_notify_add(self.keyboard._on_scanner_enabled)
        config.window.window_handles_notify_add(self._on_window_handles_changed)

        # misc
        config.keyboard.show_click_buttons_notify_add(update_ui)
        config.lockdown.lockdown_notify_add(update_ui)
        if config.mousetweaks:
            config.mousetweaks.state_notify_add(update_ui_no_resize)

        # create status icon
        self.status_icon = Indicator()
        self.status_icon.set_keyboard(self.keyboard)
        self.do_connect(self.status_icon.get_menu(), "quit-onboard",
                        lambda x: self.do_quit_onboard())

        # Callbacks to use when icp or status icon is toggled
        config.show_status_icon_notify_add(self.show_hide_status_icon)
        config.icp.in_use_notify_add(self.cb_icp_in_use_toggled)

        self.show_hide_status_icon(config.show_status_icon)


        # Minimize to IconPalette if running under GDM
        if 'RUNNING_UNDER_GDM' in os.environ:
            _logger.info("RUNNING_UNDER_GDM set, turning on icon palette")
            config.icp.in_use = True
            _logger.info("RUNNING_UNDER_GDM set, turning off indicator")
            config.show_status_icon = False

            # For some reason the new values don't arrive in gsettings when
            # running the unit test "test_running_in_live_cd_environment".
            # -> Force gsettings to apply them, that seems to do the trick.
            config.icp.apply()
            config.apply()

        # unity-2d needs the skip-task-bar hint set before the first mapping.
        self.show_hide_taskbar()


        # Check gnome-screen-saver integration
        # onboard_xembed_enabled                False True     True      True
        # config.gss.embedded_keyboard_enabled  any   False    any       False
        # config.gss.embedded_keyboard_command  any   empty    !=onboard ==onboard
        # Action:                               nop   enable   Question1 Question2
        #                                             silently
        if not config.xid_mode and \
           config.onboard_xembed_enabled:

            # If it appears, that nothing has touched the gss keys before,
            # silently enable gss integration with onboard.
            if not config.gss.embedded_keyboard_enabled and \
               not config.gss.embedded_keyboard_command:
                config.enable_gss_embedding(True)

            # If onboard is configured to be embedded into the unlock screen
            # dialog, and the embedding command is different from onboard, ask
            # the user what to do
            elif not config.is_onboard_in_xembed_command_string():
                question = _("Onboard is configured to appear with the dialog to "
                             "unlock the screen; for example to dismiss the "
                             "password-protected screensaver.\n\n"
                             "However the system is not configured anymore to use "
                             "Onboard to unlock the screen. A possible reason can "
                             "be that another application configured the system to "
                             "use something else.\n\n"
                             "Would you like to reconfigure the system to show "
                             "Onboard when unlocking the screen?")
                _logger.warning("showing dialog: '{}'".format(question))
                reply = show_confirmation_dialog(question,
                                                 self._window,
                                                 config.is_force_to_top())
                if reply == True:
                    config.enable_gss_embedding(True)
                else:
                    config.onboard_xembed_enabled = False
            else:
                if not config.gss.embedded_keyboard_enabled:
                    question = _("Onboard is configured to appear with the dialog "
                                 "to unlock the screen; for example to dismiss "
                                 "the password-protected screensaver.\n\n"
                                 "However this function is disabled in the system.\n\n"
                                 "Would you like to activate it?")
                    _logger.warning("showing dialog: '{}'".format(question))
                    reply = show_confirmation_dialog(question,
                                                     self._window,
                                                     config.is_force_to_top())
                    if reply == True:
                        config.enable_gss_embedding(True)
                    else:
                        config.onboard_xembed_enabled = False

        # check if gnome accessibility is enabled for auto-show
        if (config.is_auto_show_enabled() or \
            config.are_word_suggestions_enabled()) and \
            not config.check_gnome_accessibility(self._window):
            config.auto_show.enabled = False
Beispiel #4
0
    def init(self):
        self.keyboard_state = None
        self.vk_timer = None
        self.reset_vk()
        self._connections = []
        self._window = None
        self.status_icon = None
        self.service_keyboard = None
        self._reload_layout_timer = Timer()

        # finish config initialization
        config.init()

        # Release pressed keys when onboard is killed.
        # Don't keep enter key stuck when being killed by lightdm.
        self._osk_util = osk.Util()
        self._osk_util.set_unix_signal_handler(signal.SIGTERM, self.on_sigterm)
        self._osk_util.set_unix_signal_handler(signal.SIGINT, self.on_sigint)

        sys.path.append(os.path.join(config.install_dir, 'scripts'))

        # Create the central keyboard model
        self.keyboard = Keyboard(self)

        # Create the initial keyboard widget
        # Care for toolkit independence only once there is another
        # supported one besides GTK.
        self.keyboard_widget = KeyboardWidget(self.keyboard)

        # create the main window
        if config.xid_mode:    # XEmbed mode for gnome-screensaver?
            # no icp, don't flash the icon palette in lightdm

            self._window = KbdPlugWindow(self.keyboard_widget)

            # write xid to stdout
            sys.stdout.write('%d\n' % self._window.get_id())
            sys.stdout.flush()
        else:
            icp = IconPalette(self.keyboard)
            icp.set_layout_view(self.keyboard_widget)
            icp.connect("activated", self._on_icon_palette_acticated)
            self.do_connect(icp.get_menu(), "quit-onboard",
                        lambda x: self.do_quit_onboard())

            self._window = KbdWindow(self.keyboard_widget, icp)
            self.do_connect(self._window, "quit-onboard",
                            lambda x: self.do_quit_onboard())

        # config.xid_mode = True
        self._window.application = self
        # need this to access screen properties
        config.main_window = self._window

        # load the initial layout
        _logger.info("Loading initial layout")
        self.reload_layout()

        # Handle command line options x, y, size after window creation
        # because the rotation code needs the window's screen.
        if not config.xid_mode:
            rect = self._window.get_rect().copy()
            options = config.options
            if options.size:
                size = options.size.split("x")
                rect.w = int(size[0])
                rect.h = int(size[1])
            if options.x is not None:
                rect.x = options.x
            if options.y is not None:
                rect.y = options.y

            # Make sure the keyboard fits on screen
            rect = self._window.limit_size(rect)

            if rect != self._window.get_rect():
                orientation = self._window.get_screen_orientation()
                self._window.write_window_rect(orientation, rect)
                self._window.restore_window_rect()  # move/resize early

        # export dbus service
        if not config.xid_mode and \
           "dbus" in globals():
            self.service_keyboard = ServiceOnboardKeyboard(self)

        # show/hide the window
        self.keyboard_widget.set_startup_visibility()

        # keep keyboard window and icon palette on top of dash
        self._keep_windows_on_top()

        # connect notifications for keyboard map and group changes
        self.keymap = Gdk.Keymap.get_default()
        # map changes
        self.do_connect(self.keymap, "keys-changed", self.cb_keys_changed)
        self.do_connect(self.keymap, "state-changed", self.cb_state_changed)
        # group changes
        Gdk.event_handler_set(cb_any_event, self)

        # connect config notifications here to keep config from holding
        # references to keyboard objects.
        once = CallOnce(50).enqueue  # delay callbacks by 50ms
        reload_layout       = lambda x: once(self.reload_layout_and_present)
        update_ui           = lambda x: once(self._update_ui)
        update_ui_no_resize = lambda x: once(self._update_ui_no_resize)
        update_transparency = \
            lambda x: once(self.keyboard_widget.update_transparency)
        update_inactive_transparency = \
            lambda x: once(self.keyboard_widget.update_inactive_transparency)

        # general
        config.auto_show.enabled_notify_add(lambda x:
                                    self.keyboard.update_auto_show())
        config.auto_show.hide_on_key_press_notify_add(lambda x:
                                    self.keyboard.update_auto_hide())

        # keyboard
        config.keyboard.key_synth_notify_add(reload_layout)
        config.keyboard.input_event_source_notify_add(lambda x:
                                    self.keyboard.update_input_event_source())
        config.keyboard.touch_input_notify_add(lambda x:
                                    self.keyboard.update_touch_input_mode())
        config.keyboard.show_secondary_labels_notify_add(update_ui)

        # window
        config.window.window_state_sticky_notify_add(
            lambda x: self._window.update_sticky_state())
        config.window.window_decoration_notify_add(
            self._on_window_options_changed)
        config.window.force_to_top_notify_add(self._on_window_options_changed)
        config.window.keep_aspect_ratio_notify_add(update_ui)

        config.window.transparency_notify_add(update_transparency)
        config.window.background_transparency_notify_add(update_transparency)
        config.window.transparent_background_notify_add(update_ui)
        config.window.enable_inactive_transparency_notify_add(update_transparency)
        config.window.inactive_transparency_notify_add(update_inactive_transparency)
        config.window.docking_notify_add(self._update_docking)

        # layout
        config.layout_filename_notify_add(reload_layout)

        # theme
        # config.gdi.gtk_theme_notify_add(self.on_gtk_theme_changed)
        config.theme_notify_add(self.on_theme_changed)
        config.key_label_font_notify_add(reload_layout)
        config.key_label_overrides_notify_add(reload_layout)
        config.theme_settings.color_scheme_filename_notify_add(reload_layout)
        config.theme_settings.key_label_font_notify_add(reload_layout)
        config.theme_settings.key_label_overrides_notify_add(reload_layout)
        config.theme_settings.theme_attributes_notify_add(update_ui)

        # snippets
        config.snippets_notify_add(reload_layout)

        # word suggestions
        config.word_suggestions.show_context_line_notify_add(update_ui)
        config.word_suggestions.enabled_notify_add(lambda x:
                                 self.keyboard.on_word_suggestions_enabled(x))
        config.word_suggestions.auto_learn_notify_add(
                                 update_ui_no_resize)
        config.typing_assistance.active_language_notify_add(lambda x: \
                                 self.keyboard.on_active_lang_id_changed())
        config.typing_assistance.spell_check_backend_notify_add(lambda x: \
                                 self.keyboard.on_spell_checker_changed())
        config.typing_assistance.auto_capitalization_notify_add(lambda x: \
                                 self.keyboard.on_word_suggestions_enabled(x))
        config.word_suggestions.spelling_suggestions_enabled_notify_add(lambda x: \
                                 self.keyboard.on_spell_checker_changed())
        config.word_suggestions.delayed_word_separators_enabled_notify_add(lambda x: \
                                 self.keyboard.on_punctuator_changed())
        config.word_suggestions.wordlist_buttons_notify_add(
                                 update_ui_no_resize)

        # universal access
        config.scanner.enabled_notify_add(self.keyboard._on_scanner_enabled)
        config.window.window_handles_notify_add(self._on_window_handles_changed)

        # misc
        config.keyboard.show_click_buttons_notify_add(update_ui)
        config.lockdown.lockdown_notify_add(update_ui)
        if config.mousetweaks:
            config.mousetweaks.state_notify_add(update_ui_no_resize)

        # create status icon
        self.status_icon = Indicator()
        self.status_icon.set_keyboard(self.keyboard)
        self.do_connect(self.status_icon.get_menu(), "quit-onboard",
                        lambda x: self.do_quit_onboard())

        # Callbacks to use when icp or status icon is toggled
        config.show_status_icon_notify_add(self.show_hide_status_icon)
        config.icp.in_use_notify_add(self.cb_icp_in_use_toggled)

        self.show_hide_status_icon(config.show_status_icon)


        # Minimize to IconPalette if running under GDM
        if 'RUNNING_UNDER_GDM' in os.environ:
            _logger.info("RUNNING_UNDER_GDM set, turning on icon palette")
            config.icp.in_use = True
            _logger.info("RUNNING_UNDER_GDM set, turning off indicator")
            config.show_status_icon = False

            # For some reason the new values don't arrive in gsettings when
            # running the unit test "test_running_in_live_cd_environment".
            # -> Force gsettings to apply them, that seems to do the trick.
            config.icp.apply()
            config.apply()

        # unity-2d needs the skip-task-bar hint set before the first mapping.
        self.show_hide_taskbar()


        # Check gnome-screen-saver integration
        # onboard_xembed_enabled                False True     True      True
        # config.gss.embedded_keyboard_enabled  any   False    any       False
        # config.gss.embedded_keyboard_command  any   empty    !=onboard ==onboard
        # Action:                               nop   enable   Question1 Question2
        #                                             silently
        if not config.xid_mode and \
           config.onboard_xembed_enabled:

            # If it appears, that nothing has touched the gss keys before,
            # silently enable gss integration with onboard.
            if not config.gss.embedded_keyboard_enabled and \
               not config.gss.embedded_keyboard_command:
                config.enable_gss_embedding(True)

            # If onboard is configured to be embedded into the unlock screen
            # dialog, and the embedding command is different from onboard, ask
            # the user what to do
            elif not config.is_onboard_in_xembed_command_string():
                question = _("Onboard is configured to appear with the dialog to "
                             "unlock the screen; for example to dismiss the "
                             "password-protected screensaver.\n\n"
                             "However the system is not configured anymore to use "
                             "Onboard to unlock the screen. A possible reason can "
                             "be that another application configured the system to "
                             "use something else.\n\n"
                             "Would you like to reconfigure the system to show "
                             "Onboard when unlocking the screen?")
                _logger.warning("showing dialog: '{}'".format(question))
                reply = show_confirmation_dialog(question,
                                                 self._window,
                                                 config.is_force_to_top())
                if reply == True:
                    config.enable_gss_embedding(True)
                else:
                    config.onboard_xembed_enabled = False
            else:
                if not config.gss.embedded_keyboard_enabled:
                    question = _("Onboard is configured to appear with the dialog "
                                 "to unlock the screen; for example to dismiss "
                                 "the password-protected screensaver.\n\n"
                                 "However this function is disabled in the system.\n\n"
                                 "Would you like to activate it?")
                    _logger.warning("showing dialog: '{}'".format(question))
                    reply = show_confirmation_dialog(question,
                                                     self._window,
                                                     config.is_force_to_top())
                    if reply == True:
                        config.enable_gss_embedding(True)
                    else:
                        config.onboard_xembed_enabled = False

        # check if gnome accessibility is enabled for auto-show
        if (config.is_auto_show_enabled() or \
            config.are_word_suggestions_enabled()) and \
            not config.check_gnome_accessibility(self._window):
            config.auto_show.enabled = False
Beispiel #5
0
class KbdWindowBase:
    """Very messy class holds the keyboard widget.  The mess is the docked window support which is disable because of numerous metacity bugs."""
    def __init__(self):
        gtk.Window.__init__(self)
        _logger.debug("Entered in __init__")
        self.keyboard = None
        self.set_accept_focus(False)
        self.grab_remove()
        self.set_keep_above(True)

        gtk.window_set_default_icon_name("onboard")
        self.set_title(_("Onboard"))

        config.geometry_notify_add(self.resize)
        self.set_default_size(config.keyboard_width, config.keyboard_height)
        config.position_notify_add(self.move)
        self.move(config.x_position, config.y_position)

        self.connect("window-state-event", self.cb_state_change)

        self.icp = IconPalette()
        self.icp.connect_object("activated", gtk.Window.deiconify, self)

        self.show_all()
        if config.start_minimized: self.iconify()
        _logger.debug("Leaving __init__")

    def on_deiconify(self, widget=None):
        self.icp.do_hide()
        self.move(config.x_position, config.y_position) # to be sure that the window manager places it correctly

    def on_iconify(self):
        if config.icp_in_use: self.icp.do_show()

    def set_keyboard(self, keyboard):
        _logger.debug("Entered in set_keyboard")
        if self.keyboard:
            self.remove(self.keyboard)
        self.keyboard = keyboard
        self.add(self.keyboard)
        self.keyboard.show()
        self.queue_draw()

    def do_set_layout(self, client, cxion_id, entry, user_data):
        _logger.debug("Entered in do_set_layout")
        return

    def do_set_gravity(self, edgeGravity):
        '''
        This will place the window on the edge corresponding to the edge gravity
        '''
        _logger.debug("Entered in do_set_gravity")
        self.edgeGravity = edgeGravity
        width, height = self.get_size()

        geom = self.get_screen().get_monitor_geometry(0)
        eg = self.edgeGravity

        x = 0
        y = 0
        if eg == gtk.gdk.GRAVITY_SOUTH:
            y = geom.height - height
            y += 29 #to account for panel.


        self.move(x, y)

        gobject.idle_add(self.do_set_strut)

    def do_set_strut(self):
        _logger.debug("Entered in do_set_strut")
        propvals = [0,0,0,0,0,0,0,0,0,0,0,0]
        """propvals = [0,#left
                0, #right
                0, #top
                300,#bottom
                0,#left_start_y
                0,#left_end_y
                0,#right_start_y
                0,#right_end_y
                0,#top_start_x
                0,#top_end_x
                0,#bottom_start_x
                3000]#bottom_end_x"""

        screen = self.get_screen()
        biggestHeight = 0
        for n in range(screen.get_n_monitors()):
            tempHeight = screen.get_monitor_geometry(n).height
            if biggestHeight < tempHeight:
                biggestHeight = tempHeight

        geom = self.get_screen().get_monitor_geometry(0)
        eg = self.edgeGravity
        x, y = self.window.get_origin()

        width,height = self.get_size()

        if eg == gtk.gdk.GRAVITY_NORTH:
            propvals[2] = height + y
            propvals[9] = width
        elif eg == gtk.gdk.GRAVITY_SOUTH and y != 0:
            #propvals[2] = y
            #propvals[9] = geom.width - 1
            propvals[3] = biggestHeight - y
            propvals[11] = width - 1

        # tell window manager to not overlap buttons with maximized window
            self.window.property_change("_NET_WM_STRUT_PARTIAL",
                                        "CARDINAL",
                                        32,
                                        gtk.gdk.PROP_MODE_REPLACE,
                                        propvals)
        self.queue_resize_no_redraw()


    def cb_state_change(self, widget, event):
        """
        This is the callback that gets executed when the user hides the
        onscreen keyboard by using the minimize button in the decoration
        of the window.
        """
        _logger.debug("Entered in cb_state_change")
        if event.changed_mask & gtk.gdk.WINDOW_STATE_ICONIFIED:
            if event.new_window_state & gtk.gdk.WINDOW_STATE_ICONIFIED:
                self.on_iconify()
            else:
                self.on_deiconify()

    def _hidden(self):
        return self.window.get_state() & gtk.gdk.WINDOW_STATE_ICONIFIED != 0
    hidden = property(_hidden)
Beispiel #6
0
class KbdWindow(KbdWindowBase, WindowRectTracker, Gtk.Window):

    def __init__(self):
        self._last_ignore_configure_time = None
        self._last_configures = []


        Gtk.Window.__init__(self,
                            urgency_hint = False)
        WindowRectTracker.__init__(self)

        self.restore_window_rect(startup = True)

        self.icp = IconPalette()
        self.icp.connect("activated", self._on_icon_palette_acticated)

        self.connect("delete-event", self._on_delete_event)
        self.connect("configure-event", self._on_configure_event)

        KbdWindowBase.__init__(self)

        once = CallOnce(100).enqueue  # call at most once per 100ms
        rect_changed = lambda x: once(self._on_config_rect_changed)
        config.window.position_notify_add(rect_changed)
        config.window.size_notify_add(rect_changed)

    def cleanup(self):
        WindowRectTracker.cleanup(self)
        KbdWindowBase.cleanup(self)
        if self.icp:
            self.icp.cleanup()
            self.icp.destroy()
            self.icp = None

    def on_visibility_changed(self, visible):
        if not self._visible and visible:
            self.move_resize(*self.get_current_rect()) # sync position

        KbdWindowBase.on_visibility_changed(self, visible)

    def _on_icon_palette_acticated(self, widget):
        self.keyboard.toggle_visible()

    def _on_config_rect_changed(self):
        """ Gsettings position or size changed """
        orientation = self.get_screen_orientation()
        rect = self.read_window_rect(orientation)

        # Only apply the new rect if it isn't the one we just wrote to
        # gsettings. Someone has to have manually changed the values
        # in gsettings to allow moving the window.
        if not self.is_known_rect(rect):
            self.restore_window_rect()

    def on_user_positioning_begin(self):
        self.stop_save_position_timer()

    def on_user_positioning_done(self):
        self.update_window_rect()
        self.update_home_rect()

    def _on_configure_event(self, widget, event):
        self.update_window_rect()

        # Configure event due to user positioning?
        result = self._filter_configure_event(self._window_rect)
        if result == 0:
            self.update_home_rect()

    def _filter_configure_event(self, rect):
        """ 
        Returns 0 for detected user positioning/sizing.
        Multiple defenses against false positives, i.e. 
        window movement by autoshow, screen rotation, whathaveyou.
        """
        
        # There is no user positioning in xembed mode.
        if config.xid_mode:
            return -1

        # There is no system provided way to move/resize in 
        # force-to-top mode. Solely rely on on_user_positioning_done(). 
        if config.window.force_to_top:
            return -2

        # There is no user positioning for nvisible windows.
        if not self.is_visible():
            return -3

        # Remember past n configure events.
        now = time.time()
        max_events = 4
        self._last_configures = self._last_configures[-(max_events - 1):]

        # Same rect as before?
        if len(self._last_configures) and \
           self._last_configures[-1][0] == rect:
            return 1

        self._last_configures.append([rect, now])


        # Only just started?
        if len(self._last_configures) < max_events:
            return 2

        # Did we just move the window by auto-show?
        if not self._last_ignore_configure_time is None and \
           time.time() - self._last_ignore_configure_time < 0.5:
            return 3

        # Is the new window rect one of our known ones?
        if self.is_known_rect(self._window_rect):
            return 4

	# Dragging the decorated frame doesn't produce continous
        # configure-events anymore as in Oneriric (Precise).
        # Disable all affected checks based on this. 
        # The home rect will probably get lost occasionally.
	if not config.has_window_decoration():

            # Less than n configure events in the last x seconds?
            first = self._last_configures[0]
            intervall = now - first[1]
            if intervall > 1.0:
                return 5

            # Is there a jump > threshold in past positions?
            r0 = self._last_configures[-1][0]
            r1 = self._last_configures[-2][0]
            dx = r1.x - r0.x
            dy = r1.y - r0.y
            d = sqrt(dx * dx + dy * dy)
            if d > 50:
                self._last_configures = [] # restart
                return 6

        return 0

    def ignore_configure_events(self):
        self._last_ignore_configure_time = time.time()

    def remember_rect(self, rect):
        """ 
        Remember the last 3 rectangles of auto-show repositioning.
        Time and order of configure events is somewhat unpredictable, 
        so don't rely only on a single remembered rect.
        """
        self._known_window_rects = self._known_window_rects[-2:]
        self._known_window_rects.append(rect) 

    def get_known_rects(self):
        """ 
        Return all rects that may have resulted from internal 
        window moves, not by user controlled drag operations.
        """
        rects = self._known_window_rects

        co = config.window.landscape
        rects.append(Rect(co.x, co.y, co.width, co.height))

        co = config.window.portrait
        rects.append(Rect(co.x, co.y, co.width, co.height))

        rects.append(self.home_rect)
        return rects

    def is_known_rect(self, rect):
        """
        The home rect should be updated in response to user positiong/resizing.
        However we are unable to detect the end of window movement/resizing
        when window decoration is enabled. Instead we check if the current
        window rect is different from the ones auto-show knows and assume
        the user has changed it in this case.
        """
        return any(rect == r for r in self.get_known_rects())

    def update_home_rect(self):
        # update home rect
        rect = self._window_rect.copy()

        # Make sure the move button stays visible
        if self.can_move_into_view():
            rect.x, rect.y = self.keyboard.limit_position(rect.x, rect.y)

        self.home_rect = rect.copy()
        self.start_save_position_timer()

    def get_current_rect(self):
        """
        Returns the window rect with auto-show
        repositioning taken into account.
        """
        if self.keyboard and \
           config.is_auto_show_enabled():
            rect = self.keyboard.auto_show \
                       .get_repositioned_window_rect(self.home_rect)
            if rect:
                return rect
        return self.home_rect

    def on_restore_window_rect(self, rect):
        """
        Overload for WindowRectTracker.
        """
        self.home_rect = rect.copy()

        # check for alternative auto-show position
        r = self.get_current_rect()
        if r != self.home_rect:
            # remember our rects to distinguish from user move/resize
            self.remember_rect(r)
            rect = r

        return rect

    def on_save_window_rect(self, rect):
        """
        Overload for WindowRectTracker.
        """
        # Ignore <rect> (self._window_rect), it may just be a temporary one
        # set by auto-show. Save the user selected home_rect instead.
        return self.home_rect

    def read_window_rect(self, orientation):
        """
        Read orientation dependent rect.
        Overload for WindowRectTracker.
        """
        if orientation == Orientation.LANDSCAPE:
            co = config.window.landscape
        else:
            co = config.window.portrait
        rect = Rect(co.x, co.y, co.width, co.height)
        return rect

    def write_window_rect(self, orientation, rect):
        """
        Write orientation dependent rect.
        Overload for WindowRectTracker.
        """
        # There are separate rects for normal and rotated screen (tablets).
        if orientation == Orientation.LANDSCAPE:
            co = config.window.landscape
        else:
            co = config.window.portrait

        config.settings.delay()
        co.x, co.y, co.width, co.height = rect
        config.settings.apply()

    def _emit_quit_onboard(self, event, data=None):
        self.emit("quit-onboard")

    def _on_delete_event(self, event, data=None):
        if config.lockdown.disable_quit:
            if self.keyboard:
                return True
        else:
            self._emit_quit_onboard(event)