-
Notifications
You must be signed in to change notification settings - Fork 16
/
mousewheelzoom.vala
189 lines (165 loc) · 5.15 KB
/
mousewheelzoom.vala
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// gnome-shell-mousewheel-zoom
// (c) Mar 2012, Tobias Quinn <[email protected]>
// GPLv3
using X;
using GLib;
const int MOUSEWHEEL_UP = 4;
const int MOUSEWHEEL_DOWN = 5;
const int[] BUTTONS = { MOUSEWHEEL_UP, MOUSEWHEEL_DOWN };
const int[] MASKS = { 0, X.KeyMask.Mod2Mask, X.KeyMask.LockMask , X.KeyMask.LockMask | X.KeyMask.Mod2Mask };
[DBus (name = "org.gnome.Magnifier")]
interface Magnifier : Object {
public abstract bool isActive() throws IOError;
public abstract void setActive(bool active) throws IOError;
public abstract GLib.ObjectPath[] getZoomRegions() throws IOError;
}
[DBus (name = "org.gnome.Magnifier.ZoomRegion")]
interface ZoomRegion : Object {
public abstract void setMagFactor(double xMagFactor, double yMagFactor) throws IOError;
public abstract double getMagFactor() throws IOError;
}
class Zoomer : GLib.Object {
// DBus proxy objects
private Magnifier mag;
private ZoomRegion zoom;
// Zoom state
private const double incr = 0.1;
private double current_zoom;
private bool zoom_active;
private bool interfaces_active;
public Zoomer() {
interfaces_active = false;
mag = Bus.get_proxy_sync(BusType.SESSION,
"org.gnome.Magnifier",
"/org/gnome/Magnifier");
do {
refresh_dbus();
} while (!interfaces_active);
// get current zoom state
zoom_active = mag.isActive();
if (zoom_active) {
current_zoom = zoom.getMagFactor();
} else {
current_zoom = 1;
}
}
private void refresh_dbus() {
try {
// refresh zoom regions (exposes ZoomRegion interface)
mag.getZoomRegions();
zoom = Bus.get_proxy_sync(BusType.SESSION,
"org.gnome.Magnifier",
"/org/gnome/Magnifier/ZoomRegion/zoomer0");
interfaces_active = true;
} catch (Error e) {
}
}
public void zoomIn() {
if (zoom_active) {
current_zoom *= (1 + incr);
} else {
current_zoom *= (1 + incr);
mag.setActive(true);
zoom_active = true;
}
try {
zoom.setMagFactor(current_zoom, current_zoom);
} catch (Error e) {
refresh_dbus();
}
}
public void zoomOut() {
if (zoom_active) {
current_zoom *= (1.0 - incr);
if (current_zoom <= 1) {
current_zoom = 1;
mag.setActive(false);
zoom_active = false;
} else {
try {
zoom.setMagFactor(current_zoom, current_zoom);
} catch (Error e) {
refresh_dbus();
}
}
}
}
}
class WatchForMagnifier : GLib.Object {
private MainLoop loop;
public WatchForMagnifier() {
// for now this blocks till the interface appears
DBusConnection conn = Bus.get_sync(BusType.SESSION);
Bus.watch_name_on_connection(conn,
"org.gnome.Magnifier",
BusNameWatcherFlags.NONE,
on_name_appeared,
on_name_vanished);
this.loop = new MainLoop();
this.loop.run();
}
private void on_name_appeared() {
message("name appeared\n");
this.loop.quit();
}
private void on_name_vanished() {
message("name vanished\n");
}
}
void main(string[] arg) {
// wait for the magnifier interface to appear
WatchForMagnifier wfm = new WatchForMagnifier();
// load appropriate key from dconf configuration
var settings = new Settings("com.tobiasquinn.mousewheelzoom");
string key = settings.get_string("modifier-key");
bool super_key = settings.get_boolean("super-key");
// default to ALT as modifier
int keymask = X.KeyMask.Mod1Mask;
switch (key) {
case "ctrl":
keymask = X.KeyMask.ControlMask;
break;
case "shift":
keymask = X.KeyMask.ShiftMask;
break;
case "super":
keymask = X.KeyMask.Mod4Mask;
break;
}
if (super_key) {
keymask = keymask | X.KeyMask.Mod4Mask;
}
// grab the chosen key and scrollwheel
X.Display disp = new X.Display();
X.Window root = disp.default_root_window();
foreach (int button in BUTTONS) {
foreach (int mask in MASKS) {
disp.grab_button(button,
keymask | mask,
root,
false,
0,
X.GrabMode.Async,
X.GrabMode.Async,
0,
0);
}
}
// process the X events
X.Event evt = Event();
Zoomer zoom = new Zoomer();
while (true) {
disp.next_event(ref evt);
switch(evt.xbutton.button) {
case MOUSEWHEEL_UP:
zoom.zoomIn();
break;
case MOUSEWHEEL_DOWN:
zoom.zoomOut();
break;
default:
stdout.printf("mousewheelzoom (vala) uncaught event\n");
break;
}
}
}