Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Gnome/gdk/   (Gnome Linux Desktop Version 4.23.2©)  Datei vom 30.5.2026 mit Größe 35 kB image not shown  

Quelle  gdkdevice.c

  Sprache: C
 

/* GDK - The GIMP Drawing Kit
 * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
 *
 * 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/>.
 */


#include "config.h"

#include <math.h>

#include "gdkdeviceprivate.h"
#include "gdkdevicetool.h"
#include "gdkdisplayprivate.h"
#include <glib/gi18n-lib.h>
#include "gdkkeysprivate.h"

/**
 * GdkDevice:
 *
 * Represents an input device, such as a keyboard, mouse or touchpad.
 *
 * See the [class@Gdk.Seat] documentation for more information
 * about the various kinds of devices, and their relationships.
 */


typedef struct _GdkAxisInfo GdkAxisInfo;

struct _GdkAxisInfo
{
  GdkAxisUse use;
  double min_axis;
  double max_axis;
  double min_value;
  double max_value;
  double resolution;
};

enum {
  CHANGED,
  TOOL_CHANGED,
  LAST_SIGNAL
};

static guint signals [LAST_SIGNAL] = { 0 };


static void gdk_device_finalize     (GObject      *object);
static void gdk_device_dispose      (GObject      *object);
static void gdk_device_set_property (GObject      *object,
                                     guint         prop_id,
                                     const GValue *value,
                                     GParamSpec   *pspec);
static void gdk_device_get_property (GObject      *object,
                                     guint         prop_id,
                                     GValue       *value,
                                     GParamSpec   *pspec);


G_DEFINE_ABSTRACT_TYPE (GdkDevice, gdk_device, G_TYPE_OBJECT)

enum {
  PROP_0,
  PROP_DISPLAY,
  PROP_NAME,
  PROP_SOURCE,
  PROP_HAS_CURSOR,
  PROP_N_AXES,
  PROP_VENDOR_ID,
  PROP_PRODUCT_ID,
  PROP_SEAT,
  PROP_NUM_TOUCHES,
  PROP_TOOL,
  PROP_DIRECTION,
  PROP_HAS_BIDI_LAYOUTS,
  PROP_CAPS_LOCK_STATE,
  PROP_NUM_LOCK_STATE,
  PROP_SCROLL_LOCK_STATE,
  PROP_MODIFIER_STATE,
  PROP_LAYOUT_NAMES,
  PROP_ACTIVE_LAYOUT_INDEX,

  LAST_PROP
};

static GParamSpec *device_props[LAST_PROP] = { NULL, };

