 44cdb20c10
			
		
	
	44cdb20c10
	
	
	
		
			
			This adds specific marshallers for all of the locations where a generic marshaller is being used. It also provides va_marshallers to reduce the chances that we get stack traces from perf going through ffi_call_unix64.
		
			
				
	
	
		
			294 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			294 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* GTK - The GIMP Toolkit
 | |
|  * Copyright (C) 2017-2018, Red Hat, Inc.
 | |
|  *
 | |
|  * This library is free software; you can redistribute it and/or
 | |
|  * modify it under the terms of the GNU Lesser General Public
 | |
|  * License as published by the Free Software Foundation; either
 | |
|  * version 2 of the License, or (at your option) any later version.
 | |
|  *
 | |
|  * This library 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
 | |
|  * Lesser General Public License for more details.
 | |
|  *
 | |
|  * You should have received a copy of the GNU Lesser General Public
 | |
|  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 | |
|  *
 | |
|  * Author(s): Carlos Garnacho <carlosg@gnome.org>
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * SECTION:gtkgesturestylus
 | |
|  * @Short_description: Gesture for stylus input
 | |
|  * @Title: GtkGestureStylus
 | |
|  * @See_also: #GtkGesture, #GtkGestureSingle
 | |
|  *
 | |
|  * #GtkGestureStylus is a #GtkGesture implementation specific to stylus
 | |
|  * input. The provided signals just provide the basic information
 | |
|  */
 | |
| 
 | |
| #include "config.h"
 | |
| #include "gtkgesturestylus.h"
 | |
| #include "gtkgesturestylusprivate.h"
 | |
| #include "gtkprivate.h"
 | |
| #include "gtkintl.h"
 | |
| #include "gtkmarshalers.h"
 | |
| #include "gtkmain.h"
 | |
| 
 | |
| G_DEFINE_TYPE (GtkGestureStylus, gtk_gesture_stylus, GTK_TYPE_GESTURE_SINGLE)
 | |
| 
 | |
| enum {
 | |
|   PROXIMITY,
 | |
|   DOWN,
 | |
|   MOTION,
 | |
|   UP,
 | |
|   N_SIGNALS
 | |
| };
 | |
| 
 | |
| static guint signals[N_SIGNALS] = { 0, };
 | |
| 
 | |
| static gboolean
 | |
| gtk_gesture_stylus_handle_event (GtkEventController *controller,
 | |
|                                  const GdkEvent     *event)
 | |
