1 /*
2  * This file is part of gtkD.
3  *
4  * gtkD is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 3
7  * of the License, or (at your option) any later version, with
8  * some exceptions, please read the COPYING file.
9  *
10  * gtkD is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with gtkD; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
18  */
19 
20 // generated automatically - do not change
21 // find conversion definition on APILookup.txt
22 // implement new conversion functionalities on the wrap.utils pakage
23 
24 
25 module gdk.DeviceManager;
26 
27 private import gdk.Device;
28 private import gdk.Display;
29 private import gdk.c.functions;
30 public  import gdk.c.types;
31 private import glib.ListG;
32 private import gobject.ObjectG;
33 private import gobject.Signals;
34 public  import gtkc.gdktypes;
35 private import std.algorithm;
36 
37 
38 /**
39  * In addition to a single pointer and keyboard for user interface input,
40  * GDK contains support for a variety of input devices, including graphics
41  * tablets, touchscreens and multiple pointers/keyboards interacting
42  * simultaneously with the user interface. Such input devices often have
43  * additional features, such as sub-pixel positioning information and
44  * additional device-dependent information.
45  * 
46  * In order to query the device hierarchy and be aware of changes in the
47  * device hierarchy (such as virtual devices being created or removed, or
48  * physical devices being plugged or unplugged), GDK provides
49  * #GdkDeviceManager.
50  * 
51  * By default, and if the platform supports it, GDK is aware of multiple
52  * keyboard/pointer pairs and multitouch devices. This behavior can be
53  * changed by calling gdk_disable_multidevice() before gdk_display_open().
54  * There should rarely be a need to do that though, since GDK defaults
55  * to a compatibility mode in which it will emit just one enter/leave
56  * event pair for all devices on a window. To enable per-device
57  * enter/leave events and other multi-pointer interaction features,
58  * gdk_window_set_support_multidevice() must be called on
59  * #GdkWindows (or gtk_widget_set_support_multidevice() on widgets).
60  * window. See the gdk_window_set_support_multidevice() documentation
61  * for more information.
62  * 
63  * On X11, multi-device support is implemented through XInput 2.
64  * Unless gdk_disable_multidevice() is called, the XInput 2
65  * #GdkDeviceManager implementation will be used as the input source.
66  * Otherwise either the core or XInput 1 implementations will be used.
67  * 
68  * For simple applications that don’t have any special interest in
69  * input devices, the so-called “client pointer”
70  * provides a reasonable approximation to a simple setup with a single
71  * pointer and keyboard. The device that has been set as the client
72  * pointer can be accessed via gdk_device_manager_get_client_pointer().
73  * 
74  * Conceptually, in multidevice mode there are 2 device types. Virtual
75  * devices (or master devices) are represented by the pointer cursors
76  * and keyboard foci that are seen on the screen. Physical devices (or
77  * slave devices) represent the hardware that is controlling the virtual
78  * devices, and thus have no visible cursor on the screen.
79  * 
80  * Virtual devices are always paired, so there is a keyboard device for every
81  * pointer device. Associations between devices may be inspected through
82  * gdk_device_get_associated_device().
83  * 
84  * There may be several virtual devices, and several physical devices could
85  * be controlling each of these virtual devices. Physical devices may also
86  * be “floating”, which means they are not attached to any virtual device.
87  * 
88  * # Master and slave devices
89  * 
90  * |[
91  * carlos@sacarino:~$ xinput list
92  * ⎡ Virtual core pointer                          id=2    [master pointer  (3)]
93  * ⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
94  * ⎜   ↳ Wacom ISDv4 E6 Pen stylus                 id=10   [slave  pointer  (2)]
95  * ⎜   ↳ Wacom ISDv4 E6 Finger touch               id=11   [slave  pointer  (2)]
96  * ⎜   ↳ SynPS/2 Synaptics TouchPad                id=13   [slave  pointer  (2)]
97  * ⎜   ↳ TPPS/2 IBM TrackPoint                     id=14   [slave  pointer  (2)]
98  * ⎜   ↳ Wacom ISDv4 E6 Pen eraser                 id=16   [slave  pointer  (2)]
99  * ⎣ Virtual core keyboard                         id=3    [master keyboard (2)]
100  * ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
101  * ↳ Power Button                              id=6    [slave  keyboard (3)]
102  * ↳ Video Bus                                 id=7    [slave  keyboard (3)]
103  * ↳ Sleep Button                              id=8    [slave  keyboard (3)]
104  * ↳ Integrated Camera                         id=9    [slave  keyboard (3)]
105  * ↳ AT Translated Set 2 keyboard              id=12   [slave  keyboard (3)]
106  * ↳ ThinkPad Extra Buttons                    id=15   [slave  keyboard (3)]
107  * ]|
108  * 
109  * By default, GDK will automatically listen for events coming from all
110  * master devices, setting the #GdkDevice for all events coming from input
111  * devices. Events containing device information are #GDK_MOTION_NOTIFY,
112  * #GDK_BUTTON_PRESS, #GDK_2BUTTON_PRESS, #GDK_3BUTTON_PRESS,
113  * #GDK_BUTTON_RELEASE, #GDK_SCROLL, #GDK_KEY_PRESS, #GDK_KEY_RELEASE,
114  * #GDK_ENTER_NOTIFY, #GDK_LEAVE_NOTIFY, #GDK_FOCUS_CHANGE,
115  * #GDK_PROXIMITY_IN, #GDK_PROXIMITY_OUT, #GDK_DRAG_ENTER, #GDK_DRAG_LEAVE,
116  * #GDK_DRAG_MOTION, #GDK_DRAG_STATUS, #GDK_DROP_START, #GDK_DROP_FINISHED
117  * and #GDK_GRAB_BROKEN. When dealing with an event on a master device,
118  * it is possible to get the source (slave) device that the event originated
119  * from via gdk_event_get_source_device().
120  * 
121  * On a standard session, all physical devices are connected by default to
122  * the "Virtual Core Pointer/Keyboard" master devices, hence routing all events
123  * through these. This behavior is only modified by device grabs, where the
124  * slave device is temporarily detached for as long as the grab is held, and
125  * more permanently by user modifications to the device hierarchy.
126  * 
127  * On certain application specific setups, it may make sense
128  * to detach a physical device from its master pointer, and mapping it to
129  * an specific window. This can be achieved by the combination of
130  * gdk_device_grab() and gdk_device_set_mode().
131  * 
132  * In order to listen for events coming from devices
133  * other than a virtual device, gdk_window_set_device_events() must be
134  * called. Generally, this function can be used to modify the event mask
135  * for any given device.
136  * 
137  * Input devices may also provide additional information besides X/Y.
138  * For example, graphics tablets may also provide pressure and X/Y tilt
139  * information. This information is device-dependent, and may be
140  * queried through gdk_device_get_axis(). In multidevice mode, virtual
141  * devices will change axes in order to always represent the physical
142  * device that is routing events through it. Whenever the physical device
143  * changes, the #GdkDevice:n-axes property will be notified, and
144  * gdk_device_list_axes() will return the new device axes.
145  * 
146  * Devices may also have associated “keys” or
147  * macro buttons. Such keys can be globally set to map into normal X
148  * keyboard events. The mapping is set using gdk_device_set_key().
149  * 
150  * In GTK+ 3.20, a new #GdkSeat object has been introduced that
151  * supersedes #GdkDeviceManager and should be preferred in newly
152  * written code.
153  */
154 public class DeviceManager : ObjectG
155 {
156 	/** the main Gtk struct */
157 	protected GdkDeviceManager* gdkDeviceManager;
158 
159 	/** Get the main Gtk struct */
160 	public GdkDeviceManager* getDeviceManagerStruct(bool transferOwnership = false)
161 	{
162 		if (transferOwnership)
163 			ownedRef = false;
164 		return gdkDeviceManager;
165 	}
166 
167 	/** the main Gtk struct as a void* */
168 	protected override void* getStruct()
169 	{
170 		return cast(void*)gdkDeviceManager;
171 	}
172 
173 	protected override void setStruct(GObject* obj)
174 	{
175 		gdkDeviceManager = cast(GdkDeviceManager*)obj;
176 		super.setStruct(obj);
177 	}
178 
179 	/**
180 	 * Sets our main struct and passes it to the parent class.
181 	 */
182 	public this (GdkDeviceManager* gdkDeviceManager, bool ownedRef = false)
183 	{
184 		this.gdkDeviceManager = gdkDeviceManager;
185 		super(cast(GObject*)gdkDeviceManager, ownedRef);
186 	}
187 
188 
189 	/** */
190 	public static GType getType()
191 	{
192 		return gdk_device_manager_get_type();
193 	}
194 
195 	/**
196 	 * Returns the client pointer, that is, the master pointer that acts as the core pointer
197 	 * for this application. In X11, window managers may change this depending on the interaction
198 	 * pattern under the presence of several pointers.
199 	 *
200 	 * You should use this function seldomly, only in code that isn’t triggered by a #GdkEvent
201 	 * and there aren’t other means to get a meaningful #GdkDevice to operate on.
202 	 *
203 	 * Deprecated: Use gdk_seat_get_pointer() instead.
204 	 *
205 	 * Returns: The client pointer. This memory is
206 	 *     owned by GDK and must not be freed or unreferenced.
207 	 *
208 	 * Since: 3.0
209 	 */
210 	public Device getClientPointer()
211 	{
212 		auto p = gdk_device_manager_get_client_pointer(gdkDeviceManager);
213 
214 		if(p is null)
215 		{
216 			return null;
217 		}
218 
219 		return ObjectG.getDObject!(Device)(cast(GdkDevice*) p);
220 	}
221 
222 	/**
223 	 * Gets the #GdkDisplay associated to @device_manager.
224 	 *
225 	 * Returns: the #GdkDisplay to which
226 	 *     @device_manager is associated to, or #NULL. This memory is
227 	 *     owned by GDK and must not be freed or unreferenced.
228 	 *
229 	 * Since: 3.0
230 	 */
231 	public Display getDisplay()
232 	{
233 		auto p = gdk_device_manager_get_display(gdkDeviceManager);
234 
235 		if(p is null)
236 		{
237 			return null;
238 		}
239 
240 		return ObjectG.getDObject!(Display)(cast(GdkDisplay*) p);
241 	}
242 
243 	/**
244 	 * Returns the list of devices of type @type currently attached to
245 	 * @device_manager.
246 	 *
247 	 * Deprecated: , use gdk_seat_get_pointer(), gdk_seat_get_keyboard()
248 	 * and gdk_seat_get_slaves() instead.
249 	 *
250 	 * Params:
251 	 *     type = device type to get.
252 	 *
253 	 * Returns: a list of
254 	 *     #GdkDevices. The returned list must be
255 	 *     freed with g_list_free (). The list elements are owned by
256 	 *     GTK+ and must not be freed or unreffed.
257 	 *
258 	 * Since: 3.0
259 	 */
260 	public ListG listDevices(GdkDeviceType type)
261 	{
262 		auto p = gdk_device_manager_list_devices(gdkDeviceManager, type);
263 
264 		if(p is null)
265 		{
266 			return null;
267 		}
268 
269 		return new ListG(cast(GList*) p);
270 	}
271 
272 	protected class OnDeviceAddedDelegateWrapper
273 	{
274 		void delegate(Device, DeviceManager) dlg;
275 		gulong handlerId;
276 
277 		this(void delegate(Device, DeviceManager) dlg)
278 		{
279 			this.dlg = dlg;
280 			onDeviceAddedListeners ~= this;
281 		}
282 
283 		void remove(OnDeviceAddedDelegateWrapper source)
284 		{
285 			foreach(index, wrapper; onDeviceAddedListeners)
286 			{
287 				if (wrapper.handlerId == source.handlerId)
288 				{
289 					onDeviceAddedListeners[index] = null;
290 					onDeviceAddedListeners = std.algorithm.remove(onDeviceAddedListeners, index);
291 					break;
292 				}
293 			}
294 		}
295 	}
296 	OnDeviceAddedDelegateWrapper[] onDeviceAddedListeners;
297 
298 	/**
299 	 * The ::device-added signal is emitted either when a new master
300 	 * pointer is created, or when a slave (Hardware) input device
301 	 * is plugged in.
302 	 *
303 	 * Params:
304 	 *     device = the newly added #GdkDevice.
305 	 */
306 	gulong addOnDeviceAdded(void delegate(Device, DeviceManager) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
307 	{
308 		auto wrapper = new OnDeviceAddedDelegateWrapper(dlg);
309 		wrapper.handlerId = Signals.connectData(
310 			this,
311 			"device-added",
312 			cast(GCallback)&callBackDeviceAdded,
313 			cast(void*)wrapper,
314 			cast(GClosureNotify)&callBackDeviceAddedDestroy,
315 			connectFlags);
316 		return wrapper.handlerId;
317 	}
318 
319 	extern(C) static void callBackDeviceAdded(GdkDeviceManager* devicemanagerStruct, GdkDevice* device, OnDeviceAddedDelegateWrapper wrapper)
320 	{
321 		wrapper.dlg(ObjectG.getDObject!(Device)(device), wrapper.outer);
322 	}
323 
324 	extern(C) static void callBackDeviceAddedDestroy(OnDeviceAddedDelegateWrapper wrapper, GClosure* closure)
325 	{
326 		wrapper.remove(wrapper);
327 	}
328 
329 	protected class OnDeviceChangedDelegateWrapper
330 	{
331 		void delegate(Device, DeviceManager) dlg;
332 		gulong handlerId;
333 
334 		this(void delegate(Device, DeviceManager) dlg)
335 		{
336 			this.dlg = dlg;
337 			onDeviceChangedListeners ~= this;
338 		}
339 
340 		void remove(OnDeviceChangedDelegateWrapper source)
341 		{
342 			foreach(index, wrapper; onDeviceChangedListeners)
343 			{
344 				if (wrapper.handlerId == source.handlerId)
345 				{
346 					onDeviceChangedListeners[index] = null;
347 					onDeviceChangedListeners = std.algorithm.remove(onDeviceChangedListeners, index);
348 					break;
349 				}
350 			}
351 		}
352 	}
353 	OnDeviceChangedDelegateWrapper[] onDeviceChangedListeners;
354 
355 	/**
356 	 * The ::device-changed signal is emitted whenever a device
357 	 * has changed in the hierarchy, either slave devices being
358 	 * disconnected from their master device or connected to
359 	 * another one, or master devices being added or removed
360 	 * a slave device.
361 	 *
362 	 * If a slave device is detached from all master devices
363 	 * (gdk_device_get_associated_device() returns %NULL), its
364 	 * #GdkDeviceType will change to %GDK_DEVICE_TYPE_FLOATING,
365 	 * if it's attached, it will change to %GDK_DEVICE_TYPE_SLAVE.
366 	 *
367 	 * Params:
368 	 *     device = the #GdkDevice that changed.
369 	 */
370 	gulong addOnDeviceChanged(void delegate(Device, DeviceManager) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
371 	{
372 		auto wrapper = new OnDeviceChangedDelegateWrapper(dlg);
373 		wrapper.handlerId = Signals.connectData(
374 			this,
375 			"device-changed",
376 			cast(GCallback)&callBackDeviceChanged,
377 			cast(void*)wrapper,
378 			cast(GClosureNotify)&callBackDeviceChangedDestroy,
379 			connectFlags);
380 		return wrapper.handlerId;
381 	}
382 
383 	extern(C) static void callBackDeviceChanged(GdkDeviceManager* devicemanagerStruct, GdkDevice* device, OnDeviceChangedDelegateWrapper wrapper)
384 	{
385 		wrapper.dlg(ObjectG.getDObject!(Device)(device), wrapper.outer);
386 	}
387 
388 	extern(C) static void callBackDeviceChangedDestroy(OnDeviceChangedDelegateWrapper wrapper, GClosure* closure)
389 	{
390 		wrapper.remove(wrapper);
391 	}
392 
393 	protected class OnDeviceRemovedDelegateWrapper
394 	{
395 		void delegate(Device, DeviceManager) dlg;
396 		gulong handlerId;
397 
398 		this(void delegate(Device, DeviceManager) dlg)
399 		{
400 			this.dlg = dlg;
401 			onDeviceRemovedListeners ~= this;
402 		}
403 
404 		void remove(OnDeviceRemovedDelegateWrapper source)
405 		{
406 			foreach(index, wrapper; onDeviceRemovedListeners)
407 			{
408 				if (wrapper.handlerId == source.handlerId)
409 				{
410 					onDeviceRemovedListeners[index] = null;
411 					onDeviceRemovedListeners = std.algorithm.remove(onDeviceRemovedListeners, index);
412 					break;
413 				}
414 			}
415 		}
416 	}
417 	OnDeviceRemovedDelegateWrapper[] onDeviceRemovedListeners;
418 
419 	/**
420 	 * The ::device-removed signal is emitted either when a master
421 	 * pointer is removed, or when a slave (Hardware) input device
422 	 * is unplugged.
423 	 *
424 	 * Params:
425 	 *     device = the just removed #GdkDevice.
426 	 */
427 	gulong addOnDeviceRemoved(void delegate(Device, DeviceManager) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
428 	{
429 		auto wrapper = new OnDeviceRemovedDelegateWrapper(dlg);
430 		wrapper.handlerId = Signals.connectData(
431 			this,
432 			"device-removed",
433 			cast(GCallback)&callBackDeviceRemoved,
434 			cast(void*)wrapper,
435 			cast(GClosureNotify)&callBackDeviceRemovedDestroy,
436 			connectFlags);
437 		return wrapper.handlerId;
438 	}
439 
440 	extern(C) static void callBackDeviceRemoved(GdkDeviceManager* devicemanagerStruct, GdkDevice* device, OnDeviceRemovedDelegateWrapper wrapper)
441 	{
442 		wrapper.dlg(ObjectG.getDObject!(Device)(device), wrapper.outer);
443 	}
444 
445 	extern(C) static void callBackDeviceRemovedDestroy(OnDeviceRemovedDelegateWrapper wrapper, GClosure* closure)
446 	{
447 		wrapper.remove(wrapper);
448 	}
449 
450 	/**
451 	 * Disables multidevice support in GDK. This call must happen prior
452 	 * to gdk_display_open(), gtk_init(), gtk_init_with_args() or
453 	 * gtk_init_check() in order to take effect.
454 	 *
455 	 * Most common GTK+ applications won’t ever need to call this. Only
456 	 * applications that do mixed GDK/Xlib calls could want to disable
457 	 * multidevice support if such Xlib code deals with input devices in
458 	 * any way and doesn’t observe the presence of XInput 2.
459 	 *
460 	 * Since: 3.0
461 	 */
462 	public static void disableMultidevice()
463 	{
464 		gdk_disable_multidevice();
465 	}
466 }