static void
gdk_device_class_init (GdkDeviceClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);

  object_class->finalize = gdk_device_finalize;
  object_class->dispose = gdk_device_dispose;
  object_class->set_property = gdk_device_set_property;
  object_class->get_property = gdk_device_get_property;

  /**
   * GdkDevice:display:
   *
   * The `GdkDisplay` the `GdkDevice` pertains to.
   */

  device_props[PROP_DISPLAY] =
      g_param_spec_object ("display", NULL, NULL,
                           GDK_TYPE_DISPLAY,
                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME);

  /**
   * GdkDevice:name:
   *
   * The device name.
   */

  device_props[PROP_NAME] =
      g_param_spec_string ("name", NULL, NULL,
                           NULL,
                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
                           G_PARAM_STATIC_NAME);

  /**
   * GdkDevice:source:
   *
   * Source type for the device.
   */

  device_props[PROP_SOURCE] =
      g_param_spec_enum ("source", NULL, NULL,
                         GDK_TYPE_INPUT_SOURCE,
                         GDK_SOURCE_MOUSE,
                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
                         G_PARAM_STATIC_NAME | G_PARAM_EXPLICIT_NOTIFY);

  /**
   * GdkDevice:has-cursor:
   *
   * Whether the device is represented by a cursor on the screen.
   */

  device_props[PROP_HAS_CURSOR] =
      g_param_spec_boolean ("has-cursor", NULL, NULL,
                            FALSE,
                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
                            G_PARAM_STATIC_NAME);

  /**
   * GdkDevice:n-axes:
   *
   * Number of axes in the device.
   */

  device_props[PROP_N_AXES] =
      g_param_spec_uint ("n-axes", NULL, NULL,
                         0, G_MAXUINT,
                         0,
                         G_PARAM_READABLE | G_PARAM_STATIC_NAME);

  /**
   * GdkDevice:vendor-id:
   *
   * Vendor ID of this device.
   *
   * See [method@Gdk.Device.get_vendor_id].
   */

  device_props[PROP_VENDOR_ID] =
      g_param_spec_string ("vendor-id", NULL, NULL,
                           NULL,
                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
                           G_PARAM_STATIC_NAME);

  /**
   * GdkDevice:product-id:
   *
   * Product ID of this device.
   *
   * See [method@Gdk.Device.get_product_id].
   */

  device_props[PROP_PRODUCT_ID] =
      g_param_spec_string ("product-id", NULL, NULL,
                           NULL,
                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
                           G_PARAM_STATIC_NAME);

  /**
   * GdkDevice:seat:
   *
   * `GdkSeat` of this device.
   */

  device_props[PROP_SEAT] =
      g_param_spec_object ("seat", NULL, NULL,
                           GDK_TYPE_SEAT,
                           G_PARAM_READWRITE |
                           G_PARAM_STATIC_NAME);

  /**
   * GdkDevice:num-touches:
   *
   * The maximal number of concurrent touches on a touch device.
   *
   * Will be 0 if the device is not a touch device or if the number
   * of touches is unknown.
   */

  device_props[PROP_NUM_TOUCHES] =
      g_param_spec_uint ("num-touches", NULL, NULL,
                         0, G_MAXUINT,
                         0,
                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
                         G_PARAM_STATIC_NAME);

  /**
   * GdkDevice:tool: (getter get_device_tool)
   *
   * The `GdkDeviceTool` that is currently used with this device.
   */

  device_props[PROP_TOOL] =
    g_param_spec_object ("tool", NULL, NULL,
                         GDK_TYPE_DEVICE_TOOL,
                         G_PARAM_READABLE | G_PARAM_STATIC_NAME);

  /**
   * GdkDevice:direction:
   *
   * The direction of the current layout.
   *
   * This is only relevant for keyboard devices.
   */

  device_props[PROP_DIRECTION] =
      g_param_spec_enum ("direction", NULL, NULL,
                         PANGO_TYPE_DIRECTION, PANGO_DIRECTION_NEUTRAL,
                         G_PARAM_READABLE | G_PARAM_STATIC_NAME);

  /**
   * GdkDevice:has-bidi-layouts:
   *
   * Whether the device has both right-to-left and left-to-right layouts.
   *
   * This is only relevant for keyboard devices.
   */

  device_props[PROP_HAS_BIDI_LAYOUTS] =
      g_param_spec_boolean ("has-bidi-layouts", NULL, NULL,
                            FALSE,
                            G_PARAM_READABLE | G_PARAM_STATIC_NAME);

  /**
   * GdkDevice:caps-lock-state:
   *
   * Whether Caps Lock is on.
   *
   * This is only relevant for keyboard devices.
   */

  device_props[PROP_CAPS_LOCK_STATE] =
      g_param_spec_boolean ("caps-lock-state", NULL, NULL,
                            FALSE,
                            G_PARAM_READABLE | G_PARAM_STATIC_NAME);

  /**
   * GdkDevice:num-lock-state:
   *
   * Whether Num Lock is on.
   *
   * This is only relevant for keyboard devices.
   */

  device_props[PROP_NUM_LOCK_STATE] =
      g_param_spec_boolean ("num-lock-state", NULL, NULL,
                            FALSE,
                            G_PARAM_READABLE | G_PARAM_STATIC_NAME);

  /**
   * GdkDevice:scroll-lock-state:
   *
   * Whether Scroll Lock is on.
   *
   * This is only relevant for keyboard devices.
   */

  device_props[PROP_SCROLL_LOCK_STATE] =
      g_param_spec_boolean ("scroll-lock-state", NULL, NULL,
                            FALSE,
                            G_PARAM_READABLE | G_PARAM_STATIC_NAME);

  /**
   * GdkDevice:modifier-state:
   *
   * The current modifier state of the device.
   *
   * This is only relevant for keyboard devices.
   */

  device_props[PROP_MODIFIER_STATE] =
      g_param_spec_flags ("modifier-state", NULL, NULL,
                          GDK_TYPE_MODIFIER_TYPE,
                          GDK_NO_MODIFIER_MASK,
                          G_PARAM_READABLE | G_PARAM_STATIC_NAME);

  /**
   * GdkDevice:active-layout-index:
   *
   * The index of the keyboard active layout of a `GdkDevice`.
   *
   * Will be -1 if there is no valid active layout.
   *
   * This is only relevant for keyboard devices.
   *
   * Value changes from compositor events, connect to notify if needed.
   *
   * Since: 4.18
   */

  device_props[PROP_ACTIVE_LAYOUT_INDEX] =
      g_param_spec_int ("active-layout-index", NULL, NULL,
                        -1, G_MAXINT, 0,
                        G_PARAM_READABLE | G_PARAM_STATIC_NAME);

  /**
   * GdkDevice:layout-names:
   *
   * The names of the keyboard layouts of a `GdkDevice`.
   *
   * This is only relevant for keyboard devices.
   *
   * Value changes from compositor events, connect to notify if needed.
   *
   * Since: 4.18
   */

  device_props[PROP_LAYOUT_NAMES] =
      g_param_spec_boxed ("layout-names", NULL, NULL,
                          G_TYPE_STRV,
                          G_PARAM_READABLE | G_PARAM_STATIC_NAME);

  g_object_class_install_properties (object_class, LAST_PROP, device_props);

  /**
   * GdkDevice::changed:
   * @device: the `GdkDevice`
   *
   * Emitted either when the number of either axes or keys changes.
   *
   * On X11 this will normally happen when the physical device
   * routing events through the logical device changes (for
   * example, user switches from the USB mouse to a tablet); in
   * that case the logical device will change to reflect the axes
   * and keys on the new physical device.
   */

  signals[CHANGED] =
    g_signal_new (g_intern_static_string ("changed"),
                  G_TYPE_FROM_CLASS (object_class),
                  G_SIGNAL_RUN_LAST,
                  0, NULL, NULL,
                  NULL,
                  G_TYPE_NONE, 0);

  /**
   * GdkDevice::tool-changed:
   * @device: the `GdkDevice`
   * @tool: The new current tool
   *
   * Emitted on pen/eraser devices whenever tools enter or leave proximity.
   */

  signals[TOOL_CHANGED] =
    g_signal_new (g_intern_static_string ("tool-changed"),
                  G_TYPE_FROM_CLASS (object_class),
                  G_SIGNAL_RUN_LAST,
                  0, NULL, NULL,
                  NULL,
                  G_TYPE_NONE, 1, GDK_TYPE_DEVICE_TOOL);
}