| {
 | |
|   GdkModifierType modifiers;
 | |
|   guint n_signal;
 | |
|   gdouble x, y;
 | |
| 
 | |
|   GTK_EVENT_CONTROLLER_CLASS (gtk_gesture_stylus_parent_class)->handle_event (controller, event);
 | |
| 
 | |
|   if (!gdk_event_get_device_tool (event))
 | |
|     return FALSE;
 | |
|   if (!gdk_event_get_coords (event, &x, &y))
 | |
|     return FALSE;
 | |
| 
 | |
|   switch ((guint) gdk_event_get_event_type (event))
 | |
|     {
 | |
|     case GDK_BUTTON_PRESS:
 | |
|       n_signal = DOWN;
 | |
|       break;
 | |
|     case GDK_BUTTON_RELEASE:
 | |
|       n_signal = UP;
 | |
|       break;
 | |
|     case GDK_MOTION_NOTIFY:
 | |
|       gdk_event_get_state (event, &modifiers);
 | |
| 
 | |
|       if (modifiers & GDK_BUTTON1_MASK)
 | |
|         n_signal = MOTION;
 | |
|       else
 | |
|         n_signal = PROXIMITY;
 | |
|       break;
 | |
|     default:
 | |
|       return FALSE;
 | |
|     }
 | |
| 
 | |
|   g_signal_emit (controller, signals[n_signal], 0, x, y);
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| static void
 | |
| gtk_gesture_stylus_class_init (GtkGestureStylusClass *klass)
 | |
| {
 | |
|   GtkEventControllerClass *event_controller_class;
 | |
| 
 | |
|   event_controller_class = GTK_EVENT_CONTROLLER_CLASS (klass);
 | |
|   event_controller_class->handle_event = gtk_gesture_stylus_handle_event;
 | |
| 
 | |
|   signals[PROXIMITY] =
 | |
|     g_signal_new (I_("proximity"),
 | |
|                   G_TYPE_FROM_CLASS (klass),
 | |
|                   G_SIGNAL_RUN_LAST,
 | |
|                   G_STRUCT_OFFSET (GtkGestureStylusClass, proximity),
 | |
|                   NULL, NULL,
 | |
|                   _gtk_marshal_VOID__DOUBLE_DOUBLE,
 | |
|                   G_TYPE_NONE, 2, G_TYPE_DOUBLE, G_TYPE_DOUBLE);
 | |
|   g_signal_set_va_marshaller (signals[PROXIMITY],
 | |
|                               G_TYPE_FROM_CLASS (klass),
 | |
|                               _gtk_marshal_VOID__DOUBLE_DOUBLEv);
 | |
| 
 | |
|   signals[DOWN] =
 | |
|     g_signal_new (I_("down"),
 | |
|                   G_TYPE_FROM_CLASS (klass),
 | |
|                   G_SIGNAL_RUN_LAST,
 | |
|                   G_STRUCT_OFFSET (GtkGestureStylusClass, down),
 | |
|                   NULL, NULL,
 | |
|                   _gtk_marshal_VOID__DOUBLE_DOUBLE,
 | |
|                   G_TYPE_NONE, 2, G_TYPE_DOUBLE, G_TYPE_DOUBLE);
 | |
|   g_signal_set_va_marshaller (signals[DOWN],
 | |
|                               G_TYPE_FROM_CLASS (klass),
 | |
|                               _gtk_marshal_VOID__DOUBLE_DOUBLEv);
 | |
| 
 | |
|   signals[MOTION] =
 | |
|     g_signal_new (I_("motion"),
 | |
|                   G_TYPE_FROM_CLASS (klass),
 | |
|                   G_SIGNAL_RUN_LAST,
 | |
|                   G_STRUCT_OFFSET (GtkGestureStylusClass, motion),
 | |
|                   NULL, NULL,
 | |
|                   _gtk_marshal_VOID__DOUBLE_DOUBLE,
 | |
|                   G_TYPE_NONE, 2, G_TYPE_DOUBLE, G_TYPE_DOUBLE);
 | |
|   g_signal_set_va_marshaller (signals[MOTION],
 | |
|                               G_TYPE_FROM_CLASS (klass),
 | |
|                               _gtk_marshal_VOID__DOUBLE_DOUBLEv);
 | |
| 
 | |
|   signals[UP] =
 | |
|     g_signal_new (I_("up"),
 | |
|                   G_TYPE_FROM_CLASS (klass),
 | |
|                   G_SIGNAL_RUN_LAST,
 | |
|                   G_STRUCT_OFFSET (GtkGestureStylusClass, up),
 | |
|                   NULL, NULL,
 | |
|                   _gtk_marshal_VOID__DOUBLE_DOUBLE,
 | |
|                   G_TYPE_NONE, 2, G_TYPE_DOUBLE, G_TYPE_DOUBLE);
 | |
|   g_signal_set_va_marshaller (signals[UP],
 | |
|                               G_TYPE_FROM_CLASS (klass),
 | |
|                               _gtk_marshal_VOID__DOUBLE_DOUBLEv);
 | |
| }
 | |
| 
 | |
| static void
 | |
| gtk_gesture_stylus_init (GtkGestureStylus *gesture)
 | |
| {
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * gtk_gesture_stylus_new:
 | |
|  * @widget: a #GtkWidget
 | |
|  *
 | |
|  * Creates a new #GtkGestureStylus.
 | |
|  *
 | |
|  * Returns: a newly created stylus gesture
 | |
|  *
 | |
|  * Since: 3.24
 | |
|  **/
 | |
| GtkGesture *
 | |
| gtk_gesture_stylus_new (GtkWidget *widget)
 | |
| {
 | |
|   return g_object_new (GTK_TYPE_GESTURE_STYLUS,
 | |
|                        "widget", widget,
 | |
|                        NULL);
 | |
| }
 | |
| 
 | |
| static const GdkEvent *
 | |
| gesture_get_current_event (GtkGestureStylus *gesture)
 | |
| {
 | |
|   GdkEventSequence *sequence;
 | |
| 
 | |
|   sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
 | |
| 
 | |
|   return gtk_gesture_get_last_event (GTK_GESTURE (gesture), sequence);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * gtk_gesture_stylus_get_axis:
 | |
|  * @gesture: a #GtkGestureStylus
 | |
|  * @axis: requested device axis
 | |
|  * @value: (out): return location for the axis value
 | |
|  *
 | |
|  * Returns the current value for the requested @axis. This function
 | |
|  * must be called from either the #GtkGestureStylus:down,
 | |
|  * #GtkGestureStylus:motion, #GtkGestureStylus:up or #GtkGestureStylus:proximity
 | |
|  * signals.
 | |
|  *
 | |
|  * Returns: #TRUE if there is a current value for the axis
 | |
|  *
 | |
|  * Since: 3.24
 | |
|  **/
 | |
| gboolean
 | |
| gtk_gesture_stylus_get_axis (GtkGestureStylus *gesture,
 | |
| 			     GdkAxisUse        axis,
 | |
| 			     gdouble          *value)
 | |
| {
 | |
|   const GdkEvent *event;
 | |
| 
 | |
|   g_return_val_if_fail (GTK_IS_GESTURE_STYLUS (gesture), FALSE);
 | |
|   g_return_val_if_fail (axis < GDK_AXIS_LAST, FALSE);
 | |
|   g_return_val_if_fail (value != NULL, FALSE);
 | |
| 
 | |
|   event = gesture_get_current_event (gesture);
 | |
|   if (!event)
 | |
|     return FALSE;
 | |
| 
 | |
|   return gdk_event_get_axis (event, axis, value);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * gtk_gesture_stylus_get_axes:
 | |
|  * @gesture: a GtkGestureStylus
 | |
|  * @axes: (array): array of requested axes, terminated with #GDK_AXIS_IGNORE
 | |
|  * @values: (out) (array): return location for the axis values
 | |
|  *
 | |
|  * Returns the current values for the requested @axes. This function
 | |
|  * must be called from either the #GtkGestureStylus:down,
 | |
|  * #GtkGestureStylus:motion, #GtkGestureStylus:up or #GtkGestureStylus:proximity
 | |
|  * signals.
 | |
|  *
 | |
|  * Returns: #TRUE if there is a current value for the axes
 | |
|  *
 | |
|  * Since: 3.24
 | |
|  **/
 | |
| gboolean
 | |
| gtk_gesture_stylus_get_axes (GtkGestureStylus  *gesture,
 | |
| 			     GdkAxisUse         axes[],
 | |
| 			     gdouble          **values)
 | |
| {
 | |
|   const GdkEvent *event;
 | |
|   GArray *array;
 | |
|   gint i = 0;
 | |
| 
 | |
|   g_return_val_if_fail (GTK_IS_GESTURE_STYLUS (gesture), FALSE);
 | |
|   g_return_val_if_fail (values != NULL, FALSE);
 | |
| 
 | |
|   event = gesture_get_current_event (gesture);
 | |
|   if (!event)
 | |
|     return FALSE;
 | |
| 
 | |
|   array = g_array_new (TRUE, FALSE, sizeof (gdouble));
 | |
| 
 | |
|   while (axes[i] != GDK_AXIS_IGNORE)
 | |
|     {
 | |
|       gdouble value;
 | |
| 
 | |
|       if (axes[i] >= GDK_AXIS_LAST)
 | |
|         {
 | |
|           g_warning ("Requesting unknown axis %d, did you "
 | |
|                      "forget to add a last GDK_AXIS_IGNORE axis?",
 | |
|                      axes[i]);
 | |
|           g_array_free (array, TRUE);
 | |
|           return FALSE;
 | |
|         }
 | |
| 
 | |
|       gdk_event_get_axis (event, axes[i], &value);
 | |
|       g_array_append_val (array, value);
 | |
|       i++;
 | |
|     }
 | |
| 
 | |
|   *values = (gdouble *) g_array_free (array, FALSE);
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * gtk_gesture_stylus_get_device_tool:
 | |
|  * @gesture: a #GtkGestureStylus
 | |
|  *
 | |
|  * Returns the #GdkDeviceTool currently driving input through this gesture.
 | |
|  * This function must be called from either the #GtkGestureStylus::down,
 | |
|  * #GtkGestureStylus::motion, #GtkGestureStylus::up or #GtkGestureStylus::proximity
 | |
|  * signal handlers.
 | |
|  *
 | |
|  * Returns: (nullable) (transfer none): The current stylus tool
 | |
|  *
 | |
|  * Since: 3.24
 | |
|  **/
 | |
| GdkDeviceTool *
 | |
| gtk_gesture_stylus_get_device_tool (GtkGestureStylus *gesture)
 | |
| {
 | |
|   const GdkEvent *event;
 | |
| 
 | |
|   g_return_val_if_fail (GTK_IS_GESTURE_STYLUS (gesture), FALSE);
 | |
| 
 | |
|   event = gesture_get_current_event (gesture);
 | |
|   if (!event)
 | |
|     return NULL;
 | |
| 
 | |
|   return gdk_event_get_device_tool (event);
 | |
| }
 |