def __init__(self, away_message=None, initial_monitor=0): super(AlbumArt, self).__init__(initial_monitor) self.get_style_context().add_class("albumart") self.set_halign(Gtk.Align.END) self.set_valign(Gtk.Align.CENTER) if not settings.get_show_albumart(): return self.watcher = singletons.MediaPlayerWatcher self.player = self.watcher.get_best_player() self.current_url = None self.image = FramedImage(status.screen.get_low_res_mode(), scale_up=True) self.image.show() self.image.set_opacity(0.0) self.add(self.image) trackers.con_tracker_get().connect(self.image, "surface-changed", self.on_surface_changed) if self.player != None: trackers.con_tracker_get().connect(self.player, "metadata-changed", self.on_metadata_changed) self.on_metadata_changed(self.player)
def __init__(self, screen, away_message=None, initial_monitor=0): super(AlbumArt, self).__init__(initial_monitor) self.screen = screen self.get_style_context().add_class("albumart") if not settings.get_show_albumart(): return self.watcher = singletons.MediaPlayerWatcher self.player = self.watcher.get_best_player() self.current_url = None self.image = FramedImage() self.image.show() self.image.set_opacity(0.0) self.add(self.image) trackers.con_tracker_get().connect(self.image, "pixbuf-changed", self.on_pixbuf_changed) if self.player != None: trackers.con_tracker_get().connect(self.player, "metadata-changed", self.on_metadata_changed) self.on_metadata_changed(self.player)
def __init__(self, away_message=None, initial_monitor=0): super(AlbumArt, self).__init__(initial_monitor) self.get_style_context().add_class("albumart") self.set_halign(Gtk.Align.END) if not settings.get_show_albumart(): return self.watcher = singletons.MediaPlayerWatcher self.player = self.watcher.get_best_player() self.current_url = None self.image = FramedImage() self.image.show() self.image.set_opacity(0.0) self.add(self.image) trackers.con_tracker_get().connect(self.image, "pixbuf-changed", self.on_pixbuf_changed) if self.player != None: trackers.con_tracker_get().connect(self.player, "metadata-changed", self.on_metadata_changed) self.on_metadata_changed(self.player)
def __init__(self): super(UnlockDialog, self).__init__() self.set_halign(Gtk.Align.CENTER) self.set_valign(Gtk.Align.CENTER) self.real_name = None self.user_name = None self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10) self.box.get_style_context().add_class("unlockbox") self.add(self.box) self.face_image = FramedImage() self.face_image.set_halign(Gtk.Align.CENTER) self.face_image.get_style_context().add_class("faceimage") self.face_image.set_no_show_all(True) self.box.pack_start(self.face_image, False, False, 10) self.realname_label = Gtk.Label(None) self.realname_label.set_alignment(0, 0.5) self.realname_label.set_halign(Gtk.Align.CENTER) self.box.pack_start(self.realname_label, False, False, 10) self.entry_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) self.box.pack_start(self.entry_box, True, True, 2) self.password_entry = PasswordEntry() trackers.con_tracker_get().connect(self.password_entry, "changed", self.on_password_entry_text_changed) trackers.con_tracker_get().connect(self.password_entry, "button-press-event", self.on_password_entry_button_press) trackers.con_tracker_get().connect(self.password_entry, "activate", self.on_auth_enter_key) self.entry_box.pack_start(self.password_entry, False, False, 15) button_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) self.entry_box.pack_end(button_box, False, False, 0) self.auth_unlock_button = TransparentButton( "screensaver-unlock-symbolic", Gtk.IconSize.LARGE_TOOLBAR) self.auth_unlock_button.set_tooltip_text(_("Unlock")) trackers.con_tracker_get().connect(self.auth_unlock_button, "clicked", self.on_unlock_clicked) button_box.pack_start(self.auth_unlock_button, False, False, 4) self.auth_switch_button = TransparentButton( "screensaver-switch-users-symbolic", Gtk.IconSize.LARGE_TOOLBAR) self.auth_switch_button.set_tooltip_text(_("Switch User")) trackers.con_tracker_get().connect(self.auth_switch_button, "clicked", self.on_switch_user_clicked) button_box.pack_start(self.auth_switch_button, False, False, 4) status.focusWidgets = [ self.password_entry, self.auth_unlock_button, self.auth_switch_button ] vbox_messages = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=2) self.capslock_label = Gtk.Label("") self.capslock_label.get_style_context().add_class("caps-message") self.capslock_label.set_alignment(0.5, 0.5) vbox_messages.pack_start(self.capslock_label, False, False, 2) self.auth_message_label = Gtk.Label("") self.auth_message_label.get_style_context().add_class("auth-message") self.auth_message_label.set_alignment(0.5, 0.5) vbox_messages.pack_start(self.auth_message_label, False, False, 2) self.box.pack_start(vbox_messages, False, False, 0) self.real_name = utils.get_user_display_name() self.user_name = utils.get_user_name() self.update_realname_label() self.account_client = singletons.AccountsServiceClient if self.account_client.is_loaded: self.on_account_client_loaded(self.account_client) else: trackers.con_tracker_get().connect(self.account_client, "account-loaded", self.on_account_client_loaded) self.keymap = Gdk.Keymap.get_default() trackers.con_tracker_get().connect(self.keymap, "state-changed", self.keymap_handler) trackers.con_tracker_get().connect_after(self, "notify::child-revealed", self.on_revealed) self.auth_client = AuthClient() trackers.con_tracker_get().connect(self.auth_client, "auth-success", self.on_authentication_success) trackers.con_tracker_get().connect(self.auth_client, "auth-failure", self.on_authentication_failure) trackers.con_tracker_get().connect(self.auth_client, "auth-cancel", self.on_authentication_cancelled) trackers.con_tracker_get().connect(self.auth_client, "auth-busy", self.on_authentication_busy_changed) trackers.con_tracker_get().connect( self.auth_client, "auth-prompt", self.on_authentication_prompt_changed)
class UnlockDialog(BaseWindow): """ The main widget for the unlock dialog - this is a direct child of the Stage's GtkOverlay. It has a number of parts, namely: - The user face image. - The user's real name (or username if the real name is unavailable) - The password entry widget - Unlock and Switch User buttons - A caps lock warning label - An invalid password error label """ __gsignals__ = { 'inhibit-timeout': (GObject.SignalFlags.RUN_LAST, None, ()), 'uninhibit-timeout': (GObject.SignalFlags.RUN_LAST, None, ()), 'authenticate-success': (GObject.SignalFlags.RUN_LAST, None, ()), 'authenticate-failure': (GObject.SignalFlags.RUN_LAST, None, ()), 'authenticate-cancel': (GObject.SignalFlags.RUN_LAST, None, ()) } def __init__(self): super(UnlockDialog, self).__init__() self.set_halign(Gtk.Align.CENTER) self.set_valign(Gtk.Align.CENTER) self.real_name = None self.user_name = None self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10) self.box.get_style_context().add_class("unlockbox") self.add(self.box) self.face_image = FramedImage() self.face_image.set_halign(Gtk.Align.CENTER) self.face_image.get_style_context().add_class("faceimage") self.face_image.set_no_show_all(True) self.box.pack_start(self.face_image, False, False, 10) self.realname_label = Gtk.Label(None) self.realname_label.set_alignment(0, 0.5) self.realname_label.set_halign(Gtk.Align.CENTER) self.box.pack_start(self.realname_label, False, False, 10) self.entry_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) self.box.pack_start(self.entry_box, True, True, 2) self.password_entry = PasswordEntry() trackers.con_tracker_get().connect(self.password_entry, "changed", self.on_password_entry_text_changed) trackers.con_tracker_get().connect(self.password_entry, "button-press-event", self.on_password_entry_button_press) trackers.con_tracker_get().connect(self.password_entry, "activate", self.on_auth_enter_key) self.entry_box.pack_start(self.password_entry, False, False, 15) button_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) self.entry_box.pack_end(button_box, False, False, 0) self.auth_unlock_button = TransparentButton( "screensaver-unlock-symbolic", Gtk.IconSize.LARGE_TOOLBAR) self.auth_unlock_button.set_tooltip_text(_("Unlock")) trackers.con_tracker_get().connect(self.auth_unlock_button, "clicked", self.on_unlock_clicked) button_box.pack_start(self.auth_unlock_button, False, False, 4) self.auth_switch_button = TransparentButton( "screensaver-switch-users-symbolic", Gtk.IconSize.LARGE_TOOLBAR) self.auth_switch_button.set_tooltip_text(_("Switch User")) trackers.con_tracker_get().connect(self.auth_switch_button, "clicked", self.on_switch_user_clicked) button_box.pack_start(self.auth_switch_button, False, False, 4) status.focusWidgets = [ self.password_entry, self.auth_unlock_button, self.auth_switch_button ] vbox_messages = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=2) self.capslock_label = Gtk.Label("") self.capslock_label.get_style_context().add_class("caps-message") self.capslock_label.set_alignment(0.5, 0.5) vbox_messages.pack_start(self.capslock_label, False, False, 2) self.auth_message_label = Gtk.Label("") self.auth_message_label.get_style_context().add_class("auth-message") self.auth_message_label.set_alignment(0.5, 0.5) vbox_messages.pack_start(self.auth_message_label, False, False, 2) self.box.pack_start(vbox_messages, False, False, 0) self.real_name = utils.get_user_display_name() self.user_name = utils.get_user_name() self.update_realname_label() self.account_client = singletons.AccountsServiceClient if self.account_client.is_loaded: self.on_account_client_loaded(self.account_client) else: trackers.con_tracker_get().connect(self.account_client, "account-loaded", self.on_account_client_loaded) self.keymap = Gdk.Keymap.get_default() trackers.con_tracker_get().connect(self.keymap, "state-changed", self.keymap_handler) trackers.con_tracker_get().connect_after(self, "notify::child-revealed", self.on_revealed) self.auth_client = AuthClient() trackers.con_tracker_get().connect(self.auth_client, "auth-success", self.on_authentication_success) trackers.con_tracker_get().connect(self.auth_client, "auth-failure", self.on_authentication_failure) trackers.con_tracker_get().connect(self.auth_client, "auth-cancel", self.on_authentication_cancelled) trackers.con_tracker_get().connect(self.auth_client, "auth-busy", self.on_authentication_busy_changed) trackers.con_tracker_get().connect( self.auth_client, "auth-prompt", self.on_authentication_prompt_changed) def initialize_auth_client(self): return self.auth_client.initialize() def cancel_auth_client(self): self.auth_client.cancel() def on_authentication_success(self, auth_client): self.clear_entry() self.emit("authenticate-success") def on_authentication_failure(self, auth_client): """ Called upon authentication failure, clears the password, sets an error message, and refocuses the password entry. """ self.clear_entry() self.auth_message_label.set_text(_("Incorrect password")) self.emit("authenticate-failure") self.emit("uninhibit-timeout") def on_authentication_cancelled(self, auth_client): self.emit("authenticate-cancel") def on_authentication_busy_changed(self, auth_client, busy): if busy: self.auth_message_label.set_text("") self.clear_entry() self.entry_box.set_sensitive(False) self.password_entry.start_progress() self.password_entry.set_placeholder_text(_("Checking...")) else: self.entry_box.set_sensitive(True) self.password_entry.stop_progress() self.password_entry.set_placeholder_text( self.password_entry.placeholder_text) def on_authentication_prompt_changed(self, auth_client, prompt): if "password:"******"Please enter your password...") else: prompt = prompt.replace(":", "") self.password_entry.placeholder_text = prompt self.password_entry.set_placeholder_text( self.password_entry.placeholder_text) def cancel(self): """ Clears the auth message text if we have any. """ self.auth_message_label.set_text("") def on_revealed(self, widget, child): """ Updates the capslock state and ensures the password is cleared when we're first shown. """ if self.get_child_revealed(): self.keymap_handler(self.keymap) else: self.password_entry.set_text("") def queue_key_event(self, event): """ Takes a propagated key event from the stage and passes it to the entry widget, possibly queueing up the first character of the password. """ if not self.password_entry.get_realized(): self.password_entry.realize() self.password_entry.grab_focus() self.password_entry.event(event) def keymap_handler(self, keymap): """ Handler for the GdkKeymap changing - updates our capslock indicator label. """ if keymap.get_caps_lock_state(): self.capslock_label.set_text(_("You have the Caps Lock key on.")) else: self.capslock_label.set_text("") def on_account_client_loaded(self, client): """ Handler for the AccountsService - requests the user real name and .face image. """ if client.get_real_name() != None: self.real_name = client.get_real_name() self.update_realname_label() if client.get_face_path() != None: self.face_image.set_from_path(client.get_face_path()) self.face_image.show() def on_password_entry_text_changed(self, editable): """ Handler for the password entry text changing - this controls the sensitivity of the unlock button, as well as returning visual focus to the entry any time a key event is received. """ if not self.password_entry.has_focus(): self.password_entry.grab_focus() def on_password_entry_button_press(self, widget, event): """ Prevents the usual copy/paste popup when right-clicking the PasswordEntry. """ if event.button == 3 and event.type == Gdk.EventType.BUTTON_PRESS: return Gdk.EVENT_STOP return Gdk.EVENT_PROPAGATE def on_unlock_clicked(self, button=None): """ Callback for the unlock button. Activates the 'progress' animation in the GtkEntry, and attempts to authenticate the password. During this time, we also inhibit the unlock timeout, so we don't fade out while waiting for an authentication result (highly unlikely.) """ self.emit("inhibit-timeout") text = self.password_entry.get_text() # We must end with a newline, fgets relies upon that to continue. if text[-1:] != "\n": text += "\n" self.auth_client.message_to_child(text) def on_auth_enter_key(self, widget): """ Implicitly activates the unlock button when the Enter/Return key is pressed. """ self.on_unlock_clicked() def on_switch_user_clicked(self, widget): """ Callback for the switch-user button. """ utils.do_user_switch() def clear_entry(self): """ Clear the password entry widget. """ self.password_entry.set_text("") def update_realname_label(self): """ Updates the name label to the current real_name. """ self.realname_label.set_text(self.real_name)
class AlbumArt(Floating, BaseWindow): """ AlbumArt It is a child of the Stage's GtkOverlay, and its placement is controlled by the overlay's child positioning function. When not Awake, it positions itself around all monitors using a timer which randomizes its halign and valign properties as well as its current monitor. """ def __init__(self, away_message=None, initial_monitor=0): super(AlbumArt, self).__init__(initial_monitor) self.get_style_context().add_class("albumart") self.set_halign(Gtk.Align.END) if not settings.get_show_albumart(): return self.watcher = singletons.MediaPlayerWatcher self.player = self.watcher.get_best_player() self.current_url = None self.image = FramedImage() self.image.show() self.image.set_opacity(0.0) self.add(self.image) trackers.con_tracker_get().connect(self.image, "pixbuf-changed", self.on_pixbuf_changed) if self.player != None: trackers.con_tracker_get().connect(self.player, "metadata-changed", self.on_metadata_changed) self.on_metadata_changed(self.player) def on_pixbuf_changed(self, image, pixbuf): if image.get_pixbuf() != None: self.image.set_opacity(1.0) else: self.image.set_opacity(0.0) def on_metadata_changed(self, player): self.update_image() def update_image(self): url = self.player.get_albumart_url() if url == self.current_url: return self.current_url = url if url == "": self.image.clear_image() f = Gio.File.new_for_uri(url) if f.get_uri_scheme() == "file": self.image.set_from_path(f.get_path()) elif f.get_uri_scheme() == "http": self.image.set_from_file(f)
class AlbumArt(Floating, BaseWindow): """ AlbumArt It is a child of the Stage's GtkOverlay, and its placement is controlled by the overlay's child positioning function. When not Awake, it positions itself around all monitors using a timer which randomizes its halign and valign properties as well as its current monitor. """ def __init__(self, screen, away_message=None, initial_monitor=0): super(AlbumArt, self).__init__(initial_monitor) self.screen = screen self.get_style_context().add_class("albumart") if not settings.get_show_albumart(): return self.watcher = singletons.MediaPlayerWatcher self.player = self.watcher.get_best_player() self.current_url = None self.image = FramedImage() self.image.show() self.image.set_opacity(0.0) self.add(self.image) trackers.con_tracker_get().connect(self.image, "pixbuf-changed", self.on_pixbuf_changed) if self.player != None: trackers.con_tracker_get().connect(self.player, "metadata-changed", self.on_metadata_changed) self.on_metadata_changed(self.player) def on_pixbuf_changed(self, image, pixbuf): if image.get_pixbuf() != None: self.image.set_opacity(1.0) else: self.image.set_opacity(0.0) def on_metadata_changed(self, player): self.update_image() def update_image(self): url = self.player.get_albumart_url() if url == self.current_url: return self.current_url = url if url == "": self.image.clear_image() f = Gio.File.new_for_uri(url) if f.get_uri_scheme() == "file": self.image.set_from_path(f.get_path()) elif f.get_uri_scheme() == "http": self.image.set_from_file(f)
def __init__(self): super(UnlockDialog, self).__init__() settings = Gio.Settings.new("org.cinnamon.desktop.lockdown") self.set_halign(Gtk.Align.CENTER) self.set_valign(Gtk.Align.CENTER) self.real_name = None self.user_name = None self.bounce_rect = None self.bounce_count = 0 self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10) self.box.get_style_context().add_class("unlockbox") self.add(self.box) self.face_image = FramedImage() self.face_image.set_halign(Gtk.Align.CENTER) self.face_image.get_style_context().add_class("faceimage") self.face_image.set_no_show_all(True) self.box.pack_start(self.face_image, False, False, 10) self.realname_label = Gtk.Label(None) self.realname_label.set_alignment(0, 0.5) self.realname_label.set_halign(Gtk.Align.CENTER) self.box.pack_start(self.realname_label, False, False, 10) self.entry_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) self.box.pack_start(self.entry_box, True, True, 2) self.password_entry = PasswordEntry() trackers.con_tracker_get().connect(self.password_entry, "changed", self.on_password_entry_text_changed) trackers.con_tracker_get().connect(self.password_entry, "button-press-event", self.on_password_entry_button_press) trackers.con_tracker_get().connect(self.password_entry, "activate", self.on_auth_enter_key) self.entry_box.pack_start(self.password_entry, False, False, 15) button_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) self.entry_box.pack_end(button_box, False, False, 0) self.auth_unlock_button = TransparentButton("screensaver-unlock-symbolic", Gtk.IconSize.LARGE_TOOLBAR) self.auth_unlock_button.set_tooltip_text(_("Unlock")) trackers.con_tracker_get().connect(self.auth_unlock_button, "clicked", self.on_unlock_clicked) button_box.pack_start(self.auth_unlock_button, False, False, 4) status.focusWidgets = [self.password_entry, self.auth_unlock_button] if not settings.get_boolean("disable-user-switching"): self.auth_switch_button = TransparentButton("screensaver-switch-users-symbolic", Gtk.IconSize.LARGE_TOOLBAR) self.auth_switch_button.set_tooltip_text(_("Switch User")) trackers.con_tracker_get().connect(self.auth_switch_button, "clicked", self.on_switch_user_clicked) button_box.pack_start(self.auth_switch_button, False, False, 4) status.focusWidgets.append(self.auth_switch_button) vbox_messages = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=2) self.capslock_label = Gtk.Label("") self.capslock_label.get_style_context().add_class("caps-message") self.capslock_label.set_alignment(0.5, 0.5) vbox_messages.pack_start(self.capslock_label, False, False, 2) self.auth_message_label = Gtk.Label("") self.auth_message_label.get_style_context().add_class("auth-message") self.auth_message_label.set_alignment(0.5, 0.5) vbox_messages.pack_start(self.auth_message_label, False, False, 2) self.box.pack_start(vbox_messages, False, False, 0) self.real_name = utils.get_user_display_name() self.user_name = utils.get_user_name() self.update_realname_label() self.account_client = singletons.AccountsServiceClient if self.account_client.is_loaded: self.on_account_client_loaded(self.account_client) else: trackers.con_tracker_get().connect(self.account_client, "account-loaded", self.on_account_client_loaded) self.keymap = Gdk.Keymap.get_default() trackers.con_tracker_get().connect(self.keymap, "state-changed", self.keymap_handler) self.keymap_handler(self.keymap) self.auth_client = AuthClient() trackers.con_tracker_get().connect(self.auth_client, "auth-success", self.on_authentication_success) trackers.con_tracker_get().connect(self.auth_client, "auth-failure", self.on_authentication_failure) trackers.con_tracker_get().connect(self.auth_client, "auth-cancel", self.on_authentication_cancelled) trackers.con_tracker_get().connect(self.auth_client, "auth-busy", self.on_authentication_busy_changed) trackers.con_tracker_get().connect(self.auth_client, "auth-prompt", self.on_authentication_prompt_changed) self.box.show_all()
class UnlockDialog(BaseWindow): """ The main widget for the unlock dialog - this is a direct child of the Stage's GtkOverlay. It has a number of parts, namely: - The user face image. - The user's real name (or username if the real name is unavailable) - The password entry widget - Unlock and Switch User buttons - A caps lock warning label - An invalid password error label """ __gsignals__ = { 'inhibit-timeout': (GObject.SignalFlags.RUN_LAST, None, ()), 'uninhibit-timeout': (GObject.SignalFlags.RUN_LAST, None, ()), 'authenticate-success': (GObject.SignalFlags.RUN_LAST, None, ()), 'authenticate-failure': (GObject.SignalFlags.RUN_LAST, None, ()), 'authenticate-cancel': (GObject.SignalFlags.RUN_LAST, None, ()) } def __init__(self): super(UnlockDialog, self).__init__() settings = Gio.Settings.new("org.cinnamon.desktop.lockdown") self.set_halign(Gtk.Align.CENTER) self.set_valign(Gtk.Align.CENTER) self.real_name = None self.user_name = None self.bounce_rect = None self.bounce_count = 0 self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10) self.box.get_style_context().add_class("unlockbox") self.add(self.box) self.face_image = FramedImage() self.face_image.set_halign(Gtk.Align.CENTER) self.face_image.get_style_context().add_class("faceimage") self.face_image.set_no_show_all(True) self.box.pack_start(self.face_image, False, False, 10) self.realname_label = Gtk.Label(None) self.realname_label.set_alignment(0, 0.5) self.realname_label.set_halign(Gtk.Align.CENTER) self.box.pack_start(self.realname_label, False, False, 10) self.entry_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) self.box.pack_start(self.entry_box, True, True, 2) self.password_entry = PasswordEntry() trackers.con_tracker_get().connect(self.password_entry, "changed", self.on_password_entry_text_changed) trackers.con_tracker_get().connect(self.password_entry, "button-press-event", self.on_password_entry_button_press) trackers.con_tracker_get().connect(self.password_entry, "activate", self.on_auth_enter_key) self.entry_box.pack_start(self.password_entry, False, False, 15) button_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) self.entry_box.pack_end(button_box, False, False, 0) self.auth_unlock_button = TransparentButton("screensaver-unlock-symbolic", Gtk.IconSize.LARGE_TOOLBAR) self.auth_unlock_button.set_tooltip_text(_("Unlock")) trackers.con_tracker_get().connect(self.auth_unlock_button, "clicked", self.on_unlock_clicked) button_box.pack_start(self.auth_unlock_button, False, False, 4) status.focusWidgets = [self.password_entry, self.auth_unlock_button] if not settings.get_boolean("disable-user-switching"): self.auth_switch_button = TransparentButton("screensaver-switch-users-symbolic", Gtk.IconSize.LARGE_TOOLBAR) self.auth_switch_button.set_tooltip_text(_("Switch User")) trackers.con_tracker_get().connect(self.auth_switch_button, "clicked", self.on_switch_user_clicked) button_box.pack_start(self.auth_switch_button, False, False, 4) status.focusWidgets.append(self.auth_switch_button) vbox_messages = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=2) self.capslock_label = Gtk.Label("") self.capslock_label.get_style_context().add_class("caps-message") self.capslock_label.set_alignment(0.5, 0.5) vbox_messages.pack_start(self.capslock_label, False, False, 2) self.auth_message_label = Gtk.Label("") self.auth_message_label.get_style_context().add_class("auth-message") self.auth_message_label.set_alignment(0.5, 0.5) vbox_messages.pack_start(self.auth_message_label, False, False, 2) self.box.pack_start(vbox_messages, False, False, 0) self.real_name = utils.get_user_display_name() self.user_name = utils.get_user_name() self.update_realname_label() self.account_client = singletons.AccountsServiceClient if self.account_client.is_loaded: self.on_account_client_loaded(self.account_client) else: trackers.con_tracker_get().connect(self.account_client, "account-loaded", self.on_account_client_loaded) self.keymap = Gdk.Keymap.get_default() trackers.con_tracker_get().connect(self.keymap, "state-changed", self.keymap_handler) self.keymap_handler(self.keymap) self.auth_client = AuthClient() trackers.con_tracker_get().connect(self.auth_client, "auth-success", self.on_authentication_success) trackers.con_tracker_get().connect(self.auth_client, "auth-failure", self.on_authentication_failure) trackers.con_tracker_get().connect(self.auth_client, "auth-cancel", self.on_authentication_cancelled) trackers.con_tracker_get().connect(self.auth_client, "auth-busy", self.on_authentication_busy_changed) trackers.con_tracker_get().connect(self.auth_client, "auth-prompt", self.on_authentication_prompt_changed) self.box.show_all() def initialize_auth_client(self): return self.auth_client.initialize() def cancel_auth_client(self): self.clear_entry() self.auth_client.cancel() def on_authentication_success(self, auth_client): self.clear_entry() self.emit("authenticate-success") def on_authentication_failure(self, auth_client): """ Called upon authentication failure, clears the password, sets an error message, and refocuses the password entry. """ self.clear_entry() self.auth_message_label.set_text(_("Incorrect password")) self.emit("authenticate-failure") self.emit("uninhibit-timeout") def on_authentication_cancelled(self, auth_client): self.emit("authenticate-cancel") def on_authentication_busy_changed(self, auth_client, busy): if busy: self.auth_message_label.set_text("") self.clear_entry() self.entry_box.set_sensitive(False) self.password_entry.start_progress() self.password_entry.set_placeholder_text (_("Checking...")) else: self.entry_box.set_sensitive(True) self.password_entry.stop_progress() self.password_entry.set_placeholder_text (self.password_entry.placeholder_text) def on_authentication_prompt_changed(self, auth_client, prompt): if "password:"******"Please enter your password...") else: prompt = prompt.replace(":", "") self.password_entry.placeholder_text = prompt self.password_entry.set_placeholder_text(self.password_entry.placeholder_text) def cancel(self): """ Clears the auth message text if we have any. """ self.auth_message_label.set_text("") def queue_key_event(self, event): """ Takes a propagated key event from the stage and passes it to the entry widget, possibly queueing up the first character of the password. """ if not self.password_entry.get_realized(): self.password_entry.realize() self.password_entry.grab_focus() self.password_entry.event(event) def keymap_handler(self, keymap): """ Handler for the GdkKeymap changing - updates our capslock indicator label. """ if keymap.get_caps_lock_state(): self.capslock_label.set_text(_("You have the Caps Lock key on.")) else: self.capslock_label.set_text("") def on_account_client_loaded(self, client): """ Handler for the AccountsService - requests the user real name and .face image. """ if client.get_real_name() != None: self.real_name = client.get_real_name() self.update_realname_label() if client.get_face_path() != None: self.face_image.set_from_path(client.get_face_path()) self.face_image.show() def on_password_entry_text_changed(self, editable): """ Handler for the password entry text changing - this controls the sensitivity of the unlock button, as well as returning visual focus to the entry any time a key event is received. """ if not self.password_entry.has_focus(): self.password_entry.grab_focus() def on_password_entry_button_press(self, widget, event): """ Prevents the usual copy/paste popup when right-clicking the PasswordEntry. """ if event.button == 3 and event.type == Gdk.EventType.BUTTON_PRESS: return Gdk.EVENT_STOP return Gdk.EVENT_PROPAGATE def on_unlock_clicked(self, button=None): """ Callback for the unlock button. Activates the 'progress' animation in the GtkEntry, and attempts to authenticate the password. During this time, we also inhibit the unlock timeout, so we don't fade out while waiting for an authentication result (highly unlikely.) """ self.emit("inhibit-timeout") text = self.password_entry.get_text() # We must end with a newline, fgets relies upon that to continue. if text[-1:] != "\n": text += "\n" self.auth_client.message_to_child(text) def on_auth_enter_key(self, widget): """ Implicitly activates the unlock button when the Enter/Return key is pressed. """ self.on_unlock_clicked() def on_switch_user_clicked(self, widget): """ Callback for the switch-user button. """ utils.do_user_switch() def clear_entry(self): """ Clear the password entry widget. """ self.password_entry.set_text("") def update_realname_label(self): """ Updates the name label to the current real_name. """ self.realname_label.set_text(self.real_name) def blink(self): GObject.timeout_add(75, self.on_blink_tick) def on_blink_tick(self, data=None): window = self.get_window() if window == None: return False x, y = window.get_position() if self.bounce_count < 6: if self.bounce_count % 2 == 0: y += 6 else: y -= 6 self.get_window().move(x, y) self.queue_draw() self.bounce_count += 1 return True self.bounce_count = 0 return False
def __init__(self): super(UnlockDialog, self).__init__() self.set_halign(Gtk.Align.CENTER) self.set_valign(Gtk.Align.CENTER) self.set_size_request(350, -1) self.real_name = None self.user_name = None self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10) self.box.get_style_context().add_class("unlockbox") self.add(self.box) self.face_image = FramedImage() self.face_image.set_halign(Gtk.Align.CENTER) self.face_image.get_style_context().add_class("faceimage") self.face_image.set_no_show_all(True) self.box.pack_start(self.face_image, False, False, 10) self.realname_label = Gtk.Label(None) self.realname_label.set_alignment(0, 0.5) self.realname_label.set_halign(Gtk.Align.CENTER) self.box.pack_start(self.realname_label, False, False, 10) self.entry_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) self.box.pack_start(self.entry_box, True, True, 2) self.password_entry = PasswordEntry() trackers.con_tracker_get().connect(self.password_entry, "changed", self.on_password_entry_text_changed) trackers.con_tracker_get().connect(self.password_entry, "button-press-event", self.on_password_entry_button_press) trackers.con_tracker_get().connect(self.password_entry, "activate", self.on_auth_enter_key) self.entry_box.pack_start(self.password_entry, True, True, 15) button_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) self.entry_box.pack_end(button_box, False, False, 0) self.auth_unlock_button = TransparentButton("screensaver-unlock-symbolic", Gtk.IconSize.LARGE_TOOLBAR) self.auth_unlock_button.set_sensitive(False) trackers.con_tracker_get().connect(self.auth_unlock_button, "clicked", self.on_unlock_clicked) button_box.pack_start(self.auth_unlock_button, False, False, 4) self.auth_switch_button = TransparentButton("screensaver-switch-users-symbolic", Gtk.IconSize.LARGE_TOOLBAR) trackers.con_tracker_get().connect(self.auth_switch_button, "clicked", self.on_switch_user_clicked) button_box.pack_start(self.auth_switch_button, False, False, 4) status.focusWidgets = [self.password_entry, self.auth_unlock_button, self.auth_switch_button] vbox_messages = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=2) self.capslock_label = Gtk.Label("") self.capslock_label.get_style_context().add_class("caps-message") self.capslock_label.set_alignment(0.5, 0.5) vbox_messages.pack_start(self.capslock_label, False, False, 2) self.auth_message_label = Gtk.Label("") self.auth_message_label.get_style_context().add_class("auth-message") self.auth_message_label.set_alignment(0.5, 0.5) vbox_messages.pack_start(self.auth_message_label, False, False, 2) self.box.pack_start(vbox_messages, False, False, 0) self.real_name = utils.get_user_display_name() self.user_name = utils.get_user_name() self.update_realname_label() self.account_client = singletons.AccountsServiceClient if self.account_client.is_loaded: self.on_account_client_loaded(self.account_client) else: trackers.con_tracker_get().connect(self.account_client, "account-loaded", self.on_account_client_loaded) self.keymap = Gdk.Keymap.get_default() trackers.con_tracker_get().connect(self.keymap, "state-changed", self.keymap_handler) trackers.con_tracker_get().connect_after(self, "notify::child-revealed", self.on_revealed)
class UnlockDialog(BaseWindow): """ The main widget for the unlock dialog - this is a direct child of the Stage's GtkOverlay. It has a number of parts, namely: - The user face image. - The user's real name (or username if the real name is unavailable) - The password entry widget - Unlock and Switch User buttons - A caps lock warning label - An invalid password error label """ __gsignals__ = { 'inhibit-timeout': (GObject.SignalFlags.RUN_LAST, None, ()), 'uninhibit-timeout': (GObject.SignalFlags.RUN_LAST, None, ()), 'auth-success': (GObject.SignalFlags.RUN_LAST, None, ()), 'auth-failure': (GObject.SignalFlags.RUN_LAST, None, ()) } def __init__(self): super(UnlockDialog, self).__init__() self.set_halign(Gtk.Align.CENTER) self.set_valign(Gtk.Align.CENTER) self.set_size_request(350, -1) self.real_name = None self.user_name = None self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10) self.box.get_style_context().add_class("unlockbox") self.add(self.box) self.face_image = FramedImage() self.face_image.set_halign(Gtk.Align.CENTER) self.face_image.get_style_context().add_class("faceimage") self.face_image.set_no_show_all(True) self.box.pack_start(self.face_image, False, False, 10) self.realname_label = Gtk.Label(None) self.realname_label.set_alignment(0, 0.5) self.realname_label.set_halign(Gtk.Align.CENTER) self.box.pack_start(self.realname_label, False, False, 10) self.entry_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) self.box.pack_start(self.entry_box, True, True, 2) self.password_entry = PasswordEntry() trackers.con_tracker_get().connect(self.password_entry, "changed", self.on_password_entry_text_changed) trackers.con_tracker_get().connect(self.password_entry, "button-press-event", self.on_password_entry_button_press) trackers.con_tracker_get().connect(self.password_entry, "activate", self.on_auth_enter_key) self.entry_box.pack_start(self.password_entry, True, True, 15) button_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) self.entry_box.pack_end(button_box, False, False, 0) self.auth_unlock_button = TransparentButton("screensaver-unlock-symbolic", Gtk.IconSize.LARGE_TOOLBAR) self.auth_unlock_button.set_sensitive(False) trackers.con_tracker_get().connect(self.auth_unlock_button, "clicked", self.on_unlock_clicked) button_box.pack_start(self.auth_unlock_button, False, False, 4) self.auth_switch_button = TransparentButton("screensaver-switch-users-symbolic", Gtk.IconSize.LARGE_TOOLBAR) trackers.con_tracker_get().connect(self.auth_switch_button, "clicked", self.on_switch_user_clicked) button_box.pack_start(self.auth_switch_button, False, False, 4) status.focusWidgets = [self.password_entry, self.auth_unlock_button, self.auth_switch_button] vbox_messages = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=2) self.capslock_label = Gtk.Label("") self.capslock_label.get_style_context().add_class("caps-message") self.capslock_label.set_alignment(0.5, 0.5) vbox_messages.pack_start(self.capslock_label, False, False, 2) self.auth_message_label = Gtk.Label("") self.auth_message_label.get_style_context().add_class("auth-message") self.auth_message_label.set_alignment(0.5, 0.5) vbox_messages.pack_start(self.auth_message_label, False, False, 2) self.box.pack_start(vbox_messages, False, False, 0) self.real_name = utils.get_user_display_name() self.user_name = utils.get_user_name() self.update_realname_label() self.account_client = singletons.AccountsServiceClient if self.account_client.is_loaded: self.on_account_client_loaded(self.account_client) else: trackers.con_tracker_get().connect(self.account_client, "account-loaded", self.on_account_client_loaded) self.keymap = Gdk.Keymap.get_default() trackers.con_tracker_get().connect(self.keymap, "state-changed", self.keymap_handler) trackers.con_tracker_get().connect_after(self, "notify::child-revealed", self.on_revealed) def cancel(self): """ Clears the auth message text if we have any. """ self.auth_message_label.set_text("") def on_revealed(self, widget, child): """ Updates the capslock state and ensures the password is cleared when we're first shown. """ if self.get_child_revealed(): self.keymap_handler(self.keymap) else: self.password_entry.set_text("") def queue_key_event(self, event): """ Takes a propagated key event from the stage and passes it to the entry widget, possibly queueing up the first character of the password. """ if not self.password_entry.get_realized(): self.password_entry.realize() self.password_entry.event(event) def keymap_handler(self, keymap): """ Handler for the GdkKeymap changing - updates our capslock indicator label. """ if keymap.get_caps_lock_state(): self.capslock_label.set_text(_("You have the Caps Lock key on.")) else: self.capslock_label.set_text("") def on_account_client_loaded(self, client): """ Handler for the AccountsService - requests the user real name and .face image. """ if client.get_real_name() != None: self.real_name = client.get_real_name() self.update_realname_label() if client.get_face_path() != None: self.face_image.set_from_path(client.get_face_path()) self.face_image.show() def on_password_entry_text_changed(self, editable): """ Handler for the password entry text changing - this controls the sensitivity of the unlock button, as well as returning visual focus to the entry any time a key event is received. """ if not self.password_entry.has_focus(): self.password_entry.grab_focus() self.auth_unlock_button.set_sensitive(editable.get_text() != "") def on_password_entry_button_press(self, widget, event): """ Prevents the usual copy/paste popup when right-clicking the PasswordEntry. """ if event.button == 3 and event.type == Gdk.EventType.BUTTON_PRESS: return Gdk.EVENT_STOP return Gdk.EVENT_PROPAGATE def on_unlock_clicked(self, button=None): """ Callback for the unlock button. Activates the 'progress' animation in the GtkEntry, and attempts to authenticate the password. During this time, we also inhibit the unlock timeout, so we don't fade out while waiting for an authentication result (highly unlikely.) """ self.emit("inhibit-timeout") text = self.password_entry.get_text() self.password_entry.start_progress() self.password_entry.set_placeholder_text (_("Checking...")) self.authenticate(text) def on_auth_enter_key(self, widget): """ Implicitly activates the unlock button when the Enter/Return key is pressed. """ if widget.get_text() == "": return self.on_unlock_clicked() def on_switch_user_clicked(self, widget): """ Callback for the switch-user button. """ utils.do_user_switch() def clear_entry(self): """ Clear the password entry widget. """ self.password_entry.set_text("") def update_realname_label(self): """ Updates the name label to the current real_name. """ self.realname_label.set_text(self.real_name) def authenticate(self, password): """ Authenticates the entered password against the system PAM provider. """ CinnamonDesktop.desktop_check_user_password(self.user_name, password, self.authenticate_callback) def authenticate_callback(self, success, data=None): """ Callback for check_user_password. Send this back to the Stage so it can react how it needs to (destroying itself or flashing the unlock widget on failure.) """ self.password_entry.stop_progress() if success: self.clear_entry() self.emit("auth-success") else: self.authentication_failed() self.emit("auth-failure") def authentication_failed(self): """ Called upon authentication failure, clears the password, sets an error message, and refocuses the password entry. """ self.clear_entry() self.password_entry.set_placeholder_text (_("Please enter your password...")) self.auth_message_label.set_text(_("Incorrect password")) self.password_entry.grab_focus() self.emit("uninhibit-timeout")