Line |
Branch |
Exec |
Source |
1 |
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- |
2 |
|
|
* |
3 |
|
|
* Copyright (C) 2010 Red Hat, Inc |
4 |
|
|
* Copyright (C) 2008 William Jon McCann <jmccann@redhat.com> |
5 |
|
|
* Copyright (C) 2010,2015 Richard Hughes <richard@hughsie.com> |
6 |
|
|
* |
7 |
|
|
* This program is free software; you can redistribute it and/or modify |
8 |
|
|
* it under the terms of the GNU General Public License as published by |
9 |
|
|
* the Free Software Foundation; either version 2 of the License, or |
10 |
|
|
* (at your option) any later version. |
11 |
|
|
* |
12 |
|
|
* This program is distributed in the hope that it will be useful, |
13 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 |
|
|
* GNU General Public License for more details. |
16 |
|
|
* |
17 |
|
|
* You should have received a copy of the GNU General Public License |
18 |
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>. |
19 |
|
|
* |
20 |
|
|
*/ |
21 |
|
|
|
22 |
|
|
#include <config.h> |
23 |
|
|
|
24 |
|
|
#include <libupower-glib/upower.h> |
25 |
|
|
#include <glib/gi18n.h> |
26 |
|
|
#include <gnome-settings-daemon/gsd-enums.h> |
27 |
|
|
#include <gio/gdesktopappinfo.h> |
28 |
|
|
|
29 |
|
|
#include "shell/cc-object-storage.h" |
30 |
|
|
#include "cc-list-row.h" |
31 |
|
|
#include "cc-battery-row.h" |
32 |
|
|
#include "cc-hostname.h" |
33 |
|
|
#include "cc-power-profile-row.h" |
34 |
|
|
#include "cc-power-profile-info-row.h" |
35 |
|
|
#include "cc-power-panel.h" |
36 |
|
|
#include "cc-power-resources.h" |
37 |
|
|
#include "cc-util.h" |
38 |
|
|
|
39 |
|
|
struct _CcPowerPanel |
40 |
|
|
{ |
41 |
|
|
CcPanel parent_instance; |
42 |
|
|
|
43 |
|
|
AdwSwitchRow *als_row; |
44 |
|
|
AdwDialog *automatic_suspend_dialog; |
45 |
|
|
CcListRow *automatic_suspend_row; |
46 |
|
|
GtkListBox *battery_listbox; |
47 |
|
|
AdwSwitchRow *battery_percentage_row; |
48 |
|
|
AdwPreferencesGroup *battery_section; |
49 |
|
|
AdwComboRow *blank_screen_row; |
50 |
|
|
GtkListBox *device_listbox; |
51 |
|
|
AdwPreferencesGroup *device_section; |
52 |
|
|
AdwSwitchRow *dim_screen_row; |
53 |
|
|
AdwPreferencesGroup *general_section; |
54 |
|
|
GtkListStore *mobile_time_liststore; |
55 |
|
|
AdwComboRow *power_button_row; |
56 |
|
|
GtkListBox *power_profile_listbox; |
57 |
|
|
GtkListBox *power_profile_info_listbox; |
58 |
|
|
AdwPreferencesGroup *power_profile_section; |
59 |
|
|
AdwSwitchRow *power_saver_low_battery_row; |
60 |
|
|
GtkComboBox *suspend_on_battery_delay_combo; |
61 |
|
|
AdwSwitchRow *suspend_on_battery_switch_row; |
62 |
|
|
GtkWidget *suspend_on_battery_group; |
63 |
|
|
GtkComboBox *suspend_on_ac_delay_combo; |
64 |
|
|
AdwSwitchRow *suspend_on_ac_switch_row; |
65 |
|
|
|
66 |
|
|
GSettings *gsd_settings; |
67 |
|
|
GSettings *session_settings; |
68 |
|
|
GSettings *interface_settings; |
69 |
|
|
UpClient *up_client; |
70 |
|
|
GPtrArray *devices; |
71 |
|
|
gboolean has_batteries; |
72 |
|
|
char *chassis_type; |
73 |
|
|
|
74 |
|
|
GDBusProxy *iio_proxy; |
75 |
|
|
guint iio_proxy_watch_id; |
76 |
|
|
gboolean has_brightness; |
77 |
|
|
|
78 |
|
|
GDBusProxy *power_profiles_proxy; |
79 |
|
|
guint power_profiles_prop_id; |
80 |
|
|
CcPowerProfileRow *power_profiles_row[NUM_CC_POWER_PROFILES]; |
81 |
|
|
gboolean power_profiles_in_update; |
82 |
|
|
gboolean has_performance_degraded; |
83 |
|
|
}; |
84 |
|
|
|
85 |
|
✗ |
CC_PANEL_REGISTER (CcPowerPanel, cc_power_panel) |
86 |
|
|
|
87 |
|
|
enum |
88 |
|
|
{ |
89 |
|
|
ACTION_MODEL_TEXT, |
90 |
|
|
ACTION_MODEL_VALUE |
91 |
|
|
}; |
92 |
|
|
|
93 |
|
|
static const char * |
94 |
|
✗ |
cc_power_panel_get_help_uri (CcPanel *panel) |
95 |
|
|
{ |
96 |
|
✗ |
return "help:gnome-help/power"; |
97 |
|
|
} |
98 |
|
|
|
99 |
|
|
static void |
100 |
|
✗ |
add_battery (CcPowerPanel *self, UpDevice *device, gboolean primary) |
101 |
|
|
{ |
102 |
|
✗ |
CcBatteryRow *row = cc_battery_row_new (device, primary); |
103 |
|
|
|
104 |
|
✗ |
gtk_list_box_append (self->battery_listbox, GTK_WIDGET (row)); |
105 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->battery_section), TRUE); |
106 |
|
✗ |
} |
107 |
|
|
|
108 |
|
|
static void |
109 |
|
✗ |
add_device (CcPowerPanel *self, UpDevice *device) |
110 |
|
|
{ |
111 |
|
✗ |
CcBatteryRow *row = cc_battery_row_new (device, FALSE); |
112 |
|
|
|
113 |
|
✗ |
gtk_list_box_append (self->device_listbox, GTK_WIDGET (row)); |
114 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->device_section), TRUE); |
115 |
|
✗ |
} |
116 |
|
|
|
117 |
|
|
static void |
118 |
|
✗ |
empty_listbox (GtkListBox *listbox) |
119 |
|
|
{ |
120 |
|
|
GtkWidget *child; |
121 |
|
|
|
122 |
|
✗ |
while ((child = gtk_widget_get_first_child (GTK_WIDGET (listbox))) != NULL) |
123 |
|
✗ |
gtk_list_box_remove (listbox, child); |
124 |
|
✗ |
} |
125 |
|
|
|
126 |
|
|
static void |
127 |
|
✗ |
update_power_saver_low_battery_row_visibility (CcPowerPanel *self) |
128 |
|
|
{ |
129 |
|
✗ |
g_autoptr(UpDevice) composite = NULL; |
130 |
|
|
UpDeviceKind kind; |
131 |
|
|
|
132 |
|
✗ |
composite = up_client_get_display_device (self->up_client); |
133 |
|
✗ |
g_object_get (composite, "kind", &kind, NULL); |
134 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->power_saver_low_battery_row), |
135 |
|
✗ |
self->power_profiles_proxy && kind == UP_DEVICE_KIND_BATTERY); |
136 |
|
✗ |
} |
137 |
|
|
|
138 |
|
|
static void |
139 |
|
✗ |
up_client_changed (CcPowerPanel *self) |
140 |
|
|
{ |
141 |
|
|
gint i; |
142 |
|
|
UpDeviceKind kind; |
143 |
|
|
guint n_batteries; |
144 |
|
|
gboolean on_ups; |
145 |
|
✗ |
g_autoptr(UpDevice) composite = NULL; |
146 |
|
|
|
147 |
|
✗ |
empty_listbox (self->battery_listbox); |
148 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->battery_section), FALSE); |
149 |
|
|
|
150 |
|
✗ |
empty_listbox (self->device_listbox); |
151 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->device_section), FALSE); |
152 |
|
|
|
153 |
|
✗ |
on_ups = FALSE; |
154 |
|
✗ |
n_batteries = 0; |
155 |
|
✗ |
composite = up_client_get_display_device (self->up_client); |
156 |
|
✗ |
g_object_get (composite, "kind", &kind, NULL); |
157 |
|
✗ |
if (kind == UP_DEVICE_KIND_UPS) |
158 |
|
|
{ |
159 |
|
✗ |
on_ups = TRUE; |
160 |
|
|
} |
161 |
|
|
else |
162 |
|
|
{ |
163 |
|
✗ |
gboolean is_extra_battery = FALSE; |
164 |
|
|
|
165 |
|
|
/* Count the batteries */ |
166 |
|
✗ |
for (i = 0; self->devices != NULL && i < self->devices->len; i++) |
167 |
|
|
{ |
168 |
|
✗ |
UpDevice *device = (UpDevice*) g_ptr_array_index (self->devices, i); |
169 |
|
✗ |
gboolean is_power_supply = FALSE; |
170 |
|
✗ |
g_object_get (device, |
171 |
|
|
"kind", &kind, |
172 |
|
|
"power-supply", &is_power_supply, |
173 |
|
|
NULL); |
174 |
|
✗ |
if (kind == UP_DEVICE_KIND_BATTERY && |
175 |
|
|
is_power_supply) |
176 |
|
|
{ |
177 |
|
✗ |
n_batteries++; |
178 |
|
✗ |
if (is_extra_battery == FALSE) |
179 |
|
|
{ |
180 |
|
✗ |
is_extra_battery = TRUE; |
181 |
|
✗ |
g_object_set_data (G_OBJECT (device), "is-main-battery", GINT_TO_POINTER(TRUE)); |
182 |
|
|
} |
183 |
|
|
} |
184 |
|
|
} |
185 |
|
|
} |
186 |
|
|
|
187 |
|
✗ |
if (n_batteries > 1) |
188 |
|
✗ |
adw_preferences_group_set_title (self->battery_section, _("Battery Levels")); |
189 |
|
✗ |
else if (on_ups) |
190 |
|
|
{ |
191 |
|
|
/* Translators: UPS is an Uninterruptible Power Supply: |
192 |
|
|
* https://en.wikipedia.org/wiki/Uninterruptible_power_supply */ |
193 |
|
✗ |
adw_preferences_group_set_title (self->battery_section, _("UPS")); |
194 |
|
|
} |
195 |
|
|
else |
196 |
|
✗ |
adw_preferences_group_set_title (self->battery_section, _("Battery Level")); |
197 |
|
|
|
198 |
|
✗ |
if (!on_ups && n_batteries > 1) |
199 |
|
✗ |
add_battery (self, composite, TRUE); |
200 |
|
|
|
201 |
|
✗ |
for (i = 0; self->devices != NULL && i < self->devices->len; i++) |
202 |
|
|
{ |
203 |
|
✗ |
UpDevice *device = (UpDevice*) g_ptr_array_index (self->devices, i); |
204 |
|
✗ |
gboolean is_power_supply = FALSE; |
205 |
|
✗ |
g_object_get (device, |
206 |
|
|
"kind", &kind, |
207 |
|
|
"power-supply", &is_power_supply, |
208 |
|
|
NULL); |
209 |
|
✗ |
if (kind == UP_DEVICE_KIND_LINE_POWER) |
210 |
|
|
{ |
211 |
|
|
/* do nothing */ |
212 |
|
|
} |
213 |
|
✗ |
else if (kind == UP_DEVICE_KIND_UPS && on_ups) |
214 |
|
|
{ |
215 |
|
✗ |
add_battery (self, device, TRUE); |
216 |
|
|
} |
217 |
|
✗ |
else if (kind == UP_DEVICE_KIND_BATTERY && is_power_supply && !on_ups && n_batteries == 1) |
218 |
|
|
{ |
219 |
|
✗ |
add_battery (self, device, TRUE); |
220 |
|
|
} |
221 |
|
✗ |
else if (kind == UP_DEVICE_KIND_BATTERY && is_power_supply) |
222 |
|
|
{ |
223 |
|
✗ |
add_battery (self, device, FALSE); |
224 |
|
|
} |
225 |
|
|
else |
226 |
|
|
{ |
227 |
|
✗ |
add_device (self, device); |
228 |
|
|
} |
229 |
|
|
} |
230 |
|
|
|
231 |
|
✗ |
update_power_saver_low_battery_row_visibility (self); |
232 |
|
✗ |
} |
233 |
|
|
|
234 |
|
|
static void |
235 |
|
✗ |
up_client_device_removed (CcPowerPanel *self, |
236 |
|
|
const char *object_path) |
237 |
|
|
{ |
238 |
|
|
guint i; |
239 |
|
|
|
240 |
|
✗ |
if (self->devices == NULL) |
241 |
|
✗ |
return; |
242 |
|
|
|
243 |
|
✗ |
for (i = 0; i < self->devices->len; i++) |
244 |
|
|
{ |
245 |
|
✗ |
UpDevice *device = g_ptr_array_index (self->devices, i); |
246 |
|
|
|
247 |
|
✗ |
if (g_strcmp0 (object_path, up_device_get_object_path (device)) == 0) |
248 |
|
|
{ |
249 |
|
✗ |
g_ptr_array_remove_index (self->devices, i); |
250 |
|
✗ |
break; |
251 |
|
|
} |
252 |
|
|
} |
253 |
|
|
|
254 |
|
✗ |
up_client_changed (self); |
255 |
|
|
} |
256 |
|
|
|
257 |
|
|
static void |
258 |
|
✗ |
up_client_device_added (CcPowerPanel *self, |
259 |
|
|
UpDevice *device) |
260 |
|
|
{ |
261 |
|
✗ |
g_ptr_array_add (self->devices, g_object_ref (device)); |
262 |
|
✗ |
g_signal_connect_object (G_OBJECT (device), "notify", |
263 |
|
|
G_CALLBACK (up_client_changed), self, G_CONNECT_SWAPPED); |
264 |
|
✗ |
up_client_changed (self); |
265 |
|
✗ |
} |
266 |
|
|
|
267 |
|
|
static void |
268 |
|
✗ |
als_row_changed_cb (CcPowerPanel *self) |
269 |
|
|
{ |
270 |
|
|
gboolean enabled; |
271 |
|
✗ |
enabled = adw_switch_row_get_active (self->als_row); |
272 |
|
✗ |
g_debug ("Setting ALS enabled %s", enabled ? "on" : "off"); |
273 |
|
✗ |
g_settings_set_boolean (self->gsd_settings, "ambient-enabled", enabled); |
274 |
|
✗ |
} |
275 |
|
|
|
276 |
|
|
static void |
277 |
|
✗ |
als_enabled_state_changed (CcPowerPanel *self) |
278 |
|
|
{ |
279 |
|
|
gboolean enabled; |
280 |
|
✗ |
gboolean visible = FALSE; |
281 |
|
|
|
282 |
|
✗ |
if (self->iio_proxy != NULL) |
283 |
|
|
{ |
284 |
|
✗ |
g_autoptr(GVariant) v = g_dbus_proxy_get_cached_property (self->iio_proxy, "HasAmbientLight"); |
285 |
|
✗ |
if (v != NULL) |
286 |
|
✗ |
visible = g_variant_get_boolean (v); |
287 |
|
|
} |
288 |
|
|
|
289 |
|
✗ |
if (gtk_widget_get_visible (GTK_WIDGET (self->als_row)) == visible) |
290 |
|
✗ |
return; |
291 |
|
|
|
292 |
|
✗ |
enabled = g_settings_get_boolean (self->gsd_settings, "ambient-enabled"); |
293 |
|
✗ |
g_debug ("ALS enabled: %s", enabled ? "on" : "off"); |
294 |
|
✗ |
g_signal_handlers_block_by_func (self->als_row, als_row_changed_cb, self); |
295 |
|
✗ |
adw_switch_row_set_active (self->als_row, enabled); |
296 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->als_row), visible && self->has_brightness); |
297 |
|
✗ |
g_signal_handlers_unblock_by_func (self->als_row, als_row_changed_cb, self); |
298 |
|
|
} |
299 |
|
|
|
300 |
|
|
static void |
301 |
|
✗ |
combo_time_changed_cb (CcPowerPanel *self, GtkWidget *widget) |
302 |
|
|
{ |
303 |
|
|
GtkTreeIter iter; |
304 |
|
|
GtkTreeModel *model; |
305 |
|
|
gint value; |
306 |
|
|
gboolean ret; |
307 |
|
✗ |
const gchar *key = (const gchar *)g_object_get_data (G_OBJECT(widget), "_gsettings_key"); |
308 |
|
|
|
309 |
|
|
/* no selection */ |
310 |
|
✗ |
ret = gtk_combo_box_get_active_iter (GTK_COMBO_BOX(widget), &iter); |
311 |
|
✗ |
if (!ret) |
312 |
|
✗ |
return; |
313 |
|
|
|
314 |
|
|
/* get entry */ |
315 |
|
✗ |
model = gtk_combo_box_get_model (GTK_COMBO_BOX(widget)); |
316 |
|
✗ |
gtk_tree_model_get (model, &iter, |
317 |
|
|
1, &value, |
318 |
|
|
-1); |
319 |
|
|
|
320 |
|
|
/* set both keys */ |
321 |
|
✗ |
g_settings_set_int (self->gsd_settings, key, value); |
322 |
|
|
} |
323 |
|
|
|
324 |
|
|
static void |
325 |
|
✗ |
set_value_for_combo (GtkComboBox *combo_box, gint value) |
326 |
|
|
{ |
327 |
|
|
GtkTreeIter iter; |
328 |
|
✗ |
g_autoptr(GtkTreeIter) insert = NULL; |
329 |
|
|
GtkTreeIter new; |
330 |
|
|
GtkTreeModel *model; |
331 |
|
|
gint value_tmp; |
332 |
|
✗ |
gint value_last = 0; |
333 |
|
✗ |
g_autofree gchar *text = NULL; |
334 |
|
|
gboolean ret; |
335 |
|
|
|
336 |
|
|
/* get entry */ |
337 |
|
✗ |
model = gtk_combo_box_get_model (combo_box); |
338 |
|
✗ |
ret = gtk_tree_model_get_iter_first (model, &iter); |
339 |
|
✗ |
if (!ret) |
340 |
|
✗ |
return; |
341 |
|
|
|
342 |
|
|
/* try to make the UI match the setting */ |
343 |
|
|
do |
344 |
|
|
{ |
345 |
|
✗ |
gtk_tree_model_get (model, &iter, |
346 |
|
|
ACTION_MODEL_VALUE, &value_tmp, |
347 |
|
|
-1); |
348 |
|
✗ |
if (value_tmp == value) |
349 |
|
|
{ |
350 |
|
✗ |
gtk_combo_box_set_active_iter (combo_box, &iter); |
351 |
|
✗ |
return; |
352 |
|
|
} |
353 |
|
|
|
354 |
|
|
/* Insert before if the next value is larger or the value is lower |
355 |
|
|
* again (i.e. "Never" is zero and last). */ |
356 |
|
✗ |
if (!insert && (value_tmp > value || value_last > value_tmp)) |
357 |
|
✗ |
insert = gtk_tree_iter_copy (&iter); |
358 |
|
|
|
359 |
|
✗ |
value_last = value_tmp; |
360 |
|
✗ |
} while (gtk_tree_model_iter_next (model, &iter)); |
361 |
|
|
|
362 |
|
|
/* The value is not listed, so add it at the best point (or the end). */ |
363 |
|
✗ |
gtk_list_store_insert_before (GTK_LIST_STORE (model), &new, insert); |
364 |
|
|
|
365 |
|
✗ |
text = cc_util_time_to_string_text (value * 1000); |
366 |
|
✗ |
gtk_list_store_set (GTK_LIST_STORE (model), &new, |
367 |
|
|
ACTION_MODEL_TEXT, text, |
368 |
|
|
ACTION_MODEL_VALUE, value, |
369 |
|
|
-1); |
370 |
|
✗ |
gtk_combo_box_set_active_iter (combo_box, &new); |
371 |
|
|
} |
372 |
|
|
|
373 |
|
|
static void |
374 |
|
✗ |
set_value_for_combo_row (AdwComboRow *combo_row, gint value) |
375 |
|
|
{ |
376 |
|
✗ |
g_autoptr (GObject) new_item = NULL; |
377 |
|
✗ |
gboolean insert = FALSE; |
378 |
|
✗ |
guint insert_before = 0; |
379 |
|
|
guint i; |
380 |
|
|
GListModel *model; |
381 |
|
✗ |
gint value_last = 0; |
382 |
|
✗ |
g_autofree gchar *text = NULL; |
383 |
|
|
|
384 |
|
|
/* try to make the UI match the setting */ |
385 |
|
✗ |
model = adw_combo_row_get_model (combo_row); |
386 |
|
✗ |
for (i = 0; i < g_list_model_get_n_items (model); i++) |
387 |
|
|
{ |
388 |
|
✗ |
g_autoptr (GObject) item = g_list_model_get_item (model, i); |
389 |
|
✗ |
gint value_tmp = GPOINTER_TO_UINT (g_object_get_data (item, "value")); |
390 |
|
✗ |
if (value_tmp == value) |
391 |
|
|
{ |
392 |
|
✗ |
adw_combo_row_set_selected (combo_row, i); |
393 |
|
✗ |
return; |
394 |
|
|
} |
395 |
|
|
|
396 |
|
|
/* Insert before if the next value is larger or the value is lower |
397 |
|
|
* again (i.e. "Never" is zero and last). */ |
398 |
|
✗ |
if (!insert && (value_tmp > value || value_last > value_tmp)) |
399 |
|
|
{ |
400 |
|
✗ |
insert = TRUE; |
401 |
|
✗ |
insert_before = i; |
402 |
|
|
} |
403 |
|
|
|
404 |
|
✗ |
value_last = value_tmp; |
405 |
|
|
} |
406 |
|
|
|
407 |
|
|
/* The value is not listed, so add it at the best point (or the end). */ |
408 |
|
✗ |
text = cc_util_time_to_string_text (value * 1000); |
409 |
|
✗ |
gtk_string_list_append (GTK_STRING_LIST (model), text); |
410 |
|
|
|
411 |
|
✗ |
new_item = g_list_model_get_item (model, i); |
412 |
|
✗ |
g_object_set_data (G_OBJECT (new_item), "value", GUINT_TO_POINTER (value)); |
413 |
|
|
|
414 |
|
✗ |
adw_combo_row_set_selected (combo_row, insert_before); |
415 |
|
|
} |
416 |
|
|
|
417 |
|
|
static void |
418 |
|
✗ |
set_ac_battery_ui_mode (CcPowerPanel *self) |
419 |
|
|
{ |
420 |
|
|
GPtrArray *devices; |
421 |
|
|
guint i; |
422 |
|
|
|
423 |
|
✗ |
self->has_batteries = FALSE; |
424 |
|
✗ |
devices = up_client_get_devices2 (self->up_client); |
425 |
|
✗ |
g_debug ("got %d devices from upower\n", devices ? devices->len : 0); |
426 |
|
|
|
427 |
|
✗ |
for (i = 0; devices != NULL && i < devices->len; i++) |
428 |
|
|
{ |
429 |
|
|
UpDevice *device; |
430 |
|
|
gboolean is_power_supply; |
431 |
|
|
UpDeviceKind kind; |
432 |
|
|
|
433 |
|
✗ |
device = g_ptr_array_index (devices, i); |
434 |
|
✗ |
g_object_get (device, |
435 |
|
|
"kind", &kind, |
436 |
|
|
"power-supply", &is_power_supply, |
437 |
|
|
NULL); |
438 |
|
✗ |
if (kind == UP_DEVICE_KIND_UPS || |
439 |
|
✗ |
(kind == UP_DEVICE_KIND_BATTERY && is_power_supply)) |
440 |
|
|
{ |
441 |
|
✗ |
self->has_batteries = TRUE; |
442 |
|
✗ |
break; |
443 |
|
|
} |
444 |
|
|
} |
445 |
|
✗ |
g_clear_pointer (&devices, g_ptr_array_unref); |
446 |
|
|
|
447 |
|
✗ |
if (!self->has_batteries) |
448 |
|
|
{ |
449 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->suspend_on_battery_group), FALSE); |
450 |
|
✗ |
adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self->suspend_on_ac_switch_row), _("When _Idle")); |
451 |
|
|
} |
452 |
|
✗ |
} |
453 |
|
|
|
454 |
|
|
static gboolean |
455 |
|
✗ |
keynav_failed_cb (CcPowerPanel *self, GtkDirectionType direction, GtkWidget *list) |
456 |
|
|
{ |
457 |
|
✗ |
if (direction != GTK_DIR_UP && direction != GTK_DIR_DOWN) |
458 |
|
✗ |
return FALSE; |
459 |
|
|
|
460 |
|
✗ |
direction = GTK_DIR_UP ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD; |
461 |
|
|
|
462 |
|
✗ |
return gtk_widget_child_focus (GTK_WIDGET (self), direction); |
463 |
|
|
} |
464 |
|
|
|
465 |
|
|
static void |
466 |
|
✗ |
blank_screen_row_changed_cb (CcPowerPanel *self) |
467 |
|
|
{ |
468 |
|
✗ |
g_autoptr (GObject) item = NULL; |
469 |
|
|
GListModel *model; |
470 |
|
|
gint selected_index; |
471 |
|
|
gint value; |
472 |
|
|
|
473 |
|
✗ |
model = adw_combo_row_get_model (self->blank_screen_row); |
474 |
|
✗ |
selected_index = adw_combo_row_get_selected (self->blank_screen_row); |
475 |
|
✗ |
if (selected_index == -1) |
476 |
|
✗ |
return; |
477 |
|
|
|
478 |
|
✗ |
item = g_list_model_get_item (model, selected_index); |
479 |
|
✗ |
value = GPOINTER_TO_UINT (g_object_get_data (item, "value")); |
480 |
|
|
|
481 |
|
✗ |
g_settings_set_uint (self->session_settings, "idle-delay", value); |
482 |
|
|
} |
483 |
|
|
|
484 |
|
|
static void |
485 |
|
✗ |
power_button_row_changed_cb (CcPowerPanel *self) |
486 |
|
|
{ |
487 |
|
✗ |
g_autoptr (GObject) item = NULL; |
488 |
|
|
GListModel *model; |
489 |
|
|
gint selected_index; |
490 |
|
|
gint value; |
491 |
|
|
|
492 |
|
✗ |
model = adw_combo_row_get_model (self->power_button_row); |
493 |
|
✗ |
selected_index = adw_combo_row_get_selected (self->power_button_row); |
494 |
|
✗ |
if (selected_index == -1) |
495 |
|
✗ |
return; |
496 |
|
|
|
497 |
|
✗ |
item = g_list_model_get_item (model, selected_index); |
498 |
|
✗ |
value = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (item), "value")); |
499 |
|
|
|
500 |
|
✗ |
g_settings_set_enum (self->gsd_settings, "power-button-action", value); |
501 |
|
|
} |
502 |
|
|
|
503 |
|
|
static void |
504 |
|
✗ |
als_enabled_setting_changed (CcPowerPanel *self) |
505 |
|
|
{ |
506 |
|
✗ |
als_enabled_state_changed (self); |
507 |
|
✗ |
} |
508 |
|
|
|
509 |
|
|
static void |
510 |
|
✗ |
iio_proxy_appeared_cb (GDBusConnection *connection, |
511 |
|
|
const gchar *name, |
512 |
|
|
const gchar *name_owner, |
513 |
|
|
gpointer user_data) |
514 |
|
|
{ |
515 |
|
✗ |
CcPowerPanel *self = CC_POWER_PANEL (user_data); |
516 |
|
✗ |
g_autoptr(GError) error = NULL; |
517 |
|
|
|
518 |
|
✗ |
self->iio_proxy = |
519 |
|
✗ |
cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SYSTEM, |
520 |
|
|
G_DBUS_PROXY_FLAGS_NONE, |
521 |
|
|
"net.hadess.SensorProxy", |
522 |
|
|
"/net/hadess/SensorProxy", |
523 |
|
|
"net.hadess.SensorProxy", |
524 |
|
|
NULL, &error); |
525 |
|
✗ |
if (error != NULL) |
526 |
|
|
{ |
527 |
|
✗ |
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
528 |
|
✗ |
g_warning ("Could not create IIO sensor proxy: %s", error->message); |
529 |
|
✗ |
return; |
530 |
|
|
} |
531 |
|
|
|
532 |
|
✗ |
g_signal_connect_object (G_OBJECT (self->iio_proxy), "g-properties-changed", |
533 |
|
|
G_CALLBACK (als_enabled_state_changed), self, |
534 |
|
|
G_CONNECT_SWAPPED); |
535 |
|
✗ |
als_enabled_state_changed (self); |
536 |
|
|
} |
537 |
|
|
|
538 |
|
|
static void |
539 |
|
✗ |
iio_proxy_vanished_cb (GDBusConnection *connection, |
540 |
|
|
const gchar *name, |
541 |
|
|
gpointer user_data) |
542 |
|
|
{ |
543 |
|
✗ |
CcPowerPanel *self = CC_POWER_PANEL (user_data); |
544 |
|
✗ |
g_clear_object (&self->iio_proxy); |
545 |
|
✗ |
als_enabled_state_changed (self); |
546 |
|
✗ |
} |
547 |
|
|
|
548 |
|
|
static gboolean |
549 |
|
✗ |
get_sleep_type (GValue *value, |
550 |
|
|
GVariant *variant, |
551 |
|
|
gpointer data) |
552 |
|
|
{ |
553 |
|
|
gboolean enabled; |
554 |
|
|
|
555 |
|
✗ |
if (g_strcmp0 (g_variant_get_string (variant, NULL), "nothing") == 0) |
556 |
|
✗ |
enabled = FALSE; |
557 |
|
|
else |
558 |
|
✗ |
enabled = TRUE; |
559 |
|
|
|
560 |
|
✗ |
g_value_set_boolean (value, enabled); |
561 |
|
|
|
562 |
|
✗ |
return TRUE; |
563 |
|
|
} |
564 |
|
|
|
565 |
|
|
static GVariant * |
566 |
|
✗ |
set_sleep_type (const GValue *value, |
567 |
|
|
const GVariantType *expected_type, |
568 |
|
|
gpointer data) |
569 |
|
|
{ |
570 |
|
|
GVariant *res; |
571 |
|
|
|
572 |
|
✗ |
if (g_value_get_boolean (value)) |
573 |
|
✗ |
res = g_variant_new_string ("suspend"); |
574 |
|
|
else |
575 |
|
✗ |
res = g_variant_new_string ("nothing"); |
576 |
|
|
|
577 |
|
✗ |
return res; |
578 |
|
|
} |
579 |
|
|
|
580 |
|
|
static void |
581 |
|
✗ |
populate_power_button_row (AdwComboRow *combo_row, |
582 |
|
|
gboolean can_suspend, |
583 |
|
|
gboolean can_hibernate) |
584 |
|
|
{ |
585 |
|
✗ |
g_autoptr (GtkStringList) string_list = NULL; |
586 |
|
|
struct { |
587 |
|
|
char *name; |
588 |
|
|
GsdPowerButtonActionType value; |
589 |
|
✗ |
} actions[] = { |
590 |
|
|
{ N_("Suspend"), GSD_POWER_BUTTON_ACTION_SUSPEND }, |
591 |
|
|
{ N_("Power Off"), GSD_POWER_BUTTON_ACTION_INTERACTIVE }, |
592 |
|
|
{ N_("Hibernate"), GSD_POWER_BUTTON_ACTION_HIBERNATE }, |
593 |
|
|
{ N_("Nothing"), GSD_POWER_BUTTON_ACTION_NOTHING } |
594 |
|
|
}; |
595 |
|
✗ |
guint item_index = 0; |
596 |
|
|
guint i; |
597 |
|
|
|
598 |
|
✗ |
string_list = gtk_string_list_new (NULL); |
599 |
|
✗ |
for (i = 0; i < G_N_ELEMENTS (actions); i++) |
600 |
|
|
{ |
601 |
|
✗ |
g_autoptr (GObject) item = NULL; |
602 |
|
|
|
603 |
|
✗ |
if (!can_suspend && actions[i].value == GSD_POWER_BUTTON_ACTION_SUSPEND) |
604 |
|
✗ |
continue; |
605 |
|
|
|
606 |
|
✗ |
if (!can_hibernate && actions[i].value == GSD_POWER_BUTTON_ACTION_HIBERNATE) |
607 |
|
✗ |
continue; |
608 |
|
|
|
609 |
|
✗ |
gtk_string_list_append (string_list, _(actions[i].name)); |
610 |
|
|
|
611 |
|
✗ |
item = g_list_model_get_item (G_LIST_MODEL (string_list), item_index++); |
612 |
|
✗ |
g_object_set_data (item, "value", GUINT_TO_POINTER (actions[i].value)); |
613 |
|
|
} |
614 |
|
|
|
615 |
|
✗ |
adw_combo_row_set_model (combo_row, G_LIST_MODEL (string_list)); |
616 |
|
✗ |
} |
617 |
|
|
|
618 |
|
|
#define NEVER 0 |
619 |
|
|
|
620 |
|
|
static void |
621 |
|
✗ |
update_automatic_suspend_label (CcPowerPanel *self) |
622 |
|
|
{ |
623 |
|
|
GsdPowerActionType ac_action; |
624 |
|
|
GsdPowerActionType battery_action; |
625 |
|
|
gint ac_timeout; |
626 |
|
|
gint battery_timeout; |
627 |
|
|
const gchar *s; |
628 |
|
|
|
629 |
|
✗ |
ac_action = g_settings_get_enum (self->gsd_settings, "sleep-inactive-ac-type"); |
630 |
|
✗ |
battery_action = g_settings_get_enum (self->gsd_settings, "sleep-inactive-battery-type"); |
631 |
|
✗ |
ac_timeout = g_settings_get_int (self->gsd_settings, "sleep-inactive-ac-timeout"); |
632 |
|
✗ |
battery_timeout = g_settings_get_int (self->gsd_settings, "sleep-inactive-battery-timeout"); |
633 |
|
|
|
634 |
|
✗ |
if (ac_timeout < 0) |
635 |
|
✗ |
g_warning ("Invalid negative timeout for 'sleep-inactive-ac-timeout': %d", ac_timeout); |
636 |
|
✗ |
if (battery_timeout < 0) |
637 |
|
✗ |
g_warning ("Invalid negative timeout for 'sleep-inactive-battery-timeout': %d", battery_timeout); |
638 |
|
|
|
639 |
|
✗ |
if (ac_action == GSD_POWER_ACTION_NOTHING || ac_timeout < 0) |
640 |
|
✗ |
ac_timeout = NEVER; |
641 |
|
✗ |
if (battery_action == GSD_POWER_ACTION_NOTHING || battery_timeout < 0) |
642 |
|
✗ |
battery_timeout = NEVER; |
643 |
|
|
|
644 |
|
✗ |
if (self->has_batteries) |
645 |
|
|
{ |
646 |
|
✗ |
if (ac_timeout == NEVER && battery_timeout == NEVER) |
647 |
|
✗ |
s = _("Off"); |
648 |
|
✗ |
else if (ac_timeout == NEVER && battery_timeout > 0) |
649 |
|
✗ |
s = _("On Battery Power"); |
650 |
|
✗ |
else if (ac_timeout > 0 && battery_timeout == NEVER) |
651 |
|
✗ |
s = _("When Plugged In"); |
652 |
|
|
else |
653 |
|
✗ |
s = _("On"); |
654 |
|
|
} |
655 |
|
|
else |
656 |
|
|
{ |
657 |
|
✗ |
if (ac_timeout == NEVER) |
658 |
|
✗ |
s = _("Off"); |
659 |
|
|
else |
660 |
|
✗ |
s = _("On"); |
661 |
|
|
} |
662 |
|
|
|
663 |
|
✗ |
cc_list_row_set_secondary_label (self->automatic_suspend_row, s); |
664 |
|
✗ |
} |
665 |
|
|
|
666 |
|
|
static void |
667 |
|
✗ |
on_suspend_settings_changed (CcPowerPanel *self, |
668 |
|
|
const char *key) |
669 |
|
|
{ |
670 |
|
✗ |
if (g_str_has_prefix (key, "sleep-inactive-")) |
671 |
|
|
{ |
672 |
|
✗ |
update_automatic_suspend_label (self); |
673 |
|
|
} |
674 |
|
✗ |
} |
675 |
|
|
|
676 |
|
|
static gboolean |
677 |
|
✗ |
can_suspend_or_hibernate (CcPowerPanel *self, |
678 |
|
|
const char *method_name) |
679 |
|
|
{ |
680 |
|
✗ |
g_autoptr(GDBusConnection) connection = NULL; |
681 |
|
✗ |
g_autoptr(GVariant) variant = NULL; |
682 |
|
✗ |
g_autoptr(GError) error = NULL; |
683 |
|
|
const char *s; |
684 |
|
|
|
685 |
|
✗ |
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, |
686 |
|
|
cc_panel_get_cancellable (CC_PANEL (self)), |
687 |
|
|
&error); |
688 |
|
✗ |
if (!connection) |
689 |
|
|
{ |
690 |
|
✗ |
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
691 |
|
✗ |
g_warning ("system bus not available: %s", error->message); |
692 |
|
✗ |
return FALSE; |
693 |
|
|
} |
694 |
|
|
|
695 |
|
✗ |
variant = g_dbus_connection_call_sync (connection, |
696 |
|
|
"org.freedesktop.login1", |
697 |
|
|
"/org/freedesktop/login1", |
698 |
|
|
"org.freedesktop.login1.Manager", |
699 |
|
|
method_name, |
700 |
|
|
NULL, |
701 |
|
|
NULL, |
702 |
|
|
G_DBUS_CALL_FLAGS_NONE, |
703 |
|
|
-1, |
704 |
|
|
cc_panel_get_cancellable (CC_PANEL (self)), |
705 |
|
|
&error); |
706 |
|
|
|
707 |
|
✗ |
if (!variant) |
708 |
|
|
{ |
709 |
|
✗ |
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
710 |
|
✗ |
g_debug ("Failed to call %s(): %s", method_name, error->message); |
711 |
|
✗ |
return FALSE; |
712 |
|
|
} |
713 |
|
|
|
714 |
|
✗ |
g_variant_get (variant, "(&s)", &s); |
715 |
|
✗ |
return g_strcmp0 (s, "yes") == 0; |
716 |
|
|
} |
717 |
|
|
|
718 |
|
|
static void |
719 |
|
✗ |
got_brightness_cb (GObject *source_object, |
720 |
|
|
GAsyncResult *res, |
721 |
|
|
gpointer user_data) |
722 |
|
|
{ |
723 |
|
✗ |
g_autoptr(GVariant) result = NULL; |
724 |
|
✗ |
g_autoptr(GError) error = NULL; |
725 |
|
✗ |
gint32 brightness = -1.0; |
726 |
|
|
CcPowerPanel *self; |
727 |
|
|
|
728 |
|
✗ |
result = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), res, &error); |
729 |
|
✗ |
if (!result) |
730 |
|
|
{ |
731 |
|
✗ |
g_debug ("Failed to get Brightness property: %s", error->message); |
732 |
|
✗ |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
733 |
|
✗ |
return; |
734 |
|
|
} |
735 |
|
|
else |
736 |
|
|
{ |
737 |
|
✗ |
g_autoptr(GVariant) v = NULL; |
738 |
|
✗ |
g_variant_get (result, "(v)", &v); |
739 |
|
✗ |
brightness = v ? g_variant_get_int32 (v) : -1.0; |
740 |
|
|
} |
741 |
|
|
|
742 |
|
✗ |
self = user_data; |
743 |
|
✗ |
self->has_brightness = brightness >= 0.0; |
744 |
|
|
|
745 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->dim_screen_row), self->has_brightness); |
746 |
|
✗ |
als_enabled_state_changed (self); |
747 |
|
|
} |
748 |
|
|
|
749 |
|
|
static void |
750 |
|
✗ |
populate_blank_screen_row (AdwComboRow *combo_row) |
751 |
|
|
{ |
752 |
|
✗ |
g_autoptr (GtkStringList) string_list = NULL; |
753 |
|
✗ |
g_autoptr (GObject) never_object = NULL; |
754 |
|
✗ |
gint minutes[] = { 1, 2, 3, 4, 5, 8, 10, 12, 15 }; |
755 |
|
|
guint i; |
756 |
|
|
|
757 |
|
✗ |
string_list = gtk_string_list_new (NULL); |
758 |
|
✗ |
for (i = 0; i < G_N_ELEMENTS (minutes); i++) |
759 |
|
|
{ |
760 |
|
✗ |
g_autoptr (GObject) item = NULL; |
761 |
|
✗ |
g_autofree gchar *text = NULL; |
762 |
|
|
|
763 |
|
|
/* Translators: Option for "Blank Screen" in "Power" panel */ |
764 |
|
✗ |
text = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, "%d minute", "%d minutes", minutes[i]), minutes[i]); |
765 |
|
✗ |
gtk_string_list_append (string_list, text); |
766 |
|
|
|
767 |
|
✗ |
item = g_list_model_get_item (G_LIST_MODEL (string_list), i); |
768 |
|
✗ |
g_object_set_data (item, "value", GUINT_TO_POINTER (minutes[i] * 60)); |
769 |
|
|
} |
770 |
|
|
|
771 |
|
✗ |
gtk_string_list_append (string_list, C_("Idle time", "Never")); |
772 |
|
✗ |
never_object = g_list_model_get_item (G_LIST_MODEL (string_list), i); |
773 |
|
✗ |
g_object_set_data (never_object, "value", GUINT_TO_POINTER (0)); |
774 |
|
|
|
775 |
|
✗ |
adw_combo_row_set_model (combo_row, G_LIST_MODEL (string_list)); |
776 |
|
✗ |
} |
777 |
|
|
|
778 |
|
|
static void |
779 |
|
✗ |
setup_power_saving (CcPowerPanel *self) |
780 |
|
|
{ |
781 |
|
✗ |
g_autoptr(GDBusConnection) connection = NULL; |
782 |
|
✗ |
g_autoptr(GError) error = NULL; |
783 |
|
|
int value; |
784 |
|
|
|
785 |
|
|
/* ambient light sensor */ |
786 |
|
✗ |
self->iio_proxy_watch_id = |
787 |
|
✗ |
g_bus_watch_name (G_BUS_TYPE_SYSTEM, |
788 |
|
|
"net.hadess.SensorProxy", |
789 |
|
|
G_BUS_NAME_WATCHER_FLAGS_NONE, |
790 |
|
|
iio_proxy_appeared_cb, |
791 |
|
|
iio_proxy_vanished_cb, |
792 |
|
|
self, NULL); |
793 |
|
✗ |
g_signal_connect_object (self->gsd_settings, "changed", |
794 |
|
|
G_CALLBACK (als_enabled_setting_changed), self, G_CONNECT_SWAPPED); |
795 |
|
|
|
796 |
|
✗ |
connection = g_bus_get_sync (G_BUS_TYPE_SESSION, |
797 |
|
|
cc_panel_get_cancellable (CC_PANEL (self)), |
798 |
|
|
&error); |
799 |
|
✗ |
if (connection) |
800 |
|
|
{ |
801 |
|
✗ |
g_dbus_connection_call (connection, |
802 |
|
|
"org.gnome.SettingsDaemon.Power", |
803 |
|
|
"/org/gnome/SettingsDaemon/Power", |
804 |
|
|
"org.freedesktop.DBus.Properties", |
805 |
|
|
"Get", |
806 |
|
|
g_variant_new ("(ss)", |
807 |
|
|
"org.gnome.SettingsDaemon.Power.Screen", |
808 |
|
|
"Brightness"), |
809 |
|
|
NULL, |
810 |
|
|
G_DBUS_CALL_FLAGS_NONE, |
811 |
|
|
-1, |
812 |
|
|
cc_panel_get_cancellable (CC_PANEL (self)), |
813 |
|
|
got_brightness_cb, |
814 |
|
|
self); |
815 |
|
|
} |
816 |
|
|
else |
817 |
|
|
{ |
818 |
|
✗ |
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
819 |
|
✗ |
g_warning ("session bus not available: %s", error->message); |
820 |
|
|
} |
821 |
|
|
|
822 |
|
|
|
823 |
|
✗ |
g_settings_bind (self->gsd_settings, "idle-dim", |
824 |
|
✗ |
self->dim_screen_row, "active", |
825 |
|
|
G_SETTINGS_BIND_DEFAULT); |
826 |
|
|
|
827 |
|
✗ |
g_signal_handlers_block_by_func (self->blank_screen_row, blank_screen_row_changed_cb, self); |
828 |
|
✗ |
populate_blank_screen_row (self->blank_screen_row); |
829 |
|
✗ |
value = g_settings_get_uint (self->session_settings, "idle-delay"); |
830 |
|
✗ |
set_value_for_combo_row (self->blank_screen_row, value); |
831 |
|
✗ |
g_signal_handlers_unblock_by_func (self->blank_screen_row, blank_screen_row_changed_cb, self); |
832 |
|
|
|
833 |
|
|
/* The default values for these settings are unfortunate for us; |
834 |
|
|
* timeout == 0, action == suspend means 'do nothing' - just |
835 |
|
|
* as timout === anything, action == nothing. |
836 |
|
|
* For our switch/combobox combination, the second choice works |
837 |
|
|
* much better, so translate the first to the second here. |
838 |
|
|
*/ |
839 |
|
✗ |
if (g_settings_get_int (self->gsd_settings, "sleep-inactive-ac-timeout") == 0) |
840 |
|
|
{ |
841 |
|
✗ |
g_settings_set_enum (self->gsd_settings, "sleep-inactive-ac-type", GSD_POWER_ACTION_NOTHING); |
842 |
|
✗ |
g_settings_set_int (self->gsd_settings, "sleep-inactive-ac-timeout", 3600); |
843 |
|
|
} |
844 |
|
✗ |
if (g_settings_get_int (self->gsd_settings, "sleep-inactive-battery-timeout") == 0) |
845 |
|
|
{ |
846 |
|
✗ |
g_settings_set_enum (self->gsd_settings, "sleep-inactive-battery-type", GSD_POWER_ACTION_NOTHING); |
847 |
|
✗ |
g_settings_set_int (self->gsd_settings, "sleep-inactive-battery-timeout", 1800); |
848 |
|
|
} |
849 |
|
|
|
850 |
|
|
/* Automatic suspend row */ |
851 |
|
✗ |
if (can_suspend_or_hibernate (self, "CanSuspend") && |
852 |
|
✗ |
g_strcmp0 (self->chassis_type, "vm") != 0) |
853 |
|
|
{ |
854 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->automatic_suspend_row), TRUE); |
855 |
|
|
|
856 |
|
✗ |
g_signal_connect_object (self->gsd_settings, "changed", G_CALLBACK (on_suspend_settings_changed), self, G_CONNECT_SWAPPED); |
857 |
|
|
|
858 |
|
✗ |
g_settings_bind_with_mapping (self->gsd_settings, "sleep-inactive-battery-type", |
859 |
|
✗ |
self->suspend_on_battery_switch_row, "active", |
860 |
|
|
G_SETTINGS_BIND_DEFAULT, |
861 |
|
|
get_sleep_type, set_sleep_type, NULL, NULL); |
862 |
|
|
|
863 |
|
✗ |
g_object_set_data (G_OBJECT (self->suspend_on_battery_delay_combo), "_gsettings_key", "sleep-inactive-battery-timeout"); |
864 |
|
✗ |
value = g_settings_get_int (self->gsd_settings, "sleep-inactive-battery-timeout"); |
865 |
|
✗ |
set_value_for_combo (self->suspend_on_battery_delay_combo, value); |
866 |
|
✗ |
g_signal_connect_object (self->suspend_on_battery_delay_combo, "changed", |
867 |
|
|
G_CALLBACK (combo_time_changed_cb), self, G_CONNECT_SWAPPED); |
868 |
|
✗ |
g_object_bind_property (self->suspend_on_battery_switch_row, "active", self->suspend_on_battery_delay_combo, "sensitive", |
869 |
|
|
G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE); |
870 |
|
|
|
871 |
|
✗ |
g_settings_bind_with_mapping (self->gsd_settings, "sleep-inactive-ac-type", |
872 |
|
✗ |
self->suspend_on_ac_switch_row, "active", |
873 |
|
|
G_SETTINGS_BIND_DEFAULT, |
874 |
|
|
get_sleep_type, set_sleep_type, NULL, NULL); |
875 |
|
|
|
876 |
|
✗ |
g_object_set_data (G_OBJECT (self->suspend_on_ac_delay_combo), "_gsettings_key", "sleep-inactive-ac-timeout"); |
877 |
|
✗ |
value = g_settings_get_int (self->gsd_settings, "sleep-inactive-ac-timeout"); |
878 |
|
✗ |
set_value_for_combo (self->suspend_on_ac_delay_combo, value); |
879 |
|
✗ |
g_signal_connect_object (self->suspend_on_ac_delay_combo, "changed", |
880 |
|
|
G_CALLBACK (combo_time_changed_cb), self, G_CONNECT_SWAPPED); |
881 |
|
✗ |
g_object_bind_property (self->suspend_on_ac_switch_row, "active", self->suspend_on_ac_delay_combo, "sensitive", |
882 |
|
|
G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE); |
883 |
|
|
|
884 |
|
✗ |
set_ac_battery_ui_mode (self); |
885 |
|
✗ |
update_automatic_suspend_label (self); |
886 |
|
|
} |
887 |
|
✗ |
} |
888 |
|
|
|
889 |
|
|
static const char * |
890 |
|
✗ |
variant_lookup_string (GVariant *dict, |
891 |
|
|
const char *key) |
892 |
|
|
{ |
893 |
|
|
GVariant *variant; |
894 |
|
|
|
895 |
|
✗ |
variant = g_variant_lookup_value (dict, key, G_VARIANT_TYPE_STRING); |
896 |
|
✗ |
if (!variant) |
897 |
|
✗ |
return NULL; |
898 |
|
✗ |
return g_variant_get_string (variant, NULL); |
899 |
|
|
} |
900 |
|
|
|
901 |
|
|
static void |
902 |
|
✗ |
performance_profile_set_active (CcPowerPanel *self, |
903 |
|
|
const char *profile_str) |
904 |
|
|
{ |
905 |
|
✗ |
CcPowerProfile profile = cc_power_profile_from_str (profile_str); |
906 |
|
|
GtkCheckButton *button; |
907 |
|
|
|
908 |
|
✗ |
button = cc_power_profile_row_get_radio_button (CC_POWER_PROFILE_ROW (self->power_profiles_row[profile])); |
909 |
|
✗ |
if (!button) { |
910 |
|
✗ |
g_warning ("Not setting profile '%s' as it doesn't have a widget", profile_str); |
911 |
|
✗ |
return; |
912 |
|
|
} |
913 |
|
✗ |
gtk_check_button_set_active (GTK_CHECK_BUTTON (button), TRUE); |
914 |
|
|
} |
915 |
|
|
|
916 |
|
|
static void |
917 |
|
✗ |
power_profile_update_info_boxes (CcPowerPanel *self) |
918 |
|
|
{ |
919 |
|
✗ |
g_autoptr(GVariant) degraded_variant = NULL; |
920 |
|
✗ |
g_autoptr(GVariant) holds_variant = NULL; |
921 |
|
✗ |
g_autoptr(GVariant) profile_variant = NULL; |
922 |
|
|
guint i, num_children; |
923 |
|
✗ |
const char *degraded = NULL; |
924 |
|
|
const char *profile; |
925 |
|
|
CcPowerProfileInfoRow *row; |
926 |
|
✗ |
int next_insert = 0; |
927 |
|
|
|
928 |
|
✗ |
empty_listbox (self->power_profile_info_listbox); |
929 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->power_profile_info_listbox), FALSE); |
930 |
|
|
|
931 |
|
✗ |
profile_variant = g_dbus_proxy_get_cached_property (self->power_profiles_proxy, "ActiveProfile"); |
932 |
|
✗ |
if (!profile_variant) |
933 |
|
|
{ |
934 |
|
✗ |
g_warning ("No 'ActiveProfile' property on power-profiles-daemon service"); |
935 |
|
✗ |
return; |
936 |
|
|
} |
937 |
|
✗ |
profile = g_variant_get_string (profile_variant, NULL); |
938 |
|
|
|
939 |
|
✗ |
degraded_variant = g_dbus_proxy_get_cached_property (self->power_profiles_proxy, "PerformanceDegraded"); |
940 |
|
✗ |
if (degraded_variant) |
941 |
|
✗ |
degraded = g_variant_get_string (degraded_variant, NULL); |
942 |
|
✗ |
if (degraded && *degraded != '\0') |
943 |
|
|
{ |
944 |
|
|
const char *text; |
945 |
|
|
|
946 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->power_profile_info_listbox), TRUE); |
947 |
|
|
|
948 |
|
✗ |
if (g_str_equal (degraded, "high-operating-temperature")) |
949 |
|
✗ |
text = _("Performance mode temporarily disabled due to high operating temperature"); |
950 |
|
✗ |
else if (g_str_equal (degraded, "lap-detected")) |
951 |
|
✗ |
text = _("Lap detected: performance mode temporarily unavailable. Move the device to a stable surface to restore."); |
952 |
|
|
else |
953 |
|
✗ |
text = _("Performance mode temporarily disabled"); |
954 |
|
|
|
955 |
|
✗ |
row = cc_power_profile_info_row_new (text); |
956 |
|
✗ |
gtk_list_box_append (self->power_profile_info_listbox, GTK_WIDGET (row)); |
957 |
|
✗ |
if (g_str_equal (profile, "performance")) |
958 |
|
✗ |
next_insert = 1; |
959 |
|
|
} |
960 |
|
|
|
961 |
|
✗ |
holds_variant = g_dbus_proxy_get_cached_property (self->power_profiles_proxy, "ActiveProfileHolds"); |
962 |
|
✗ |
if (!holds_variant) |
963 |
|
|
{ |
964 |
|
✗ |
g_warning ("No 'ActiveProfileHolds' property on power-profiles-daemon service"); |
965 |
|
✗ |
return; |
966 |
|
|
} |
967 |
|
|
|
968 |
|
✗ |
num_children = g_variant_n_children (holds_variant); |
969 |
|
✗ |
for (i = 0; i < num_children; i++) |
970 |
|
|
{ |
971 |
|
✗ |
g_autoptr(GDesktopAppInfo) app_info = NULL; |
972 |
|
✗ |
g_autoptr(GVariant) hold_variant = NULL; |
973 |
|
✗ |
g_autofree char *text = NULL; |
974 |
|
|
const char *app_id, *held_profile, *reason, *name; |
975 |
|
|
|
976 |
|
✗ |
hold_variant = g_variant_get_child_value (holds_variant, i); |
977 |
|
✗ |
if (!hold_variant || !g_variant_is_of_type (hold_variant, G_VARIANT_TYPE ("a{sv}"))) |
978 |
|
✗ |
continue; |
979 |
|
|
|
980 |
|
✗ |
app_id = variant_lookup_string (hold_variant, "ApplicationId"); |
981 |
|
✗ |
if (!app_id) |
982 |
|
✗ |
continue; |
983 |
|
|
|
984 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->power_profile_info_listbox), TRUE); |
985 |
|
|
|
986 |
|
✗ |
app_info = g_desktop_app_info_new (app_id); |
987 |
|
✗ |
name = app_info ? g_app_info_get_name (G_APP_INFO (app_info)) : app_id; |
988 |
|
✗ |
held_profile = variant_lookup_string (hold_variant, "Profile"); |
989 |
|
✗ |
reason = variant_lookup_string (hold_variant, "Reason"); |
990 |
|
✗ |
g_debug ("Adding info row for %s hold by %s: %s", held_profile, app_id, reason); |
991 |
|
|
|
992 |
|
✗ |
if (g_strcmp0 (held_profile, "power-saver") == 0 && |
993 |
|
✗ |
g_strcmp0 (app_id, "org.gnome.SettingsDaemon.Power") == 0) |
994 |
|
|
{ |
995 |
|
✗ |
text = g_strdup (_("Power saver enabled due to low battery. Previous mode will be restored when battery is charged.")); |
996 |
|
|
} |
997 |
|
|
else |
998 |
|
|
{ |
999 |
|
✗ |
switch (cc_power_profile_from_str (held_profile)) |
1000 |
|
|
{ |
1001 |
|
✗ |
case CC_POWER_PROFILE_POWER_SAVER: |
1002 |
|
|
/* translators: "%s" is an application name */ |
1003 |
|
✗ |
text = g_strdup_printf (_("Power Saver mode activated by “%s”"), name); |
1004 |
|
✗ |
break; |
1005 |
|
✗ |
case CC_POWER_PROFILE_PERFORMANCE: |
1006 |
|
|
/* translators: "%s" is an application name */ |
1007 |
|
✗ |
text = g_strdup_printf (_("Performance mode activated by “%s”"), name); |
1008 |
|
✗ |
break; |
1009 |
|
✗ |
default: |
1010 |
|
✗ |
g_assert_not_reached (); |
1011 |
|
|
} |
1012 |
|
|
} |
1013 |
|
|
|
1014 |
|
✗ |
row = cc_power_profile_info_row_new (text); |
1015 |
|
✗ |
if (g_strcmp0 (held_profile, profile) != 0) |
1016 |
|
✗ |
gtk_list_box_insert (GTK_LIST_BOX (self->power_profile_info_listbox), GTK_WIDGET (row), -1); |
1017 |
|
|
else |
1018 |
|
✗ |
gtk_list_box_insert (GTK_LIST_BOX (self->power_profile_info_listbox), GTK_WIDGET (row), next_insert); |
1019 |
|
|
} |
1020 |
|
|
} |
1021 |
|
|
|
1022 |
|
|
static gint |
1023 |
|
✗ |
perf_profile_list_box_sort (GtkListBoxRow *row1, |
1024 |
|
|
GtkListBoxRow *row2, |
1025 |
|
|
gpointer user_data) |
1026 |
|
|
{ |
1027 |
|
|
CcPowerProfile row1_profile, row2_profile; |
1028 |
|
|
|
1029 |
|
✗ |
row1_profile = cc_power_profile_row_get_profile (CC_POWER_PROFILE_ROW (row1)); |
1030 |
|
✗ |
row2_profile = cc_power_profile_row_get_profile (CC_POWER_PROFILE_ROW (row2)); |
1031 |
|
|
|
1032 |
|
✗ |
if (row1_profile < row2_profile) |
1033 |
|
✗ |
return -1; |
1034 |
|
✗ |
if (row1_profile > row2_profile) |
1035 |
|
✗ |
return 1; |
1036 |
|
✗ |
return 0; |
1037 |
|
|
} |
1038 |
|
|
|
1039 |
|
|
static void |
1040 |
|
✗ |
power_profiles_properties_changed_cb (CcPowerPanel *self, |
1041 |
|
|
GVariant *changed_properties, |
1042 |
|
|
GStrv invalidated_properties, |
1043 |
|
|
GDBusProxy *proxy) |
1044 |
|
|
{ |
1045 |
|
✗ |
g_autoptr(GVariantIter) iter = NULL; |
1046 |
|
|
const char *key; |
1047 |
|
✗ |
g_autoptr(GVariant) value = NULL; |
1048 |
|
|
|
1049 |
|
✗ |
g_variant_get (changed_properties, "a{sv}", &iter); |
1050 |
|
✗ |
while (g_variant_iter_next (iter, "{&sv}", &key, &value)) |
1051 |
|
|
{ |
1052 |
|
✗ |
if (g_strcmp0 (key, "PerformanceDegraded") == 0 || |
1053 |
|
✗ |
g_strcmp0 (key, "ActiveProfileHolds") == 0) |
1054 |
|
|
{ |
1055 |
|
✗ |
power_profile_update_info_boxes (self); |
1056 |
|
|
} |
1057 |
|
✗ |
else if (g_strcmp0 (key, "ActiveProfile") == 0) |
1058 |
|
|
{ |
1059 |
|
✗ |
self->power_profiles_in_update = TRUE; |
1060 |
|
✗ |
performance_profile_set_active (self, g_variant_get_string (value, NULL)); |
1061 |
|
✗ |
self->power_profiles_in_update = FALSE; |
1062 |
|
|
} |
1063 |
|
|
else |
1064 |
|
|
{ |
1065 |
|
✗ |
g_debug ("Unhandled change on '%s' property", key); |
1066 |
|
|
} |
1067 |
|
|
} |
1068 |
|
✗ |
} |
1069 |
|
|
|
1070 |
|
|
static void |
1071 |
|
✗ |
set_active_profile_cb (GObject *source_object, |
1072 |
|
|
GAsyncResult *res, |
1073 |
|
|
gpointer user_data) |
1074 |
|
|
{ |
1075 |
|
✗ |
g_autoptr(GVariant) variant = NULL; |
1076 |
|
✗ |
g_autoptr(GError) error = NULL; |
1077 |
|
|
|
1078 |
|
✗ |
variant = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), |
1079 |
|
|
res, &error); |
1080 |
|
✗ |
if (!variant) |
1081 |
|
|
{ |
1082 |
|
✗ |
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
1083 |
|
✗ |
g_warning ("Could not set active profile: %s", error->message); |
1084 |
|
|
} |
1085 |
|
✗ |
} |
1086 |
|
|
|
1087 |
|
|
static void |
1088 |
|
✗ |
power_profile_button_toggled_cb (CcPowerProfileRow *row, |
1089 |
|
|
gpointer user_data) |
1090 |
|
|
{ |
1091 |
|
✗ |
CcPowerPanel *self = user_data; |
1092 |
|
|
CcPowerProfile profile; |
1093 |
|
✗ |
g_autoptr(GDBusConnection) connection = NULL; |
1094 |
|
✗ |
g_autoptr(GError) error = NULL; |
1095 |
|
|
|
1096 |
|
✗ |
if (!cc_power_profile_row_get_active (row)) |
1097 |
|
✗ |
return; |
1098 |
|
✗ |
if (self->power_profiles_in_update) |
1099 |
|
✗ |
return; |
1100 |
|
|
|
1101 |
|
✗ |
profile = cc_power_profile_row_get_profile (row); |
1102 |
|
|
|
1103 |
|
✗ |
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, |
1104 |
|
|
cc_panel_get_cancellable (CC_PANEL (self)), |
1105 |
|
|
&error); |
1106 |
|
✗ |
if (!connection) |
1107 |
|
|
{ |
1108 |
|
✗ |
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
1109 |
|
✗ |
g_warning ("system bus not available: %s", error->message); |
1110 |
|
✗ |
return; |
1111 |
|
|
} |
1112 |
|
|
|
1113 |
|
✗ |
g_dbus_connection_call (connection, |
1114 |
|
|
"net.hadess.PowerProfiles", |
1115 |
|
|
"/net/hadess/PowerProfiles", |
1116 |
|
|
"org.freedesktop.DBus.Properties", |
1117 |
|
|
"Set", |
1118 |
|
|
g_variant_new ("(ssv)", |
1119 |
|
|
"net.hadess.PowerProfiles", |
1120 |
|
|
"ActiveProfile", |
1121 |
|
✗ |
g_variant_new_string (cc_power_profile_to_str (profile))), |
1122 |
|
|
NULL, |
1123 |
|
|
G_DBUS_CALL_FLAGS_NONE, |
1124 |
|
|
-1, |
1125 |
|
|
cc_panel_get_cancellable (CC_PANEL (self)), |
1126 |
|
|
set_active_profile_cb, |
1127 |
|
|
NULL); |
1128 |
|
|
} |
1129 |
|
|
|
1130 |
|
|
static void |
1131 |
|
✗ |
setup_power_profiles (CcPowerPanel *self) |
1132 |
|
|
{ |
1133 |
|
✗ |
g_autoptr(GDBusConnection) connection = NULL; |
1134 |
|
✗ |
g_autoptr(GVariant) variant = NULL; |
1135 |
|
✗ |
g_autoptr(GVariant) props = NULL; |
1136 |
|
|
guint i, num_children; |
1137 |
|
✗ |
g_autoptr(GError) error = NULL; |
1138 |
|
|
const char *performance_degraded; |
1139 |
|
|
const char *active_profile; |
1140 |
|
✗ |
g_autoptr(GVariant) profiles = NULL; |
1141 |
|
|
GtkCheckButton *last_button; |
1142 |
|
|
|
1143 |
|
✗ |
self->power_profiles_proxy = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SYSTEM, |
1144 |
|
|
G_DBUS_PROXY_FLAGS_NONE, |
1145 |
|
|
"net.hadess.PowerProfiles", |
1146 |
|
|
"/net/hadess/PowerProfiles", |
1147 |
|
|
"net.hadess.PowerProfiles", |
1148 |
|
|
NULL, |
1149 |
|
|
&error); |
1150 |
|
|
|
1151 |
|
✗ |
if (!self->power_profiles_proxy) |
1152 |
|
|
{ |
1153 |
|
✗ |
g_debug ("Could not create Power Profiles proxy: %s", error->message); |
1154 |
|
✗ |
return; |
1155 |
|
|
} |
1156 |
|
|
|
1157 |
|
✗ |
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, |
1158 |
|
|
cc_panel_get_cancellable (CC_PANEL (self)), |
1159 |
|
|
&error); |
1160 |
|
✗ |
if (!connection) |
1161 |
|
|
{ |
1162 |
|
✗ |
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
1163 |
|
✗ |
g_warning ("system bus not available: %s", error->message); |
1164 |
|
✗ |
return; |
1165 |
|
|
} |
1166 |
|
|
|
1167 |
|
✗ |
variant = g_dbus_connection_call_sync (connection, |
1168 |
|
|
"net.hadess.PowerProfiles", |
1169 |
|
|
"/net/hadess/PowerProfiles", |
1170 |
|
|
"org.freedesktop.DBus.Properties", |
1171 |
|
|
"GetAll", |
1172 |
|
|
g_variant_new ("(s)", |
1173 |
|
|
"net.hadess.PowerProfiles"), |
1174 |
|
|
NULL, |
1175 |
|
|
G_DBUS_CALL_FLAGS_NONE, |
1176 |
|
|
-1, |
1177 |
|
|
NULL, |
1178 |
|
|
&error); |
1179 |
|
|
|
1180 |
|
✗ |
if (!variant) |
1181 |
|
|
{ |
1182 |
|
✗ |
g_debug ("Failed to get properties for Power Profiles: %s", |
1183 |
|
|
error->message); |
1184 |
|
✗ |
g_clear_object (&self->power_profiles_proxy); |
1185 |
|
✗ |
return; |
1186 |
|
|
} |
1187 |
|
|
|
1188 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->power_profile_section), TRUE); |
1189 |
|
|
|
1190 |
|
✗ |
props = g_variant_get_child_value (variant, 0); |
1191 |
|
✗ |
performance_degraded = variant_lookup_string (props, "PerformanceDegraded"); |
1192 |
|
✗ |
self->has_performance_degraded = performance_degraded != NULL; |
1193 |
|
✗ |
active_profile = variant_lookup_string (props, "ActiveProfile"); |
1194 |
|
|
|
1195 |
|
✗ |
last_button = NULL; |
1196 |
|
✗ |
profiles = g_variant_lookup_value (props, "Profiles", NULL); |
1197 |
|
✗ |
num_children = g_variant_n_children (profiles); |
1198 |
|
✗ |
for (i = 0; i < num_children; i++) |
1199 |
|
|
{ |
1200 |
|
✗ |
g_autoptr(GVariant) profile_variant; |
1201 |
|
|
const char *name; |
1202 |
|
|
GtkCheckButton *button; |
1203 |
|
|
CcPowerProfile profile; |
1204 |
|
|
CcPowerProfileRow *row; |
1205 |
|
|
|
1206 |
|
✗ |
profile_variant = g_variant_get_child_value (profiles, i); |
1207 |
|
✗ |
if (!profile_variant || |
1208 |
|
✗ |
!g_variant_is_of_type (profile_variant, G_VARIANT_TYPE ("a{sv}"))) |
1209 |
|
✗ |
continue; |
1210 |
|
|
|
1211 |
|
✗ |
name = variant_lookup_string (profile_variant, "Profile"); |
1212 |
|
✗ |
if (!name) |
1213 |
|
✗ |
continue; |
1214 |
|
✗ |
g_debug ("Adding row for profile '%s' (driver: %s)", |
1215 |
|
|
name, variant_lookup_string (profile_variant, "Driver")); |
1216 |
|
|
|
1217 |
|
✗ |
profile = cc_power_profile_from_str (name); |
1218 |
|
✗ |
row = cc_power_profile_row_new (cc_power_profile_from_str (name)); |
1219 |
|
✗ |
g_signal_connect_object (G_OBJECT (row), "button-toggled", |
1220 |
|
|
G_CALLBACK (power_profile_button_toggled_cb), self, |
1221 |
|
|
0); |
1222 |
|
✗ |
self->power_profiles_row[profile] = row; |
1223 |
|
✗ |
gtk_list_box_append (self->power_profile_listbox, GTK_WIDGET (row)); |
1224 |
|
|
|
1225 |
|
|
/* Connect radio button to group */ |
1226 |
|
✗ |
button = cc_power_profile_row_get_radio_button (row); |
1227 |
|
✗ |
gtk_check_button_set_group (button, last_button); |
1228 |
|
✗ |
last_button = button; |
1229 |
|
|
} |
1230 |
|
|
|
1231 |
|
✗ |
self->power_profiles_in_update = TRUE; |
1232 |
|
✗ |
performance_profile_set_active (self, active_profile); |
1233 |
|
✗ |
self->power_profiles_in_update = FALSE; |
1234 |
|
|
|
1235 |
|
✗ |
self->power_profiles_prop_id = g_signal_connect_object (G_OBJECT (self->power_profiles_proxy), "g-properties-changed", |
1236 |
|
|
G_CALLBACK (power_profiles_properties_changed_cb), self, G_CONNECT_SWAPPED); |
1237 |
|
|
|
1238 |
|
✗ |
if (self->has_performance_degraded) |
1239 |
|
✗ |
power_profile_update_info_boxes (self); |
1240 |
|
|
|
1241 |
|
✗ |
update_power_saver_low_battery_row_visibility (self); |
1242 |
|
|
} |
1243 |
|
|
|
1244 |
|
|
static void |
1245 |
|
✗ |
setup_general_section (CcPowerPanel *self) |
1246 |
|
|
{ |
1247 |
|
✗ |
gboolean can_suspend, can_hibernate, show_section = FALSE; |
1248 |
|
|
|
1249 |
|
✗ |
can_suspend = can_suspend_or_hibernate (self, "CanSuspend"); |
1250 |
|
✗ |
can_hibernate = can_suspend_or_hibernate (self, "CanHibernate"); |
1251 |
|
|
|
1252 |
|
✗ |
if ((can_hibernate || can_suspend) && |
1253 |
|
✗ |
g_strcmp0 (self->chassis_type, "vm") != 0 && |
1254 |
|
✗ |
g_strcmp0 (self->chassis_type, "tablet") != 0 && |
1255 |
|
✗ |
g_strcmp0 (self->chassis_type, "handset") != 0) |
1256 |
|
|
{ |
1257 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->power_button_row), TRUE); |
1258 |
|
|
|
1259 |
|
✗ |
g_signal_handlers_block_by_func (self->power_button_row, |
1260 |
|
|
power_button_row_changed_cb, |
1261 |
|
|
self); |
1262 |
|
✗ |
populate_power_button_row (self->power_button_row, |
1263 |
|
|
can_suspend, |
1264 |
|
|
can_hibernate); |
1265 |
|
✗ |
set_value_for_combo_row (self->power_button_row, |
1266 |
|
|
g_settings_get_enum (self->gsd_settings, "power-button-action")); |
1267 |
|
✗ |
g_signal_handlers_unblock_by_func (self->power_button_row, |
1268 |
|
|
power_button_row_changed_cb, |
1269 |
|
|
self); |
1270 |
|
|
|
1271 |
|
✗ |
show_section = TRUE; |
1272 |
|
|
} |
1273 |
|
|
|
1274 |
|
✗ |
if (self->has_batteries) |
1275 |
|
|
{ |
1276 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->battery_percentage_row), TRUE); |
1277 |
|
|
|
1278 |
|
✗ |
g_settings_bind (self->interface_settings, "show-battery-percentage", |
1279 |
|
✗ |
self->battery_percentage_row, "active", |
1280 |
|
|
G_SETTINGS_BIND_DEFAULT); |
1281 |
|
|
|
1282 |
|
✗ |
show_section = TRUE; |
1283 |
|
|
} |
1284 |
|
|
|
1285 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->general_section), show_section); |
1286 |
|
✗ |
} |
1287 |
|
|
|
1288 |
|
|
static gint |
1289 |
|
✗ |
battery_sort_func (GtkListBoxRow *a, GtkListBoxRow *b, gpointer data) |
1290 |
|
|
{ |
1291 |
|
✗ |
CcBatteryRow *row_a = CC_BATTERY_ROW (a); |
1292 |
|
✗ |
CcBatteryRow *row_b = CC_BATTERY_ROW (b); |
1293 |
|
|
gboolean a_primary; |
1294 |
|
|
gboolean b_primary; |
1295 |
|
|
UpDeviceKind a_kind; |
1296 |
|
|
UpDeviceKind b_kind; |
1297 |
|
|
|
1298 |
|
✗ |
a_primary = cc_battery_row_get_primary(row_a); |
1299 |
|
✗ |
b_primary = cc_battery_row_get_primary(row_b); |
1300 |
|
|
|
1301 |
|
✗ |
if (a_primary) |
1302 |
|
✗ |
return -1; |
1303 |
|
✗ |
else if (b_primary) |
1304 |
|
✗ |
return 1; |
1305 |
|
|
|
1306 |
|
✗ |
a_kind = cc_battery_row_get_kind(row_a); |
1307 |
|
✗ |
b_kind = cc_battery_row_get_kind(row_b); |
1308 |
|
|
|
1309 |
|
✗ |
return a_kind - b_kind; |
1310 |
|
|
} |
1311 |
|
|
|
1312 |
|
|
static void |
1313 |
|
✗ |
cc_power_panel_dispose (GObject *object) |
1314 |
|
|
{ |
1315 |
|
✗ |
CcPowerPanel *self = CC_POWER_PANEL (object); |
1316 |
|
|
|
1317 |
|
✗ |
g_signal_handlers_disconnect_by_func (self->blank_screen_row, blank_screen_row_changed_cb, self); |
1318 |
|
✗ |
g_signal_handlers_disconnect_by_func (self->power_button_row, power_button_row_changed_cb, self); |
1319 |
|
|
|
1320 |
|
✗ |
g_clear_pointer (&self->chassis_type, g_free); |
1321 |
|
✗ |
g_clear_object (&self->gsd_settings); |
1322 |
|
✗ |
g_clear_object (&self->session_settings); |
1323 |
|
✗ |
g_clear_object (&self->interface_settings); |
1324 |
|
✗ |
g_clear_pointer (&self->devices, g_ptr_array_unref); |
1325 |
|
✗ |
g_clear_object (&self->up_client); |
1326 |
|
✗ |
g_clear_object (&self->iio_proxy); |
1327 |
|
✗ |
g_clear_object (&self->power_profiles_proxy); |
1328 |
|
✗ |
if (self->iio_proxy_watch_id != 0) |
1329 |
|
✗ |
g_bus_unwatch_name (self->iio_proxy_watch_id); |
1330 |
|
✗ |
self->iio_proxy_watch_id = 0; |
1331 |
|
|
|
1332 |
|
✗ |
G_OBJECT_CLASS (cc_power_panel_parent_class)->dispose (object); |
1333 |
|
✗ |
} |
1334 |
|
|
|
1335 |
|
|
static void |
1336 |
|
✗ |
cc_power_panel_class_init (CcPowerPanelClass *klass) |
1337 |
|
|
{ |
1338 |
|
✗ |
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); |
1339 |
|
✗ |
GObjectClass *object_class = G_OBJECT_CLASS (klass); |
1340 |
|
✗ |
CcPanelClass *panel_class = CC_PANEL_CLASS (klass); |
1341 |
|
|
|
1342 |
|
✗ |
object_class->dispose = cc_power_panel_dispose; |
1343 |
|
|
|
1344 |
|
✗ |
panel_class->get_help_uri = cc_power_panel_get_help_uri; |
1345 |
|
|
|
1346 |
|
✗ |
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/power/cc-power-panel.ui"); |
1347 |
|
|
|
1348 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, als_row); |
1349 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, automatic_suspend_dialog); |
1350 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, automatic_suspend_row); |
1351 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, battery_listbox); |
1352 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, battery_percentage_row); |
1353 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, battery_section); |
1354 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, blank_screen_row); |
1355 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, device_listbox); |
1356 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, device_section); |
1357 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, dim_screen_row); |
1358 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, general_section); |
1359 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, mobile_time_liststore); |
1360 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, power_button_row); |
1361 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, power_profile_listbox); |
1362 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, power_profile_info_listbox); |
1363 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, power_profile_section); |
1364 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, power_saver_low_battery_row); |
1365 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, suspend_on_battery_delay_combo); |
1366 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, suspend_on_battery_switch_row); |
1367 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, suspend_on_battery_group); |
1368 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, suspend_on_ac_delay_combo); |
1369 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, suspend_on_ac_switch_row); |
1370 |
|
|
|
1371 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, als_row_changed_cb); |
1372 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, blank_screen_row_changed_cb); |
1373 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, keynav_failed_cb); |
1374 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, power_button_row_changed_cb); |
1375 |
|
✗ |
} |
1376 |
|
|
|
1377 |
|
|
static void |
1378 |
|
✗ |
cc_power_panel_init (CcPowerPanel *self) |
1379 |
|
|
{ |
1380 |
|
|
guint i; |
1381 |
|
✗ |
g_autoptr(GtkCssProvider) provider = NULL; |
1382 |
|
|
|
1383 |
|
✗ |
g_resources_register (cc_power_get_resource ()); |
1384 |
|
|
|
1385 |
|
✗ |
gtk_widget_init_template (GTK_WIDGET (self)); |
1386 |
|
|
|
1387 |
|
✗ |
provider = gtk_css_provider_new (); |
1388 |
|
✗ |
gtk_css_provider_load_from_resource (provider, "/org/gnome/control-center/power/power.css"); |
1389 |
|
✗ |
gtk_style_context_add_provider_for_display (gdk_display_get_default (), |
1390 |
|
✗ |
GTK_STYLE_PROVIDER (provider), |
1391 |
|
|
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); |
1392 |
|
|
|
1393 |
|
✗ |
self->chassis_type = cc_hostname_get_chassis_type (cc_hostname_get_default ()); |
1394 |
|
|
|
1395 |
|
|
/* Use a different list of suspend times based on the chassis type */ |
1396 |
|
✗ |
if (g_strcmp0 (self->chassis_type, "tablet") == 0 || |
1397 |
|
✗ |
g_strcmp0 (self->chassis_type, "watch") == 0 || |
1398 |
|
✗ |
g_strcmp0 (self->chassis_type, "handset") == 0) |
1399 |
|
|
{ |
1400 |
|
✗ |
gtk_combo_box_set_model (GTK_COMBO_BOX (self->suspend_on_battery_delay_combo), |
1401 |
|
✗ |
GTK_TREE_MODEL (self->mobile_time_liststore)); |
1402 |
|
✗ |
gtk_combo_box_set_model (GTK_COMBO_BOX (self->suspend_on_ac_delay_combo), |
1403 |
|
✗ |
GTK_TREE_MODEL (self->mobile_time_liststore)); |
1404 |
|
|
} |
1405 |
|
|
|
1406 |
|
✗ |
self->up_client = up_client_new (); |
1407 |
|
|
|
1408 |
|
✗ |
self->gsd_settings = g_settings_new ("org.gnome.settings-daemon.plugins.power"); |
1409 |
|
✗ |
self->session_settings = g_settings_new ("org.gnome.desktop.session"); |
1410 |
|
✗ |
self->interface_settings = g_settings_new ("org.gnome.desktop.interface"); |
1411 |
|
|
|
1412 |
|
✗ |
gtk_list_box_set_sort_func (self->battery_listbox, |
1413 |
|
|
(GtkListBoxSortFunc)battery_sort_func, NULL, NULL); |
1414 |
|
|
|
1415 |
|
✗ |
gtk_list_box_set_sort_func (self->device_listbox, |
1416 |
|
|
(GtkListBoxSortFunc)battery_sort_func, NULL, NULL); |
1417 |
|
|
|
1418 |
|
✗ |
gtk_list_box_set_sort_func (self->power_profile_listbox, |
1419 |
|
|
perf_profile_list_box_sort, |
1420 |
|
|
NULL, NULL); |
1421 |
|
✗ |
setup_power_profiles (self); |
1422 |
|
|
|
1423 |
|
✗ |
setup_power_saving (self); |
1424 |
|
✗ |
g_settings_bind (self->gsd_settings, "power-saver-profile-on-low-battery", |
1425 |
|
✗ |
self->power_saver_low_battery_row, "active", |
1426 |
|
|
G_SETTINGS_BIND_DEFAULT); |
1427 |
|
|
|
1428 |
|
✗ |
setup_general_section (self); |
1429 |
|
|
|
1430 |
|
|
/* populate batteries */ |
1431 |
|
✗ |
g_signal_connect_object (self->up_client, "device-added", G_CALLBACK (up_client_device_added), self, G_CONNECT_SWAPPED); |
1432 |
|
✗ |
g_signal_connect_object (self->up_client, "device-removed", G_CALLBACK (up_client_device_removed), self, G_CONNECT_SWAPPED); |
1433 |
|
|
|
1434 |
|
✗ |
self->devices = up_client_get_devices2 (self->up_client); |
1435 |
|
✗ |
for (i = 0; self->devices != NULL && i < self->devices->len; i++) { |
1436 |
|
✗ |
UpDevice *device = g_ptr_array_index (self->devices, i); |
1437 |
|
✗ |
g_signal_connect_object (G_OBJECT (device), "notify", |
1438 |
|
|
G_CALLBACK (up_client_changed), self, G_CONNECT_SWAPPED); |
1439 |
|
|
} |
1440 |
|
✗ |
up_client_changed (self); |
1441 |
|
✗ |
} |
1442 |
|
|
|