static void
gdk_device_init (GdkDevice *device)
{
  device->axes = g_array_new (FALSETRUEsizeof (GdkAxisInfo));
}

static void
gdk_device_finalize (GObject *object)
{
  GdkDevice *device = GDK_DEVICE (object);

  if (device->axes)
    {
      g_array_free (device->axes, TRUE);
      device->axes = NULL;
    }

  g_clear_pointer (&device->name, g_free);
  g_clear_pointer (&device->vendor_id, g_free);
  g_clear_pointer (&device->product_id, g_free);

  G_OBJECT_CLASS (gdk_device_parent_class)->finalize (object);
}

static void
gdk_device_dispose (GObject *object)
{
  GdkDevice *device = GDK_DEVICE (object);
  GdkDevice *associated = device->associated;

  if (associated)
    _gdk_device_remove_physical_device (associated, device);

  if (associated)
    {
      device->associated = NULL;

      if (associated->associated == device)
        _gdk_device_set_associated_device (associated, NULL);

      g_object_unref (associated);
    }

  g_clear_object (&device->last_tool);

  G_OBJECT_CLASS (gdk_device_parent_class)->dispose (object);
}

static void
gdk_device_set_property (GObject      *object,
                         guint         prop_id,
                         const GValue *value,
                         GParamSpec   *pspec)
{
  GdkDevice *device = GDK_DEVICE (object);

  switch (prop_id)
    {
    case PROP_DISPLAY:
      device->display = g_value_get_object (value);
      break;
    case PROP_NAME:
      g_free (device->name);

      device->name = g_value_dup_string (value);
      break;
    case PROP_SOURCE:
      device->source = g_value_get_enum (value);
      break;
    case PROP_HAS_CURSOR:
      device->has_cursor = g_value_get_boolean (value);
      break;
    case PROP_VENDOR_ID:
      device->vendor_id = g_value_dup_string (value);
      break;
    case PROP_PRODUCT_ID:
      device->product_id = g_value_dup_string (value);
      break;
    case PROP_SEAT:
      device->seat = g_value_get_object (value);
      break;
    case PROP_NUM_TOUCHES:
      device->num_touches = g_value_get_uint (value);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

static void
gdk_device_get_property (GObject    *object,
                         guint       prop_id,
                         GValue     *value,
                         GParamSpec *pspec)
{
  GdkDevice *device = GDK_DEVICE (object);

  switch (prop_id)
    {
    case PROP_DISPLAY:
      g_value_set_object (value, device->display);
      break;
    case PROP_NAME:
      g_value_set_string (value, device->name);
      break;
    case PROP_SOURCE:
      g_value_set_enum (value, device->source);
      break;
    case PROP_HAS_CURSOR:
      g_value_set_boolean (value, device->has_cursor);
      break;
    case PROP_N_AXES:
      g_value_set_uint (value, device->axes->len);
      break;
    case PROP_VENDOR_ID:
      g_value_set_string (value, device->vendor_id);
      break;
    case PROP_PRODUCT_ID:
      g_value_set_string (value, device->product_id);
      break;
    case PROP_SEAT:
      g_value_set_object (value, device->seat);
      break;
    case PROP_NUM_TOUCHES:
      g_value_set_uint (value, device->num_touches);
      break;
    case PROP_TOOL:
      g_value_set_object (value, device->last_tool);
      break;
    case PROP_DIRECTION:
      g_value_set_enum (value, gdk_device_get_direction (device));
      break;
    case PROP_HAS_BIDI_LAYOUTS:
      g_value_set_boolean (value, gdk_device_has_bidi_layouts (device));
      break;
    case PROP_CAPS_LOCK_STATE:
      g_value_set_boolean (value, gdk_device_get_caps_lock_state (device));
      break;
    case PROP_NUM_LOCK_STATE:
      g_value_set_boolean (value, gdk_device_get_num_lock_state (device));
      break;
    case PROP_SCROLL_LOCK_STATE:
      g_value_set_boolean (value, gdk_device_get_scroll_lock_state (device));
      break;
    case PROP_MODIFIER_STATE:
      g_value_set_flags (value, gdk_device_get_modifier_state (device));
      break;
    case PROP_ACTIVE_LAYOUT_INDEX:
      g_value_set_int (value, gdk_device_get_active_layout_index (device));
      break;
    case PROP_LAYOUT_NAMES:
      g_value_set_boxed (value, gdk_device_get_layout_names (device));
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

/**
 * gdk_device_get_surface_at_position:
 * @device: pointer `GdkDevice` to query info to
 * @win_x: (out) (optional): return location for the X coordinate
 *   of the device location relative to the surface origin
 * @win_y: (out) (optional): return location for the Y coordinate
 *   of the device location relative to the surface origin
 *
 * Obtains the surface underneath @device, returning the location of the
 * device in @win_x and @win_y.
 *
 * Returns %NULL if the surface tree under @device is not known to GDK
 * (for example, belongs to another application).
 *
 * Returns: (nullable) (transfer none): the `GdkSurface` under the
 *   device position
 */

GdkSurface *
gdk_device_get_surface_at_position (GdkDevice *device,
                                    double    *win_x,
                                    double    *win_y)
{
  double tmp_x, tmp_y;
  GdkSurface *surface;

  g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
  g_return_val_if_fail (device->source != GDK_SOURCE_KEYBOARD, NULL);

  surface = _gdk_device_surface_at_position (device, &tmp_x, &tmp_y, NULL);

  if (win_x)
    *win_x = tmp_x;
  if (win_y)
    *win_y = tmp_y;

  return surface;
}

/**
 * gdk_device_get_name:
 * @device: a GdkDevice`
 *
 * The name of the device, suitable for showing in a user interface.
 *
 * Returns: a name
 */

const char *
gdk_device_get_name (GdkDevice *device)
{
  g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);

  return device->name;
}

/**
 * gdk_device_get_has_cursor:
 * @device: a `GdkDevice`
 *
 * Determines whether the pointer follows device motion.
 *
 * This is not meaningful for keyboard devices, which
 * don't have a pointer.
 *
 * Returns: %TRUE if the pointer follows device motion
 */

gboolean
gdk_device_get_has_cursor (GdkDevice *device)
{
  g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);

  return device->has_cursor;
}

/**
 * gdk_device_get_source:
 * @device: a `GdkDevice`
 *
 * Determines the type of the device.
 *
 * Returns: a `GdkInputSource`
 */

GdkInputSource
gdk_device_get_source (GdkDevice *device)
{
  g_return_val_if_fail (GDK_IS_DEVICE (device), 0);

  return device->source;
}

/**
 * gdk_device_get_axis_use:
 * @device: a pointer `GdkDevice`
 * @index_: the index of the axi.
 *
 * Returns the axis use for @index_.
 *
 * Returns: a `GdkAxisUse` specifying how the axis is used.
 */

GdkAxisUse
gdk_device_get_axis_use (GdkDevice *device,
                         guint      index_)
{
  GdkAxisInfo *info;

  g_return_val_if_fail (GDK_IS_DEVICE (device), GDK_AXIS_IGNORE);
  g_return_val_if_fail (device->source != GDK_SOURCE_KEYBOARD, GDK_AXIS_IGNORE);
  g_return_val_if_fail (index_ < device->axes->len, GDK_AXIS_IGNORE);

  info = &g_array_index (device->axes, GdkAxisInfo, index_);

  return info->use;
}

/**
 * gdk_device_get_display:
 * @device: a `GdkDevice`
 *
 * Returns the `GdkDisplay` to which @device pertains.
 *
 * Returns: (transfer none): a `GdkDisplay`
 */

GdkDisplay *
gdk_device_get_display (GdkDevice *device)
{
  g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);

  return device->display;
}

void
_gdk_device_set_associated_device (GdkDevice *device,
                                   GdkDevice *associated)
{
  g_return_if_fail (GDK_IS_DEVICE (device));
  g_return_if_fail (associated == NULL || GDK_IS_DEVICE (associated));

  g_set_object (&device->associated, associated);
}

/*
 * gdk_device_list_physical_devices:
 * @device: a logical `GdkDevice`
 *
 * Returns the list of physical devices attached to the given logical
 * `GdkDevice`.
 *
 * Returns: (nullable) (transfer container) (element-type GdkDevice):
 *   the list of physical devices attached to a logical `GdkDevice`
 */

GList *
gdk_device_list_physical_devices (GdkDevice *device)
{
  g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);

  return g_list_copy (device->physical_devices);
}

