diff --git a/data/theme/cinnamon-sass/widgets/_dialogs.scss b/data/theme/cinnamon-sass/widgets/_dialogs.scss index 64f1411d30..caa6cc6efb 100644 --- a/data/theme/cinnamon-sass/widgets/_dialogs.scss +++ b/data/theme/cinnamon-sass/widgets/_dialogs.scss @@ -27,47 +27,50 @@ } } -// endSessionDialog.js -.end-session-dialog { - width: 40em; - transition-duration: 100ms; +// Lists in dialogs - .dialog-content-box { - spacing: $base_margin * 3; - width: 30em; - } +.dialog-list { + spacing: $base_padding * 3; - .end-session-dialog-inhibitor-list-frame { - background-color: $light_bg_color; - border-radius: $base_border_radius; - border: 1px solid $borders_color; - padding-left: 5px; - padding-right: 5px; - padding-top: 2px; - padding-bottom: 2px; - } + .dialog-list-title { + @extend %heading; + text-align: center; + } - .end-session-dialog-inhibitor-list { - spacing-rows: 5px; - spacing-columns: 20px; - padding: 2px; - } + .dialog-list-scrollview { max-height: 200px; } + .dialog-list-box { + spacing: 1em; - .end-session-dialog-inhibitor-list-reason { - width: 25em; + .dialog-list-item { + spacing: 1em; + + .dialog-list-item-title { font-weight: bold; } + .dialog-list-item-description { + @extend %caption; + color: darken($fg_color, 5%); + } } + } +} + +// End session dialog + +.end-session-dialog { + width: 40em; + + .dialog-content-box { spacing: 0; } - .end-session-dialog-progress-bar { - min-width: 160px; - -barlevel-height: 6px; - -barlevel-background-color: $base_color; - -barlevel-active-background-color: $fg_color; - -barlevel-amplify-color: $warning_color; - -barlevel-amplify-separator-width: $base_padding * 0.5; + .dialog-list { + spacing: 0; - &:ltr { margin-right: $base_padding; } - &:rtl { margin-left: $base_padding; } + .dialog-list-title { + color: $warning_color; + background-color: tranparentize($warning_color, 0.9); + padding: $base_padding * 1.5; + border-radius: $base_border_radius; + margin: $base_margin 0; } + } } // message dialog diff --git a/js/ui/cinnamonDBus.js b/js/ui/cinnamonDBus.js index 69ecb6169b..9867368285 100644 --- a/js/ui/cinnamonDBus.js +++ b/js/ui/cinnamonDBus.js @@ -521,13 +521,13 @@ CinnamonDBus.prototype = { ShowEndSessionDialog(mode) { GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { - Main.show_end_session_dialog(mode); + Main.showEndSessionDialog(mode); return GLib.SOURCE_REMOVE; }); }, CloseEndSessionDialog() { - Main.close_end_session_dialog(); + Main.closeEndSessionDialog(); }, CinnamonVersion: Config.PACKAGE_VERSION diff --git a/js/ui/dialog.js b/js/ui/dialog.js index 2e8fdcfdc0..92acc84ae8 100644 --- a/js/ui/dialog.js +++ b/js/ui/dialog.js @@ -205,6 +205,7 @@ var MessageDialogContent = GObject.registerClass({ style_class: 'message-dialog-content', x_expand: true, vertical: true, + important: true, }; super._init(Object.assign(defaultParams, params)); @@ -270,3 +271,125 @@ var MessageDialogContent = GObject.registerClass({ this.notify('description'); } }); + +var ListSection = GObject.registerClass({ + Properties: { + 'title': GObject.ParamSpec.string( + 'title', 'title', 'title', + GObject.ParamFlags.READWRITE | + GObject.ParamFlags.CONSTRUCT, + null), + }, +}, class ListSection extends St.BoxLayout { + _init(params) { + this._title = new St.Label({ style_class: 'dialog-list-title' }); + + this.list = new St.BoxLayout({ + style_class: 'dialog-list-box', + vertical: true, + }); + + this._listScrollView = new St.ScrollView({ + style_class: 'dialog-list-scrollview', + hscrollbar_policy: St.PolicyType.NEVER, + }); + this._listScrollView.add_actor(this.list); + + super._init({ + style_class: 'dialog-list', + x_expand: true, + vertical: true, + important: true, + ...params, + }); + + this.label_actor = this._title; + this.add_child(this._title); + this.add_child(this._listScrollView); + } + + get title() { + return this._title.text; + } + + set title(title) { + _setLabel(this._title, title); + this.notify('title'); + } +}); + +var ListSectionItem = GObject.registerClass({ + Properties: { + 'icon-actor': GObject.ParamSpec.object( + 'icon-actor', 'icon-actor', 'Icon actor', + GObject.ParamFlags.READWRITE, + Clutter.Actor.$gtype), + 'title': GObject.ParamSpec.string( + 'title', 'title', 'title', + GObject.ParamFlags.READWRITE | + GObject.ParamFlags.CONSTRUCT, + null), + 'description': GObject.ParamSpec.string( + 'description', 'description', 'description', + GObject.ParamFlags.READWRITE | + GObject.ParamFlags.CONSTRUCT, + null), + }, +}, class ListSectionItem extends St.BoxLayout{ + _init(params) { + this._iconActorBin = new St.Bin(); + + let textLayout = new St.BoxLayout({ + vertical: true, + y_expand: true, + y_align: Clutter.ActorAlign.CENTER, + }); + + this._title = new St.Label({ style_class: 'dialog-list-item-title' }); + + this._description = new St.Label({ + style_class: 'dialog-list-item-description', + }); + + textLayout.add_child(this._title); + textLayout.add_child(this._description); + + super._init({ + style_class: 'dialog-list-item', + important: true, + ...params, + }); + + + this.label_actor = this._title; + this.add_child(this._iconActorBin); + this.add_child(textLayout); + } + + get iconActor() { + return this._iconActorBin.get_child(); + } + + set iconActor(actor) { + this._iconActorBin.set_child(actor); + this.notify('icon-actor'); + } + + get title() { + return this._title.text; + } + + set title(title) { + _setLabel(this._title, title); + this.notify('title'); + } + + get description() { + return this._description.text; + } + + set description(description) { + _setLabel(this._description, description); + this.notify('description'); + } +}); diff --git a/js/ui/endSessionDialog.js b/js/ui/endSessionDialog.js index 953e06b955..feac208b8f 100644 --- a/js/ui/endSessionDialog.js +++ b/js/ui/endSessionDialog.js @@ -7,10 +7,7 @@ const GObject = imports.gi.GObject; const St = imports.gi.St; const Dialog = imports.ui.dialog; -const Main = imports.ui.main; -const Layout = imports.ui.layout; -const {BarLevel} = imports.ui.barLevel; -const {Separator} = imports.ui.separator; +const ModalDialog = imports.ui.modalDialog; const SessionDialogInterface = " \ @@ -52,212 +49,189 @@ const ResponseCode = { NONE: 9 } -const DIALOG_WIDTH = 800; -const DIALOG_HEIGHT = 300; +var EndSessionDialog = GObject.registerClass( +class EndSessionDialog extends ModalDialog.ModalDialog { + _init(mode) { + super._init({ + styleClass: 'end-session-dialog', + }); -var EndSessionDialog = class { - constructor(mode) { this._mode = mode; this._inhibited = false; this._settings = new Gio.Settings({ schema_id: 'org.cinnamon.SessionManager' }); - this._delay_duration = this._settings.get_int("quit-time-delay"); - this._current_time = this._delay_duration; - this._progress_timer_id = 0; - this._default_action = null; - - // persistent actors - this._dialog = null; - this._inhibitor_table = null; - this._progress_label = null; - this._progress_bar = null; - - this._dialog = new Dialog.Dialog(Main.uiGroup, 'end-session-dialog'); - global.focus_manager.add_group(this._dialog); - Main.layoutManager.trackChrome(this._dialog); - - - this._dialog_proxy = new Gio.DBusProxy( - { - g_connection: Gio.DBus.session, - g_interface_name: "org.cinnamon.SessionManager.EndSessionDialog", - g_interface_info: SessionDialogInfo, - g_name: 'org.gnome.SessionManager', - g_object_path: '/org/gnome/SessionManager', - g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START - } - ); + this._currentTime = this._settings.get_int('quit-time-delay'); + this._progressTimerId = 0; + this._defaultAction = null; + + this._messageDialogContent = new Dialog.MessageDialogContent(); + this._messageDialogContent.description = " "; + this.contentLayout.add_child(this._messageDialogContent); + + this._applicationsSection = new Dialog.ListSection({ + title: _("Some applications are busy or have unsaved work."), + }); + this.contentLayout.add_child(this._applicationsSection); + this._applicationsSection.visible = false; + + this._dialogProxy = new Gio.DBusProxy({ + g_connection: Gio.DBus.session, + g_interface_name: "org.cinnamon.SessionManager.EndSessionDialog", + g_interface_info: SessionDialogInfo, + g_name: 'org.gnome.SessionManager', + g_object_path: '/org/gnome/SessionManager', + g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START + }); - this._dialog_proxy.init(null); + this._dialogProxy.init(null); - this._dialog_proxy.connect("g-signal", this._proxy_signal_received.bind(this)); - this._dialog_proxy.GetCapabilitiesRemote(this._get_capabilities_cb.bind(this)); + this._dialogProxy.connect("g-signal", this._proxySignalReceived.bind(this)); + this._dialogProxy.GetCapabilitiesRemote(this._getCapabilities.bind(this)); } - _proxy_signal_received(proxy, sender, signal, params) { + _proxySignalReceived(proxy, sender, signal, params) { if (signal === "InhibitorsChanged") { const inhibitors = params.deep_unpack()[0]; if (inhibitors && inhibitors.length > 0) { this._inhibited = true; - this._present_inhibitor_info(inhibitors); + this._presentInhibitorInfo(inhibitors); } else { if (this._inhibited) { - this._dialog_proxy.IgnoreInhibitorsRemote(); + this._dialogProxy.IgnoreInhibitorsRemote(); } } } } - _add_cancel() { - this._dialog.addButton({ + _addCancel() { + this.addButton({ label: _("Cancel"), action: () => { - this._dialog_proxy.CancelRemote(); + this._dialogProxy.CancelRemote(); }, key: Clutter.KEY_Escape }); } - _get_capabilities_cb(result, error) { + _getCapabilities(result, error) { if (error) { global.logError('Error getting capabilities: ' + error.message); return; } - var [can_switch_user, can_stop, can_restart, can_hybrid_sleep, can_suspend, can_hibernate, can_logout] = result[0]; + var [canSwitchUser, canStop, canRestart, canHybridSleep, canSuspend, canHibernate, canLogout] = result[0]; var content = null; switch(this._mode) { case DialogMode.LOGOUT: - if (can_switch_user) { - this._dialog.addButton({ + this._addCancel(); + + if (canSwitchUser) { + this.addButton({ label: _("Switch User"), - action: this._dialog_proxy.SwitchUserRemote.bind(this._dialog_proxy) + action: this._dialogProxy.SwitchUserRemote.bind(this._dialogProxy) }); } - this._add_cancel() - - this._default_action = this._dialog_proxy.LogoutRemote.bind(this._dialog_proxy); - this._dialog.addButton({ + this._defaultAction = this._dialogProxy.LogoutRemote.bind(this._dialogProxy); + this.addButton({ label: _("Log Out"), - action: this._default_action, + action: this._defaultAction, destructive_action: true, default: true }); - content = new Dialog.MessageDialogContent({ - title: _("Log Out?") - }); + this._messageDialogContent.title = _("Log Out"); break; case DialogMode.SHUTDOWN: - if (can_suspend) { - this._dialog.addButton({ + this._addCancel(); + + if (canSuspend) { + this.addButton({ label: _("Suspend"), - action: this._dialog_proxy.SuspendRemote.bind(this._dialog_proxy) + action: () => { + this._dialogProxy.SuspendRemote(); + this.close(); + }, }); } - if (can_hibernate) { - this._dialog.addButton({ + + if (canHibernate) { + this.addButton({ label: _("Hibernate"), - action: this._dialog_proxy.HibernateRemote.bind(this._dialog_proxy) + action: this._dialogProxy.HibernateRemote.bind(this._dialogProxy) }); } - this._add_cancel(); - - if (can_restart) { - this._dialog.addButton({ + if (canRestart) { + this.addButton({ label: _("Restart"), - action: this._dialog_proxy.RestartRemote.bind(this._dialog_proxy), + action: this._dialogProxy.RestartRemote.bind(this._dialogProxy), }); } - if (can_stop) { - this._default_action = this._dialog_proxy.ShutdownRemote.bind(this._dialog_proxy); - this._dialog.addButton({ + + if (canStop) { + this._defaultAction = this._dialogProxy.ShutdownRemote.bind(this._dialogProxy); + this.addButton({ label: _("Shut Down"), - action: this._default_action, + action: this._defaultAction, destructive_action: true, default: true, }); } - content = new Dialog.MessageDialogContent({ - title: _("Shut Down?") - }); + this._messageDialogContent.title = _("Shut Down"); break; case DialogMode.REBOOT: - if (!can_restart) { + this._addCancel(); + + if (!canRestart) { global.logError("Restart not available"); - this._dialog_proxy.CancelRemote(); + this._dialogProxy.CancelRemote(); this.destroy(); return; } - this._add_cancel(); - - this._default_action = this._dialog_proxy.RestartRemote.bind(this._dialog_proxy); - this._dialog.addButton({ + this._defaultAction = this._dialogProxy.RestartRemote.bind(this._dialogProxy); + this.addButton({ label: _("Restart"), - action: this._default_action, + action: this._defaultAction, destructive_action: true, default: true }); - content = new Dialog.MessageDialogContent({ - title: _("Restart?") - }); + this._messageDialogContent.title = _("Restart"); - break + break; } - this._dialog.contentLayout.add_child(content); - if (this._settings.get_boolean("quit-delay-toggle")) { - this._add_delay_timer(); + this._addDelayTimer(); } - - this._position_dialog(); } - _position_dialog() { - const monitor = Main.layoutManager.currentMonitor; + _addDelayTimer() { + this._updateProgress(); - this._dialog.set_position( - monitor.x + Math.floor((monitor.width - this._dialog.width) / 2), - monitor.y + Math.floor((monitor.height - this._dialog.height) / 2) - ); + this._progressTimerId = GLib.timeout_add( + GLib.PRIORITY_DEFAULT, 1000, this._updateProgress.bind(this)); } - _add_delay_timer() { - this._progress_label = new St.Label(); - this._dialog.contentLayout.add_child(this._progress_label); - - this._progress_bar = new BarLevel({ style_class: "end-session-dialog-progress-bar", value: 1.0, maximum_value: 1.0 }); - this._dialog.contentLayout.add_child(this._progress_bar); - - this._update_progress(); - - this._progress_timer_id = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, this._update_progress.bind(this)); - } - - _remove_delay_timer() { - if (this._progress_timer_id) { - GLib.source_remove(this._progress_timer_id); - this._progress_timer_id = 0; + _removeDelayTimer() { + if (this._progressTimerId) { + GLib.source_remove(this._progressTimerId); + this._progressTimerId = 0; } } - _update_progress() { - this._progress_bar.value = (this._current_time / this._delay_duration); - - if (this._current_time == 0) { - if (this._default_action != null) { - this._default_action(); + _updateProgress() { + if (this._currentTime == 0) { + if (this._defaultAction != null) { + this._defaultAction(); } - this._progress_timer_id = 0; + this._progressTimerId = 0; return GLib.SOURCE_REMOVE; } @@ -268,113 +242,73 @@ var EndSessionDialog = class { text = ngettext( "You will be logged out in %d second.", "You will be logged out in %d seconds.", - this._current_time).format(this._current_time); + this._currentTime).format(this._currentTime); break; case DialogMode.SHUTDOWN: text = ngettext( "The computer will shut down in %d second.", "The computer will shut down in %d seconds.", - this._current_time).format(this._current_time); + this._currentTime).format(this._currentTime); break; case DialogMode.REBOOT: text = ngettext( "The computer will restart in %d second.", "The computer will restart in %d seconds.", - this._current_time).format(this._current_time); + this._currentTime).format(this._currentTime); break; } - this._progress_label.set_text(text); - - this._current_time--; + this._messageDialogContent.description = text; + this._currentTime--; return GLib.SOURCE_CONTINUE; } - _present_inhibitor_info(inhibitor_infos) { - this._remove_delay_timer(); - - this._dialog.clearButtons(); - this._dialog.contentLayout.remove_all_children(); - - const content = new Dialog.MessageDialogContent({ - title: _("Some programs are still running"), - description: _("Waiting for programs to finish. Interrupting these programs may cause you to lose work.") - }); - this._dialog.contentLayout.add_child(content); - - const bin = new St.Bin({ style_class: "end-session-dialog-inhibitor-list-frame" }); - this._dialog.contentLayout.add_child(bin); - - this._inhibitor_table = new St.Table({ style_class: "end-session-dialog-inhibitor-list" }); - bin.set_child(this._inhibitor_table); - - let row = 0; + _presentInhibitorInfo(inhibitorInfos) { + this._removeDelayTimer(); + this.clearButtons(); + this._messageDialogContent.description = null; - - const infos = inhibitor_infos; + const infos = inhibitorInfos; for (let i = 0; i < infos.length; i++) { const info = infos[i]; - const [name_str, gicon_str, reason_str, id] = info; + const [nameStr, giconStr, reasonStr, id] = info; try { - const name = (name_str == "none") ? _("Unknown") : name_str; - const app = new St.Label({ text: name }); - - const reason = new St.Label({ text: reason_str, style_class: "end-session-dialog-inhibitor-list-reason" }); - reason.clutter_text.line_wrap = true; + const name = (nameStr == "none") ? _("Unknown") : nameStr; + const iconName = (giconStr == 'none') ? ('application-x-executable') : giconStr; - const gicon = Gio.Icon.new_for_string(gicon_str); + const gicon = Gio.Icon.new_for_string(iconName); const icon = new St.Icon({ gicon: gicon }); - this._inhibitor_table.add(app, { - row: row, - col: 0, - col_span: 1, - x_align: St.Align.START + let item = new Dialog.ListSectionItem({ + icon_actor: icon, + title: name, + description: reasonStr, }); - this._inhibitor_table.add(reason, { - row: row, - col: 1, - col_span: 1, - x_expand: true, - }); - - row++; - - if (i < infos.length - 1) { - this._inhibitor_table.add(new Separator().actor, { - row: row, - col: 0, - col_span: 2, - x_expand: true - }); - - row++; - } + this._applicationsSection.list.add_child(item); + this._applicationsSection.visible = true; } catch (e) { global.logError(e); } } - this._add_cancel(); + this._addCancel(); - this._dialog.addButton({ + this.addButton({ label: _("Ignore and continue"), - action: this._dialog_proxy.IgnoreInhibitorsRemote.bind(this._dialog_proxy), + action: this._dialogProxy.IgnoreInhibitorsRemote.bind(this._dialogProxy), destructive_action: true, default: true }); } - destroy() { - this._remove_delay_timer() + close() { + super.close(); - this._dialog_proxy = null; - this._dialog.destroy(); - this._dialog = null; + this._removeDelayTimer(); + this._dialogProxy = null; } -}; - +}); diff --git a/js/ui/main.js b/js/ui/main.js index 023100579a..2f878a06d9 100644 --- a/js/ui/main.js +++ b/js/ui/main.js @@ -195,7 +195,7 @@ var popup_rendering_actor = null; var xlet_startup_error = false; -var end_session_dialog = null; +var endSessionDialog = null; var gpuOffloadHelper = null; var gpu_offload_supported = false; @@ -1583,20 +1583,21 @@ function restartCinnamon(showOsd = false) { global.reexec_self(); } -function show_end_session_dialog(mode) { - if (end_session_dialog != null) { +function showEndSessionDialog(mode) { + if (endSessionDialog != null) { global.logWarning("End session dialog already exists"); return; } - end_session_dialog = new EndSessionDialog(mode); + endSessionDialog = new EndSessionDialog(mode); + endSessionDialog.open(); } -function close_end_session_dialog() { - if (end_session_dialog == null) { +function closeEndSessionDialog() { + if (endSessionDialog == null) { return; } - end_session_dialog.destroy(); - end_session_dialog = null; + endSessionDialog.close(); + endSessionDialog = null; }