aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Kerr <charles.kerr@canonical.com>2015-03-25 12:42:28 -0500
committerCharles Kerr <charles.kerr@canonical.com>2015-03-25 12:42:28 -0500
commit9e29a4fdb99b722c43af1268312db68fff17fc60 (patch)
treeb4225826a96ca428e02f8badeb52f506047256b8
parent432db089ea22325c85718d43e4fbe148cbb94109 (diff)
downloadayatana-indicator-datetime-9e29a4fdb99b722c43af1268312db68fff17fc60.tar.gz
ayatana-indicator-datetime-9e29a4fdb99b722c43af1268312db68fff17fc60.tar.bz2
ayatana-indicator-datetime-9e29a4fdb99b722c43af1268312db68fff17fc60.zip
60 seconds after triggering an alarm, release our keepDisplayOn request
-rw-r--r--include/notifications/awake.h6
-rw-r--r--src/awake.cpp134
-rw-r--r--src/snap.cpp23
3 files changed, 113 insertions, 50 deletions
diff --git a/include/notifications/awake.h b/include/notifications/awake.h
index bc38817..9c9d434 100644
--- a/include/notifications/awake.h
+++ b/include/notifications/awake.h
@@ -39,6 +39,12 @@ public:
explicit Awake(const std::string& app_name);
~Awake();
+ /** Whether or not the display is forced on */
+ bool display_forced() const;
+
+ /** Set the display force on/off */
+ void set_display_forced(bool forced);
+
private:
class Impl;
std::unique_ptr<Impl> impl;
diff --git a/src/awake.cpp b/src/awake.cpp
index 57358ab..fda4099 100644
--- a/src/awake.cpp
+++ b/src/awake.cpp
@@ -22,7 +22,7 @@
#include <gio/gio.h>
-#include <limits>
+#include <set>
namespace unity {
namespace indicator {
@@ -56,6 +56,19 @@ public:
}
}
+ bool display_forced() const
+ {
+ return !m_screen_cookies.empty();
+ }
+
+ void set_display_forced(bool force)
+ {
+ if (force)
+ force_screen();
+ else if (!force)
+ unforce_screen();
+ }
+
private:
static void on_system_bus_ready (GObject *,
@@ -95,19 +108,7 @@ private:
on_force_awake_response,
self);
- // ask unity-system-compositor to turn on the screen
- g_dbus_connection_call (system_bus,
- BUS_SCREEN_NAME,
- BUS_SCREEN_PATH,
- BUS_SCREEN_INTERFACE,
- "keepDisplayOn",
- nullptr,
- G_VARIANT_TYPE("(i)"),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- self->m_cancellable,
- on_force_screen_response,
- self);
+ self->force_screen();
g_object_unref (system_bus);
}
@@ -146,6 +147,53 @@ private:
}
}
+ void unforce_awake ()
+ {
+ g_return_if_fail (G_IS_DBUS_CONNECTION(m_system_bus));
+
+ if (m_awake_cookie != nullptr)
+ {
+ g_dbus_connection_call (m_system_bus,
+ BUS_POWERD_NAME,
+ BUS_POWERD_PATH,
+ BUS_POWERD_INTERFACE,
+ "clearSysState",
+ g_variant_new("(s)", m_awake_cookie),
+ nullptr,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ nullptr,
+ nullptr,
+ nullptr);
+
+ g_clear_pointer (&m_awake_cookie, g_free);
+ }
+ }
+
+ /***
+ **** FORCE DISPLAY ON
+ ***/
+
+ void force_screen()
+ {
+ g_return_if_fail (G_IS_DBUS_CONNECTION(m_system_bus));
+ g_return_if_fail (m_screen_cookies.empty());
+
+ // ask unity-system-compositor to turn on the screen
+ g_dbus_connection_call (m_system_bus,
+ BUS_SCREEN_NAME,
+ BUS_SCREEN_PATH,
+ BUS_SCREEN_INTERFACE,
+ "keepDisplayOn",
+ nullptr,
+ G_VARIANT_TYPE("(i)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ m_cancellable,
+ on_force_screen_response,
+ this);
+ }
+
static void on_force_screen_response (GObject * connection,
GAsyncResult * res,
gpointer gself)
@@ -171,34 +219,11 @@ private:
{
auto self = static_cast<Impl*>(gself);
- self->m_screen_cookie = NO_SCREEN_COOKIE;
- g_variant_get (args, "(i)", &self->m_screen_cookie);
- g_debug ("m_screen_cookie is now '%d'", self->m_screen_cookie);
-
+ gint32 cookie = 0;
+ g_variant_get (args, "(i)", &cookie);
g_variant_unref (args);
- }
- }
-
- void unforce_awake ()
- {
- g_return_if_fail (G_IS_DBUS_CONNECTION(m_system_bus));
-
- if (m_awake_cookie != nullptr)
- {
- g_dbus_connection_call (m_system_bus,
- BUS_POWERD_NAME,
- BUS_POWERD_PATH,
- BUS_POWERD_INTERFACE,
- "clearSysState",
- g_variant_new("(s)", m_awake_cookie),
- nullptr,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- nullptr,
- nullptr,
- nullptr);
-
- g_clear_pointer (&m_awake_cookie, g_free);
+ g_debug ("got screen_cookie '%d'", (int)cookie);
+ self->m_screen_cookies.insert (cookie);
}
}
@@ -206,32 +231,34 @@ private:
{
g_return_if_fail (G_IS_DBUS_CONNECTION(m_system_bus));
- if (m_screen_cookie != NO_SCREEN_COOKIE)
+ for (auto cookie : m_screen_cookies)
{
g_dbus_connection_call (m_system_bus,
BUS_SCREEN_NAME,
BUS_SCREEN_PATH,
BUS_SCREEN_INTERFACE,
"removeDisplayOnRequest",
- g_variant_new("(i)", m_screen_cookie),
+ g_variant_new("(i)", cookie),
nullptr,
G_DBUS_CALL_FLAGS_NONE,
-1,
nullptr,
nullptr,
nullptr);
-
- m_screen_cookie = NO_SCREEN_COOKIE;
}
+
+ m_screen_cookies.clear();
}
const std::string m_app_name;
GCancellable * m_cancellable = nullptr;
GDBusConnection * m_system_bus = nullptr;
char * m_awake_cookie = nullptr;
- int32_t m_screen_cookie = NO_SCREEN_COOKIE;
- static constexpr int32_t NO_SCREEN_COOKIE { std::numeric_limits<int32_t>::min() };
+ // In general there will only be one cookie in this container...
+ // holding N cookies is a safeguard in case the client calls force_screen()
+ // while there's aleady a pending keepDisplayOn call on the bus.
+ std::set<int32_t> m_screen_cookies;
};
/***
@@ -247,6 +274,19 @@ Awake::~Awake()
{
}
+bool
+Awake::display_forced() const
+{
+ return impl->display_forced();
+}
+
+void
+Awake::set_display_forced(bool forced)
+{
+ impl->set_display_forced(forced);
+}
+
+
/***
****
***/
diff --git a/src/snap.cpp b/src/snap.cpp
index e655d2d..80f200d 100644
--- a/src/snap.cpp
+++ b/src/snap.cpp
@@ -88,8 +88,9 @@ public:
intervention and shouldn't loop the sound. */
const bool interactive = appointment.is_ubuntu_alarm() && m_engine->supports_actions();
- // force the system to stay awake
- auto awake = std::make_shared<uin::Awake>(m_engine->app_name());
+ // Force the system to stay awake.
+ // In a clean world this would be a shared_ptr, but we use it as a GSourceFunc arg...
+ auto awake = new uin::Awake(m_engine->app_name());
// calendar events are muted in silent mode; alarm clocks never are
std::shared_ptr<uin::Sound> sound;
@@ -137,15 +138,31 @@ public:
b.add_action ("snooze", _("Snooze"));
}
+ // Don't keep the screen on forever.
+ // If the alarm keeps going on and on, release our screen-on lock
+ // after awhile to prevent unneccesary battery drain
+ constexpr int screen_awake_seconds { 60 };
+ auto awake_timeout_func = [](gpointer a){
+ static_cast<uin::Awake*>(a)->set_display_forced(false);
+ return G_SOURCE_REMOVE;
+ };
+ auto awake_timeout_tag = g_timeout_add_seconds (screen_awake_seconds,
+ awake_timeout_func,
+ awake);
+
// add 'sound', 'haptic', and 'awake' objects to the capture so
// they stay alive until the closed callback is called; i.e.,
// for the lifespan of the notficiation
- b.set_closed_callback([appointment, snooze, ok, sound, awake, haptic]
+ b.set_closed_callback([appointment, snooze, ok, sound, haptic,
+ awake, awake_timeout_tag]
(const std::string& action){
if (action == "snooze")
snooze(appointment);
else
ok(appointment);
+
+ g_source_remove(awake_timeout_tag);
+ delete awake;
});
const auto key = m_engine->show(b);