void
_gdk_device_add_physical_device (GdkDevice *device,
                                 GdkDevice *physical)
{
  if (!g_list_find (device->physical_devices, physical))
    device->physical_devices = g_list_prepend (device->physical_devices, physical);
}

void
_gdk_device_remove_physical_device (GdkDevice *device,
                                    GdkDevice *physical)
{
  GList *elem;

  elem = g_list_find (device->physical_devices, physical);
  if (elem == NULL)
    return;

  device->physical_devices = g_list_delete_link (device->physical_devices, elem);
}

/*
 * gdk_device_get_n_axes:
 * @device: a pointer `GdkDevice`
 *
 * Returns the number of axes the device currently has.
 *
 * Returns: the number of axes.
 */

int
gdk_device_get_n_axes (GdkDevice *device)
{
  g_return_val_if_fail (GDK_IS_DEVICE (device), 0);
  g_return_val_if_fail (device->source != GDK_SOURCE_KEYBOARD, 0);

  return device->axes->len;
}

/*
 * gdk_device_get_axis: (skip)
 * @device: a `GdkDevice`
 * @axes: (array): pointer to an array of axes
 * @use: the use to look for
 * @value: (out): location to store the found value
 *
 * Interprets an array of `double` as axis values and get the value
 * for a given axis use.
 *
 * Returns: %TRUE if the given axis use was found, otherwise %FALSE
 */

