summaryrefslogtreecommitdiff
path: root/src/utilities/focusGrabber.vala
blob: b551defca92cf01a8e9cbcd50f3a34318989d83c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*
Copyright (c) 2011 by Simon Schneegans

This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option)
any later version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
more details.

You should have received a copy of the GNU General Public License along with
this program.  If not, see <http://www.gnu.org/licenses/>.
*/

namespace GnomePie {

/////////////////////////////////////////////////////////////////////////
/// Some helper methods which focus the input on a given Gtk.Window.
/////////////////////////////////////////////////////////////////////////

public class FocusGrabber : GLib.Object {

    /////////////////////////////////////////////////////////////////////
    /// Utilities for grabbing focus.
    /// Code roughly from Gnome-Do/Synapse.
    /////////////////////////////////////////////////////////////////////

    public static void grab(Gdk.Window window, bool keyboard = true, bool pointer = true, bool owner_events = true) {
        if (keyboard || pointer) {
            window.raise();
            window.focus(Gdk.CURRENT_TIME);

            if (!try_grab_window(window, keyboard, pointer, owner_events)) {
                int i = 0;
                Timeout.add(100, () => {
                    if (++i >= 100) return false;
                    return !try_grab_window(window, keyboard, pointer, owner_events);
                });
            }
        }
    }

    /////////////////////////////////////////////////////////////////////
    /// Code roughly from Gnome-Do/Synapse.
    /////////////////////////////////////////////////////////////////////

    public static void ungrab(bool keyboard = true, bool pointer = true) {
        var display = Gdk.Display.get_default();
        var manager = display.get_device_manager();

        GLib.List<weak Gdk.Device?> list = manager.list_devices(Gdk.DeviceType.MASTER);

        foreach(var device in list) {
            if ((device.input_source == Gdk.InputSource.KEYBOARD && keyboard)
             || (device.input_source != Gdk.InputSource.KEYBOARD && pointer))

                device.ungrab(Gdk.CURRENT_TIME);
        }
    }

    /////////////////////////////////////////////////////////////////////
    /// Code roughly from Gnome-Do/Synapse.
    /////////////////////////////////////////////////////////////////////

    private static bool try_grab_window(Gdk.Window window, bool keyboard, bool pointer, bool owner_events) {
        var display = Gdk.Display.get_default();
        var manager = display.get_device_manager();

        bool grabbed_all = true;

        GLib.List<weak Gdk.Device?> list = manager.list_devices(Gdk.DeviceType.MASTER);

        foreach(var device in list) {
            if ((device.input_source == Gdk.InputSource.KEYBOARD && keyboard)
             || (device.input_source != Gdk.InputSource.KEYBOARD && pointer)) {

                var status = device.grab(window, Gdk.GrabOwnership.APPLICATION, owner_events,
                                         Gdk.EventMask.ALL_EVENTS_MASK, null, Gdk.CURRENT_TIME);

                if (status != Gdk.GrabStatus.SUCCESS)
                    grabbed_all = false;
            }
        }

        if (grabbed_all)
            return true;

        ungrab(keyboard, pointer);

        return false;
    }
}

}