From 9e29a4fdb99b722c43af1268312db68fff17fc60 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 25 Mar 2015 12:42:28 -0500 Subject: 60 seconds after triggering an alarm, release our keepDisplayOn request --- include/notifications/awake.h | 6 ++ src/awake.cpp | 134 +++++++++++++++++++++++++++--------------- src/snap.cpp | 23 +++++++- 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; 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 -#include +#include 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(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::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 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(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 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(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); -- cgit v1.2.3