gboolean
gdk_device_get_axis (GdkDevice  *device,
                     double     *axes,
                     GdkAxisUse  use,
                     double     *value)
{
  int i;

  g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
  g_return_val_if_fail (device->source != GDK_SOURCE_KEYBOARD, FALSE);

  if (axes == NULL)
    return FALSE;

  g_return_val_if_fail (device->axes != NULL, FALSE);

  for (i = 0; i < device->axes->len; i++)
    {
      GdkAxisInfo axis_info;

      axis_info = g_array_index (device->axes, GdkAxisInfo, i);

      if (axis_info.use != use)
        continue;

      if (value)
        *value = axes[i];

      return TRUE;
    }

  return FALSE;
}

/* Private API */
void
_gdk_device_reset_axes (GdkDevice *device)
{
  int i;

  for (i = device->axes->len - 1; i >= 0; i--)
    g_array_remove_index (device->axes, i);

  g_object_notify_by_pspec (G_OBJECT (device), device_props[PROP_N_AXES]);
}

guint
_gdk_device_add_axis (GdkDevice   *device,
                      GdkAxisUse   use,
                      double       min_value,
                      double       max_value,
                      double       resolution)
{
  GdkAxisInfo axis_info;
  guint pos;

  axis_info.use = use;
  axis_info.min_value = min_value;
  axis_info.max_value = max_value;
  axis_info.resolution = resolution;

  switch ((guint) use)
    {
    case GDK_AXIS_X:
    case GDK_AXIS_Y:
      axis_info.min_axis = 0;
      axis_info.max_axis = 0;
      break;
    case GDK_AXIS_XTILT:
    case GDK_AXIS_YTILT:
      axis_info.min_axis = -1;
      axis_info.max_axis = 1;
      break;
    default:
      axis_info.min_axis = 0;
      axis_info.max_axis = 1;
      break;
    }

  device->axes = g_array_append_val (device->axes, axis_info);
  pos = device->axes->len - 1;

  g_object_notify_by_pspec (G_OBJECT (device), device_props[PROP_N_AXES]);

  return pos;
}

void
_gdk_device_get_axis_info (GdkDevice   *device,
                           guint        index_,
                           GdkAxisUse   *use,
                           double       *min_value,
                           double       *max_value,
                           double       *resolution)
{
  GdkAxisInfo *info;

  g_return_if_fail (GDK_IS_DEVICE (device));
  g_return_if_fail (index_ < device->axes->len);

  info = &g_array_index (device->axes, GdkAxisInfo, index_);

  *use = info->use;
  *min_value = info->min_value;
  *max_value = info->max_value;
  *resolution = info->resolution;
}

static GdkAxisInfo *
find_axis_info (GArray     *array,
                GdkAxisUse  use)
{
  GdkAxisInfo *info;
  int i;

  for (i = 0; i < GDK_AXIS_LAST; i++)
    {
      info = &g_array_index (array, GdkAxisInfo, i);

      if (info->use == use)
        return info;
    }

  return NULL;
}

