]> git.tdb.fi Git - libs/gui.git/commitdiff
Track the currently focused window in Display
authorMikko Rasa <tdb@tdb.fi>
Sun, 7 Feb 2016 13:53:19 +0000 (15:53 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sun, 7 Feb 2016 13:53:19 +0000 (15:53 +0200)
On mobile platforms it's important for applications to stop rendering or
otherwise using excessive amounts of CPU power when inactive.

OS X code is a dummy implementation because I need more time to understand
the relevant events on that platform.

source/graphics/android/display.cpp
source/graphics/android/window.cpp
source/graphics/cocoa/display.cpp
source/graphics/cocoa/window.cpp
source/graphics/display.cpp
source/graphics/display.h
source/graphics/window.h
source/graphics/windows/display.cpp
source/graphics/windows/window.cpp
source/graphics/x11/display.cpp
source/graphics/x11/window.cpp

index 5823b918b5f135db36bf60d805ea207552d56fc2..bd2cf273bb93514a9cd9dd14d89ff67c3f6ab19b 100644 (file)
@@ -9,7 +9,8 @@ namespace Msp {
 namespace Graphics {
 
 Display::Display(const string &):
-       primary_monitor(0)
+       primary_monitor(0),
+       focus_window(0)
 {
        Android::MainThread *thread = reinterpret_cast<Android::MainThread *>(Application::get_data());
        if(!thread->is_starting_up())
index 3a584203527743e18ae4d8c5b5e849bba3b66a50..be1441adcb9ad68ab7e320a8fdc0c99ce15a3ffc 100644 (file)
@@ -57,6 +57,7 @@ bool Window::event(const Event &evnt)
                display.remove_window(*this);
                display.add_window(*this);
                priv->signal_window_acquired.emit(priv->window);
+               signal_got_focus.emit();
                break;
        case WINDOW_RESIZED:
                options.width = ANativeWindow_getWidth(priv->window);
@@ -64,6 +65,7 @@ bool Window::event(const Event &evnt)
                signal_resize.emit(options.width, options.height);
                break;
        case WINDOW_DESTROYED:
+               signal_lost_focus.emit();
                priv->signal_window_lost.emit();
                priv->window = 0;
                display.remove_window(*this);
index f5c39d8bd609a9f9b08dc4d1d7d9b38b1a228ad2..b9ce492771a4b265d162dc7f61a9e234b723ad79 100644 (file)
@@ -10,7 +10,8 @@ namespace Graphics {
 
 Display::Display(const string &):
        primary_monitor(0),
-       priv(new Private)
+       priv(new Private),
+       focus_window(0)
 {
        static ErrorDialog err_dlg(0);
 
index abaefe2fdc4c6e81980fa951746cacf354ba4def..796e9695f8d16134abb77c063f4a0381c1aa6984 100644 (file)
@@ -63,6 +63,7 @@ bool Window::event(const Event &ev)
        case KEY_UP:
        case OTHER_MOUSE_DOWN:
        case OTHER_MOUSE_UP:
+               signal_got_focus.emit();
                signal_input_event.emit(ev);
                break;
        case MOUSE_MOVED:
index 40112a35f9408760c5f6ab05ea286033403282b1..1c7b639a06d8f993b72ef92fb19d9d211271ed5b 100644 (file)
@@ -1,4 +1,5 @@
 #include <cmath>
+#include <sigc++/bind.h>
 #include "display.h"
 #include "display_private.h"
 #include "window.h"
@@ -11,11 +12,15 @@ namespace Graphics {
 void Display::add_window(Window &wnd)
 {
        priv->windows[wnd.get_private().window] = &wnd;
+       wnd.signal_got_focus.connect(sigc::bind(sigc::mem_fun(this, &Display::window_got_focus), sigc::ref(wnd)));
+       wnd.signal_lost_focus.connect(sigc::mem_fun(this, &Display::window_lost_focus));
 }
 
 void Display::remove_window(Window &wnd)
 {
        priv->windows.erase(wnd.get_private().window);
+       if(&wnd==focus_window)
+               focus_window = 0;
 }
 
 const VideoMode &Display::get_desktop_mode() const
@@ -66,11 +71,28 @@ const VideoMode *Display::find_mode(unsigned width, unsigned height) const
        return find_mode(VideoMode(width, height));
 }
 
+void Display::window_got_focus(Window &w)
+{
+       focus_window = &w;
+}
+
+void Display::window_lost_focus()
+{
+       focus_window = 0;
+}
+
 void Display::tick()
 {
        check_error();
 
+       Window *old_focus = focus_window;
+
        while(process_events()) ;
+
+       if(old_focus && !focus_window)
+               signal_lost_focus.emit();
+       else if(!old_focus && focus_window)
+               signal_got_focus.emit();
 }
 
 } // namespace Graphics
index 9c62b51ee854d1fe3fb98858a4f924f97cdce5d4..092abbe1404afa2fe303883ed49cce9f5cfbe478 100644 (file)
@@ -4,6 +4,7 @@
 #include <list>
 #include <stdexcept>
 #include <string>
+#include <sigc++/signal.h>
 #include "errordialog.h"
 #include "monitor.h"
 #include "videomode.h"
@@ -18,12 +19,16 @@ class Display
 public:
        struct Private;
 
+       sigc::signal<void> signal_got_focus;
+       sigc::signal<void> signal_lost_focus;
+
 private:
        std::list<Monitor> monitors;
        Monitor *primary_monitor;
        std::list<VideoMode> modes;
        Private *priv;
        ErrorDialog *err_dialog;
+       Window *focus_window;
 
 public:
        Display(const std::string &disp_name = std::string());
@@ -42,6 +47,13 @@ public:
        const VideoMode *find_mode(const VideoMode &, float = 0.5f) const;
        const VideoMode *find_mode(unsigned, unsigned) const;
 
+private:
+       void window_got_focus(Window &);
+       void window_lost_focus();
+public:
+       Window *get_focus_window() const { return focus_window; }
+
+public:
        void tick();
 private:
        bool process_events();
index 31fa248a65e2a7080fdbfeebfd1a4d290e39d689..2d4376e1761baf82c7e59316b7823e5436721d9b 100644 (file)
@@ -33,6 +33,9 @@ public:
        objects instead. */
        sigc::signal<void, const Event &> signal_input_event;
 
+       sigc::signal<void> signal_got_focus;
+       sigc::signal<void> signal_lost_focus;
+
        sigc::signal<void, int, int> signal_move;
        sigc::signal<void, unsigned, unsigned> signal_resize;
        sigc::signal<void, unsigned, unsigned, unsigned, unsigned, const Event &> signal_expose;
index b9388e31f8ed297b85efbe20bd44b488bf7cc5b4..d767bebd2e8ea11e67ddfd8a442f22ad1c539522 100644 (file)
@@ -9,7 +9,8 @@ namespace Graphics {
 
 Display::Display(const string &):
        primary_monitor(0),
-       priv(new Private)
+       priv(new Private),
+       focus_window(0)
 {
        static ErrorDialog err_dlg(0);
 
index 046894f7e8815c2a90864cead486c3ac1c2163d7..c6aab7d6351a32ba35775e8524716873b193e540 100644 (file)
@@ -201,6 +201,12 @@ bool Window::event(const Event &evnt)
                        signal_expose.emit(update_rect.left, update_rect.top, width, height, evnt);
                }
                break;
+       case WM_SETFOCUS:
+               signal_got_focus.emit();
+               break;
+       case WM_KILLFOCUS:
+               signal_lost_focus.emit();
+               break;
        default:
                return false;
        }
index 634e91096f38cf7ce78a4c47e177e3bab8c0c7e8..c23f46d26a21417cb14483c562401f3bbe7d9575 100644 (file)
@@ -84,7 +84,8 @@ namespace Graphics {
 
 Display::Display(const string &disp_name):
        primary_monitor(0),
-       priv(new Private)
+       priv(new Private),
+       focus_window(0)
 {
        if(disp_name.empty())
                priv->display = XOpenDisplay(0);
index 52f37a35137e986e81fcf840e32b64e4b33a01e0..7513d3ffb14ebb958efe5e7d9b33a9f65e0482e4 100644 (file)
@@ -32,7 +32,7 @@ void Window::platform_init()
 
        XSetWindowAttributes attr;
        attr.override_redirect = options.fullscreen;
-       attr.event_mask = ButtonPressMask|ButtonReleaseMask|PointerMotionMask|KeyPressMask|KeyReleaseMask|StructureNotifyMask|EnterWindowMask|ExposureMask;
+       attr.event_mask = ButtonPressMask|ButtonReleaseMask|PointerMotionMask|KeyPressMask|KeyReleaseMask|StructureNotifyMask|EnterWindowMask|ExposureMask|FocusChangeMask;
 
        priv->window = XCreateWindow(dpy,
                display.get_private().root_window,
@@ -250,6 +250,12 @@ bool Window::event(const Event &evnt)
        case Expose:
                signal_expose.emit(ev.xexpose.x, ev.xexpose.y, ev.xexpose.width, ev.xexpose.height, evnt);
                break;
+       case FocusIn:
+               signal_got_focus.emit();
+               break;
+       case FocusOut:
+               signal_lost_focus.emit();
+               break;
        default:
                return false;
        }