Turn on backlight on short click
[gregoa/zavai.git] / src / app_power.vala
1 /*
2  * app_power - zavai power handling
3  *
4  * Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 using GLib;
22
23 namespace zavai {
24 namespace ui {
25 namespace power {
26
27 public class Power : zavai.Resource, Object
28 {
29         public dynamic DBus.Object usage;
30         public bool screen_locked;
31         private int screen_lock_fd;
32
33         private bool hide_after_closing_power_menu;
34
35         public Power()
36         {
37                 screen_locked = false;
38                 screen_lock_fd = -1;
39                 hide_after_closing_power_menu = false;
40
41                 usage = zavai.registry.sbus.get_object(
42                         "org.freesmartphone.ousaged",
43                         "/org/freesmartphone/Usage",
44                         "org.freesmartphone.Usage");
45
46                 zavai.input.power_button.power_button += on_power_button;
47                 zavai.input.power_button.request("zavai.ui.powerbutton.power");
48         }
49
50         public void shutdown()
51         {
52                 zavai.input.power_button.release("zavai.ui.powerbutton.power");
53         }
54
55         public void do_suspend() { usage.Suspend(); }
56         public void do_shutdown() { usage.Shutdown(); }
57         public void do_reboot() { usage.Reboot(); }
58
59         public void set_screen_lock(bool locked)
60         {
61                 if (locked && screen_locked)
62                         return;
63                 if (!locked && !screen_locked)
64                         return;
65
66                 if (locked)
67                 {
68                         screen_lock_fd = Posix.open("/dev/input/event1", Posix.O_RDWR | Posix.O_NONBLOCK);
69                         if (screen_lock_fd < 0)
70                         {
71                                 zavai.log.error("Cannot open /dev/input/event1");
72                                 return;
73                         }
74
75                         int EVIOCGRAB = 0x40044590;
76                         if (Posix.ioctl(screen_lock_fd, EVIOCGRAB, locked ? 1 : 0) != 0)
77                         {
78                                 zavai.log.error("Cannot EVIOCGRAB /dev/input/event1");
79                                 Posix.close(screen_lock_fd);
80                                 return;
81                         }
82                 } else {
83                         Posix.close(screen_lock_fd);
84                 }
85                 screen_locked = locked;
86         }
87
88         private void on_power_button(Posix.timeval* t, bool pressed)
89         {
90                 if (!pressed)
91                 {
92                         if (screen_locked)
93                         {
94                                 time_t now = new time_t();
95                                 if (now < t->tv_sec + 2)
96                                 {
97                                         // Short press: turn on backlight for a bit
98                                         backlight.wiggle();
99                                 } else {
100                                         // Long press: unlock
101                                         set_screen_lock(false);
102                                 }
103                         }
104                         else
105                         {
106                                 power_menu.toggle();
107                         }
108                 }
109         }
110 }
111
112 public class BatteryIcon : Gtk.StatusIcon
113 {
114         public dynamic DBus.Object battery;
115         protected string last_status;
116         protected int last_capacity;
117
118         public BatteryIcon()
119         {
120                 battery = zavai.registry.sbus.get_object(
121                         "org.freesmartphone.odeviced",
122                         "/org/freesmartphone/Device/PowerSupply/battery",
123                         "org.freesmartphone.Device.PowerSupply");
124
125                 // activate += on_activate;
126
127                 battery.PowerStatus += on_power_status;
128                 battery.Capacity += on_capacity;
129
130                 last_status = battery.GetPowerStatus();
131                 last_capacity = battery.GetCapacity();
132                 
133                 update_icon();
134         }
135
136         private void on_power_status(dynamic DBus.Object bat, string status)
137         {
138                 zavai.log.info("New battery status: " + status);
139                 last_status = status;
140                 update_icon();
141         }
142
143         private void on_capacity(dynamic DBus.Object bat, int val)
144         {
145 stderr.printf("NEW CAPACITY: %d\n", val);
146                 last_capacity = val;
147                 update_icon();
148         }
149
150         /*
151         private void on_activate()
152         {
153         }
154         */
155
156         protected void update_icon()
157         {
158                 string name = zavai.config.icondir + "/battery/";
159
160                 if (last_status == "charging")
161                         name += "%02d0_charging_500.png".printf(last_capacity/10);
162                 else
163                         name += "%02d0.png".printf(last_capacity/10);
164
165 stderr.printf("Loading icon from %s\n", name);
166
167                 set_from_file(name);
168         }
169 }
170
171 public class ScreenLockButton : Gtk.Button
172 {
173         public ScreenLockButton()
174         {
175                 label = "Lock screen";
176                 clicked += on_clicked;
177                 set_size_request(0, zavai.config.min_button_height);
178         }
179
180         public void on_clicked()
181         {
182                 zavai.log.info("Locking screen");
183                 power.set_screen_lock(true);
184                 power_menu.hide();
185         }
186 }
187
188 public class SuspendButton : Gtk.Button
189 {
190         public SuspendButton()
191         {
192                 label = "Suspend";
193                 clicked += on_clicked;
194                 set_size_request(0, zavai.config.min_button_height);
195         }
196
197         public void on_clicked()
198         {
199                 zavai.log.info("Suspending the phone via FSO");
200                 power.do_suspend();
201                 power_menu.hide();
202         }
203 }
204
205 public class ShutdownButton : Gtk.Button
206 {
207         public ShutdownButton()
208         {
209                 label = "Shut down";
210                 clicked += on_clicked;
211                 set_size_request(0, zavai.config.min_button_height);
212         }
213
214         public void on_clicked()
215         {
216                 zavai.log.info("Shutting down the phone via FSO");
217                 power.do_shutdown();
218                 power_menu.hide();
219         }
220 }
221
222 public class RebootButton : Gtk.Button
223 {
224         public RebootButton()
225         {
226                 label = "Reboot";
227                 clicked += on_clicked;
228                 set_size_request(0, zavai.config.min_button_height);
229         }
230
231         public void on_clicked()
232         {
233                 zavai.log.info("Rebooting the phone via FSO");
234                 power.do_reboot();
235                 power_menu.hide();
236         }
237 }
238
239 // For a list of dbus services, look in /etc/dbus-1/system.d/
240 public class Backlight: zavai.Service
241 {
242         public dynamic DBus.Object usage;
243
244         public Backlight()
245         {
246                 name = "backlight";
247
248                 usage = zavai.registry.sbus.get_object(
249                         "org.freesmartphone.ousaged",
250                         "/org/freesmartphone/Usage",
251                         "org.freesmartphone.Usage");
252         }
253
254         // Turn the backlight and then let it fade off
255         public void wiggle()
256         {
257                 // There must be a better method
258                 usage.RequestResource("Display");
259                 usage.ReleaseResource("Display");
260         }
261
262         /// Request GPS resource
263         public override void start()
264         {
265                 if (started) return;
266                 try {
267                         usage.RequestResource("Display");
268                         zavai.log.info("Acquired display");
269                         base.start();
270                 } catch (GLib.Error e) {
271                         zavai.log.error(e.message);
272                 }
273                 base.start();
274         }
275
276         // Release usage of GPS
277         public override void stop()
278         {
279                 if (!started) return;
280                 try {
281                         usage.ReleaseResource("Display");
282                         zavai.log.info("Released display");
283                         base.stop();
284                 } catch (GLib.Error e) {
285                         zavai.log.error(e.message);
286                 }
287                 base.stop();
288         }
289 }
290
291 public class PowerMenu : zavai.Resource, Gtk.Window
292 {
293         protected Gtk.VBox vbox;
294         protected ScreenLockButton act_screen_lock;
295         protected SuspendButton act_suspend;
296         protected ShutdownButton act_shutdown;
297         protected RebootButton act_reboot;
298         protected ServiceRequestLink act_backlight_on;
299         protected bool shown;
300
301         public PowerMenu()
302         {
303                 type = Gtk.WindowType.TOPLEVEL;
304                 title = "Power Menu";
305                 shown = false;
306                 destroy_with_parent = true;
307                 set_transient_for(zavai.app);
308                 set_modal(true);
309                 set_position(Gtk.WindowPosition.CENTER_ON_PARENT);
310                 set_size_request(300, 500);
311
312                 vbox = new Gtk.VBox(false, 0);
313                 add(vbox);
314
315                 //destroy += Gtk.main_quit;
316                 //set_events(get_events() | Gdk.EventMask.VISIBILITY_NOTIFY_MASK);
317                 //visibility_notify_event += on_visibility;
318                 set_skip_pager_hint(true);
319                 set_skip_taskbar_hint(true);
320                 set_type_hint(Gdk.WindowTypeHint.POPUP_MENU);
321
322                 act_screen_lock = new ScreenLockButton();
323                 vbox.pack_start(act_screen_lock, false, false, 0);
324
325                 act_suspend = new SuspendButton();
326                 vbox.pack_start(act_suspend, false, false, 0);
327
328                 act_shutdown = new ShutdownButton();
329                 vbox.pack_start(act_shutdown, false, false, 0);
330
331                 act_reboot = new RebootButton();
332                 vbox.pack_start(act_reboot, false, false, 0);
333
334                 act_backlight_on = new ServiceRequestLink("backlight", "Keep backlight on", "Let backlight fade");
335                 vbox.pack_start(act_backlight_on, false, false, 0);
336
337                 //vbox.show_all();
338         }
339
340         public void toggle()
341         {
342                 if (!shown)
343                 {
344                         show_all();
345                         show();
346                         visible = true;
347                         present();
348                         shown = true;
349                 } else {
350                         // TODO: do more in case it is visible but has no visibility (is covered by others)
351                         visible = !visible;
352                         if (visible)
353                                 present();
354                 }                               
355         }
356
357         public void hide()
358         {
359                 visible = false;
360         }
361
362         public void shutdown() {}
363 }
364
365 /*
366 public class TogglePowerMenu : Gtk.Button
367 {
368         public TogglePowerMenu()
369         {
370                 label = "Toggle power menu";
371                 clicked += on_clicked;
372                 set_size_request(0, zavai.config.min_button_height);
373         }
374
375         public void on_clicked()
376         {
377                 zavai.log.info("Toggling power menu");
378                 power_menu.toggle();
379         }
380 }
381 */
382
383 Power power;
384 PowerMenu power_menu;
385 BatteryIcon battery_icon;
386 Backlight backlight;
387 //TogglePowerMenu tpm;
388
389 public void init()
390 {
391         power = new Power();
392         backlight = new Backlight();
393         zavai.registry.register_service(backlight);
394
395         battery_icon = new BatteryIcon();
396         battery_icon.set_visible(true);
397
398         power_menu = new PowerMenu();
399         zavai.registry.register_resource("powermenu", power_menu);
400         
401     //zavai.registry.getmenu("menu.main").add_applet("menu.power");
402         //tpm = new TogglePowerMenu();
403     //zavai.registry.getmenu("menu.main").add_widget(tpm);
404
405     /*
406         raise_icon = new RaiseIcon();
407         raise_icon.set_visible(true);
408
409         close_or_back = new CloseOrBack();
410         close_or_back.set_visible(true);
411
412         window_list = new WindowList("Current apps");
413         zavai.registry.register_applet("wm.list", window_list);
414         zavai.registry.getmenu("menu.main").add_applet("wm.list");
415
416         try {
417                 launcher = new Launcher("Run program");
418         } catch (Error e) {
419                 zavai.log.error("Not running launcher: " + e.message);
420                 launcher = null;
421         }
422
423         if (launcher != null)
424         {
425                 zavai.registry.register_applet("wm.launcher", launcher);
426                 zavai.registry.getmenu("menu.main").add_applet("wm.launcher");
427         }
428     */
429 }
430
431 }
432 }
433 }