gboolean
_gdk_device_translate_surface_coord (GdkDevice *device,
                                     GdkSurface *surface,
                                     guint      index_,
                                     double     value,
                                     double    *axis_value)
{
  GdkAxisInfo axis_info;
  GdkAxisInfo *axis_info_x, *axis_info_y;
  double device_width, device_height;
  double x_offset, y_offset;
  double x_scale, y_scale;
  double x_min, y_min;
  double x_resolution, y_resolution;
  double device_aspect;
  int surface_width, surface_height;

  if (index_ >= device->axes->len)
    return FALSE;

  axis_info = g_array_index (device->axes, GdkAxisInfo, index_);

  if (axis_info.use != GDK_AXIS_X &&
      axis_info.use != GDK_AXIS_Y)
    return FALSE;

  if (axis_info.use == GDK_AXIS_X)
    {
      axis_info_x = &axis_info;
      axis_info_y = find_axis_info (device->axes, GDK_AXIS_Y);
      if (axis_info_y == NULL)
        return FALSE;
    }
  else
    {
      axis_info_x = find_axis_info (device->axes, GDK_AXIS_X);
      axis_info_y = &axis_info;
      if (axis_info_x == NULL)
        return FALSE;
    }

  device_width = axis_info_x->max_value - axis_info_x->min_value;
  device_height = axis_info_y->max_value - axis_info_y->min_value;

  x_min = axis_info_x->min_value;
  y_min = axis_info_y->min_value;

  surface_width = gdk_surface_get_width (surface);
  surface_height = gdk_surface_get_height (surface);

  x_resolution = axis_info_x->resolution;
  y_resolution = axis_info_y->resolution;

  /*
   * Some drivers incorrectly report the resolution of the device
   * as zero (in particular linuxwacom < 0.5.3 with usb tablets).
   * This causes the device_aspect to become NaN and totally
   * breaks windowed mode.  If this is the case, the best we can
   * do is to assume the resolution is non-zero is equal in both
   * directions (which is true for many devices).  The absolute
   * value of the resolution doesn't matter since we only use the
   * ratio.
   */

  if (x_resolution == 0 || y_resolution == 0)
    {
      x_resolution = 1;
      y_resolution = 1;
    }

  device_aspect = (device_height * y_resolution) /
    (device_width * x_resolution);

  if (device_aspect * surface_width >= surface_height)
    {
      /* device taller than surface */
      x_scale = surface_width / device_width;
      y_scale = (x_scale * x_resolution) / y_resolution;

      x_offset = 0;
      y_offset = - (device_height * y_scale - surface_height) / 2;
    }
  else
    {
      /* surface taller than device */
      y_scale = surface_height / device_height;
      x_scale = (y_scale * y_resolution) / x_resolution;

      y_offset = 0;
      x_offset = - (device_width * x_scale - surface_width) / 2;
    }

  if (axis_value)
    {
      if (axis_info.use == GDK_AXIS_X)
        *axis_value = x_offset + x_scale * (value - x_min);
      else
        *axis_value = y_offset + y_scale * (value - y_min);
    }

  return TRUE;
}

gboolean
_gdk_device_translate_screen_coord (GdkDevice *device,
                                    GdkSurface *surface,
                                    double     surface_root_x,
                                    double     surface_root_y,
                                    double     screen_width,
                                    double     screen_height,
                                    guint      index_,
                                    double     value,
                                    double    *axis_value)
{
  GdkAxisInfo axis_info;
  double axis_width, scale, offset;

  if (index_ >= device->axes->len)
    return FALSE;

  axis_info = g_array_index (device->axes, GdkAxisInfo, index_);

  if (axis_info.use != GDK_AXIS_X &&
      axis_info.use != GDK_AXIS_Y)
    return FALSE;

  axis_width = axis_info.max_value - axis_info.min_value;

  if (axis_info.use == GDK_AXIS_X)
    {
      if (axis_width > 0)
        scale = screen_width / axis_width;
      else
        scale = 1;

      offset = - surface_root_x;
    }
  else
    {
      if (axis_width > 0)
        scale = screen_height / axis_width;
      else
        scale = 1;

      offset = - surface_root_y;
    }

  if (axis_value)
    *axis_value = offset + scale * (value - axis_info.min_value);

  return TRUE;
}

gboolean
_gdk_device_translate_axis (GdkDevice *device,
                            guint      index_,
                            double     value,
                            double    *axis_value)
{
  GdkAxisInfo axis_info;
  double axis_width, out;

  if (index_ >= device->axes->len)
    return FALSE;

  axis_info = g_array_index (device->axes, GdkAxisInfo, index_);

  if (axis_info.use == GDK_AXIS_X ||
      axis_info.use == GDK_AXIS_Y)
    return FALSE;

  axis_width = axis_info.max_value - axis_info.min_value;
  out = (axis_info.max_axis * (value - axis_info.min_value) +
         axis_info.min_axis * (axis_info.max_value - value)) / axis_width;

  if (axis_value)
    *axis_value = out;

  return TRUE;
}

GdkSurface *
_gdk_device_surface_at_position (GdkDevice       *device,
                                 double          *win_x,
                                 double          *win_y,
                                 GdkModifierType *mask)
{
  return GDK_DEVICE_GET_CLASS (device)->surface_at_position (device,
                                                             win_x,
                                                             win_y,
                                                             mask);
}

