@@ -11,6 +11,9 @@ public class Monitor.ProcessView : Granite.Bin {
1111 private ProcessInfoView process_info_view;
1212 private TreeViewModel treeview_model;
1313
14+ private SimpleAction end_action;
15+ private SimpleAction kill_action;
16+
1417 construct {
1518 treeview_model = new TreeViewModel ();
1619
@@ -47,11 +50,98 @@ public class Monitor.ProcessView : Granite.Bin {
4750 child = paned;
4851
4952 notify[" needle" ]. connect (filter_model. refilter);
53+
54+ kill_action = new SimpleAction (" kill" , null );
55+ kill_action. activate. connect (action_kill);
56+
57+ end_action = new SimpleAction (" end" , null );
58+ end_action. activate. connect (action_end);
59+
60+ var action_group = new SimpleActionGroup ();
61+ action_group. add_action (kill_action);
62+ action_group. add_action (end_action);
63+
64+ insert_action_group (" process" , action_group);
65+
66+ var key_controller = new Gtk .EventControllerKey ();
67+ key_controller. key_pressed. connect ((keyval, keycode, state) = > {
68+ if ((state & Gdk . ModifierType . CONTROL_MASK ) != 0 ) {
69+ switch (keyval) {
70+ case Gdk . Key . k:
71+ activate_action (" process.kill" , null );
72+ return Gdk . EVENT_STOP ;
73+ case Gdk . Key . e:
74+ activate_action (" process.end" , null );
75+ return Gdk . EVENT_STOP ;
76+ }
77+ }
78+
79+ return Gdk . EVENT_PROPAGATE ;
80+ });
81+
82+ add_controller (key_controller);
83+ }
84+
85+ private void action_end () {
86+ var confirmation_dialog = new Granite .MessageDialog (
87+ _(" Ask “%s ” to shut down?" ). printf (process_info_view. process. application_name),
88+ _(" The process will be asked to initiate shutdown tasks and close. In some cases the process may not quit." ),
89+ new ThemedIcon (" system-shutdown" ),
90+ Gtk . ButtonsType . CANCEL
91+ ) {
92+ badge_icon = new ThemedIcon (" dialog-question" ),
93+ modal = true ,
94+ transient_for = (Gtk . Window ) get_root ()
95+ };
96+
97+ var accept_button = confirmation_dialog.add_button (_ ("Shut Down "), Gtk.ResponseType.ACCEPT);
98+ accept_button.add_css_class (Granite .CssClass .SUGGESTED );
99+
100+ confirmation_dialog.response.connect ((response ) => {
101+ if (response == Gtk . ResponseType . ACCEPT ) {
102+ // TODO: maybe add a toast that process killed
103+ process_info_view. process. end ();
104+ }
105+
106+ confirmation_dialog. close ();
107+ });
108+
109+ confirmation_dialog.present ();
110+ }
111+
112+ private void action_kill () {
113+ var confirmation_dialog = new Granite .MessageDialog (
114+ _(" Force “%s ” to quit without initiating shutdown tasks?" ). printf (process_info_view. process. application_name),
115+ _(" This may lead to data loss. Only Force Quit if Shut Down has failed." ),
116+ new ThemedIcon (" computer-fail" ),
117+ Gtk . ButtonsType . CANCEL
118+ ) {
119+ badge_icon = new ThemedIcon (" process-stop" ),
120+ modal = true ,
121+ transient_for = (Gtk . Window ) get_root ()
122+ };
123+
124+ var accept_button = confirmation_dialog.add_button (_ ("Force Quit "), Gtk.ResponseType.ACCEPT);
125+ accept_button.add_css_class (Granite .CssClass .DESTRUCTIVE );
126+
127+ confirmation_dialog.response.connect ((response ) => {
128+ if (response == Gtk . ResponseType . ACCEPT ) {
129+ // @TODO: maybe add a toast that process killed
130+ process_info_view. process. kill ();
131+ }
132+
133+ confirmation_dialog. close ();
134+ });
135+
136+ confirmation_dialog.present ();
50137 }
51138
52139 public void on_process_selected (Process process) {
53140 process_info_view. process = process;
54141 process_info_view. visible = true ;
142+
143+ end_action. set_enabled (process. uid == Posix . getuid ());
144+ kill_action. set_enabled (process. uid == Posix . getuid ());
55145 }
56146
57147 public void update () {
0 commit comments