Merge branch 'wip/xkb-support'
* wip/xkb-support: x11: Use XKB to translate keycodes into key symbols x11: Use XKB to track the Locks state x11: Use XKB detectable auto-repeat x11: Add a Keymap ancillary object x11: Store the group inside the event platform data events: Add platform-data to allocated Events build: Check for the XKB extension
This commit is contained in:
commit
ff56f4ac6f
1
README
1
README
@ -28,6 +28,7 @@ On X11, Clutter depends on the following extensions
|
|||||||
• XExt
|
• XExt
|
||||||
• XFixes
|
• XFixes
|
||||||
• XInput 1.x (if --enable-xinput is passed to configure)
|
• XInput 1.x (if --enable-xinput is passed to configure)
|
||||||
|
• XKB
|
||||||
|
|
||||||
When running the OpenGL flavor, Clutter requires at least version 1.3
|
When running the OpenGL flavor, Clutter requires at least version 1.3
|
||||||
or 1.2 with the multitexturing extension. However to build Clutter
|
or 1.2 with the multitexturing extension. However to build Clutter
|
||||||
|
@ -518,6 +518,36 @@ _clutter_backend_get_units_per_em (ClutterBackend *backend,
|
|||||||
return priv->units_per_em;
|
return priv->units_per_em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_clutter_backend_copy_event_data (ClutterBackend *backend,
|
||||||
|
ClutterEvent *src,
|
||||||
|
ClutterEvent *dest)
|
||||||
|
{
|
||||||
|
ClutterBackendClass *klass;
|
||||||
|
|
||||||
|
g_return_if_fail (CLUTTER_IS_BACKEND (backend));
|
||||||
|
g_return_if_fail (src != NULL);
|
||||||
|
g_return_if_fail (dest != NULL);
|
||||||
|
|
||||||
|
klass = CLUTTER_BACKEND_GET_CLASS (backend);
|
||||||
|
if (klass->copy_event_data != NULL)
|
||||||
|
klass->copy_event_data (backend, src, dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_clutter_backend_free_event_data (ClutterBackend *backend,
|
||||||
|
ClutterEvent *event)
|
||||||
|
{
|
||||||
|
ClutterBackendClass *klass;
|
||||||
|
|
||||||
|
g_return_if_fail (CLUTTER_IS_BACKEND (backend));
|
||||||
|
g_return_if_fail (event != NULL);
|
||||||
|
|
||||||
|
klass = CLUTTER_BACKEND_GET_CLASS (backend);
|
||||||
|
if (klass->free_event_data != NULL)
|
||||||
|
klass->free_event_data (backend, event);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_get_default_backend:
|
* clutter_get_default_backend:
|
||||||
*
|
*
|
||||||
|
@ -85,6 +85,12 @@ struct _ClutterBackendClass
|
|||||||
ClutterStage *stage);
|
ClutterStage *stage);
|
||||||
ClutterDeviceManager *(* get_device_manager) (ClutterBackend *backend);
|
ClutterDeviceManager *(* get_device_manager) (ClutterBackend *backend);
|
||||||
|
|
||||||
|
void (* copy_event_data) (ClutterBackend *backend,
|
||||||
|
ClutterEvent *src,
|
||||||
|
ClutterEvent *dest);
|
||||||
|
void (* free_event_data) (ClutterBackend *backend,
|
||||||
|
ClutterEvent *event);
|
||||||
|
|
||||||
/* signals */
|
/* signals */
|
||||||
void (* resolution_changed) (ClutterBackend *backend);
|
void (* resolution_changed) (ClutterBackend *backend);
|
||||||
void (* font_changed) (ClutterBackend *backend);
|
void (* font_changed) (ClutterBackend *backend);
|
||||||
|
@ -43,6 +43,52 @@
|
|||||||
* be synthesized by Clutter itself or by the application code.
|
* be synthesized by Clutter itself or by the application code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
typedef struct _ClutterEventPrivate {
|
||||||
|
ClutterEvent base;
|
||||||
|
|
||||||
|
gpointer platform_data;
|
||||||
|
} ClutterEventPrivate;
|
||||||
|
|
||||||
|
static GHashTable *all_events = NULL;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
is_event_allocated (const ClutterEvent *event)
|
||||||
|
{
|
||||||
|
if (all_events == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return g_hash_table_lookup (all_events, event) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _clutter_event_get_platform_data:
|
||||||
|
* @event: a #ClutterEvent
|
||||||
|
*
|
||||||
|
* Retrieves the pointer to platform-specific data inside an event
|
||||||
|
*
|
||||||
|
* Return value: a pointer to platform-specific data
|
||||||
|
*
|
||||||
|
* Since: 1.4
|
||||||
|
*/
|
||||||
|
gpointer
|
||||||
|
_clutter_event_get_platform_data (const ClutterEvent *event)
|
||||||
|
{
|
||||||
|
if (!is_event_allocated (event))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return ((ClutterEventPrivate *) event)->platform_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_clutter_event_set_platform_data (ClutterEvent *event,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
if (!is_event_allocated (event))
|
||||||
|
return;
|
||||||
|
|
||||||
|
((ClutterEventPrivate *) event)->platform_data = data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_event_type:
|
* clutter_event_type:
|
||||||
* @event: a #ClutterEvent
|
* @event: a #ClutterEvent
|
||||||
@ -606,10 +652,18 @@ ClutterEvent *
|
|||||||
clutter_event_new (ClutterEventType type)
|
clutter_event_new (ClutterEventType type)
|
||||||
{
|
{
|
||||||
ClutterEvent *new_event;
|
ClutterEvent *new_event;
|
||||||
|
ClutterEventPrivate *priv;
|
||||||
|
|
||||||
new_event = g_slice_new0 (ClutterEvent);
|
priv = g_slice_new0 (ClutterEventPrivate);
|
||||||
|
|
||||||
|
new_event = (ClutterEvent *) priv;
|
||||||
new_event->type = new_event->any.type = type;
|
new_event->type = new_event->any.type = type;
|
||||||
|
|
||||||
|
if (all_events == NULL)
|
||||||
|
all_events = g_hash_table_new (NULL, NULL);
|
||||||
|
|
||||||
|
g_hash_table_replace (all_events, priv, GUINT_TO_POINTER (1));
|
||||||
|
|
||||||
return new_event;
|
return new_event;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -631,6 +685,11 @@ clutter_event_copy (ClutterEvent *event)
|
|||||||
new_event = clutter_event_new (CLUTTER_NOTHING);
|
new_event = clutter_event_new (CLUTTER_NOTHING);
|
||||||
*new_event = *event;
|
*new_event = *event;
|
||||||
|
|
||||||
|
if (is_event_allocated (event))
|
||||||
|
_clutter_backend_copy_event_data (clutter_get_default_backend (),
|
||||||
|
event,
|
||||||
|
new_event);
|
||||||
|
|
||||||
return new_event;
|
return new_event;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -644,7 +703,12 @@ void
|
|||||||
clutter_event_free (ClutterEvent *event)
|
clutter_event_free (ClutterEvent *event)
|
||||||
{
|
{
|
||||||
if (G_LIKELY (event != NULL))
|
if (G_LIKELY (event != NULL))
|
||||||
g_slice_free (ClutterEvent, event);
|
{
|
||||||
|
_clutter_backend_free_event_data (clutter_get_default_backend (), event);
|
||||||
|
|
||||||
|
g_hash_table_remove (all_events, event);
|
||||||
|
g_slice_free (ClutterEventPrivate, (ClutterEventPrivate *) event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -245,7 +245,6 @@ int _clutter_stage_get_pending_swaps (ClutterStage *stage);
|
|||||||
|
|
||||||
gboolean _clutter_stage_has_full_redraw_queued (ClutterStage *stage);
|
gboolean _clutter_stage_has_full_redraw_queued (ClutterStage *stage);
|
||||||
|
|
||||||
|
|
||||||
/* vfuncs implemented by backend */
|
/* vfuncs implemented by backend */
|
||||||
GType _clutter_backend_impl_get_type (void);
|
GType _clutter_backend_impl_get_type (void);
|
||||||
|
|
||||||
@ -270,6 +269,12 @@ gboolean _clutter_backend_post_parse (ClutterBackend *backend,
|
|||||||
GError **error);
|
GError **error);
|
||||||
void _clutter_backend_init_events (ClutterBackend *backend);
|
void _clutter_backend_init_events (ClutterBackend *backend);
|
||||||
|
|
||||||
|
void _clutter_backend_copy_event_data (ClutterBackend *backend,
|
||||||
|
ClutterEvent *src,
|
||||||
|
ClutterEvent *dest);
|
||||||
|
void _clutter_backend_free_event_data (ClutterBackend *backend,
|
||||||
|
ClutterEvent *event);
|
||||||
|
|
||||||
ClutterFeatureFlags _clutter_backend_get_features (ClutterBackend *backend);
|
ClutterFeatureFlags _clutter_backend_get_features (ClutterBackend *backend);
|
||||||
|
|
||||||
gfloat _clutter_backend_get_units_per_em (ClutterBackend *backend,
|
gfloat _clutter_backend_get_units_per_em (ClutterBackend *backend,
|
||||||
@ -341,6 +346,10 @@ void _clutter_effect_post_paint (ClutterEffect *effect);
|
|||||||
|
|
||||||
GType _clutter_layout_manager_get_child_meta_type (ClutterLayoutManager *manager);
|
GType _clutter_layout_manager_get_child_meta_type (ClutterLayoutManager *manager);
|
||||||
|
|
||||||
|
void _clutter_event_set_platform_data (ClutterEvent *event,
|
||||||
|
gpointer data);
|
||||||
|
gpointer _clutter_event_get_platform_data (const ClutterEvent *event);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* _HAVE_CLUTTER_PRIVATE_H */
|
#endif /* _HAVE_CLUTTER_PRIVATE_H */
|
||||||
|
@ -46,6 +46,8 @@ libclutter_x11_la_SOURCES = \
|
|||||||
$(srcdir)/clutter-event-x11.c \
|
$(srcdir)/clutter-event-x11.c \
|
||||||
$(srcdir)/clutter-input-device-x11.h \
|
$(srcdir)/clutter-input-device-x11.h \
|
||||||
$(srcdir)/clutter-input-device-x11.c \
|
$(srcdir)/clutter-input-device-x11.c \
|
||||||
|
$(srcdir)/clutter-keymap-x11.h \
|
||||||
|
$(srcdir)/clutter-keymap-x11.c \
|
||||||
$(srcdir)/clutter-settings-x11.h \
|
$(srcdir)/clutter-settings-x11.h \
|
||||||
$(srcdir)/clutter-stage-x11.h \
|
$(srcdir)/clutter-stage-x11.h \
|
||||||
$(srcdir)/clutter-stage-x11.c \
|
$(srcdir)/clutter-stage-x11.c \
|
||||||
|
@ -319,6 +319,12 @@ clutter_backend_x11_post_parse (ClutterBackend *backend,
|
|||||||
"backend", backend_x11,
|
"backend", backend_x11,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
/* register keymap */
|
||||||
|
backend_x11->keymap =
|
||||||
|
g_object_new (CLUTTER_TYPE_KEYMAP_X11,
|
||||||
|
"backend", backend_x11,
|
||||||
|
NULL);
|
||||||
|
|
||||||
/* create XSETTINGS client */
|
/* create XSETTINGS client */
|
||||||
backend_x11->xsettings =
|
backend_x11->xsettings =
|
||||||
_clutter_xsettings_client_new (backend_x11->xdpy,
|
_clutter_xsettings_client_new (backend_x11->xdpy,
|
||||||
@ -475,6 +481,29 @@ clutter_backend_x11_get_features (ClutterBackend *backend)
|
|||||||
return CLUTTER_FEATURE_STAGE_USER_RESIZE | CLUTTER_FEATURE_STAGE_CURSOR;
|
return CLUTTER_FEATURE_STAGE_USER_RESIZE | CLUTTER_FEATURE_STAGE_CURSOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_backend_x11_copy_event_data (ClutterBackend *backend,
|
||||||
|
ClutterEvent *src,
|
||||||
|
ClutterEvent *dest)
|
||||||
|
{
|
||||||
|
gpointer event_x11;
|
||||||
|
|
||||||
|
event_x11 = _clutter_event_get_platform_data (src);
|
||||||
|
if (event_x11 != NULL)
|
||||||
|
_clutter_event_set_platform_data (dest, _clutter_event_x11_copy (event_x11));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_backend_x11_free_event_data (ClutterBackend *backend,
|
||||||
|
ClutterEvent *event)
|
||||||
|
{
|
||||||
|
gpointer event_x11;
|
||||||
|
|
||||||
|
event_x11 = _clutter_event_get_platform_data (event);
|
||||||
|
if (event_x11 != NULL)
|
||||||
|
_clutter_event_x11_free (event_x11);
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
clutter_backend_x11_handle_event (ClutterBackendX11 *backend_x11,
|
clutter_backend_x11_handle_event (ClutterBackendX11 *backend_x11,
|
||||||
XEvent *xevent)
|
XEvent *xevent)
|
||||||
@ -516,6 +545,8 @@ clutter_backend_x11_class_init (ClutterBackendX11Class *klass)
|
|||||||
backend_class->add_options = clutter_backend_x11_add_options;
|
backend_class->add_options = clutter_backend_x11_add_options;
|
||||||
backend_class->get_features = clutter_backend_x11_get_features;
|
backend_class->get_features = clutter_backend_x11_get_features;
|
||||||
backend_class->get_device_manager = clutter_backend_x11_get_device_manager;
|
backend_class->get_device_manager = clutter_backend_x11_get_device_manager;
|
||||||
|
backend_class->copy_event_data = clutter_backend_x11_copy_event_data;
|
||||||
|
backend_class->free_event_data = clutter_backend_x11_free_event_data;
|
||||||
|
|
||||||
backendx11_class->handle_event = clutter_backend_x11_handle_event;
|
backendx11_class->handle_event = clutter_backend_x11_handle_event;
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include "clutter-x11.h"
|
#include "clutter-x11.h"
|
||||||
|
|
||||||
|
#include "clutter-keymap-x11.h"
|
||||||
#include "xsettings/xsettings-client.h"
|
#include "xsettings/xsettings-client.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
@ -88,6 +89,11 @@ struct _ClutterBackendX11
|
|||||||
|
|
||||||
XSettingsClient *xsettings;
|
XSettingsClient *xsettings;
|
||||||
Window xsettings_xwin;
|
Window xsettings_xwin;
|
||||||
|
|
||||||
|
ClutterKeymapX11 *keymap;
|
||||||
|
int xkb_event_base;
|
||||||
|
gboolean use_xkb;
|
||||||
|
gboolean have_xkb_autorepeat;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ClutterBackendX11Class
|
struct _ClutterBackendX11Class
|
||||||
@ -109,6 +115,9 @@ struct _ClutterBackendX11Class
|
|||||||
XEvent *xevent);
|
XEvent *xevent);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* platform-specific event data */
|
||||||
|
typedef struct _ClutterEventX11 ClutterEventX11;
|
||||||
|
|
||||||
void _clutter_backend_x11_events_init (ClutterBackend *backend);
|
void _clutter_backend_x11_events_init (ClutterBackend *backend);
|
||||||
void _clutter_backend_x11_events_uninit (ClutterBackend *backend);
|
void _clutter_backend_x11_events_uninit (ClutterBackend *backend);
|
||||||
|
|
||||||
@ -146,6 +155,15 @@ _clutter_x11_get_device_for_xid (XID id);
|
|||||||
void
|
void
|
||||||
_clutter_x11_select_events (Window xwin);
|
_clutter_x11_select_events (Window xwin);
|
||||||
|
|
||||||
|
ClutterEventX11 *
|
||||||
|
_clutter_event_x11_new (void);
|
||||||
|
|
||||||
|
ClutterEventX11 *
|
||||||
|
_clutter_event_x11_copy (ClutterEventX11 *event_x11);
|
||||||
|
|
||||||
|
void
|
||||||
|
_clutter_event_x11_free (ClutterEventX11 *event_x11);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __CLUTTER_BACKEND_X11_H__ */
|
#endif /* __CLUTTER_BACKEND_X11_H__ */
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include "clutter-stage-x11.h"
|
#include "clutter-stage-x11.h"
|
||||||
#include "clutter-backend-x11.h"
|
#include "clutter-backend-x11.h"
|
||||||
|
#include "clutter-keymap-x11.h"
|
||||||
#include "clutter-x11.h"
|
#include "clutter-x11.h"
|
||||||
|
|
||||||
#include "../clutter-backend.h"
|
#include "../clutter-backend.h"
|
||||||
@ -54,6 +55,10 @@
|
|||||||
#include <X11/extensions/XInput.h>
|
#include <X11/extensions/XInput.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_XKB
|
||||||
|
#include <X11/XKBlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* XEMBED protocol support for toolkit embedding */
|
/* XEMBED protocol support for toolkit embedding */
|
||||||
#define XEMBED_MAPPED (1 << 0)
|
#define XEMBED_MAPPED (1 << 0)
|
||||||
#define MAX_SUPPORTED_XEMBED_VERSION 1
|
#define MAX_SUPPORTED_XEMBED_VERSION 1
|
||||||
@ -85,6 +90,38 @@ struct _ClutterEventSource
|
|||||||
GPollFD event_poll_fd;
|
GPollFD event_poll_fd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct _ClutterEventX11
|
||||||
|
{
|
||||||
|
/* additional fields for Key events */
|
||||||
|
gint key_group;
|
||||||
|
|
||||||
|
guint key_is_modifier : 1;
|
||||||
|
guint num_lock_set : 1;
|
||||||
|
guint caps_lock_set : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
ClutterEventX11 *
|
||||||
|
_clutter_event_x11_new (void)
|
||||||
|
{
|
||||||
|
return g_slice_new0 (ClutterEventX11);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClutterEventX11 *
|
||||||
|
_clutter_event_x11_copy (ClutterEventX11 *event_x11)
|
||||||
|
{
|
||||||
|
if (event_x11 != NULL)
|
||||||
|
return g_slice_dup (ClutterEventX11, event_x11);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_clutter_event_x11_free (ClutterEventX11 *event_x11)
|
||||||
|
{
|
||||||
|
if (event_x11 != NULL)
|
||||||
|
g_slice_free (ClutterEventX11, event_x11);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean clutter_event_prepare (GSource *source,
|
static gboolean clutter_event_prepare (GSource *source,
|
||||||
gint *timeout);
|
gint *timeout);
|
||||||
static gboolean clutter_event_check (GSource *source);
|
static gboolean clutter_event_check (GSource *source);
|
||||||
@ -295,16 +332,18 @@ convert_xdevicekey_to_xkey (XDeviceKeyEvent *xkev,
|
|||||||
}
|
}
|
||||||
#endif /* HAVE_XINPUT */
|
#endif /* HAVE_XINPUT */
|
||||||
|
|
||||||
static void
|
static inline void
|
||||||
translate_key_event (ClutterBackend *backend,
|
translate_key_event (ClutterBackendX11 *backend_x11,
|
||||||
ClutterEvent *event,
|
ClutterEvent *event,
|
||||||
XEvent *xevent)
|
XEvent *xevent)
|
||||||
{
|
{
|
||||||
char buffer[256+1];
|
ClutterEventX11 *event_x11;
|
||||||
|
char buffer[256 + 1];
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
CLUTTER_NOTE (EVENT, "Translating key %s event",
|
/* KeyEvents have platform specific data associated to them */
|
||||||
xevent->xany.type == KeyPress ? "press" : "release");
|
event_x11 = _clutter_event_x11_new ();
|
||||||
|
_clutter_event_set_platform_data (event, event_x11);
|
||||||
|
|
||||||
event->key.time = xevent->xkey.time;
|
event->key.time = xevent->xkey.time;
|
||||||
event->key.modifier_state = (ClutterModifierType) xevent->xkey.state;
|
event->key.modifier_state = (ClutterModifierType) xevent->xkey.state;
|
||||||
@ -312,9 +351,21 @@ translate_key_event (ClutterBackend *backend,
|
|||||||
|
|
||||||
/* keyval is the key ignoring all modifiers ('1' vs. '!') */
|
/* keyval is the key ignoring all modifiers ('1' vs. '!') */
|
||||||
event->key.keyval =
|
event->key.keyval =
|
||||||
XKeycodeToKeysym (xevent->xkey.display,
|
_clutter_keymap_x11_translate_key_state (backend_x11->keymap,
|
||||||
xevent->xkey.keycode,
|
event->key.hardware_keycode,
|
||||||
0);
|
event->key.modifier_state,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
event_x11->key_group =
|
||||||
|
_clutter_keymap_x11_get_key_group (backend_x11->keymap,
|
||||||
|
event->key.modifier_state);
|
||||||
|
event_x11->key_is_modifier =
|
||||||
|
_clutter_keymap_x11_get_is_modifier (backend_x11->keymap,
|
||||||
|
event->key.hardware_keycode);
|
||||||
|
event_x11->num_lock_set =
|
||||||
|
_clutter_keymap_x11_get_num_lock_state (backend_x11->keymap);
|
||||||
|
event_x11->caps_lock_set =
|
||||||
|
_clutter_keymap_x11_get_caps_lock_state (backend_x11->keymap);
|
||||||
|
|
||||||
/* unicode_value is the printable representation */
|
/* unicode_value is the printable representation */
|
||||||
n = XLookupString (&xevent->xkey, buffer, sizeof (buffer) - 1, NULL, NULL);
|
n = XLookupString (&xevent->xkey, buffer, sizeof (buffer) - 1, NULL, NULL);
|
||||||
@ -324,10 +375,13 @@ translate_key_event (ClutterBackend *backend,
|
|||||||
event->key.unicode_value = g_utf8_get_char_validated (buffer, n);
|
event->key.unicode_value = g_utf8_get_char_validated (buffer, n);
|
||||||
if ((event->key.unicode_value != -1) &&
|
if ((event->key.unicode_value != -1) &&
|
||||||
(event->key.unicode_value != -2))
|
(event->key.unicode_value != -2))
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
event->key.unicode_value = (gunichar)'\0';
|
event->key.unicode_value = (gunichar)'\0';
|
||||||
|
|
||||||
|
out:
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -509,7 +563,9 @@ event_translate (ClutterBackend *backend,
|
|||||||
if ((stage_x11->state & CLUTTER_STAGE_STATE_FULLSCREEN) ||
|
if ((stage_x11->state & CLUTTER_STAGE_STATE_FULLSCREEN) ||
|
||||||
(stage_x11->xwin_width != xevent->xconfigure.width) ||
|
(stage_x11->xwin_width != xevent->xconfigure.width) ||
|
||||||
(stage_x11->xwin_height != xevent->xconfigure.height))
|
(stage_x11->xwin_height != xevent->xconfigure.height))
|
||||||
|
{
|
||||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (stage));
|
clutter_actor_queue_relayout (CLUTTER_ACTOR (stage));
|
||||||
|
}
|
||||||
|
|
||||||
/* If we're fullscreened, we want these variables to
|
/* If we're fullscreened, we want these variables to
|
||||||
* represent the size of the window before it was set
|
* represent the size of the window before it was set
|
||||||
@ -669,7 +725,7 @@ event_translate (ClutterBackend *backend,
|
|||||||
clutter_device_manager_get_core_device (manager,
|
clutter_device_manager_get_core_device (manager,
|
||||||
CLUTTER_KEYBOARD_DEVICE);
|
CLUTTER_KEYBOARD_DEVICE);
|
||||||
|
|
||||||
translate_key_event (backend, event, xevent);
|
translate_key_event (backend_x11, event, xevent);
|
||||||
|
|
||||||
set_user_time (backend_x11, &xwindow, xevent->xkey.time);
|
set_user_time (backend_x11, &xwindow, xevent->xkey.time);
|
||||||
break;
|
break;
|
||||||
@ -685,8 +741,11 @@ event_translate (ClutterBackend *backend,
|
|||||||
* the next event and check if it's a KeyPress for the same key
|
* the next event and check if it's a KeyPress for the same key
|
||||||
* and timestamp - and then ignore it if it matches the
|
* and timestamp - and then ignore it if it matches the
|
||||||
* KeyRelease
|
* KeyRelease
|
||||||
|
*
|
||||||
|
* if we have XKB, and autorepeat is enabled, then this becomes
|
||||||
|
* a no-op
|
||||||
*/
|
*/
|
||||||
if (XPending (xevent->xkey.display))
|
if (!backend_x11->have_xkb_autorepeat && XPending (xevent->xkey.display))
|
||||||
{
|
{
|
||||||
XEvent next_event;
|
XEvent next_event;
|
||||||
|
|
||||||
@ -706,7 +765,7 @@ event_translate (ClutterBackend *backend,
|
|||||||
clutter_device_manager_get_core_device (manager,
|
clutter_device_manager_get_core_device (manager,
|
||||||
CLUTTER_KEYBOARD_DEVICE);
|
CLUTTER_KEYBOARD_DEVICE);
|
||||||
|
|
||||||
translate_key_event (backend, event, xevent);
|
translate_key_event (backend_x11, event, xevent);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -986,7 +1045,7 @@ event_translate (ClutterBackend *backend,
|
|||||||
? CLUTTER_KEY_PRESS
|
? CLUTTER_KEY_PRESS
|
||||||
: CLUTTER_KEY_RELEASE;
|
: CLUTTER_KEY_RELEASE;
|
||||||
|
|
||||||
translate_key_event (backend, event, &xevent_converted);
|
translate_key_event (backend_x11, event, &xevent_converted);
|
||||||
|
|
||||||
if (xevent->type == key_press)
|
if (xevent->type == key_press)
|
||||||
set_user_time (backend_x11, &xwindow, xkev->time);
|
set_user_time (backend_x11, &xwindow, xkev->time);
|
||||||
@ -1031,10 +1090,8 @@ events_queue (ClutterBackend *backend)
|
|||||||
g_queue_push_head (clutter_context->events_queue, event);
|
g_queue_push_head (clutter_context->events_queue, event);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
clutter_event_free (event);
|
clutter_event_free (event);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1209,3 +1266,29 @@ clutter_x11_get_current_event_time (void)
|
|||||||
|
|
||||||
return CLUTTER_BACKEND_X11 (backend)->last_event_time;
|
return CLUTTER_BACKEND_X11 (backend)->last_event_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_x11_event_get_key_group:
|
||||||
|
* @event: a #ClutterEvent of type %CLUTTER_KEY_PRESS or %CLUTTER_KEY_RELEASE
|
||||||
|
*
|
||||||
|
* Retrieves the group for the modifiers set in @event
|
||||||
|
*
|
||||||
|
* Return value: the group id
|
||||||
|
*
|
||||||
|
* Since: 1.4
|
||||||
|
*/
|
||||||
|
gint
|
||||||
|
clutter_x11_event_get_key_group (const ClutterEvent *event)
|
||||||
|
{
|
||||||
|
ClutterEventX11 *event_x11;
|
||||||
|
|
||||||
|
g_return_val_if_fail (event != NULL, 0);
|
||||||
|
g_return_val_if_fail (event->type == CLUTTER_KEY_PRESS ||
|
||||||
|
event->type == CLUTTER_KEY_RELEASE, 0);
|
||||||
|
|
||||||
|
event_x11 = _clutter_event_get_platform_data (event);
|
||||||
|
if (event_x11 == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return event_x11->key_group;
|
||||||
|
}
|
||||||
|
422
clutter/x11/clutter-keymap-x11.c
Normal file
422
clutter/x11/clutter-keymap-x11.c
Normal file
@ -0,0 +1,422 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Intel Corp.
|
||||||
|
*
|
||||||
|
* 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: Emmanuele Bassi <ebassi@linux.intel.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "clutter-keymap-x11.h"
|
||||||
|
#include "clutter-backend-x11.h"
|
||||||
|
|
||||||
|
#include "clutter-debug.h"
|
||||||
|
#include "clutter-private.h"
|
||||||
|
|
||||||
|
#include <X11/Xatom.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_XINPUT
|
||||||
|
#include <X11/extensions/XInput.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_XKB
|
||||||
|
#include <X11/XKBlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct _ClutterKeymapX11Class ClutterKeymapX11Class;
|
||||||
|
|
||||||
|
struct _ClutterKeymapX11
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
ClutterBackend *backend;
|
||||||
|
|
||||||
|
gint min_keycode;
|
||||||
|
gint max_keycode;
|
||||||
|
|
||||||
|
ClutterModifierType modmap[8];
|
||||||
|
|
||||||
|
ClutterModifierType num_lock_mask;
|
||||||
|
|
||||||
|
#ifdef HAVE_XKB
|
||||||
|
XkbDescPtr xkb_desc;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
guint caps_lock_state : 1;
|
||||||
|
guint num_lock_state : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _ClutterKeymapX11Class
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_BACKEND
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (ClutterKeymapX11, clutter_keymap_x11, G_TYPE_OBJECT);
|
||||||
|
|
||||||
|
#ifdef HAVE_XKB
|
||||||
|
|
||||||
|
/* code adapted from gdk/x11/gdkkeys-x11.c - update_modmap */
|
||||||
|
static void
|
||||||
|
update_modmap (Display *display,
|
||||||
|
ClutterKeymapX11 *keymap_x11)
|
||||||
|
{
|
||||||
|
static struct {
|
||||||
|
const gchar *name;
|
||||||
|
Atom atom;
|
||||||
|
ClutterModifierType mask;
|
||||||
|
} vmods[] = {
|
||||||
|
{ "Meta", 0, CLUTTER_META_MASK },
|
||||||
|
{ "Super", 0, CLUTTER_SUPER_MASK },
|
||||||
|
{ "Hyper", 0, CLUTTER_HYPER_MASK },
|
||||||
|
{ NULL, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
int i, j, k;
|
||||||
|
|
||||||
|
if (vmods[0].atom == 0)
|
||||||
|
for (i = 0; vmods[i].name; i++)
|
||||||
|
vmods[i].atom = XInternAtom (display, vmods[i].name, FALSE);
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
keymap_x11->modmap[i] = 1 << i;
|
||||||
|
|
||||||
|
for (i = 0; i < XkbNumVirtualMods; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; vmods[j].atom; j++)
|
||||||
|
{
|
||||||
|
if (keymap_x11->xkb_desc->names->vmods[i] == vmods[j].atom)
|
||||||
|
{
|
||||||
|
for (k = 0; k < 8; k++)
|
||||||
|
{
|
||||||
|
if (keymap_x11->xkb_desc->server->vmods[i] & (1 << k))
|
||||||
|
keymap_x11->modmap[k] |= vmods[j].mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static XkbDescPtr
|
||||||
|
get_xkb (ClutterKeymapX11 *keymap_x11)
|
||||||
|
{
|
||||||
|
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (keymap_x11->backend);
|
||||||
|
|
||||||
|
if (keymap_x11->max_keycode == 0)
|
||||||
|
XDisplayKeycodes (backend_x11->xdpy,
|
||||||
|
&keymap_x11->min_keycode,
|
||||||
|
&keymap_x11->max_keycode);
|
||||||
|
|
||||||
|
if (keymap_x11->xkb_desc == NULL)
|
||||||
|
{
|
||||||
|
int flags = XkbKeySymsMask
|
||||||
|
| XkbKeyTypesMask
|
||||||
|
| XkbModifierMapMask
|
||||||
|
| XkbVirtualModsMask;
|
||||||
|
|
||||||
|
keymap_x11->xkb_desc = XkbGetMap (backend_x11->xdpy, flags, XkbUseCoreKbd);
|
||||||
|
if (G_UNLIKELY (keymap_x11->xkb_desc == NULL))
|
||||||
|
{
|
||||||
|
g_error ("Failed to get the keymap from XKB");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
flags = XkbGroupNamesMask | XkbVirtualModNamesMask;
|
||||||
|
XkbGetNames (backend_x11->xdpy, flags, keymap_x11->xkb_desc);
|
||||||
|
|
||||||
|
update_modmap (backend_x11->xdpy, keymap_x11);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keymap_x11->num_lock_mask == 0)
|
||||||
|
keymap_x11->num_lock_mask = XkbKeysymToModifiers (backend_x11->xdpy,
|
||||||
|
XK_Num_Lock);
|
||||||
|
|
||||||
|
return keymap_x11->xkb_desc;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_XKB */
|
||||||
|
|
||||||
|
#ifdef HAVE_XKB
|
||||||
|
static void
|
||||||
|
update_locked_mods (ClutterKeymapX11 *keymap_x11,
|
||||||
|
gint locked_mods)
|
||||||
|
{
|
||||||
|
gboolean old_caps_lock_state, old_num_lock_state;
|
||||||
|
|
||||||
|
old_caps_lock_state = keymap_x11->caps_lock_state;
|
||||||
|
old_num_lock_state = keymap_x11->num_lock_state;
|
||||||
|
|
||||||
|
keymap_x11->caps_lock_state = (locked_mods & CLUTTER_LOCK_MASK) != 0;
|
||||||
|
keymap_x11->num_lock_state = (locked_mods & keymap_x11->num_lock_mask) != 0;
|
||||||
|
|
||||||
|
CLUTTER_NOTE (BACKEND, "Locks state changed - Num: %s, Caps: %s",
|
||||||
|
keymap_x11->num_lock_state ? "set" : "unset",
|
||||||
|
keymap_x11->caps_lock_state ? "set" : "unset");
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* Add signal to ClutterBackend? */
|
||||||
|
if ((keymap_x11->caps_lock_state != old_caps_lock_state) ||
|
||||||
|
(keymap_x11->num_lock_state != old_num_lock_state))
|
||||||
|
g_signal_emit_by_name (keymap_x11->backend, "key-lock-changed");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClutterX11FilterReturn
|
||||||
|
xkb_filter (XEvent *xevent,
|
||||||
|
ClutterEvent *event,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
ClutterBackendX11 *backend_x11 = data;
|
||||||
|
ClutterKeymapX11 *keymap_x11 = backend_x11->keymap;
|
||||||
|
|
||||||
|
g_assert (keymap_x11 != NULL);
|
||||||
|
|
||||||
|
if (!backend_x11->use_xkb)
|
||||||
|
return CLUTTER_X11_FILTER_CONTINUE;
|
||||||
|
|
||||||
|
if (xevent->type == backend_x11->xkb_event_base)
|
||||||
|
{
|
||||||
|
XkbEvent *xkb_event = (XkbEvent *) xevent;
|
||||||
|
|
||||||
|
CLUTTER_NOTE (BACKEND, "Received XKB event [%d]",
|
||||||
|
xkb_event->any.xkb_type);
|
||||||
|
|
||||||
|
switch (xkb_event->any.xkb_type)
|
||||||
|
{
|
||||||
|
case XkbStateNotify:
|
||||||
|
update_locked_mods (keymap_x11, xkb_event->state.locked_mods);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CLUTTER_X11_FILTER_CONTINUE;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_XKB */
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_keymap_x11_constructed (GObject *gobject)
|
||||||
|
{
|
||||||
|
ClutterKeymapX11 *keymap_x11 = CLUTTER_KEYMAP_X11 (gobject);
|
||||||
|
ClutterBackendX11 *backend_x11;
|
||||||
|
|
||||||
|
g_assert (keymap_x11->backend != NULL);
|
||||||
|
backend_x11 = CLUTTER_BACKEND_X11 (keymap_x11->backend);
|
||||||
|
|
||||||
|
#if HAVE_XKB
|
||||||
|
{
|
||||||
|
gint xkb_major = XkbMajorVersion;
|
||||||
|
gint xkb_minor = XkbMinorVersion;
|
||||||
|
|
||||||
|
if (XkbLibraryVersion (&xkb_major, &xkb_minor))
|
||||||
|
{
|
||||||
|
xkb_major = XkbMajorVersion;
|
||||||
|
xkb_minor = XkbMinorVersion;
|
||||||
|
|
||||||
|
if (XkbQueryExtension (backend_x11->xdpy,
|
||||||
|
NULL, &backend_x11->xkb_event_base, NULL,
|
||||||
|
&xkb_major, &xkb_minor))
|
||||||
|
{
|
||||||
|
Bool detectable_autorepeat_supported;
|
||||||
|
|
||||||
|
backend_x11->use_xkb = TRUE;
|
||||||
|
|
||||||
|
XkbSelectEvents (backend_x11->xdpy,
|
||||||
|
XkbUseCoreKbd,
|
||||||
|
XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask,
|
||||||
|
XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask);
|
||||||
|
|
||||||
|
XkbSelectEventDetails (backend_x11->xdpy,
|
||||||
|
XkbUseCoreKbd, XkbStateNotify,
|
||||||
|
XkbAllStateComponentsMask,
|
||||||
|
XkbGroupLockMask|XkbModifierLockMask);
|
||||||
|
|
||||||
|
clutter_x11_add_filter (xkb_filter, backend_x11);
|
||||||
|
|
||||||
|
/* enable XKB autorepeat */
|
||||||
|
XkbSetDetectableAutoRepeat (backend_x11->xdpy,
|
||||||
|
True,
|
||||||
|
&detectable_autorepeat_supported);
|
||||||
|
|
||||||
|
backend_x11->have_xkb_autorepeat = detectable_autorepeat_supported;
|
||||||
|
|
||||||
|
CLUTTER_NOTE (BACKEND, "Detectable autorepeat: %s",
|
||||||
|
backend_x11->have_xkb_autorepeat ? "supported"
|
||||||
|
: "not supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* HAVE_XKB */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_keymap_x11_set_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
ClutterKeymapX11 *keymap = CLUTTER_KEYMAP_X11 (gobject);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_BACKEND:
|
||||||
|
keymap->backend = g_value_get_object (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_keymap_x11_finalize (GObject *gobject)
|
||||||
|
{
|
||||||
|
ClutterKeymapX11 *keymap;
|
||||||
|
|
||||||
|
keymap = CLUTTER_KEYMAP_X11 (gobject);
|
||||||
|
|
||||||
|
#ifdef HAVE_XKB
|
||||||
|
if (keymap->xkb_desc != NULL)
|
||||||
|
XkbFreeKeyboard (keymap->xkb_desc, XkbAllComponentsMask, True);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (clutter_keymap_x11_parent_class)->finalize (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_keymap_x11_class_init (ClutterKeymapX11Class *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
GParamSpec *pspec;
|
||||||
|
|
||||||
|
gobject_class->constructed = clutter_keymap_x11_constructed;
|
||||||
|
gobject_class->set_property = clutter_keymap_x11_set_property;
|
||||||
|
gobject_class->finalize = clutter_keymap_x11_finalize;
|
||||||
|
|
||||||
|
pspec = g_param_spec_object ("backend",
|
||||||
|
"Backend",
|
||||||
|
"The Clutter backend",
|
||||||
|
CLUTTER_TYPE_BACKEND,
|
||||||
|
CLUTTER_PARAM_WRITABLE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY);
|
||||||
|
g_object_class_install_property (gobject_class, PROP_BACKEND, pspec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_keymap_x11_init (ClutterKeymapX11 *keymap)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
gint
|
||||||
|
_clutter_keymap_x11_get_key_group (ClutterKeymapX11 *keymap,
|
||||||
|
ClutterModifierType state)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_XKB
|
||||||
|
return XkbGroupForCoreState (state);
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif /* HAVE_XKB */
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_clutter_keymap_x11_get_num_lock_state (ClutterKeymapX11 *keymap)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (CLUTTER_IS_KEYMAP_X11 (keymap), FALSE);
|
||||||
|
|
||||||
|
return keymap->num_lock_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_clutter_keymap_x11_get_caps_lock_state (ClutterKeymapX11 *keymap)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (CLUTTER_IS_KEYMAP_X11 (keymap), FALSE);
|
||||||
|
|
||||||
|
return keymap->caps_lock_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
gint
|
||||||
|
_clutter_keymap_x11_translate_key_state (ClutterKeymapX11 *keymap,
|
||||||
|
guint hardware_keycode,
|
||||||
|
ClutterModifierType modifier_state,
|
||||||
|
ClutterModifierType *mods_p)
|
||||||
|
{
|
||||||
|
ClutterBackendX11 *backend_x11;
|
||||||
|
ClutterModifierType unconsumed_modifiers = 0;
|
||||||
|
gint retval;
|
||||||
|
|
||||||
|
g_return_val_if_fail (CLUTTER_IS_KEYMAP_X11 (keymap), 0);
|
||||||
|
|
||||||
|
backend_x11 = CLUTTER_BACKEND_X11 (keymap->backend);
|
||||||
|
|
||||||
|
#ifdef HAVE_XKB
|
||||||
|
if (backend_x11->use_xkb)
|
||||||
|
{
|
||||||
|
XkbDescRec *xkb = get_xkb (keymap);
|
||||||
|
KeySym tmp_keysym;
|
||||||
|
|
||||||
|
if (XkbTranslateKeyCode (xkb, hardware_keycode, modifier_state,
|
||||||
|
&unconsumed_modifiers,
|
||||||
|
&tmp_keysym))
|
||||||
|
{
|
||||||
|
retval = tmp_keysym;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
retval = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* HAVE_XKB */
|
||||||
|
retval = XKeycodeToKeysym (backend_x11->xdpy, hardware_keycode, 0);
|
||||||
|
|
||||||
|
if (mods_p)
|
||||||
|
*mods_p = unconsumed_modifiers;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_clutter_keymap_x11_get_is_modifier (ClutterKeymapX11 *keymap,
|
||||||
|
guint keycode)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (CLUTTER_IS_KEYMAP_X11 (keymap), FALSE);
|
||||||
|
|
||||||
|
if (keycode < keymap->min_keycode || keycode > keymap->max_keycode)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
#ifdef HAVE_XKB
|
||||||
|
if (CLUTTER_BACKEND_X11 (keymap->backend)->use_xkb)
|
||||||
|
{
|
||||||
|
XkbDescRec *xkb = get_xkb (keymap);
|
||||||
|
|
||||||
|
if (xkb->map->modmap && xkb->map->modmap[keycode] != 0)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_XKB */
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
53
clutter/x11/clutter-keymap-x11.h
Normal file
53
clutter/x11/clutter-keymap-x11.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Intel Corp.
|
||||||
|
*
|
||||||
|
* 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: Emmanuele Bassi <ebassi@linux.intel.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CLUTTER_KEYMAP_X11_H__
|
||||||
|
#define __CLUTTER_KEYMAP_X11_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <clutter/clutter-event.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define CLUTTER_TYPE_KEYMAP_X11 (clutter_keymap_x11_get_type ())
|
||||||
|
#define CLUTTER_KEYMAP_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_KEYMAP_X11, ClutterKeymapX11))
|
||||||
|
#define CLUTTER_IS_KEYMAP_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_KEYMAP_X11))
|
||||||
|
|
||||||
|
typedef struct _ClutterKeymapX11 ClutterKeymapX11;
|
||||||
|
|
||||||
|
GType clutter_keymap_x11_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
gint _clutter_keymap_x11_get_key_group (ClutterKeymapX11 *keymap,
|
||||||
|
ClutterModifierType state);
|
||||||
|
gboolean _clutter_keymap_x11_get_num_lock_state (ClutterKeymapX11 *keymap);
|
||||||
|
gboolean _clutter_keymap_x11_get_caps_lock_state (ClutterKeymapX11 *keymap);
|
||||||
|
gint _clutter_keymap_x11_translate_key_state (ClutterKeymapX11 *keymap,
|
||||||
|
guint hardware_keycode,
|
||||||
|
ClutterModifierType modifier_state,
|
||||||
|
ClutterModifierType *mods_p);
|
||||||
|
gboolean _clutter_keymap_x11_get_is_modifier (ClutterKeymapX11 *keymap,
|
||||||
|
guint keycode);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __CLUTTER_KEYMAP_X11_H__ */
|
@ -141,6 +141,8 @@ gboolean clutter_x11_get_use_argb_visual (void);
|
|||||||
|
|
||||||
Time clutter_x11_get_current_event_time (void);
|
Time clutter_x11_get_current_event_time (void);
|
||||||
|
|
||||||
|
gint clutter_x11_event_get_key_group (const ClutterEvent *event);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __CLUTTER_X11_H__ */
|
#endif /* __CLUTTER_X11_H__ */
|
||||||
|
20
configure.ac
20
configure.ac
@ -692,7 +692,7 @@ AS_IF([test "x$SUPPORT_XLIB" = "x1"],
|
|||||||
|
|
||||||
[yes],
|
[yes],
|
||||||
[
|
[
|
||||||
AC_DEFINE(HAVE_XINPUT, 1, Use the XINPUT X extension)
|
AC_DEFINE(HAVE_XINPUT, 1, [Use the XINPUT X extension])
|
||||||
|
|
||||||
X11_LIBS="$X11_LIBS -lXi"
|
X11_LIBS="$X11_LIBS -lXi"
|
||||||
X11_PC_FILES="$X11_PC_FILES xi"
|
X11_PC_FILES="$X11_PC_FILES xi"
|
||||||
@ -702,6 +702,23 @@ AS_IF([test "x$SUPPORT_XLIB" = "x1"],
|
|||||||
[],
|
[],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# XKB
|
||||||
|
clutter_save_CPPFLAGS="$CPPFLAGS"
|
||||||
|
CPPFLAGS="$CPPFLAGS $X11_CFLAGS"
|
||||||
|
|
||||||
|
clutter_save_LIBS="$LIBS"
|
||||||
|
LIBS="$LIBS $X11_LIBS"
|
||||||
|
|
||||||
|
have_xkb=no
|
||||||
|
AC_CHECK_FUNC([XkbQueryExtension],
|
||||||
|
[
|
||||||
|
AC_DEFINE(HAVE_XKB, 1, [Define to use XKB extension])
|
||||||
|
have_xkb=yes
|
||||||
|
])
|
||||||
|
|
||||||
|
CPPFLAGS="$clutter_save_CPPFLAGS"
|
||||||
|
LIBS="$clutter_save_LIBS"
|
||||||
|
|
||||||
x11_tests=yes
|
x11_tests=yes
|
||||||
BACKEND_PC_FILES="$BACKEND_PC_FILES $X11_PC_FILES"
|
BACKEND_PC_FILES="$BACKEND_PC_FILES $X11_PC_FILES"
|
||||||
FLAVOUR_LIBS="$FLAVOUR_LIBS $X11_LIBS"
|
FLAVOUR_LIBS="$FLAVOUR_LIBS $X11_LIBS"
|
||||||
@ -1144,6 +1161,7 @@ fi
|
|||||||
|
|
||||||
if test "x$SUPPORT_XLIB" = "x1"; then
|
if test "x$SUPPORT_XLIB" = "x1"; then
|
||||||
echo " Enable XInput 1.0: ${xinput}"
|
echo " Enable XInput 1.0: ${xinput}"
|
||||||
|
echo " Enable XKB: ${have_xkb}"
|
||||||
echo " Enable X11 tests: ${x11_tests}"
|
echo " Enable X11 tests: ${x11_tests}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user