Compare commits
20 Commits
css-border
...
wip/waylan
Author | SHA1 | Date | |
---|---|---|---|
|
35a643a3c2 | ||
|
2833214d45 | ||
|
6bf3b1de28 | ||
|
5924983ef4 | ||
|
5d88fe3516 | ||
|
b6fd24300c | ||
|
8e173a09f9 | ||
|
766bc583f5 | ||
|
23aa1652b8 | ||
|
d971d7fb66 | ||
|
537c4c9cb7 | ||
|
9369f294e3 | ||
|
46e06dab9b | ||
|
2467510297 | ||
|
a20481cdb1 | ||
|
1041c04d07 | ||
|
1f920d59e8 | ||
|
d6f9ed2a99 | ||
|
2ce5df5e12 | ||
|
ca108c7af4 |
@@ -1,11 +1,12 @@
|
||||
/* Event Axes
|
||||
/* Touch and Drawing Tablets
|
||||
*
|
||||
* Demonstrates advanced handling of event information from exotic
|
||||
* input devices.
|
||||
*
|
||||
* On one hand, this snippet demonstrates management of input axes,
|
||||
* On one hand, this snippet demonstrates management of drawing tablets,
|
||||
* those contain additional information for the pointer other than
|
||||
* X/Y coordinates.
|
||||
* X/Y coordinates. Tablet pads events are mapped to actions, which
|
||||
* are both defined and interpreted by the application.
|
||||
*
|
||||
* Input axes are dependent on hardware devices, on linux/unix you
|
||||
* can see the device axes through xinput list <device>. Each time
|
||||
@@ -20,6 +21,7 @@
|
||||
* touchpoints can be tracked.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
typedef struct {
|
||||
@@ -51,7 +53,30 @@ const gchar *colors[] = {
|
||||
"burlywood"
|
||||
};
|
||||
|
||||
static GtkPadActionEntry pad_actions[] = {
|
||||
{ GTK_PAD_ACTION_BUTTON, 1, -1, N_("Nuclear strike"), "pad.nuke" },
|
||||
{ GTK_PAD_ACTION_BUTTON, 2, -1, N_("Release siberian methane reserves"), "pad.heat" },
|
||||
{ GTK_PAD_ACTION_BUTTON, 3, -1, N_("Release solar flare"), "pad.fry" },
|
||||
{ GTK_PAD_ACTION_BUTTON, 4, -1, N_("De-stabilize Oort cloud"), "pad.fall" },
|
||||
{ GTK_PAD_ACTION_BUTTON, 5, -1, N_("Ignite WR-104"), "pad.burst" },
|
||||
{ GTK_PAD_ACTION_BUTTON, 6, -1, N_("Lart whoever asks about this button"), "pad.lart" },
|
||||
{ GTK_PAD_ACTION_RING, -1, -1, N_("Earth axial tilt"), "pad.tilt" },
|
||||
{ GTK_PAD_ACTION_STRIP, -1, -1, N_("Extent of weak nuclear force"), "pad.dissolve" },
|
||||
};
|
||||
|
||||
static const gchar *pad_action_results[] = {
|
||||
"☢",
|
||||
"♨",
|
||||
"☼",
|
||||
"☄",
|
||||
"⚡",
|
||||
"💫",
|
||||
"◑",
|
||||
"⚛"
|
||||
};
|
||||
|
||||
static guint cur_color = 0;
|
||||
static guint pad_action_timeout_id = 0;
|
||||
|
||||
static AxesInfo *
|
||||
axes_info_new (void)
|
||||
@@ -488,12 +513,108 @@ draw_cb (GtkWidget *widget,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
update_label_text (GtkWidget *label,
|
||||
const gchar *text)
|
||||
{
|
||||
gchar *markup = NULL;
|
||||
|
||||
if (text)
|
||||
markup = g_strdup_printf ("<span font='48.0'>%s</span>", text);
|
||||
gtk_label_set_markup (GTK_LABEL (label), markup);
|
||||
g_free (markup);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
reset_label_text_timeout_cb (gpointer user_data)
|
||||
{
|
||||
GtkWidget *label = user_data;
|
||||
|
||||
update_label_text (label, NULL);
|
||||
pad_action_timeout_id = 0;
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
update_label_and_timeout (GtkWidget *label,
|
||||
const gchar *text)
|
||||
{
|
||||
if (pad_action_timeout_id)
|
||||
g_source_remove (pad_action_timeout_id);
|
||||
|
||||
update_label_text (label, text);
|
||||
pad_action_timeout_id = g_timeout_add (200, reset_label_text_timeout_cb, label);
|
||||
}
|
||||
|
||||
static void
|
||||
on_action_activate (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkWidget *label = user_data;
|
||||
const gchar *result;
|
||||
gchar *str;
|
||||
|
||||
result = g_object_get_data (G_OBJECT (action), "action-result");
|
||||
|
||||
if (!parameter)
|
||||
update_label_and_timeout (label, result);
|
||||
else
|
||||
{
|
||||
str = g_strdup_printf ("%s %.2f", result, g_variant_get_double (parameter));
|
||||
update_label_and_timeout (label, str);
|
||||
g_free (str);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
init_pad_controller (GtkWidget *window,
|
||||
GtkWidget *label)
|
||||
{
|
||||
GtkPadController *pad_controller;
|
||||
GSimpleActionGroup *action_group;
|
||||
GSimpleAction *action;
|
||||
gint i;
|
||||
|
||||
action_group = g_simple_action_group_new ();
|
||||
pad_controller = gtk_pad_controller_new (GTK_WINDOW (window),
|
||||
G_ACTION_GROUP (action_group),
|
||||
NULL);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (pad_actions); i++)
|
||||
{
|
||||
if (pad_actions[i].type == GTK_PAD_ACTION_BUTTON)
|
||||
{
|
||||
action = g_simple_action_new (pad_actions[i].action_name, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
action = g_simple_action_new_stateful (pad_actions[i].action_name,
|
||||
G_VARIANT_TYPE_DOUBLE, NULL);
|
||||
}
|
||||
|
||||
g_signal_connect (action, "activate",
|
||||
G_CALLBACK (on_action_activate), label);
|
||||
g_object_set_data (G_OBJECT (action), "action-result",
|
||||
(gpointer) pad_action_results[i]);
|
||||
g_action_map_add_action (G_ACTION_MAP (action_group), G_ACTION (action));
|
||||
g_object_unref (action);
|
||||
}
|
||||
|
||||
gtk_pad_controller_set_action_entries (pad_controller, pad_actions,
|
||||
G_N_ELEMENTS (pad_actions));
|
||||
g_object_set_data_full (G_OBJECT (window), "pad-controller",
|
||||
pad_controller, g_object_unref);
|
||||
|
||||
g_object_unref (action_group);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_event_axes (GtkWidget *toplevel)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
EventData *event_data;
|
||||
GtkWidget *box;
|
||||
GtkWidget *box, *label;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
@@ -524,6 +645,12 @@ do_event_axes (GtkWidget *toplevel)
|
||||
G_CALLBACK (event_cb), event_data);
|
||||
g_signal_connect (box, "draw",
|
||||
G_CALLBACK (draw_cb), event_data);
|
||||
|
||||
label = gtk_label_new ("");
|
||||
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (box), label);
|
||||
|
||||
init_pad_controller (window, label);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
@@ -25,6 +25,7 @@
|
||||
<xi:include href="xml/gdkseat.xml" />
|
||||
<xi:include href="xml/gdkmonitor.xml" />
|
||||
<xi:include href="xml/gdkdevice.xml" />
|
||||
<xi:include href="xml/gdkdevicepad.xml" />
|
||||
<xi:include href="xml/regions.xml" />
|
||||
<xi:include href="xml/pixbufs.xml" />
|
||||
<xi:include href="xml/rgba_colors.xml" />
|
||||
|
@@ -796,6 +796,25 @@ gdk_device_type_get_type
|
||||
GDK_MAX_TIMECOORD_AXES
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<TITLE>GdkDevicePad</TITLE>
|
||||
<FILE>gdkdevicepad</FILE>
|
||||
GdkDevicePad
|
||||
GdkDevicePadFeature
|
||||
gdk_device_pad_get_n_groups
|
||||
gdk_device_pad_get_group_n_modes
|
||||
gdk_device_pad_get_n_features
|
||||
gdk_device_pad_get_feature_group
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GDK_TYPE_DEVICE_PAD
|
||||
GDK_DEVICE_PAD
|
||||
GDK_IS_DEVICE_PAD
|
||||
|
||||
<SUBSECTION Private>
|
||||
gdk_device_pad_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<TITLE>GdkSeat</TITLE>
|
||||
<FILE>gdkseat</FILE>
|
||||
@@ -941,6 +960,9 @@ GdkEventOwnerChange
|
||||
GdkEventGrabBroken
|
||||
GdkEventTouchpadSwipe
|
||||
GdkEventTouchpadPinch
|
||||
GdkEventPadButton
|
||||
GdkEventPadAxis
|
||||
GdkEventPadGroupMode
|
||||
|
||||
<SUBSECTION>
|
||||
GdkScrollDirection
|
||||
|
@@ -4,6 +4,7 @@ gdk_app_launch_context_get_type
|
||||
gdk_cursor_get_type
|
||||
gdk_device_get_type
|
||||
gdk_device_manager_get_type
|
||||
gdk_device_pad_get_type
|
||||
gdk_display_get_type
|
||||
gdk_display_manager_get_type
|
||||
gdk_drag_context_get_type
|
||||
|
@@ -299,7 +299,7 @@
|
||||
</chapter>
|
||||
|
||||
<chapter id="Gestures">
|
||||
<title>Gestures</title>
|
||||
<title>Gestures and event handling</title>
|
||||
<xi:include href="xml/gtkeventcontroller.xml" />
|
||||
<xi:include href="xml/gtkgesture.xml" />
|
||||
<xi:include href="xml/gtkgesturesingle.xml" />
|
||||
@@ -310,6 +310,7 @@
|
||||
<xi:include href="xml/gtkgestureswipe.xml" />
|
||||
<xi:include href="xml/gtkgesturerotate.xml" />
|
||||
<xi:include href="xml/gtkgesturezoom.xml" />
|
||||
<xi:include href="xml/gtkpadcontroller.xml" />
|
||||
</chapter>
|
||||
|
||||
<chapter id="DeprecatedObjects">
|
||||
|
@@ -8450,6 +8450,28 @@ GTK_GESTURE_ZOOM_GET_CLASS
|
||||
gtk_gesture_zoom_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkpadcontroller</FILE>
|
||||
<TITLE>GtkPadController</TITLE>
|
||||
GtkPadController
|
||||
gtk_pad_controller_new
|
||||
gtk_pad_controller_set_action_entries
|
||||
gtk_pad_controller_set_action
|
||||
GtkPadActionType
|
||||
GtkPadActionEntry
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GTK_TYPE_PAD_CONTROLLER
|
||||
GTK_PAD_CONTROLLER
|
||||
GTK_PAD_CONTROLLER_CLASS
|
||||
GTK_IS_PAD_CONTROLLER
|
||||
GTK_IS_PAD_CONTROLLER_CLASS
|
||||
GTK_PAD_CONTROLLER_GET_CLASS
|
||||
|
||||
<SUBSECTION Private>
|
||||
gtk_pad_controller_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkstacksidebar</FILE>
|
||||
GtkStackSidebar
|
||||
|
@@ -133,6 +133,7 @@ gtk_numerable_icon_get_type
|
||||
gtk_offscreen_window_get_type
|
||||
gtk_orientable_get_type
|
||||
gtk_overlay_get_type
|
||||
gtk_pad_controller_get_type
|
||||
gtk_page_setup_get_type
|
||||
@DISABLE_ON_W32@gtk_page_setup_unix_dialog_get_type
|
||||
gtk_paned_get_type
|
||||
|
@@ -71,6 +71,7 @@ gdk_public_h_sources = \
|
||||
gdkcairo.h \
|
||||
gdkcursor.h \
|
||||
gdkdevice.h \
|
||||
gdkdevicepad.h \
|
||||
gdkdevicetool.h \
|
||||
gdkdevicemanager.h \
|
||||
gdkdisplay.h \
|
||||
@@ -114,6 +115,7 @@ gdk_private_headers = \
|
||||
gdkcursorprivate.h \
|
||||
gdkdevicemanagerprivate.h \
|
||||
gdkdeviceprivate.h \
|
||||
gdkdevicepadprivate.h \
|
||||
gdkdevicetoolprivate.h \
|
||||
gdkdisplaymanagerprivate.h \
|
||||
gdkdisplayprivate.h \
|
||||
@@ -144,6 +146,7 @@ gdk_c_sources = \
|
||||
gdkcursor.c \
|
||||
gdkdeprecated.c \
|
||||
gdkdevice.c \
|
||||
gdkdevicepad.c \
|
||||
gdkdevicetool.c \
|
||||
gdkdevicemanager.c \
|
||||
gdkdisplay.c \
|
||||
|
@@ -33,6 +33,7 @@
|
||||
#include <gdk/gdkcairo.h>
|
||||
#include <gdk/gdkcursor.h>
|
||||
#include <gdk/gdkdevice.h>
|
||||
#include <gdk/gdkdevicepad.h>
|
||||
#include <gdk/gdkdevicetool.h>
|
||||
#include <gdk/gdkdevicemanager.h>
|
||||
#include <gdk/gdkdisplay.h>
|
||||
|
@@ -49,6 +49,9 @@ typedef struct _GdkTimeCoord GdkTimeCoord;
|
||||
* as a touchpad. This device type has been added in 3.4.
|
||||
* @GDK_SOURCE_TRACKPOINT: the device is a trackpoint. This device type has been
|
||||
* added in 3.22
|
||||
* @GDK_SOURCE_TABLET_PAD: the device is a "pad", a collection of buttons,
|
||||
* rings and strips found in drawing tablets. This device type has been
|
||||
* added in 3.22.
|
||||
*
|
||||
* An enumeration describing the type of an input device in general terms.
|
||||
*/
|
||||
@@ -61,7 +64,8 @@ typedef enum
|
||||
GDK_SOURCE_KEYBOARD,
|
||||
GDK_SOURCE_TOUCHSCREEN,
|
||||
GDK_SOURCE_TOUCHPAD,
|
||||
GDK_SOURCE_TRACKPOINT
|
||||
GDK_SOURCE_TRACKPOINT,
|
||||
GDK_SOURCE_TABLET_PAD
|
||||
} GdkInputSource;
|
||||
|
||||
/**
|
||||
|
150
gdk/gdkdevicepad.c
Normal file
150
gdk/gdkdevicepad.c
Normal file
@@ -0,0 +1,150 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2016 Red Hat
|
||||
*
|
||||
* 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: Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:gdkdevicepad
|
||||
* @Short_description: Pad device interface
|
||||
* @Title: GtkDevicePad
|
||||
*
|
||||
* #GdkDevicePad is an interface implemented by devices of type
|
||||
* %GDK_SOURCE_TABLET_PAD, it allows querying the features provided
|
||||
* by the pad device.
|
||||
*
|
||||
* Tablet pads may contain one or more groups, each containing a subset
|
||||
* of the buttons/rings/strips available. gdk_device_pad_get_n_groups()
|
||||
* can be used to obtain the number of groups, gdk_device_pad_get_n_features()
|
||||
* and gdk_device_pad_get_feature_group() can be combined to find out the
|
||||
* number of buttons/rings/strips the device has, and how are they grouped.
|
||||
*
|
||||
* Each of those groups have different modes, which may be used to map
|
||||
* each individual pad feature to multiple actions. Only one mode is
|
||||
* effective (current) for each given group, different groups may have
|
||||
* different current modes. The number of available modes in a group can
|
||||
* be found out through gdk_device_pad_get_group_n_modes(), and the current
|
||||
* mode for a given group will be notified through the #GdkEventPadGroupMode
|
||||
* event.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkdevicepad.h"
|
||||
#include "gdkdevicepadprivate.h"
|
||||
#include "gdkdeviceprivate.h"
|
||||
|
||||
G_DEFINE_INTERFACE (GdkDevicePad, gdk_device_pad, GDK_TYPE_DEVICE)
|
||||
|
||||
static void
|
||||
gdk_device_pad_default_init (GdkDevicePadInterface *pad)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_pad_get_n_groups:
|
||||
* @pad: a #GdkDevicePad
|
||||
*
|
||||
* Returns the number of groups this pad device has. Pads have
|
||||
* at least one group. A pad group is a subcollection of
|
||||
* buttons/strip/rings that is affected collectively by a same
|
||||
* current mode.
|
||||
*
|
||||
* Returns: The number of button/ring/strip groups in the pad.
|
||||
*
|
||||
* Since: 3.22
|
||||
**/
|
||||
gint
|
||||
gdk_device_pad_get_n_groups (GdkDevicePad *pad)
|
||||
{
|
||||
GdkDevicePadInterface *iface = GDK_DEVICE_PAD_GET_IFACE (pad);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DEVICE_PAD (pad), 0);
|
||||
|
||||
return iface->get_n_groups (pad);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_pad_get_group_n_modes:
|
||||
* @pad: a #GdkDevicePad
|
||||
* @group_idx: group to get the number of available modes from
|
||||
*
|
||||
* Returns the number of modes that @group may have.
|
||||
*
|
||||
* Returns: The number of modes available in @group.
|
||||
*
|
||||
* Since: 3.22
|
||||
**/
|
||||
gint
|
||||
gdk_device_pad_get_group_n_modes (GdkDevicePad *pad,
|
||||
gint group_idx)
|
||||
{
|
||||
GdkDevicePadInterface *iface = GDK_DEVICE_PAD_GET_IFACE (pad);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DEVICE_PAD (pad), 0);
|
||||
g_return_val_if_fail (group_idx >= 0, 0);
|
||||
|
||||
return iface->get_group_n_modes (pad, group_idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_pad_get_n_features:
|
||||
* @pad: a #GdkDevicePad
|
||||
* @feature: a pad feature
|
||||
*
|
||||
* Returns the number of features a tablet pad has.
|
||||
*
|
||||
* Returns: The amount of elements of type @feature that this pad has.
|
||||
*
|
||||
* Since: 3.22
|
||||
**/
|
||||
gint
|
||||
gdk_device_pad_get_n_features (GdkDevicePad *pad,
|
||||
GdkDevicePadFeature feature)
|
||||
{
|
||||
GdkDevicePadInterface *iface = GDK_DEVICE_PAD_GET_IFACE (pad);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DEVICE_PAD (pad), 0);
|
||||
|
||||
return iface->get_n_features (pad, feature);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_pad_get_feature_group:
|
||||
* @pad: a #GdkDevicePad
|
||||
* @feature: the feature type to get the group from
|
||||
* @feature_idx: the index of the feature to get the group from
|
||||
*
|
||||
* Returns the group the given @feature and @idx belong to,
|
||||
* or -1 if feature/index do not exist in @pad.
|
||||
*
|
||||
* Returns: The group number of the queried pad feature.
|
||||
*
|
||||
* Since: 3.22
|
||||
**/
|
||||
gint
|
||||
gdk_device_pad_get_feature_group (GdkDevicePad *pad,
|
||||
GdkDevicePadFeature feature,
|
||||
gint idx)
|
||||
{
|
||||
GdkDevicePadInterface *iface = GDK_DEVICE_PAD_GET_IFACE (pad);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DEVICE_PAD (pad), -1);
|
||||
g_return_val_if_fail (idx >= 0, -1);
|
||||
|
||||
return iface->get_feature_group (pad, feature, idx);
|
||||
}
|
74
gdk/gdkdevicepad.h
Normal file
74
gdk/gdkdevicepad.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2016 Red Hat
|
||||
*
|
||||
* 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: Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GDK_DEVICE_PAD_H__
|
||||
#define __GDK_DEVICE_PAD_H__
|
||||
|
||||
#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION)
|
||||
#error "Only <gdk/gdk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdkversionmacros.h>
|
||||
#include <gdk/gdktypes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_DEVICE_PAD (gdk_device_pad_get_type ())
|
||||
#define GDK_DEVICE_PAD(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_DEVICE_PAD, GdkDevicePad))
|
||||
#define GDK_IS_DEVICE_PAD(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_DEVICE_PAD))
|
||||
|
||||
typedef struct _GdkDevicePad GdkDevicePad;
|
||||
typedef struct _GdkDevicePadInterface GdkDevicePadInterface;
|
||||
|
||||
/**
|
||||
* GdkDevicePadFeature:
|
||||
* @GDK_DEVICE_PAD_FEATURE_BUTTON: a button
|
||||
* @GDK_DEVICE_PAD_FEATURE_RING: a ring-shaped interactive area
|
||||
* @GDK_DEVICE_PAD_FEATURE_STRIP: a straight interactive area
|
||||
*
|
||||
* A pad feature.
|
||||
*/
|
||||
typedef enum {
|
||||
GDK_DEVICE_PAD_FEATURE_BUTTON,
|
||||
GDK_DEVICE_PAD_FEATURE_RING,
|
||||
GDK_DEVICE_PAD_FEATURE_STRIP
|
||||
} GdkDevicePadFeature;
|
||||
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
GType gdk_device_pad_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
gint gdk_device_pad_get_n_groups (GdkDevicePad *pad);
|
||||
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
gint gdk_device_pad_get_group_n_modes (GdkDevicePad *pad,
|
||||
gint group_idx);
|
||||
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
gint gdk_device_pad_get_n_features (GdkDevicePad *pad,
|
||||
GdkDevicePadFeature feature);
|
||||
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
gint gdk_device_pad_get_feature_group (GdkDevicePad *pad,
|
||||
GdkDevicePadFeature feature,
|
||||
gint feature_idx);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_DEVICE_PAD_H__ */
|
45
gdk/gdkdevicepadprivate.h
Normal file
45
gdk/gdkdevicepadprivate.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2016 Red Hat
|
||||
*
|
||||
* 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: Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GDK_DEVICE_PAD_PRIVATE_H__
|
||||
#define __GDK_DEVICE_PAD_PRIVATE_H__
|
||||
|
||||
#include "gdkdevicepad.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_DEVICE_PAD_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GDK_TYPE_DEVICE_PAD, GdkDevicePadInterface))
|
||||
|
||||
struct _GdkDevicePadInterface {
|
||||
GTypeInterface parent_interface;
|
||||
|
||||
gint (* get_n_groups) (GdkDevicePad *pad);
|
||||
|
||||
gint (* get_group_n_modes) (GdkDevicePad *pad,
|
||||
gint group);
|
||||
gint (* get_n_features) (GdkDevicePad *pad,
|
||||
GdkDevicePadFeature feature);
|
||||
gint (* get_feature_group) (GdkDevicePad *pad,
|
||||
GdkDevicePadFeature feature,
|
||||
gint idx);
|
||||
};
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_DEVICE_PAD_PRIVATE_H__ */
|
@@ -31,6 +31,7 @@ enum {
|
||||
TOOL_PROP_SERIAL,
|
||||
TOOL_PROP_TOOL_TYPE,
|
||||
TOOL_PROP_AXES,
|
||||
TOOL_PROP_HARDWARE_ID,
|
||||
N_TOOL_PROPS
|
||||
};
|
||||
|
||||
@@ -55,6 +56,9 @@ gdk_device_tool_set_property (GObject *object,
|
||||
case TOOL_PROP_AXES:
|
||||
tool->tool_axes = g_value_get_flags (value);
|
||||
break;
|
||||
case TOOL_PROP_HARDWARE_ID:
|
||||
tool->hw_id = g_value_get_uint64 (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -80,6 +84,9 @@ gdk_device_tool_get_property (GObject *object,
|
||||
case TOOL_PROP_AXES:
|
||||
g_value_set_flags (value, tool->tool_axes);
|
||||
break;
|
||||
case TOOL_PROP_HARDWARE_ID:
|
||||
g_value_set_uint64 (value, tool->hw_id);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -113,6 +120,12 @@ gdk_device_tool_class_init (GdkDeviceToolClass *klass)
|
||||
GDK_TYPE_AXIS_FLAGS, 0,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
tool_props[TOOL_PROP_HARDWARE_ID] = g_param_spec_uint64 ("hardware-id",
|
||||
"Hardware ID",
|
||||
"Hardware ID",
|
||||
0, G_MAXUINT64, 0,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_properties (object_class, N_TOOL_PROPS, tool_props);
|
||||
}
|
||||
@@ -124,11 +137,13 @@ gdk_device_tool_init (GdkDeviceTool *tool)
|
||||
|
||||
GdkDeviceTool *
|
||||
gdk_device_tool_new (guint64 serial,
|
||||
guint64 hw_id,
|
||||
GdkDeviceToolType type,
|
||||
GdkAxisFlags tool_axes)
|
||||
{
|
||||
return g_object_new (GDK_TYPE_DEVICE_TOOL,
|
||||
"serial", serial,
|
||||
"hardware-id", hw_id,
|
||||
"tool-type", type,
|
||||
"axes", tool_axes,
|
||||
NULL);
|
||||
@@ -153,6 +168,32 @@ gdk_device_tool_get_serial (GdkDeviceTool *tool)
|
||||
return tool->serial;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_tool_get_hardware_id:
|
||||
* @tool: a #GdkDeviceTool
|
||||
*
|
||||
* Gets the hardware ID of this tool, or 0 if it's not known. When
|
||||
* non-zero, the identificator is unique for the given tool model,
|
||||
* meaning that two identical tools will share the same @hardware_id,
|
||||
* but will have different serial numbers (see gdk_device_tool_get_serial()).
|
||||
*
|
||||
* This is a more concrete (and device specific) method to identify
|
||||
* a #GdkDeviceTool than gdk_device_tool_get_tool_type(), as a tablet
|
||||
* may support multiple devices with the same #GdkDeviceToolType,
|
||||
* but having different hardware identificators.
|
||||
*
|
||||
* Returns: The hardware identificator of this tool.
|
||||
*
|
||||
* Since: 3.22
|
||||
**/
|
||||
guint64
|
||||
gdk_device_tool_get_hardware_id (GdkDeviceTool *tool)
|
||||
{
|
||||
g_return_val_if_fail (tool != NULL, 0);
|
||||
|
||||
return tool->hw_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_tool_get_tool_type:
|
||||
* @tool: a #GdkDeviceTool
|
||||
|
@@ -67,6 +67,9 @@ GType gdk_device_tool_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
guint64 gdk_device_tool_get_serial (GdkDeviceTool *tool);
|
||||
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
guint64 gdk_device_tool_get_hardware_id (GdkDeviceTool *tool);
|
||||
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
GdkDeviceToolType gdk_device_tool_get_tool_type (GdkDeviceTool *tool);
|
||||
|
||||
|
@@ -28,6 +28,7 @@ struct _GdkDeviceTool
|
||||
{
|
||||
GObject parent_instance;
|
||||
guint64 serial;
|
||||
guint64 hw_id;
|
||||
GdkDeviceToolType type;
|
||||
GdkAxisFlags tool_axes;
|
||||
};
|
||||
@@ -38,6 +39,7 @@ struct _GdkDeviceToolClass
|
||||
};
|
||||
|
||||
GdkDeviceTool *gdk_device_tool_new (guint64 serial,
|
||||
guint64 hw_id,
|
||||
GdkDeviceToolType type,
|
||||
GdkAxisFlags tool_axes);
|
||||
|
||||
|
@@ -920,6 +920,14 @@ gdk_event_get_time (const GdkEvent *event)
|
||||
case GDK_DROP_START:
|
||||
case GDK_DROP_FINISHED:
|
||||
return event->dnd.time;
|
||||
case GDK_PAD_BUTTON_PRESS:
|
||||
case GDK_PAD_BUTTON_RELEASE:
|
||||
return event->pad_button.time;
|
||||
case GDK_PAD_RING:
|
||||
case GDK_PAD_STRIP:
|
||||
return event->pad_axis.time;
|
||||
case GDK_PAD_GROUP_MODE:
|
||||
return event->pad_group_mode.time;
|
||||
case GDK_CLIENT_EVENT:
|
||||
case GDK_VISIBILITY_NOTIFY:
|
||||
case GDK_CONFIGURE:
|
||||
@@ -1023,6 +1031,11 @@ gdk_event_get_state (const GdkEvent *event,
|
||||
case GDK_SETTING:
|
||||
case GDK_OWNER_CHANGE:
|
||||
case GDK_GRAB_BROKEN:
|
||||
case GDK_PAD_BUTTON_PRESS:
|
||||
case GDK_PAD_BUTTON_RELEASE:
|
||||
case GDK_PAD_RING:
|
||||
case GDK_PAD_STRIP:
|
||||
case GDK_PAD_GROUP_MODE:
|
||||
case GDK_EVENT_LAST:
|
||||
/* no state field */
|
||||
break;
|
||||
@@ -1213,6 +1226,10 @@ gdk_event_get_button (const GdkEvent *event,
|
||||
case GDK_BUTTON_RELEASE:
|
||||
number = event->button.button;
|
||||
break;
|
||||
case GDK_PAD_BUTTON_PRESS:
|
||||
case GDK_PAD_BUTTON_RELEASE:
|
||||
number = event->pad_button.button;
|
||||
break;
|
||||
default:
|
||||
fetched = FALSE;
|
||||
break;
|
||||
|
106
gdk/gdkevents.h
106
gdk/gdkevents.h
@@ -142,6 +142,9 @@ typedef struct _GdkEventSetting GdkEventSetting;
|
||||
typedef struct _GdkEventGrabBroken GdkEventGrabBroken;
|
||||
typedef struct _GdkEventTouchpadSwipe GdkEventTouchpadSwipe;
|
||||
typedef struct _GdkEventTouchpadPinch GdkEventTouchpadPinch;
|
||||
typedef struct _GdkEventPadButton GdkEventPadButton;
|
||||
typedef struct _GdkEventPadAxis GdkEventPadAxis;
|
||||
typedef struct _GdkEventPadGroupMode GdkEventPadGroupMode;
|
||||
|
||||
typedef struct _GdkEventSequence GdkEventSequence;
|
||||
|
||||
@@ -278,6 +281,16 @@ typedef GdkFilterReturn (*GdkFilterFunc) (GdkXEvent *xevent,
|
||||
* is determined by its phase field. This event type was added in 3.18.
|
||||
* @GDK_TOUCHPAD_PINCH: A touchpad pinch gesture event, the current state
|
||||
* is determined by its phase field. This event type was added in 3.18.
|
||||
* @GDK_PAD_BUTTON_PRESS: A tablet pad button press event. This event type
|
||||
* was added in 3.22.
|
||||
* @GDK_PAD_BUTTON_RELEASE: A tablet pad button release event. This event type
|
||||
* was added in 3.22.
|
||||
* @GDK_PAD_RING: A tablet pad axis event from a "ring". This event type was
|
||||
* added in 3.22.
|
||||
* @GDK_PAD_STRIP: A tablet pad axis event from a "strip". This event type was
|
||||
* added in 3.22.
|
||||
* @GDK_PAD_GROUP_MODE: A tablet pad group mode change. This event type was
|
||||
* added in 3.22.
|
||||
* @GDK_EVENT_LAST: marks the end of the GdkEventType enumeration. Added in 2.18
|
||||
*
|
||||
* Specifies the type of the event.
|
||||
@@ -340,6 +353,11 @@ typedef enum
|
||||
GDK_TOUCH_CANCEL = 40,
|
||||
GDK_TOUCHPAD_SWIPE = 41,
|
||||
GDK_TOUCHPAD_PINCH = 42,
|
||||
GDK_PAD_BUTTON_PRESS = 43,
|
||||
GDK_PAD_BUTTON_RELEASE = 44,
|
||||
GDK_PAD_RING = 45,
|
||||
GDK_PAD_STRIP = 46,
|
||||
GDK_PAD_GROUP_MODE = 47,
|
||||
GDK_EVENT_LAST /* helper variable for decls */
|
||||
} GdkEventType;
|
||||
|
||||
@@ -1240,6 +1258,86 @@ struct _GdkEventTouchpadPinch {
|
||||
guint state;
|
||||
};
|
||||
|
||||
/**
|
||||
* GdkEventPadButton:
|
||||
* @type: the type of the event (%GDK_PAD_BUTTON_PRESS or %GDK_PAD_BUTTON_RELEASE).
|
||||
* @window: the window which received the event.
|
||||
* @send_event: %TRUE if the event was sent explicitly.
|
||||
* @time: the time of the event in milliseconds.
|
||||
* @group: the pad group the button belongs to. A %GDK_SOURCE_TABLET_PAD device
|
||||
* may have one or more groups containing a set of buttons/rings/strips each.
|
||||
* @button: The pad button that was pressed.
|
||||
* @mode: The current mode of @group. Different groups in a %GDK_SOURCE_TABLET_PAD
|
||||
* device may have different current modes.
|
||||
*
|
||||
* Generated during %GDK_SOURCE_TABLET_PAD button presses and releases.
|
||||
*
|
||||
* Since: 3.22
|
||||
*/
|
||||
struct _GdkEventPadButton {
|
||||
GdkEventType type;
|
||||
GdkWindow *window;
|
||||
gint8 send_event;
|
||||
guint32 time;
|
||||
guint group;
|
||||
guint button;
|
||||
guint mode;
|
||||
};
|
||||
|
||||
/**
|
||||
* GdkEventPadAxis:
|
||||
* @type: the type of the event (%GDK_PAD_RING or %GDK_PAD_STRIP).
|
||||
* @window: the window which received the event.
|
||||
* @send_event: %TRUE if the event was sent explicitly.
|
||||
* @time: the time of the event in milliseconds.
|
||||
* @group: the pad group the ring/strip belongs to. A %GDK_SOURCE_TABLET_PAD
|
||||
* device may have one or more groups containing a set of buttons/rings/strips
|
||||
* each.
|
||||
* @index: number of strip/ring that was interacted. This number is 0-indexed.
|
||||
* @mode: The current mode of @group. Different groups in a %GDK_SOURCE_TABLET_PAD
|
||||
* device may have different current modes.
|
||||
* @value: The current value for the given axis.
|
||||
*
|
||||
* Generated during %GDK_SOURCE_TABLET_PAD interaction with tactile sensors.
|
||||
*
|
||||
* Since: 3.22
|
||||
*/
|
||||
struct _GdkEventPadAxis {
|
||||
GdkEventType type;
|
||||
GdkWindow *window;
|
||||
gint8 send_event;
|
||||
guint32 time;
|
||||
guint group;
|
||||
guint index;
|
||||
guint mode;
|
||||
gdouble value;
|
||||
};
|
||||
|
||||
/**
|
||||
* GdkEventPadGroupMode:
|
||||
* @type: the type of the event (%GDK_PAD_GROUP_MODE).
|
||||
* @window: the window which received the event.
|
||||
* @send_event: %TRUE if the event was sent explicitly.
|
||||
* @time: the time of the event in milliseconds.
|
||||
* @group: the pad group that is switching mode. A %GDK_SOURCE_TABLET_PAD
|
||||
* device may have one or more groups containing a set of buttons/rings/strips
|
||||
* each.
|
||||
* @mode: The new mode of @group. Different groups in a %GDK_SOURCE_TABLET_PAD
|
||||
* device may have different current modes.
|
||||
*
|
||||
* Generated during %GDK_SOURCE_TABLET_PAD mode switches in a group.
|
||||
*
|
||||
* Since: 3.22
|
||||
*/
|
||||
struct _GdkEventPadGroupMode {
|
||||
GdkEventType type;
|
||||
GdkWindow *window;
|
||||
gint8 send_event;
|
||||
guint32 time;
|
||||
guint group;
|
||||
guint mode;
|
||||
};
|
||||
|
||||
/**
|
||||
* GdkEvent:
|
||||
* @type: the #GdkEventType
|
||||
@@ -1262,6 +1360,11 @@ struct _GdkEventTouchpadPinch {
|
||||
* @window_state: a #GdkEventWindowState
|
||||
* @setting: a #GdkEventSetting
|
||||
* @grab_broken: a #GdkEventGrabBroken
|
||||
* @touchpad_swipe: a #GdkEventTouchpadSwipe
|
||||
* @touchpad_pinch: a #GdkEventTouchpadPinch
|
||||
* @pad_button: a #GdkEventPadButton
|
||||
* @pad_axis: a #GdkEventPadAxis
|
||||
* @pad_group_mode: a #GdkEventPadGroupMode
|
||||
*
|
||||
* A #GdkEvent contains a union of all of the event types,
|
||||
* and allows access to the data fields in a number of ways.
|
||||
@@ -1318,6 +1421,9 @@ union _GdkEvent
|
||||
GdkEventGrabBroken grab_broken;
|
||||
GdkEventTouchpadSwipe touchpad_swipe;
|
||||
GdkEventTouchpadPinch touchpad_pinch;
|
||||
GdkEventPadButton pad_button;
|
||||
GdkEventPadAxis pad_axis;
|
||||
GdkEventPadGroupMode pad_group_mode;
|
||||
};
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
|
@@ -394,6 +394,7 @@ typedef enum
|
||||
* @GDK_TOUCH_MASK: receive touch events. Since 3.4
|
||||
* @GDK_SMOOTH_SCROLL_MASK: receive smooth scrolling events. Since 3.4
|
||||
@GDK_TOUCHPAD_GESTURE_MASK: receive touchpad gesture events. Since 3.18
|
||||
* @GDK_TABLET_PAD_MASK: receive tablet pad events. Since 3.22
|
||||
* @GDK_ALL_EVENTS_MASK: the combination of all the above event masks.
|
||||
*
|
||||
* A set of bit-flags to indicate which events a window is to receive.
|
||||
@@ -449,6 +450,7 @@ typedef enum
|
||||
GDK_TOUCH_MASK = 1 << 22,
|
||||
GDK_SMOOTH_SCROLL_MASK = 1 << 23,
|
||||
GDK_TOUCHPAD_GESTURE_MASK = 1 << 24,
|
||||
GDK_TABLET_PAD_MASK = 1 << 25,
|
||||
GDK_ALL_EVENTS_MASK = 0xFFFFFE
|
||||
} GdkEventMask;
|
||||
|
||||
|
@@ -7960,6 +7960,11 @@ static const guint type_masks[] = {
|
||||
GDK_TOUCH_MASK, /* GDK_TOUCH_CANCEL = 40 */
|
||||
GDK_TOUCHPAD_GESTURE_MASK, /* GDK_TOUCHPAD_SWIPE = 41 */
|
||||
GDK_TOUCHPAD_GESTURE_MASK, /* GDK_TOUCHPAD_PINCH = 42 */
|
||||
GDK_TABLET_PAD_MASK, /* GDK_PAD_BUTTON_PRESS = 43 */
|
||||
GDK_TABLET_PAD_MASK, /* GDK_PAD_BUTTON_RELEASE = 44 */
|
||||
GDK_TABLET_PAD_MASK, /* GDK_PAD_RING = 45 */
|
||||
GDK_TABLET_PAD_MASK, /* GDK_PAD_STRIP = 46 */
|
||||
GDK_TABLET_PAD_MASK, /* GDK_PAD_GROUP_MODE = 47 */
|
||||
};
|
||||
G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
|
||||
|
||||
@@ -9855,7 +9860,8 @@ _gdk_windowing_got_event (GdkDisplay *display,
|
||||
|
||||
if (device)
|
||||
{
|
||||
if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
|
||||
if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD &&
|
||||
gdk_device_get_source (device) != GDK_SOURCE_TABLET_PAD)
|
||||
{
|
||||
pointer_info = _gdk_display_get_pointer_info (display, device);
|
||||
|
||||
|
@@ -29,6 +29,7 @@
|
||||
#include "gdkwayland.h"
|
||||
#include "gdkkeysyms.h"
|
||||
#include "gdkdeviceprivate.h"
|
||||
#include "gdkdevicepadprivate.h"
|
||||
#include "gdkdevicetoolprivate.h"
|
||||
#include "gdkdevicemanagerprivate.h"
|
||||
#include "gdkseatprivate.h"
|
||||
@@ -45,11 +46,16 @@
|
||||
|
||||
#define BUTTON_BASE (BTN_LEFT - 1) /* Used to translate to 1-indexed buttons */
|
||||
|
||||
typedef struct _GdkWaylandDevicePad GdkWaylandDevicePad;
|
||||
typedef struct _GdkWaylandDevicePadClass GdkWaylandDevicePadClass;
|
||||
|
||||
typedef struct _GdkWaylandTouchData GdkWaylandTouchData;
|
||||
typedef struct _GdkWaylandPointerFrameData GdkWaylandPointerFrameData;
|
||||
typedef struct _GdkWaylandPointerData GdkWaylandPointerData;
|
||||
typedef struct _GdkWaylandTabletData GdkWaylandTabletData;
|
||||
typedef struct _GdkWaylandTabletToolData GdkWaylandTabletToolData;
|
||||
typedef struct _GdkWaylandTabletPadGroupData GdkWaylandTabletPadGroupData;
|
||||
typedef struct _GdkWaylandTabletPadData GdkWaylandTabletPadData;
|
||||
|
||||
struct _GdkWaylandTouchData
|
||||
{
|
||||
@@ -112,6 +118,42 @@ struct _GdkWaylandTabletToolData
|
||||
GdkWaylandTabletData *current_tablet;
|
||||
};
|
||||
|
||||
struct _GdkWaylandTabletPadGroupData
|
||||
{
|
||||
GdkWaylandTabletPadData *pad;
|
||||
struct zwp_tablet_pad_group_v2 *wp_tablet_pad_group;
|
||||
GList *rings;
|
||||
GList *strips;
|
||||
GList *buttons;
|
||||
|
||||
guint mode_switch_serial;
|
||||
guint n_modes;
|
||||
guint current_mode;
|
||||
|
||||
struct {
|
||||
guint source;
|
||||
gboolean is_stop;
|
||||
gdouble value;
|
||||
} axis_tmp_info;
|
||||
};
|
||||
|
||||
struct _GdkWaylandTabletPadData
|
||||
{
|
||||
GdkSeat *seat;
|
||||
struct zwp_tablet_pad_v2 *wp_tablet_pad;
|
||||
GdkDevice *device;
|
||||
|
||||
GdkWaylandTabletData *current_tablet;
|
||||
|
||||
guint enter_serial;
|
||||
uint32_t n_buttons;
|
||||
gchar *path;
|
||||
|
||||
GList *rings;
|
||||
GList *strips;
|
||||
GList *mode_groups;
|
||||
};
|
||||
|
||||
struct _GdkWaylandTabletData
|
||||
{
|
||||
struct zwp_tablet_v2 *wp_tablet;
|
||||
@@ -127,6 +169,8 @@ struct _GdkWaylandTabletData
|
||||
GdkSeat *seat;
|
||||
GdkWaylandPointerData pointer_info;
|
||||
|
||||
GList *pads;
|
||||
|
||||
GdkWaylandTabletToolData *current_tool;
|
||||
|
||||
gint axis_indices[GDK_AXIS_LAST];
|
||||
@@ -164,6 +208,7 @@ struct _GdkWaylandSeat
|
||||
GHashTable *touches;
|
||||
GList *tablets;
|
||||
GList *tablet_tools;
|
||||
GList *tablet_pads;
|
||||
|
||||
GdkWaylandPointerData pointer_info;
|
||||
GdkWaylandPointerData touch_info;
|
||||
@@ -216,6 +261,25 @@ struct _GdkWaylandDeviceClass
|
||||
|
||||
G_DEFINE_TYPE (GdkWaylandDevice, gdk_wayland_device, GDK_TYPE_DEVICE)
|
||||
|
||||
struct _GdkWaylandDevicePad
|
||||
{
|
||||
GdkWaylandDevice parent_instance;
|
||||
};
|
||||
|
||||
struct _GdkWaylandDevicePadClass
|
||||
{
|
||||
GdkWaylandDeviceClass parent_class;
|
||||
};
|
||||
|
||||
static void gdk_wayland_device_pad_iface_init (GdkDevicePadInterface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GdkWaylandDevicePad, gdk_wayland_device_pad,
|
||||
GDK_TYPE_WAYLAND_DEVICE,
|
||||
G_IMPLEMENT_INTERFACE (GDK_TYPE_DEVICE_PAD,
|
||||
gdk_wayland_device_pad_iface_init))
|
||||
|
||||
#define GDK_TYPE_WAYLAND_DEVICE_PAD (gdk_wayland_device_pad_get_type ())
|
||||
|
||||
#define GDK_TYPE_WAYLAND_DEVICE_MANAGER (gdk_wayland_device_manager_get_type ())
|
||||
#define GDK_WAYLAND_DEVICE_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_WAYLAND_DEVICE_MANAGER, GdkWaylandDeviceManager))
|
||||
#define GDK_WAYLAND_DEVICE_MANAGER_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_WAYLAND_DEVICE_MANAGER, GdkWaylandDeviceManagerClass))
|
||||
@@ -308,6 +372,24 @@ gdk_wayland_device_manager_find_tablet (GdkWaylandSeat *seat,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GdkWaylandTabletPadData *
|
||||
gdk_wayland_device_manager_find_pad (GdkWaylandSeat *seat,
|
||||
GdkDevice *device)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = seat->tablet_pads; l; l = l->next)
|
||||
{
|
||||
GdkWaylandTabletPadData *pad = l->data;
|
||||
|
||||
if (pad->device == device)
|
||||
return pad;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
gdk_wayland_device_update_window_cursor (GdkDevice *device)
|
||||
{
|
||||
@@ -790,6 +872,131 @@ gdk_wayland_device_init (GdkWaylandDevice *device_core)
|
||||
_gdk_device_add_axis (device, GDK_NONE, GDK_AXIS_Y, 0, 0, 1);
|
||||
}
|
||||
|
||||
static gint
|
||||
gdk_wayland_device_pad_get_n_groups (GdkDevicePad *pad)
|
||||
{
|
||||
GdkSeat *seat = gdk_device_get_seat (GDK_DEVICE (pad));
|
||||
GdkWaylandTabletPadData *data;
|
||||
|
||||
data = gdk_wayland_device_manager_find_pad (GDK_WAYLAND_SEAT (seat),
|
||||
GDK_DEVICE (pad));
|
||||
g_assert (data != NULL);
|
||||
|
||||
return g_list_length (data->mode_groups);
|
||||
}
|
||||
|
||||
static gint
|
||||
gdk_wayland_device_pad_get_group_n_modes (GdkDevicePad *pad,
|
||||
gint n_group)
|
||||
{
|
||||
GdkSeat *seat = gdk_device_get_seat (GDK_DEVICE (pad));
|
||||
GdkWaylandTabletPadGroupData *group;
|
||||
GdkWaylandTabletPadData *data;
|
||||
|
||||
data = gdk_wayland_device_manager_find_pad (GDK_WAYLAND_SEAT (seat),
|
||||
GDK_DEVICE (pad));
|
||||
g_assert (data != NULL);
|
||||
|
||||
group = g_list_nth_data (data->mode_groups, n_group);
|
||||
if (!group)
|
||||
return -1;
|
||||
|
||||
return group->n_modes;
|
||||
}
|
||||
|
||||
static gint
|
||||
gdk_wayland_device_pad_get_n_features (GdkDevicePad *pad,
|
||||
GdkDevicePadFeature feature)
|
||||
{
|
||||
GdkSeat *seat = gdk_device_get_seat (GDK_DEVICE (pad));
|
||||
GdkWaylandTabletPadData *data;
|
||||
|
||||
data = gdk_wayland_device_manager_find_pad (GDK_WAYLAND_SEAT (seat),
|
||||
GDK_DEVICE (pad));
|
||||
g_assert (data != NULL);
|
||||
|
||||
switch (feature)
|
||||
{
|
||||
case GDK_DEVICE_PAD_FEATURE_BUTTON:
|
||||
return data->n_buttons;
|
||||
case GDK_DEVICE_PAD_FEATURE_RING:
|
||||
return g_list_length (data->rings);
|
||||
case GDK_DEVICE_PAD_FEATURE_STRIP:
|
||||
return g_list_length (data->strips);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static gint
|
||||
gdk_wayland_device_pad_get_feature_group (GdkDevicePad *pad,
|
||||
GdkDevicePadFeature feature,
|
||||
gint idx)
|
||||
{
|
||||
GdkSeat *seat = gdk_device_get_seat (GDK_DEVICE (pad));
|
||||
GdkWaylandTabletPadGroupData *group;
|
||||
GdkWaylandTabletPadData *data;
|
||||
GList *l;
|
||||
gint i;
|
||||
|
||||
data = gdk_wayland_device_manager_find_pad (GDK_WAYLAND_SEAT (seat),
|
||||
GDK_DEVICE (pad));
|
||||
g_assert (data != NULL);
|
||||
|
||||
for (l = data->mode_groups, i = 0; l; l = l->next, i++)
|
||||
{
|
||||
group = l->data;
|
||||
|
||||
switch (feature)
|
||||
{
|
||||
case GDK_DEVICE_PAD_FEATURE_BUTTON:
|
||||
if (g_list_find (group->buttons, GINT_TO_POINTER (idx)))
|
||||
return i;
|
||||
break;
|
||||
case GDK_DEVICE_PAD_FEATURE_RING:
|
||||
{
|
||||
gpointer ring;
|
||||
|
||||
ring = g_list_nth_data (data->rings, idx);
|
||||
if (ring && g_list_find (group->rings, ring))
|
||||
return i;
|
||||
break;
|
||||
}
|
||||
case GDK_DEVICE_PAD_FEATURE_STRIP:
|
||||
{
|
||||
gpointer strip;
|
||||
strip = g_list_nth_data (data->strips, idx);
|
||||
if (strip && g_list_find (group->strips, strip))
|
||||
return i;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_device_pad_iface_init (GdkDevicePadInterface *iface)
|
||||
{
|
||||
iface->get_n_groups = gdk_wayland_device_pad_get_n_groups;
|
||||
iface->get_group_n_modes = gdk_wayland_device_pad_get_group_n_modes;
|
||||
iface->get_n_features = gdk_wayland_device_pad_get_n_features;
|
||||
iface->get_feature_group = gdk_wayland_device_pad_get_feature_group;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_device_pad_class_init (GdkWaylandDevicePadClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_device_pad_init (GdkWaylandDevicePad *pad)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_wayland_device_get_wl_seat:
|
||||
* @device: (type GdkWaylandDevice): a #GdkDevice
|
||||
@@ -2551,6 +2758,43 @@ _gdk_wayland_seat_remove_tablet (GdkWaylandSeat *seat,
|
||||
g_free (tablet);
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_wayland_seat_remove_tablet_pad (GdkWaylandSeat *seat,
|
||||
GdkWaylandTabletPadData *pad)
|
||||
{
|
||||
GdkWaylandDeviceManager *device_manager =
|
||||
GDK_WAYLAND_DEVICE_MANAGER (seat->device_manager);
|
||||
|
||||
seat->tablet_pads = g_list_remove (seat->tablet_pads, pad);
|
||||
|
||||
device_manager->devices =
|
||||
g_list_remove (device_manager->devices, pad->device);
|
||||
g_signal_emit_by_name (device_manager, "device-removed", pad->device);
|
||||
|
||||
_gdk_device_set_associated_device (pad->device, NULL);
|
||||
|
||||
g_object_unref (pad->device);
|
||||
g_free (pad);
|
||||
}
|
||||
|
||||
static GdkWaylandTabletPadGroupData *
|
||||
tablet_pad_lookup_button_group (GdkWaylandTabletPadData *pad,
|
||||
uint32_t button)
|
||||
{
|
||||
GdkWaylandTabletPadGroupData *group;
|
||||
GList *l;
|
||||
|
||||
for (l = pad->mode_groups; l; l = l->next)
|
||||
{
|
||||
group = l->data;
|
||||
|
||||
if (g_list_find (group->buttons, GUINT_TO_POINTER (button)))
|
||||
return group;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_handle_name (void *data,
|
||||
struct zwp_tablet_v2 *wp_tablet,
|
||||
@@ -3105,7 +3349,9 @@ tablet_tool_handle_done (void *data,
|
||||
{
|
||||
GdkWaylandTabletToolData *tool = data;
|
||||
|
||||
tool->tool = gdk_device_tool_new (tool->hardware_serial, tool->type, tool->axes);
|
||||
tool->tool = gdk_device_tool_new (tool->hardware_serial,
|
||||
tool->hardware_id_wacom,
|
||||
tool->type, tool->axes);
|
||||
gdk_seat_tool_added (tool->seat, tool->tool);
|
||||
}
|
||||
|
||||
@@ -3617,6 +3863,437 @@ static const struct zwp_tablet_tool_v2_listener tablet_tool_listener = {
|
||||
tablet_tool_handle_frame,
|
||||
};
|
||||
|
||||
static void
|
||||
tablet_pad_ring_handle_source (void *data,
|
||||
struct zwp_tablet_pad_ring_v2 *wp_tablet_pad_ring,
|
||||
uint32_t source)
|
||||
{
|
||||
GdkWaylandTabletPadGroupData *group = data;
|
||||
|
||||
g_debug (G_STRLOC ": %s ring = %p source = %d",
|
||||
G_STRFUNC, wp_tablet_pad_ring, source);
|
||||
|
||||
group->axis_tmp_info.source = source;
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_ring_handle_angle (void *data,
|
||||
struct zwp_tablet_pad_ring_v2 *wp_tablet_pad_ring,
|
||||
wl_fixed_t angle)
|
||||
{
|
||||
GdkWaylandTabletPadGroupData *group = data;
|
||||
|
||||
g_debug (G_STRLOC ": %s ring = %p angle = %f",
|
||||
G_STRFUNC, wp_tablet_pad_ring, wl_fixed_to_double (angle));
|
||||
|
||||
group->axis_tmp_info.value = wl_fixed_to_double (angle);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_ring_handle_stop (void *data,
|
||||
struct zwp_tablet_pad_ring_v2 *wp_tablet_pad_ring)
|
||||
{
|
||||
GdkWaylandTabletPadGroupData *group = data;
|
||||
|
||||
g_debug (G_STRLOC ": %s ring = %p", G_STRFUNC, wp_tablet_pad_ring);
|
||||
|
||||
group->axis_tmp_info.is_stop = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_ring_handle_frame (void *data,
|
||||
struct zwp_tablet_pad_ring_v2 *wp_tablet_pad_ring,
|
||||
uint32_t time)
|
||||
{
|
||||
GdkWaylandTabletPadGroupData *group = data;
|
||||
GdkWaylandTabletPadData *pad = group->pad;
|
||||
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
|
||||
GdkEvent *event;
|
||||
|
||||
g_debug (G_STRLOC ": %s ring = %p", G_STRFUNC, wp_tablet_pad_ring);
|
||||
|
||||
event = gdk_event_new (GDK_PAD_RING);
|
||||
g_set_object (&event->pad_axis.window, seat->keyboard_focus);
|
||||
event->pad_axis.time = time;
|
||||
event->pad_axis.group = g_list_index (pad->mode_groups, group);
|
||||
event->pad_axis.index = g_list_index (pad->rings, wp_tablet_pad_ring);
|
||||
event->pad_axis.mode = group->current_mode;
|
||||
event->pad_axis.value = group->axis_tmp_info.value;
|
||||
gdk_event_set_device (event, pad->device);
|
||||
gdk_event_set_source_device (event, pad->device);
|
||||
|
||||
_gdk_wayland_display_deliver_event (gdk_seat_get_display (pad->seat),
|
||||
event);
|
||||
}
|
||||
|
||||
static const struct zwp_tablet_pad_ring_v2_listener tablet_pad_ring_listener = {
|
||||
tablet_pad_ring_handle_source,
|
||||
tablet_pad_ring_handle_angle,
|
||||
tablet_pad_ring_handle_stop,
|
||||
tablet_pad_ring_handle_frame,
|
||||
};
|
||||
|
||||
static void
|
||||
tablet_pad_strip_handle_source (void *data,
|
||||
struct zwp_tablet_pad_strip_v2 *wp_tablet_pad_strip,
|
||||
uint32_t source)
|
||||
{
|
||||
GdkWaylandTabletPadGroupData *group = data;
|
||||
|
||||
g_debug (G_STRLOC ": %s strip = %p source = %d",
|
||||
G_STRFUNC, wp_tablet_pad_strip, source);
|
||||
|
||||
group->axis_tmp_info.source = source;
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_strip_handle_position (void *data,
|
||||
struct zwp_tablet_pad_strip_v2 *wp_tablet_pad_strip,
|
||||
uint32_t position)
|
||||
{
|
||||
GdkWaylandTabletPadGroupData *group = data;
|
||||
|
||||
g_debug (G_STRLOC ": %s strip = %p position = %d",
|
||||
G_STRFUNC, wp_tablet_pad_strip, position);
|
||||
|
||||
group->axis_tmp_info.value = (gdouble) position / 65535;
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_strip_handle_stop (void *data,
|
||||
struct zwp_tablet_pad_strip_v2 *wp_tablet_pad_strip)
|
||||
{
|
||||
GdkWaylandTabletPadGroupData *group = data;
|
||||
|
||||
g_debug (G_STRLOC ": %s strip = %p",
|
||||
G_STRFUNC, wp_tablet_pad_strip);
|
||||
|
||||
group->axis_tmp_info.is_stop = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_strip_handle_frame (void *data,
|
||||
struct zwp_tablet_pad_strip_v2 *wp_tablet_pad_strip,
|
||||
uint32_t time)
|
||||
{
|
||||
GdkWaylandTabletPadGroupData *group = data;
|
||||
GdkWaylandTabletPadData *pad = group->pad;
|
||||
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
|
||||
GdkEvent *event;
|
||||
|
||||
g_debug (G_STRLOC ": %s strip = %p",
|
||||
G_STRFUNC, wp_tablet_pad_strip);
|
||||
|
||||
event = gdk_event_new (GDK_PAD_STRIP);
|
||||
g_set_object (&event->pad_axis.window, seat->keyboard_focus);
|
||||
event->pad_axis.time = time;
|
||||
event->pad_axis.group = g_list_index (pad->mode_groups, group);
|
||||
event->pad_axis.index = g_list_index (pad->strips, wp_tablet_pad_strip);
|
||||
event->pad_axis.mode = group->current_mode;
|
||||
event->pad_axis.value = group->axis_tmp_info.value;
|
||||
|
||||
gdk_event_set_device (event, pad->device);
|
||||
gdk_event_set_source_device (event, pad->device);
|
||||
|
||||
_gdk_wayland_display_deliver_event (gdk_seat_get_display (pad->seat),
|
||||
event);
|
||||
}
|
||||
|
||||
static const struct zwp_tablet_pad_strip_v2_listener tablet_pad_strip_listener = {
|
||||
tablet_pad_strip_handle_source,
|
||||
tablet_pad_strip_handle_position,
|
||||
tablet_pad_strip_handle_stop,
|
||||
tablet_pad_strip_handle_frame,
|
||||
};
|
||||
|
||||
static void
|
||||
tablet_pad_group_handle_buttons (void *data,
|
||||
struct zwp_tablet_pad_group_v2 *wp_tablet_pad_group,
|
||||
struct wl_array *buttons)
|
||||
{
|
||||
GdkWaylandTabletPadGroupData *group = data;
|
||||
uint32_t *p;
|
||||
|
||||
g_debug (G_STRLOC ": %s pad group = %p, n_buttons = %ld",
|
||||
G_STRFUNC, wp_tablet_pad_group, buttons->size);
|
||||
|
||||
wl_array_for_each (p, buttons)
|
||||
{
|
||||
group->buttons = g_list_prepend (group->buttons, GUINT_TO_POINTER (*p));
|
||||
}
|
||||
|
||||
group->buttons = g_list_reverse (group->buttons);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_group_handle_ring (void *data,
|
||||
struct zwp_tablet_pad_group_v2 *wp_tablet_pad_group,
|
||||
struct zwp_tablet_pad_ring_v2 *wp_tablet_pad_ring)
|
||||
{
|
||||
GdkWaylandTabletPadGroupData *group = data;
|
||||
|
||||
g_debug (G_STRLOC ": %s pad group = %p, ring = %p",
|
||||
G_STRFUNC, wp_tablet_pad_group, wp_tablet_pad_ring);
|
||||
|
||||
zwp_tablet_pad_ring_v2_add_listener (wp_tablet_pad_ring,
|
||||
&tablet_pad_ring_listener, group);
|
||||
zwp_tablet_pad_ring_v2_set_user_data (wp_tablet_pad_ring, group);
|
||||
|
||||
group->rings = g_list_append (group->rings, wp_tablet_pad_ring);
|
||||
group->pad->rings = g_list_append (group->pad->rings, wp_tablet_pad_ring);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_group_handle_strip (void *data,
|
||||
struct zwp_tablet_pad_group_v2 *wp_tablet_pad_group,
|
||||
struct zwp_tablet_pad_strip_v2 *wp_tablet_pad_strip)
|
||||
{
|
||||
GdkWaylandTabletPadGroupData *group = data;
|
||||
|
||||
g_debug (G_STRLOC ": %s pad group = %p, strip = %p",
|
||||
G_STRFUNC, wp_tablet_pad_group, wp_tablet_pad_strip);
|
||||
|
||||
zwp_tablet_pad_strip_v2_add_listener (wp_tablet_pad_strip,
|
||||
&tablet_pad_strip_listener, group);
|
||||
zwp_tablet_pad_strip_v2_set_user_data (wp_tablet_pad_strip, group);
|
||||
|
||||
group->strips = g_list_append (group->strips, wp_tablet_pad_strip);
|
||||
group->pad->strips = g_list_append (group->pad->strips, wp_tablet_pad_strip);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_group_handle_modes (void *data,
|
||||
struct zwp_tablet_pad_group_v2 *wp_tablet_pad_group,
|
||||
uint32_t modes)
|
||||
{
|
||||
GdkWaylandTabletPadGroupData *group = data;
|
||||
|
||||
g_debug (G_STRLOC ": %s pad group = %p, n_modes = %d",
|
||||
G_STRFUNC, wp_tablet_pad_group, modes);
|
||||
|
||||
group->n_modes = modes;
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_group_handle_done (void *data,
|
||||
struct zwp_tablet_pad_group_v2 *wp_tablet_pad_group)
|
||||
{
|
||||
g_debug (G_STRLOC ": %s pad group = %p", G_STRFUNC, wp_tablet_pad_group);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_group_handle_mode (void *data,
|
||||
struct zwp_tablet_pad_group_v2 *wp_tablet_pad_group,
|
||||
uint32_t time,
|
||||
uint32_t serial,
|
||||
uint32_t mode)
|
||||
{
|
||||
GdkWaylandTabletPadGroupData *group = data;
|
||||
GdkWaylandTabletPadData *pad = group->pad;
|
||||
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
|
||||
GdkEvent *event;
|
||||
guint n_group;
|
||||
|
||||
g_debug (G_STRLOC ": %s pad group = %p, mode = %d",
|
||||
G_STRFUNC, wp_tablet_pad_group, mode);
|
||||
|
||||
group->mode_switch_serial = serial;
|
||||
group->current_mode = mode;
|
||||
n_group = g_list_index (pad->mode_groups, group);
|
||||
|
||||
event = gdk_event_new (GDK_PAD_GROUP_MODE);
|
||||
g_set_object (&event->pad_button.window, seat->keyboard_focus);
|
||||
event->pad_group_mode.group = n_group;
|
||||
event->pad_group_mode.mode = mode;
|
||||
event->pad_group_mode.time = time;
|
||||
gdk_event_set_device (event, pad->device);
|
||||
gdk_event_set_source_device (event, pad->device);
|
||||
|
||||
_gdk_wayland_display_deliver_event (gdk_seat_get_display (pad->seat),
|
||||
event);
|
||||
}
|
||||
|
||||
static const struct zwp_tablet_pad_group_v2_listener tablet_pad_group_listener = {
|
||||
tablet_pad_group_handle_buttons,
|
||||
tablet_pad_group_handle_ring,
|
||||
tablet_pad_group_handle_strip,
|
||||
tablet_pad_group_handle_modes,
|
||||
tablet_pad_group_handle_done,
|
||||
tablet_pad_group_handle_mode,
|
||||
};
|
||||
|
||||
static void
|
||||
tablet_pad_handle_group (void *data,
|
||||
struct zwp_tablet_pad_v2 *wp_tablet_pad,
|
||||
struct zwp_tablet_pad_group_v2 *wp_tablet_pad_group)
|
||||
{
|
||||
GdkWaylandTabletPadData *pad = data;
|
||||
GdkWaylandTabletPadGroupData *group;
|
||||
|
||||
g_debug (G_STRLOC ": %s pad group = %p, group = %p",
|
||||
G_STRFUNC, wp_tablet_pad_group, wp_tablet_pad_group);
|
||||
|
||||
group = g_new0 (GdkWaylandTabletPadGroupData, 1);
|
||||
group->wp_tablet_pad_group = wp_tablet_pad_group;
|
||||
group->pad = pad;
|
||||
|
||||
zwp_tablet_pad_group_v2_add_listener (wp_tablet_pad_group,
|
||||
&tablet_pad_group_listener, group);
|
||||
zwp_tablet_pad_group_v2_set_user_data (wp_tablet_pad_group, group);
|
||||
pad->mode_groups = g_list_append (pad->mode_groups, group);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_handle_path (void *data,
|
||||
struct zwp_tablet_pad_v2 *wp_tablet_pad,
|
||||
const char *path)
|
||||
{
|
||||
GdkWaylandTabletPadData *pad = data;
|
||||
|
||||
g_debug (G_STRLOC ": %s pad = %p, path = %s",
|
||||
G_STRFUNC, wp_tablet_pad, path);
|
||||
|
||||
pad->path = g_strdup (path);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_handle_buttons (void *data,
|
||||
struct zwp_tablet_pad_v2 *wp_tablet_pad,
|
||||
uint32_t buttons)
|
||||
{
|
||||
GdkWaylandTabletPadData *pad = data;
|
||||
|
||||
g_debug (G_STRLOC ": %s pad = %p, n_buttons = %d",
|
||||
G_STRFUNC, wp_tablet_pad, buttons);
|
||||
|
||||
pad->n_buttons = buttons;
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_handle_done (void *data,
|
||||
struct zwp_tablet_pad_v2 *wp_tablet_pad)
|
||||
{
|
||||
GdkWaylandTabletPadData *pad = data;
|
||||
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
|
||||
GdkWaylandDeviceManager *device_manager =
|
||||
GDK_WAYLAND_DEVICE_MANAGER (seat->device_manager);
|
||||
|
||||
g_debug (G_STRLOC ": %s pad = %p", G_STRFUNC, wp_tablet_pad);
|
||||
|
||||
pad->device =
|
||||
g_object_new (GDK_TYPE_WAYLAND_DEVICE_PAD,
|
||||
"name", "Pad device",
|
||||
"type", GDK_DEVICE_TYPE_SLAVE,
|
||||
"input-source", GDK_SOURCE_TABLET_PAD,
|
||||
"input-mode", GDK_MODE_SCREEN,
|
||||
"display", gdk_seat_get_display (pad->seat),
|
||||
"device-manager", device_manager,
|
||||
"seat", seat,
|
||||
NULL);
|
||||
|
||||
_gdk_device_set_associated_device (pad->device, seat->master_keyboard);
|
||||
g_signal_emit_by_name (device_manager, "device-added", pad->device);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_handle_button (void *data,
|
||||
struct zwp_tablet_pad_v2 *wp_tablet_pad,
|
||||
uint32_t time,
|
||||
uint32_t button,
|
||||
uint32_t state)
|
||||
{
|
||||
GdkWaylandTabletPadData *pad = data;
|
||||
GdkWaylandTabletPadGroupData *group;
|
||||
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
|
||||
GdkEvent *event;
|
||||
gint n_group;
|
||||
|
||||
g_debug (G_STRLOC ": %s pad = %p, button = %d, state = %d",
|
||||
G_STRFUNC, wp_tablet_pad, button, state);
|
||||
|
||||
group = tablet_pad_lookup_button_group (pad, button);
|
||||
n_group = g_list_index (pad->mode_groups, group);
|
||||
|
||||
event = gdk_event_new (state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED ?
|
||||
GDK_PAD_BUTTON_PRESS :
|
||||
GDK_PAD_BUTTON_RELEASE);
|
||||
g_set_object (&event->pad_button.window, seat->keyboard_focus);
|
||||
event->pad_button.button = button;
|
||||
event->pad_button.group = n_group;
|
||||
event->pad_button.mode = group->current_mode;
|
||||
event->pad_button.time = time;
|
||||
gdk_event_set_device (event, pad->device);
|
||||
gdk_event_set_source_device (event, pad->device);
|
||||
|
||||
_gdk_wayland_display_deliver_event (gdk_seat_get_display (pad->seat),
|
||||
event);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_handle_enter (void *data,
|
||||
struct zwp_tablet_pad_v2 *wp_tablet_pad,
|
||||
uint32_t serial,
|
||||
struct zwp_tablet_v2 *wp_tablet,
|
||||
struct wl_surface *surface)
|
||||
{
|
||||
GdkWaylandTabletPadData *pad = data;
|
||||
GdkWaylandTabletData *tablet = zwp_tablet_v2_get_user_data (wp_tablet);
|
||||
|
||||
g_debug (G_STRLOC ": %s pad = %p, tablet = %p surface = %p",
|
||||
G_STRFUNC, wp_tablet_pad, wp_tablet, surface);
|
||||
|
||||
/* Relate pad and tablet */
|
||||
tablet->pads = g_list_prepend (tablet->pads, pad);
|
||||
pad->current_tablet = tablet;
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_handle_leave (void *data,
|
||||
struct zwp_tablet_pad_v2 *wp_tablet_pad,
|
||||
uint32_t serial,
|
||||
struct wl_surface *surface)
|
||||
{
|
||||
GdkWaylandTabletPadData *pad = data;
|
||||
|
||||
g_debug (G_STRLOC ": %s pad = %p, surface = %p",
|
||||
G_STRFUNC, wp_tablet_pad, surface);
|
||||
|
||||
if (pad->current_tablet)
|
||||
{
|
||||
pad->current_tablet->pads = g_list_remove (pad->current_tablet->pads, pad);
|
||||
pad->current_tablet = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_handle_removed (void *data,
|
||||
struct zwp_tablet_pad_v2 *wp_tablet_pad)
|
||||
{
|
||||
GdkWaylandTabletPadData *pad = data;
|
||||
|
||||
g_debug (G_STRLOC ": %s pad = %p", G_STRFUNC, wp_tablet_pad);
|
||||
|
||||
/* Remove from the current tablet */
|
||||
if (pad->current_tablet)
|
||||
{
|
||||
pad->current_tablet->pads = g_list_remove (pad->current_tablet->pads, pad);
|
||||
pad->current_tablet = NULL;
|
||||
}
|
||||
|
||||
_gdk_wayland_seat_remove_tablet_pad (GDK_WAYLAND_SEAT (pad->seat), pad);
|
||||
}
|
||||
|
||||
static const struct zwp_tablet_pad_v2_listener tablet_pad_listener = {
|
||||
tablet_pad_handle_group,
|
||||
tablet_pad_handle_path,
|
||||
tablet_pad_handle_buttons,
|
||||
tablet_pad_handle_done,
|
||||
tablet_pad_handle_button,
|
||||
tablet_pad_handle_enter,
|
||||
tablet_pad_handle_leave,
|
||||
tablet_pad_handle_removed,
|
||||
};
|
||||
|
||||
static void
|
||||
tablet_seat_handle_tablet_added (void *data,
|
||||
struct zwp_tablet_seat_v2 *wp_tablet_seat,
|
||||
@@ -3662,8 +4339,17 @@ tablet_seat_handle_pad_added (void *data,
|
||||
struct zwp_tablet_seat_v2 *wp_tablet_seat,
|
||||
struct zwp_tablet_pad_v2 *wp_tablet_pad)
|
||||
{
|
||||
/* Unhandled at the moment */
|
||||
zwp_tablet_pad_v2_destroy (wp_tablet_pad);
|
||||
GdkWaylandSeat *seat = data;
|
||||
GdkWaylandTabletPadData *pad;
|
||||
|
||||
pad = g_new0 (GdkWaylandTabletPadData, 1);
|
||||
pad->wp_tablet_pad = wp_tablet_pad;
|
||||
pad->seat = GDK_SEAT (seat);
|
||||
|
||||
zwp_tablet_pad_v2_add_listener (wp_tablet_pad, &tablet_pad_listener, pad);
|
||||
zwp_tablet_pad_v2_set_user_data (wp_tablet_pad, pad);
|
||||
|
||||
seat->tablet_pads = g_list_prepend (seat->tablet_pads, pad);
|
||||
}
|
||||
|
||||
static const struct zwp_tablet_seat_v2_listener tablet_seat_listener = {
|
||||
@@ -3827,6 +4513,9 @@ gdk_wayland_seat_finalize (GObject *object)
|
||||
for (l = seat->tablet_tools; l != NULL; l = l->next)
|
||||
_gdk_wayland_seat_remove_tool (seat, l->data);
|
||||
|
||||
for (l = seat->tablet_pads; l != NULL; l = l->next)
|
||||
_gdk_wayland_seat_remove_tablet_pad (seat, l->data);
|
||||
|
||||
for (l = seat->tablets; l != NULL; l = l->next)
|
||||
_gdk_wayland_seat_remove_tablet (seat, l->data);
|
||||
|
||||
@@ -4476,3 +5165,102 @@ gdk_wayland_device_get_drop_context (GdkDevice *device)
|
||||
|
||||
return GDK_WAYLAND_SEAT (seat)->drop_context;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_wayland_device_get_node_path:
|
||||
* @device: a #GdkDevice
|
||||
*
|
||||
* Returns the /dev/input/event* path of this device.
|
||||
* For #GdkDevices that possibly coalesce multiple hardware
|
||||
* devices (eg. mouse, keyboard, touch,...), this function
|
||||
* will return %NULL.
|
||||
*
|
||||
* This is most notably implemented for devices of type
|
||||
* %GDK_SOURCE_PEN, %GDK_SOURCE_ERASER and %GDK_SOURCE_TABLET_PAD.
|
||||
*
|
||||
* Returns: the /dev/input/event* path of this device
|
||||
**/
|
||||
const gchar *
|
||||
gdk_wayland_device_get_node_path (GdkDevice *device)
|
||||
{
|
||||
GdkWaylandTabletData *tablet;
|
||||
GdkWaylandTabletPadData *pad;
|
||||
|
||||
GdkSeat *seat;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
|
||||
|
||||
seat = gdk_device_get_seat (device);
|
||||
tablet = gdk_wayland_device_manager_find_tablet (GDK_WAYLAND_SEAT (seat),
|
||||
device);
|
||||
if (tablet)
|
||||
return tablet->path;
|
||||
|
||||
pad = gdk_wayland_device_manager_find_pad (GDK_WAYLAND_SEAT (seat), device);
|
||||
if (pad)
|
||||
return pad->path;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_wayland_device_pad_set_feedback:
|
||||
* @device: a %GDK_SOURCE_TABLET_PAD device
|
||||
* @feature: Feature to set the feedback label for
|
||||
* @feature_idx: 0-indexed index of the feature to set the feedback label for
|
||||
* @label: Feedback label
|
||||
*
|
||||
* Sets the feedback label for the given feature/index. This may be used by the
|
||||
* compositor to provide user feedback of the actions available/performed.
|
||||
**/
|
||||
void
|
||||
gdk_wayland_device_pad_set_feedback (GdkDevice *device,
|
||||
GdkDevicePadFeature feature,
|
||||
guint feature_idx,
|
||||
const gchar *label)
|
||||
{
|
||||
GdkWaylandTabletPadData *pad;
|
||||
GdkWaylandTabletPadGroupData *group;
|
||||
GdkSeat *seat;
|
||||
|
||||
seat = gdk_device_get_seat (device);
|
||||
pad = gdk_wayland_device_manager_find_pad (GDK_WAYLAND_SEAT (seat),
|
||||
device);
|
||||
if (!pad)
|
||||
return;
|
||||
|
||||
if (feature == GDK_DEVICE_PAD_FEATURE_BUTTON)
|
||||
{
|
||||
group = tablet_pad_lookup_button_group (pad, feature_idx);
|
||||
if (!group)
|
||||
return;
|
||||
|
||||
zwp_tablet_pad_v2_set_feedback (pad->wp_tablet_pad, feature_idx, label,
|
||||
group->mode_switch_serial);
|
||||
}
|
||||
else if (feature == GDK_DEVICE_PAD_FEATURE_RING)
|
||||
{
|
||||
struct zwp_tablet_pad_ring_v2 *wp_pad_ring;
|
||||
|
||||
wp_pad_ring = g_list_nth_data (pad->rings, feature_idx);
|
||||
if (!wp_pad_ring)
|
||||
return;
|
||||
|
||||
group = zwp_tablet_pad_ring_v2_get_user_data (wp_pad_ring);
|
||||
zwp_tablet_pad_ring_v2_set_feedback (wp_pad_ring, label,
|
||||
group->mode_switch_serial);
|
||||
|
||||
}
|
||||
else if (feature == GDK_DEVICE_PAD_FEATURE_STRIP)
|
||||
{
|
||||
struct zwp_tablet_pad_strip_v2 *wp_pad_strip;
|
||||
|
||||
wp_pad_strip = g_list_nth_data (pad->strips, feature_idx);
|
||||
if (!wp_pad_strip)
|
||||
return;
|
||||
|
||||
group = zwp_tablet_pad_strip_v2_get_user_data (wp_pad_strip);
|
||||
zwp_tablet_pad_strip_v2_set_feedback (wp_pad_strip, label,
|
||||
group->mode_switch_serial);
|
||||
}
|
||||
}
|
||||
|
@@ -55,6 +55,14 @@ struct wl_keyboard *gdk_wayland_device_get_wl_keyboard (GdkDevice *device);
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
struct wl_seat *gdk_wayland_seat_get_wl_seat (GdkSeat *seat);
|
||||
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
const gchar *gdk_wayland_device_get_node_path (GdkDevice *device);
|
||||
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
void gdk_wayland_device_pad_set_feedback (GdkDevice *device,
|
||||
GdkDevicePadFeature element,
|
||||
guint idx,
|
||||
const gchar *label);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@@ -1030,7 +1030,7 @@ handle_property_change (GdkX11DeviceManagerXI2 *device_manager,
|
||||
|
||||
if (!tool && serial_id > 0)
|
||||
{
|
||||
tool = gdk_device_tool_new (serial_id,
|
||||
tool = gdk_device_tool_new (serial_id, 0,
|
||||
GDK_DEVICE_TOOL_TYPE_UNKNOWN, 0);
|
||||
gdk_seat_default_add_tool (GDK_SEAT_DEFAULT (seat), tool);
|
||||
}
|
||||
|
@@ -250,6 +250,7 @@ gtk_public_h_sources = \
|
||||
gtkoffscreenwindow.h \
|
||||
gtkorientable.h \
|
||||
gtkoverlay.h \
|
||||
gtkpadcontroller.h \
|
||||
gtkpagesetup.h \
|
||||
gtkpaned.h \
|
||||
gtkpapersize.h \
|
||||
@@ -829,6 +830,7 @@ gtk_base_c_sources = \
|
||||
gtkoffscreenwindow.c \
|
||||
gtkorientable.c \
|
||||
gtkoverlay.c \
|
||||
gtkpadcontroller.c \
|
||||
gtkpagesetup.c \
|
||||
gtkpaned.c \
|
||||
gtkpango.c \
|
||||
|
@@ -152,6 +152,7 @@
|
||||
#include <gtk/gtkoffscreenwindow.h>
|
||||
#include <gtk/gtkorientable.h>
|
||||
#include <gtk/gtkoverlay.h>
|
||||
#include <gtk/gtkpadcontroller.h>
|
||||
#include <gtk/gtkpagesetup.h>
|
||||
#include <gtk/gtkpapersize.h>
|
||||
#include <gtk/gtkpaned.h>
|
||||
|
@@ -37,6 +37,9 @@ struct _GtkEventControllerClass
|
||||
|
||||
/*<private>*/
|
||||
|
||||
/* Tells whether the event is filtered out, %TRUE makes
|
||||
* the event unseen by the handle_event vfunc.
|
||||
*/
|
||||
gboolean (* filter_event) (GtkEventController *controller,
|
||||
const GdkEvent *event);
|
||||
gpointer padding[10];
|
||||
|
@@ -1875,6 +1875,11 @@ gtk_main_do_event (GdkEvent *event)
|
||||
case GDK_TOUCH_CANCEL:
|
||||
case GDK_TOUCHPAD_SWIPE:
|
||||
case GDK_TOUCHPAD_PINCH:
|
||||
case GDK_PAD_BUTTON_PRESS:
|
||||
case GDK_PAD_BUTTON_RELEASE:
|
||||
case GDK_PAD_RING:
|
||||
case GDK_PAD_STRIP:
|
||||
case GDK_PAD_GROUP_MODE:
|
||||
if (!_gtk_propagate_captured_event (grab_widget, event, topmost_widget))
|
||||
gtk_propagate_event (grab_widget, event);
|
||||
break;
|
||||
|
520
gtk/gtkpadcontroller.c
Normal file
520
gtk/gtkpadcontroller.c
Normal file
@@ -0,0 +1,520 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2016, 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:gtkpadcontroller
|
||||
* @Short_description: Controller for drawing tablet pads
|
||||
* @Title: GtkPadController
|
||||
* @See_also: #GtkEventController, #GdkDevicePad
|
||||
*
|
||||
* #GtkPadController is an event controller for the pads found in drawing
|
||||
* tablets (The collection of buttons and tactile sensors often found around
|
||||
* the stylus-sensitive area).
|
||||
*
|
||||
* These buttons and sensors have no implicit meaning, and by default they
|
||||
* perform no action, this event controller is provided to map those to
|
||||
* #GAction objects, thus letting the application give those a more semantic
|
||||
* meaning.
|
||||
*
|
||||
* Buttons and sensors are not constrained to triggering a single action, some
|
||||
* %GDK_SOURCE_TABLET_PAD devices feature multiple "modes", all these input
|
||||
* elements have one current mode, which may determine the final action
|
||||
* being triggered. Pad devices often divide buttons and sensors into groups,
|
||||
* all elements in a group share the same current mode, but different groups
|
||||
* may have different modes. See gdk_device_pad_get_n_groups() and
|
||||
* gdk_device_pad_get_group_n_modes().
|
||||
*
|
||||
* Each of the actions that a given button/strip/ring performs for a given
|
||||
* mode is defined by #GtkPadActionEntry, it contains an action name that
|
||||
* will be looked up in the given #GActionGroup and activated whenever the
|
||||
* specified input element and mode are triggered.
|
||||
*
|
||||
* A simple example of #GtkPadController usage, assigning button 1 in all
|
||||
* modes and pad devices to an "invert-selection" action:
|
||||
* |[
|
||||
* GtkPadActionEntry *pad_actions[] = {
|
||||
* { GTK_PAD_ACTION_BUTTON, 1, -1, "Invert selection", "pad-actions.invert-selection" },
|
||||
* …
|
||||
* };
|
||||
*
|
||||
* …
|
||||
* action_group = g_simple_action_group_new ();
|
||||
* action = g_simple_action_new ("pad-actions.invert-selection", NULL);
|
||||
* g_signal_connect (action, "activate", on_invert_selection_activated, NULL);
|
||||
* g_action_map_add_action (G_ACTION_MAP (action_group), action);
|
||||
* …
|
||||
* pad_controller = gtk_pad_controller_new (window, action_group, NULL);
|
||||
* ]|
|
||||
*
|
||||
* The actions belonging to rings/strips will be activated with a parameter
|
||||
* of type %G_VARIANT_TYPE_DOUBLE bearing the value of the given axis, it
|
||||
* is recommended that those are made stateful and accepting this #GVariantType.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkeventcontrollerprivate.h"
|
||||
#include "gtkpadcontroller.h"
|
||||
#include "gtkwindow.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkintl.h"
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
#include <gdk/wayland/gdkwayland.h>
|
||||
#endif
|
||||
|
||||
struct _GtkPadController {
|
||||
GtkEventController parent_instance;
|
||||
GActionGroup *action_group;
|
||||
GdkDevice *pad;
|
||||
|
||||
GList *entries;
|
||||
};
|
||||
|
||||
struct _GtkPadControllerClass {
|
||||
GtkEventControllerClass parent_class;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_ACTION_GROUP,
|
||||
PROP_PAD,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
static GParamSpec *pspecs[N_PROPS] = { NULL };
|
||||
|
||||
G_DEFINE_TYPE (GtkPadController, gtk_pad_controller, GTK_TYPE_EVENT_CONTROLLER)
|
||||
|
||||
static GtkPadActionEntry *
|
||||
gtk_pad_action_entry_copy (const GtkPadActionEntry *entry)
|
||||
{
|
||||
GtkPadActionEntry *copy;
|
||||
|
||||
copy = g_slice_new0 (GtkPadActionEntry);
|
||||
*copy = *entry;
|
||||
copy->label = g_strdup (entry->label);
|
||||
copy->action_name = g_strdup (entry->action_name);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_pad_action_entry_free (GtkPadActionEntry *entry)
|
||||
{
|
||||
g_free (entry->label);
|
||||
g_free (entry->action_name);
|
||||
g_slice_free (GtkPadActionEntry, entry);
|
||||
}
|
||||
|
||||
static const GtkPadActionEntry *
|
||||
gtk_pad_action_find_match (GtkPadController *controller,
|
||||
GtkPadActionType type,
|
||||
gint index,
|
||||
gint mode)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = controller->entries; l; l = l->next)
|
||||
{
|
||||
GtkPadActionEntry *entry = l->data;
|
||||
gboolean match_index = FALSE, match_mode = FALSE;
|
||||
|
||||
if (entry->type != type)
|
||||
continue;
|
||||
|
||||
match_index = entry->index < 0 || entry->index == index;
|
||||
match_mode = entry->mode < 0 || entry->mode == mode;
|
||||
|
||||
if (match_index && match_mode)
|
||||
return entry;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_pad_controller_activate_action (GtkPadController *controller,
|
||||
const GtkPadActionEntry *entry)
|
||||
{
|
||||
g_action_group_activate_action (controller->action_group,
|
||||
entry->action_name,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_pad_controller_activate_action_with_axis (GtkPadController *controller,
|
||||
const GtkPadActionEntry *entry,
|
||||
gdouble value)
|
||||
{
|
||||
g_action_group_activate_action (controller->action_group,
|
||||
entry->action_name,
|
||||
g_variant_new_double (value));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_pad_controller_handle_mode_switch (GtkPadController *controller,
|
||||
GdkDevice *pad,
|
||||
guint group,
|
||||
guint mode)
|
||||
{
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (GDK_IS_WAYLAND_DISPLAY (gdk_device_get_display (pad)))
|
||||
{
|
||||
const GtkPadActionEntry *entry;
|
||||
gint elem, idx, n_features;
|
||||
|
||||
for (elem = GTK_PAD_ACTION_BUTTON; elem <= GTK_PAD_ACTION_STRIP; elem++)
|
||||
{
|
||||
n_features = gdk_device_pad_get_n_features (GDK_DEVICE_PAD (pad),
|
||||
elem);
|
||||
|
||||
for (idx = 0; idx < n_features; idx++)
|
||||
{
|
||||
if (gdk_device_pad_get_feature_group (GDK_DEVICE_PAD (pad),
|
||||
elem, idx) != group)
|
||||
continue;
|
||||
|
||||
entry = gtk_pad_action_find_match (controller, elem, idx, mode);
|
||||
if (!entry)
|
||||
continue;
|
||||
if (!g_action_group_has_action (controller->action_group,
|
||||
entry->action_name))
|
||||
continue;
|
||||
|
||||
gdk_wayland_device_pad_set_feedback (pad, elem, idx,
|
||||
g_dgettext (NULL, entry->label));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_pad_controller_filter_event (GtkEventController *controller,
|
||||
const GdkEvent *event)
|
||||
{
|
||||
GtkPadController *pad_controller = GTK_PAD_CONTROLLER (controller);
|
||||
|
||||
if (event->type != GDK_PAD_BUTTON_PRESS &&
|
||||
event->type != GDK_PAD_BUTTON_RELEASE &&
|
||||
event->type != GDK_PAD_RING &&
|
||||
event->type != GDK_PAD_STRIP &&
|
||||
event->type != GDK_PAD_GROUP_MODE)
|
||||
return TRUE;
|
||||
|
||||
if (pad_controller->pad &&
|
||||
gdk_event_get_source_device (event) != pad_controller->pad)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_pad_controller_handle_event (GtkEventController *controller,
|
||||
const GdkEvent *event)
|
||||
{
|
||||
GtkPadController *pad_controller = GTK_PAD_CONTROLLER (controller);
|
||||
const GtkPadActionEntry *entry;
|
||||
GtkPadActionType type;
|
||||
gint index, mode;
|
||||
|
||||
if (event->type == GDK_PAD_GROUP_MODE)
|
||||
{
|
||||
gtk_pad_controller_handle_mode_switch (pad_controller,
|
||||
gdk_event_get_source_device (event),
|
||||
event->pad_group_mode.group,
|
||||
event->pad_group_mode.mode);
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case GDK_PAD_BUTTON_PRESS:
|
||||
type = GTK_PAD_ACTION_BUTTON;
|
||||
index = event->pad_button.button;
|
||||
mode = event->pad_button.mode;
|
||||
break;
|
||||
case GDK_PAD_RING:
|
||||
case GDK_PAD_STRIP:
|
||||
type = event->type == GDK_PAD_RING ?
|
||||
GTK_PAD_ACTION_RING : GTK_PAD_ACTION_STRIP;
|
||||
index = event->pad_axis.index;
|
||||
mode = event->pad_axis.mode;
|
||||
break;
|
||||
default:
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
entry = gtk_pad_action_find_match (pad_controller,
|
||||
type, index, mode);
|
||||
if (!entry)
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
|
||||
if (event->type == GDK_PAD_RING ||
|
||||
event->type == GDK_PAD_STRIP)
|
||||
{
|
||||
gtk_pad_controller_activate_action_with_axis (pad_controller, entry,
|
||||
event->pad_axis.value);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_pad_controller_activate_action (pad_controller, entry);
|
||||
}
|
||||
|
||||
return GDK_EVENT_STOP;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_pad_controller_set_pad (GtkPadController *controller,
|
||||
GdkDevice *pad)
|
||||
{
|
||||
g_return_if_fail (!pad || GDK_IS_DEVICE (pad));
|
||||
g_return_if_fail (!pad || gdk_device_get_source (pad) == GDK_SOURCE_TABLET_PAD);
|
||||
|
||||
g_set_object (&controller->pad, pad);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_pad_controller_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkPadController *controller = GTK_PAD_CONTROLLER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ACTION_GROUP:
|
||||
controller->action_group = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_PAD:
|
||||
gtk_pad_controller_set_pad (controller, g_value_get_object (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_pad_controller_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkPadController *controller = GTK_PAD_CONTROLLER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ACTION_GROUP:
|
||||
g_value_set_object (value, controller->action_group);
|
||||
break;
|
||||
case PROP_PAD:
|
||||
g_value_set_object (value, controller->pad);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_pad_controller_dispose (GObject *object)
|
||||
{
|
||||
GtkPadController *controller = GTK_PAD_CONTROLLER (object);
|
||||
|
||||
g_clear_object (&controller->action_group);
|
||||
g_clear_object (&controller->pad);
|
||||
|
||||
G_OBJECT_CLASS (gtk_pad_controller_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_pad_controller_finalize (GObject *object)
|
||||
{
|
||||
GtkPadController *controller = GTK_PAD_CONTROLLER (object);
|
||||
|
||||
g_list_free_full (controller->entries, (GDestroyNotify) gtk_pad_action_entry_free);
|
||||
|
||||
G_OBJECT_CLASS (gtk_pad_controller_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_pad_controller_class_init (GtkPadControllerClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkEventControllerClass *controller_class = GTK_EVENT_CONTROLLER_CLASS (klass);
|
||||
|
||||
controller_class->filter_event = gtk_pad_controller_filter_event;
|
||||
controller_class->handle_event = gtk_pad_controller_handle_event;
|
||||
|
||||
object_class->set_property = gtk_pad_controller_set_property;
|
||||
object_class->get_property = gtk_pad_controller_get_property;
|
||||
object_class->dispose = gtk_pad_controller_dispose;
|
||||
object_class->finalize = gtk_pad_controller_finalize;
|
||||
|
||||
pspecs[PROP_ACTION_GROUP] =
|
||||
g_param_spec_object ("action-group",
|
||||
P_("Action group"),
|
||||
P_("Action group to launch actions from"),
|
||||
G_TYPE_ACTION_GROUP,
|
||||
GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
pspecs[PROP_PAD] =
|
||||
g_param_spec_object ("pad",
|
||||
P_("Pad device"),
|
||||
P_("Pad device to control"),
|
||||
GDK_TYPE_DEVICE,
|
||||
GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, pspecs);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_pad_controller_init (GtkPadController *controller)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_pad_controller_new:
|
||||
* @window: a #GtkWindow
|
||||
* @group: #GActionGroup to trigger actions from
|
||||
* @pad: (nullable): A %GDK_SOURCE_TABLET_PAD device, or %NULL to handle all pads
|
||||
*
|
||||
* Creates a new #GtkPadController that will associate events from @pad to
|
||||
* actions. A %NULL pad may be provided so the controller manages all pad devices
|
||||
* generically, it is discouraged to mix #GtkPadController objects with %NULL
|
||||
* and non-%NULL @pad argument on the same @window, as execution order is not
|
||||
* guaranteed.
|
||||
*
|
||||
* The #GtkPadController is created with no mapped actions. In order to map pad
|
||||
* events to actions, use gtk_pad_controller_set_action_entries() or
|
||||
* gtk_pad_controller_set_action().
|
||||
*
|
||||
* Returns: A newly created #GtkPadController
|
||||
*
|
||||
* Since: 3.22
|
||||
**/
|
||||
GtkPadController *
|
||||
gtk_pad_controller_new (GtkWindow *window,
|
||||
GActionGroup *group,
|
||||
GdkDevice *pad)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
|
||||
g_return_val_if_fail (G_IS_ACTION_GROUP (group), NULL);
|
||||
g_return_val_if_fail (!pad || GDK_IS_DEVICE (pad), NULL);
|
||||
g_return_val_if_fail (!pad || gdk_device_get_source (pad) == GDK_SOURCE_TABLET_PAD, NULL);
|
||||
|
||||
return g_object_new (GTK_TYPE_PAD_CONTROLLER,
|
||||
"propagation-phase", GTK_PHASE_CAPTURE,
|
||||
"widget", window,
|
||||
"action-group", group,
|
||||
"pad", pad,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static gint
|
||||
entry_compare_func (gconstpointer a,
|
||||
gconstpointer b)
|
||||
{
|
||||
const GtkPadActionEntry *entry1 = a, *entry2 = b;
|
||||
|
||||
if (entry1->mode > entry2->mode)
|
||||
return -1;
|
||||
else if (entry1->mode < entry2->mode)
|
||||
return 1;
|
||||
else if (entry1->index > entry2->index)
|
||||
return -1;
|
||||
else if (entry1->index < entry2->index)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_pad_controller_add_entry (GtkPadController *controller,
|
||||
const GtkPadActionEntry *entry)
|
||||
{
|
||||
GtkPadActionEntry *copy;
|
||||
|
||||
copy = gtk_pad_action_entry_copy (entry);
|
||||
controller->entries = g_list_insert_sorted (controller->entries, copy,
|
||||
(GCompareFunc) entry_compare_func);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_pad_controller_set_action_entries:
|
||||
* @controller: a #GtkPadController
|
||||
* @entries: (array length=n_entries): the action entries to set on @controller
|
||||
* @n_entries: the number of elements in @entries
|
||||
*
|
||||
* This is a convenience function to add a group of action entries on
|
||||
* @controller. See #GtkPadActionEntry and gtk_pad_controller_set_action().
|
||||
*
|
||||
* Since: 3.22
|
||||
**/
|
||||
void
|
||||
gtk_pad_controller_set_action_entries (GtkPadController *controller,
|
||||
const GtkPadActionEntry *entries,
|
||||
gint n_entries)
|
||||
{
|
||||
gint i;
|
||||
|
||||
g_return_if_fail (GTK_IS_PAD_CONTROLLER (controller));
|
||||
g_return_if_fail (entries != NULL);
|
||||
|
||||
for (i = 0; i < n_entries; i++)
|
||||
gtk_pad_controller_add_entry (controller, &entries[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_pad_controller_set_action:
|
||||
* @controller: a #GtkPadController
|
||||
* @type: the type of pad feature that will trigger this action
|
||||
* @index: the 0-indexed button/ring/strip number that will trigger this action
|
||||
* @mode: the mode that will trigger this action, or -1 for all modes.
|
||||
* @label: Human readable description of this action, this string should
|
||||
* be deemed user-visible.
|
||||
* @action_name: action name that will be activated in the #GActionGroup
|
||||
*
|
||||
* Adds an individual action to @controller. This action will only be activated
|
||||
* if the given button/ring/strip number in @index is interacted while
|
||||
* the current mode is @mode. -1 may be used for simple cases, so the action
|
||||
* is triggered on all modes.
|
||||
*
|
||||
* The given @label should be considered user-visible, so internationalization
|
||||
* rules apply. Some windowing systems may be able to use those for user
|
||||
* feedback.
|
||||
*
|
||||
* Since: 3.22
|
||||
**/
|
||||
void
|
||||
gtk_pad_controller_set_action (GtkPadController *controller,
|
||||
GtkPadActionType type,
|
||||
gint index,
|
||||
gint mode,
|
||||
const gchar *label,
|
||||
const gchar *action_name)
|
||||
{
|
||||
GtkPadActionEntry entry = { type, index, mode,
|
||||
(gchar *) label, (gchar *) action_name };
|
||||
|
||||
g_return_if_fail (GTK_IS_PAD_CONTROLLER (controller));
|
||||
g_return_if_fail (type <= GTK_PAD_ACTION_RING);
|
||||
|
||||
gtk_pad_controller_add_entry (controller, &entry);
|
||||
}
|
99
gtk/gtkpadcontroller.h
Normal file
99
gtk/gtkpadcontroller.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2016, 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>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_PAD_CONTROLLER_H__
|
||||
#define __GTK_PAD_CONTROLLER_H__
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gtk/gtkeventcontroller.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_PAD_CONTROLLER (gtk_pad_controller_get_type ())
|
||||
#define GTK_PAD_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_PAD_CONTROLLER, GtkPadController))
|
||||
#define GTK_PAD_CONTROLLER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_PAD_CONTROLLER, GtkPadControllerClass))
|
||||
#define GTK_IS_PAD_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_PAD_CONTROLLER))
|
||||
#define GTK_IS_PAD_CONTROLLER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_PAD_CONTROLLER))
|
||||
#define GTK_PAD_CONTROLLER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_PAD_CONTROLLER, GtkPadControllerClass))
|
||||
|
||||
typedef struct _GtkPadController GtkPadController;
|
||||
typedef struct _GtkPadControllerClass GtkPadControllerClass;
|
||||
typedef struct _GtkPadActionEntry GtkPadActionEntry;
|
||||
|
||||
/**
|
||||
* GtkPadActionType:
|
||||
* @GTK_PAD_ACTION_BUTTON: Action is triggered by a pad button
|
||||
* @GTK_PAD_ACTION_RING: Action is triggered by a pad ring
|
||||
* @GTK_PAD_ACTION_STRIP: Action is triggered by a pad strip
|
||||
*
|
||||
* The type of a pad action.
|
||||
*/
|
||||
typedef enum {
|
||||
GTK_PAD_ACTION_BUTTON,
|
||||
GTK_PAD_ACTION_RING,
|
||||
GTK_PAD_ACTION_STRIP
|
||||
} GtkPadActionType;
|
||||
|
||||
/**
|
||||
* GtkPadActionEntry:
|
||||
* @type: the type of pad feature that will trigger this action entry.
|
||||
* @index: the 0-indexed button/ring/strip number that will trigger this action
|
||||
* entry.
|
||||
* @mode: the mode that will trigger this action entry, or -1 for all modes.
|
||||
* @label: Human readable description of this action entry, this string should
|
||||
* be deemed user-visible.
|
||||
* @action_name: action name that will be activated in the #GActionGroup.
|
||||
*
|
||||
* Struct defining a pad action entry.
|
||||
*/
|
||||
struct _GtkPadActionEntry {
|
||||
GtkPadActionType type;
|
||||
gint index;
|
||||
gint mode;
|
||||
gchar *label;
|
||||
gchar *action_name;
|
||||
};
|
||||
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
GType gtk_pad_controller_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
GtkPadController *gtk_pad_controller_new (GtkWindow *window,
|
||||
GActionGroup *group,
|
||||
GdkDevice *pad);
|
||||
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
void gtk_pad_controller_set_action_entries (GtkPadController *controller,
|
||||
const GtkPadActionEntry *entries,
|
||||
gint n_entries);
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
void gtk_pad_controller_set_action (GtkPadController *controller,
|
||||
GtkPadActionType type,
|
||||
gint index,
|
||||
gint mode,
|
||||
const gchar *label,
|
||||
const gchar *action_name);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_PAD_CONTROLLER_H__ */
|
@@ -7617,6 +7617,11 @@ gtk_widget_event_internal (GtkWidget *widget,
|
||||
case GDK_TOUCHPAD_PINCH:
|
||||
return_val |= _gtk_widget_run_controllers (widget, event, GTK_PHASE_BUBBLE);
|
||||
/* Fall through */
|
||||
case GDK_PAD_BUTTON_PRESS:
|
||||
case GDK_PAD_BUTTON_RELEASE:
|
||||
case GDK_PAD_RING:
|
||||
case GDK_PAD_STRIP:
|
||||
case GDK_PAD_GROUP_MODE:
|
||||
case GDK_EXPOSE:
|
||||
case GDK_NOTHING:
|
||||
signal_num = -1;
|
||||
|
Reference in New Issue
Block a user