/**
 * gdk_device_get_vendor_id:
 * @device: a physical `GdkDevice`
 *
 * Returns the vendor ID of this device.
 *
 * This ID is retrieved from the device, and does not change.
 *
 * This function, together with [method@Gdk.Device.get_product_id],
 * can be used to eg. compose `GSettings` paths to store settings
 * for this device.
 *
 * ```c
 *  static GSettings *
 *  get_device_settings (GdkDevice *device)
 *  {
 *    const char *vendor, *product;
 *    GSettings *settings;
 *    GdkDevice *device;
 *    char *path;
 *
 *    vendor = gdk_device_get_vendor_id (device);
 *    product = gdk_device_get_product_id (device);
 *
 *    path = g_strdup_printf ("/org/example/app/devices/%s:%s/", vendor, product);
 *    settings = g_settings_new_with_path (DEVICE_SCHEMA, path);
 *    g_free (path);
 *
 *    return settings;
 *  }
 * ```
 *
 * Returns: (nullable): the vendor ID
 */

const char *
gdk_device_get_vendor_id (GdkDevice *device)
{
  g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);

  return device->vendor_id;
}

/**
 * gdk_device_get_product_id:
 * @device: a physical `GdkDevice`
 *
 * Returns the product ID of this device.
 *
 * This ID is retrieved from the device, and does not change.
 * See [method@Gdk.Device.get_vendor_id] for more information.
 *
 * Returns: (nullable): the product ID
 */

const char *
gdk_device_get_product_id (GdkDevice *device)
{
  g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);

  return device->product_id;
}

void
gdk_device_set_seat (GdkDevice *device,
                     GdkSeat   *seat)
{
  g_return_if_fail (GDK_IS_DEVICE (device));
  g_return_if_fail (!seat || GDK_IS_SEAT (seat));

  if (device->seat == seat)
    return;

  device->seat = seat;
  g_object_notify_by_pspec (G_OBJECT (device), device_props[PROP_SEAT]);
}

/**
 * gdk_device_get_seat:
 * @device: A `GdkDevice`
 *
 * Returns the `GdkSeat` the device belongs to.
 *
 * Returns: (transfer none): a `GdkSeat`
 */

GdkSeat *
gdk_device_get_seat (GdkDevice *device)
{
  g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);

  return device->seat;
}

void
gdk_device_update_tool (GdkDevice     *device,
                        GdkDeviceTool *tool)
{
  g_return_if_fail (GDK_IS_DEVICE (device));

  if (g_set_object (&device->last_tool, tool))
    {
      g_object_notify_by_pspec (G_OBJECT (device), device_props[PROP_TOOL]);
      g_signal_emit (device, signals[TOOL_CHANGED], 0, tool);
    }
}

/**
 * gdk_device_get_num_touches:
 * @device: a `GdkDevice`
 *
 * Retrieves the number of touch points associated to @device.
 *
 * Returns: the number of touch points
 */

guint
gdk_device_get_num_touches (GdkDevice *device)
{
  g_return_val_if_fail (GDK_IS_DEVICE (device), 0);

  return device->num_touches;
}

/**
 * gdk_device_get_device_tool: (get-property tool)
 * @device: a `GdkDevice`
 *
 * Retrieves the current tool for @device.
 *
 * Returns: (transfer none) (nullable): the `GdkDeviceTool`
 */

GdkDeviceTool *
gdk_device_get_device_tool (GdkDevice *device)
{
  g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);

  return device->last_tool;
}

/**
 * gdk_device_get_caps_lock_state:
 * @device: a `GdkDevice`
 *
 * Retrieves whether the Caps Lock modifier of the keyboard is locked.
 *
 * This is only relevant for keyboard devices.
 *
 * Returns: %TRUE if Caps Lock is on for @device
 */

gboolean
gdk_device_get_caps_lock_state (GdkDevice *device)
{
  GdkKeymap *keymap = gdk_display_get_keymap (device->display);

  if (device->source == GDK_SOURCE_KEYBOARD)
    return gdk_keymap_get_caps_lock_state (keymap);

  return FALSE;
}

/**
 * gdk_device_get_num_lock_state:
 * @device: a ``GdkDevice`
 *
 * Retrieves whether the Num Lock modifier of the keyboard is locked.
 *
 * This is only relevant for keyboard devices.
 *
 * Returns: %TRUE if Num Lock is on for @device
 */

gboolean
gdk_device_get_num_lock_state (GdkDevice *device)
{
  GdkKeymap *keymap = gdk_display_get_keymap (device->display);

  if (device->source == GDK_SOURCE_KEYBOARD)
    return gdk_keymap_get_num_lock_state (keymap);

  return FALSE;
}

/**
 * gdk_device_get_scroll_lock_state:
 * @device: a `GdkDevice`
 *
 * Retrieves whether the Scroll Lock modifier of the keyboard is locked.
 *
 * This is only relevant for keyboard devices.
 *
 * Returns: %TRUE if Scroll Lock is on for @device
 */

gboolean
gdk_device_get_scroll_lock_state (GdkDevice *device)
{
  GdkKeymap *keymap = gdk_display_get_keymap (device->display);

  if (device->source == GDK_SOURCE_KEYBOARD)
    return gdk_keymap_get_scroll_lock_state (keymap);

  return FALSE;
}

/**
 * gdk_device_get_modifier_state:
 * @device: a `GdkDevice`
 *
 * Retrieves the current modifier state of the keyboard.
 *
 * This is only relevant for keyboard devices.
 *
 * Returns: the current modifier state
 */

GdkModifierType
gdk_device_get_modifier_state (GdkDevice *device)
{
  GdkKeymap *keymap = gdk_display_get_keymap (device->display);

  if (device->source == GDK_SOURCE_KEYBOARD)
    return gdk_keymap_get_modifier_state (keymap);

  return 0;
}

/**
 * gdk_device_get_active_layout_index:
 * @device: a `GdkDevice`
 *
 * Retrieves the index of the active layout of the keyboard.
 *
 * If there is no valid active layout for the `GdkDevice`, this function will
 * return -1;
 *
 * This is only relevant for keyboard devices.
 *
 * Returns: The layout index of the active layout or -1.
 *
 * Since: 4.18
 */

gint
gdk_device_get_active_layout_index (GdkDevice *device)
{
  GdkKeymap *keymap = gdk_display_get_keymap (device->display);

  if (device->source == GDK_SOURCE_KEYBOARD)
    return gdk_keymap_get_active_layout_index (keymap);

  return -1;
}

/**
 * gdk_device_get_layout_names:
 * @device: a `GdkDevice`
 *
 * Retrieves the names of the layouts of the keyboard.
 *
 * This is only relevant for keyboard devices.
 *
 * Returns: (transfer full) (nullable) (array zero-terminated=1):
 *   %NULL-terminated array of strings of layouts,
 *
 * Since: 4.18
 */

char **
gdk_device_get_layout_names (GdkDevice *device)
{
  GdkKeymap *keymap = gdk_display_get_keymap (device->display);

  if (device->source == GDK_SOURCE_KEYBOARD)
    return gdk_keymap_get_layout_names (keymap);

  return NULL;
}

/**
 * gdk_device_get_direction:
 * @device: a `GdkDevice`
 *
 * Returns the direction of effective layout of the keyboard.
 *
 * This is only relevant for keyboard devices.
 *
 * The direction of a layout is the direction of the majority
 * of its symbols. See [func@Pango.unichar_direction].
 *
 * Returns: %PANGO_DIRECTION_LTR or %PANGO_DIRECTION_RTL
 *   if it can determine the direction. %PANGO_DIRECTION_NEUTRAL
 *   otherwise
 */

PangoDirection
gdk_device_get_direction (GdkDevice *device)
{
  GdkKeymap *keymap = gdk_display_get_keymap (device->display);

  if (device->source == GDK_SOURCE_KEYBOARD)
    return gdk_keymap_get_direction (keymap);

  return PANGO_DIRECTION_NEUTRAL;
}

/**
 * gdk_device_has_bidi_layouts:
 * @device: a `GdkDevice`
 *
 * Determines if layouts for both right-to-left and
 * left-to-right languages are in use on the keyboard.
 *
 * This is only relevant for keyboard devices.
 *
 * Returns: %TRUE if there are layouts with both directions, %FALSE otherwise
 */

gboolean
gdk_device_has_bidi_layouts (GdkDevice *device)
{
  GdkKeymap *keymap = gdk_display_get_keymap (device->display);

  if (device->source == GDK_SOURCE_KEYBOARD)
    return gdk_keymap_have_bidi_layouts (keymap);

  return FALSE;
}

void
gdk_device_set_timestamp (GdkDevice *device,
                          guint32    timestamp)
{
  device->timestamp = timestamp;
}

/**
 * gdk_device_get_timestamp:
 * @device: a `GdkDevice`
 *
 * Returns the timestamp of the last activity for this device.
 *
 * In practice, this means the timestamp of the last event that was
 * received from the OS for this device. (GTK may occasionally produce
 * events for a device that are not received from the OS, and will not
 * update the timestamp).
 *
 * Returns: the timestamp of the last activity for this device
 *
 * Since: 4.2
 */

guint32
gdk_device_get_timestamp (GdkDevice *device)
{
  g_return_val_if_fail (GDK_IS_DEVICE (device), GDK_CURRENT_TIME);

  return device->timestamp;
}

Messung V0.5 in Prozent
C=98 H=96 G=96

¤ Dauer der Verarbeitung: 0.9 Sekunden  (vorverarbeitet am  2026-07-03) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.