* 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include "config.h"
+#include "gdkkeysyms.h"
#include "gdkkeysprivate.h"
#include "gdkdisplay.h"
#include "gdkdisplaymanagerprivate.h"
LAST_SIGNAL
};
+
+static GdkModifierType gdk_keymap_real_get_modifier_mask (GdkKeymap *keymap,
+ GdkModifierIntent intent);
+
+
static guint signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE (GdkKeymap, gdk_keymap, G_TYPE_OBJECT)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ klass->get_modifier_mask = gdk_keymap_real_get_modifier_mask;
+
/**
* GdkKeymap::direction-changed:
* @keymap: the object on which the signal is emitted
- *
+ *
* The ::direction-changed signal gets emitted when the direction of
- * the keymap changes.
+ * the keymap changes.
*
* Since: 2.0
*/
G_STRUCT_OFFSET (GdkKeymapClass, state_changed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE,
+ G_TYPE_NONE,
0);
}
gdk_keyval_to_upper (guint keyval)
{
guint result;
-
+
gdk_keyval_convert_case (keyval, NULL, &result);
return result;
gdk_keyval_to_lower (guint keyval)
{
guint result;
-
+
gdk_keyval_convert_case (keyval, &result, NULL);
return result;
if (keyval)
{
guint upper_val = 0;
-
+
gdk_keyval_convert_case (keyval, NULL, &upper_val);
return upper_val == keyval;
}
if (keyval)
{
guint lower_val = 0;
-
+
gdk_keyval_convert_case (keyval, &lower_val, NULL);
return lower_val == keyval;
}
return FALSE;
}
-/**
+/**
* gdk_keymap_get_default:
*
* Returns the #GdkKeymap attached to the default display.
/**
* gdk_keymap_get_direction:
- * @keymap: a #GdkKeymap or %NULL to use the default keymap
+ * @keymap: a #GdkKeymap
*
* Returns the direction of effective layout of the keymap.
*
PangoDirection
gdk_keymap_get_direction (GdkKeymap *keymap)
{
- return GDK_KEYMAP_GET_CLASS(keymap)->get_direction (keymap);
+ g_return_val_if_fail (GDK_IS_KEYMAP (keymap), PANGO_DIRECTION_LTR);
+
+ return GDK_KEYMAP_GET_CLASS (keymap)->get_direction (keymap);
}
/**
* gdk_keymap_have_bidi_layouts:
- * @keymap: a #GdkKeymap or %NULL to use the default keymap
+ * @keymap: a #GdkKeymap
*
* Determines if keyboard layouts for both right-to-left and left-to-right
* languages are in use.
gboolean
gdk_keymap_have_bidi_layouts (GdkKeymap *keymap)
{
- return GDK_KEYMAP_GET_CLASS(keymap)->have_bidi_layouts (keymap);
+ g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
+
+ return GDK_KEYMAP_GET_CLASS (keymap)->have_bidi_layouts (keymap);
}
/**
gboolean
gdk_keymap_get_caps_lock_state (GdkKeymap *keymap)
{
- return GDK_KEYMAP_GET_CLASS(keymap)->get_caps_lock_state (keymap);
+ g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
+
+ return GDK_KEYMAP_GET_CLASS (keymap)->get_caps_lock_state (keymap);
}
/**
gboolean
gdk_keymap_get_num_lock_state (GdkKeymap *keymap)
{
- return GDK_KEYMAP_GET_CLASS(keymap)->get_num_lock_state (keymap);
+ g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
+
+ return GDK_KEYMAP_GET_CLASS (keymap)->get_num_lock_state (keymap);
+}
+
+/**
+ * gdk_keymap_get_modifier_state:
+ * @keymap: a #GdkKeymap
+ *
+ * Returns the current modifier state.
+ *
+ * Returns: the current modifier state.
+ *
+ * Since: 3.4
+ */
+guint
+gdk_keymap_get_modifier_state (GdkKeymap *keymap)
+{
+ g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
+
+ if (GDK_KEYMAP_GET_CLASS (keymap)->get_modifier_state)
+ return GDK_KEYMAP_GET_CLASS (keymap)->get_modifier_state (keymap);
+
+ return 0;
}
/**
* gdk_keymap_get_entries_for_keyval:
- * @keymap: (allow-none): a #GdkKeymap, or %NULL to use the default keymap
+ * @keymap: a #GdkKeymap
* @keyval: a keyval, such as %GDK_a, %GDK_Up, %GDK_Return, etc.
- * @keys: (out): return location for an array of #GdkKeymapKey
- * @n_keys: (out): return location for number of elements in returned array
+ * @keys: (out) (array length=n_keys) (transfer full): return location
+ * for an array of #GdkKeymapKey
+ * @n_keys: return location for number of elements in returned array
*
* Obtains a list of keycode/group/level combinations that will
* generate @keyval. Groups and levels are two kinds of keyboard mode;
GdkKeymapKey **keys,
gint *n_keys)
{
- return GDK_KEYMAP_GET_CLASS(keymap)->get_entries_for_keyval (keymap, keyval, keys, n_keys);
+ g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
+ g_return_val_if_fail (keys != NULL, FALSE);
+ g_return_val_if_fail (n_keys != NULL, FALSE);
+ g_return_val_if_fail (keyval != 0, FALSE);
+
+ return GDK_KEYMAP_GET_CLASS (keymap)->get_entries_for_keyval (keymap, keyval,
+ keys, n_keys);
}
/**
* gdk_keymap_get_entries_for_keycode:
- * @keymap: (allow-none): a #GdkKeymap or %NULL to use the default keymap
+ * @keymap: a #GdkKeymap
* @hardware_keycode: a keycode
- * @keys: (out): return location for array of #GdkKeymapKey, or %NULL
- * @keyvals: (out): return location for array of keyvals, or %NULL
+ * @keys: (out) (array length=n_entries) (transfer full): return
+ * location for array of #GdkKeymapKey, or %NULL
+ * @keyvals: (out) (array length=n_entries) (transfer full): return
+ * location for array of keyvals, or %NULL
* @n_entries: length of @keys and @keyvals
*
* Returns the keyvals bound to @hardware_keycode.
guint **keyvals,
gint *n_entries)
{
- return GDK_KEYMAP_GET_CLASS(keymap)->get_entries_for_keycode (keymap, hardware_keycode, keys, keyvals, n_entries);
+ g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
+ g_return_val_if_fail (n_entries != NULL, FALSE);
+
+ return GDK_KEYMAP_GET_CLASS (keymap)->get_entries_for_keycode (keymap, hardware_keycode,
+ keys, keyvals, n_entries);
}
/**
* gdk_keymap_lookup_key:
- * @keymap: a #GdkKeymap or %NULL to use the default keymap
+ * @keymap: a #GdkKeymap
* @key: a #GdkKeymapKey with keycode, group, and level initialized
*
* Looks up the keyval mapped to a keycode/group/level triplet.
gdk_keymap_lookup_key (GdkKeymap *keymap,
const GdkKeymapKey *key)
{
- return GDK_KEYMAP_GET_CLASS(keymap)->lookup_key (keymap, key);
+ g_return_val_if_fail (GDK_IS_KEYMAP (keymap), 0);
+ g_return_val_if_fail (key != NULL, 0);
+
+ return GDK_KEYMAP_GET_CLASS (keymap)->lookup_key (keymap, key);
}
/**
* gdk_keymap_translate_keyboard_state:
- * @keymap: (allow-none): a #GdkKeymap, or %NULL to use the default
+ * @keymap: a #GdkKeymap
* @hardware_keycode: a keycode
* @state: a modifier state
* @group: active keyboard group
* @keyval: (out) (allow-none): return location for keyval, or %NULL
- * @effective_group: (out) (allow-none): return location for effective group, or %NULL
- * @level: (out) (allow-none): return location for level, or %NULL
- * @consumed_modifiers: (out) (allow-none): return location for modifiers that were used to
- * determine the group or level, or %NULL
+ * @effective_group: (out) (allow-none): return location for effective
+ * group, or %NULL
+ * @level: (out) (allow-none): return location for level, or %NULL
+ * @consumed_modifiers: (out) (allow-none): return location for modifiers
+ * that were used to determine the group or level, or %NULL
*
* Translates the contents of a #GdkEventKey into a keyval, effective
* group, and level. Modifiers that affected the translation and
* are thus unavailable for application use are returned in
- * @consumed_modifiers. See <xref linkend="key-group-explanation"/> for an explanation of
- * groups and levels. The @effective_group is the group that was
+ * @consumed_modifiers.
+ * See <xref linkend="key-group-explanation"/> for an explanation of
+ * groups and levels. The @effective_group is the group that was
* actually used for the translation; some keys such as Enter are not
* affected by the active keyboard group. The @level is derived from
* @state. For convenience, #GdkEventKey already contains the translated
gint *level,
GdkModifierType *consumed_modifiers)
{
- return GDK_KEYMAP_GET_CLASS(keymap)->translate_keyboard_state (keymap,
+ g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
+
+ return GDK_KEYMAP_GET_CLASS (keymap)->translate_keyboard_state (keymap,
hardware_keycode,
state,
group,
/**
* gdk_keymap_add_virtual_modifiers:
* @keymap: a #GdkKeymap
- * @state: pointer to the modifier mask to change
+ * @state: (inout): pointer to the modifier mask to change
*
- * Adds virtual modifiers (i.e. Super, Hyper and Meta) which correspond
- * to the real modifiers (i.e Mod2, Mod3, ...) in @modifiers.
- * are set in @state to their non-virtual counterparts (i.e. Mod2,
- * Mod3,...) and set the corresponding bits in @state.
+ * Maps the non-virtual modifiers (i.e Mod2, Mod3, ...) which are set
+ * in @state to the virtual modifiers (i.e. Super, Hyper and Meta) and
+ * set the corresponding bits in @state.
*
* GDK already does this before delivering key events, but for
* compatibility reasons, it only sets the first virtual modifier
gdk_keymap_add_virtual_modifiers (GdkKeymap *keymap,
GdkModifierType *state)
{
- GDK_KEYMAP_GET_CLASS(keymap)->add_virtual_modifiers (keymap, state);
+ g_return_if_fail (GDK_IS_KEYMAP (keymap));
+
+ GDK_KEYMAP_GET_CLASS (keymap)->add_virtual_modifiers (keymap, state);
}
/**
* gdk_keymap_map_virtual_modifiers:
* @keymap: a #GdkKeymap
- * @state: pointer to the modifier state to map
+ * @state: (inout): pointer to the modifier state to map
*
* Maps the virtual modifiers (i.e. Super, Hyper and Meta) which
* are set in @state to their non-virtual counterparts (i.e. Mod2,
gdk_keymap_map_virtual_modifiers (GdkKeymap *keymap,
GdkModifierType *state)
{
+ g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
+
return GDK_KEYMAP_GET_CLASS(keymap)->map_virtual_modifiers (keymap, state);
}
+static GdkModifierType
+gdk_keymap_real_get_modifier_mask (GdkKeymap *keymap,
+ GdkModifierIntent intent)
+{
+ switch (intent)
+ {
+ case GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR:
+ return GDK_CONTROL_MASK;
+
+ case GDK_MODIFIER_INTENT_CONTEXT_MENU:
+ return 0;
+
+ case GDK_MODIFIER_INTENT_EXTEND_SELECTION:
+ return GDK_SHIFT_MASK;
+
+ case GDK_MODIFIER_INTENT_MODIFY_SELECTION:
+ return GDK_CONTROL_MASK;
+
+ case GDK_MODIFIER_INTENT_NO_TEXT_INPUT:
+ return GDK_MOD1_MASK | GDK_CONTROL_MASK;
+
+ case GDK_MODIFIER_INTENT_SHIFT_GROUP:
+ return 0;
+
+ default:
+ g_return_val_if_reached (0);
+ }
+}
+
+/**
+ * gdk_keymap_get_modifier_mask:
+ * @keymap: a #GdkKeymap
+ * @intent: the use case for the modifier mask
+ *
+ * Returns the modifier mask the @keymap's windowing system backend
+ * uses for a particular purpose.
+ *
+ * Note that this function always returns real hardware modifiers, not
+ * virtual ones (e.g. it will return #GDK_MOD1_MASK rather than
+ * #GDK_META_MASK if the backend maps MOD1 to META), so there are use
+ * cases where the return value of this function has to be transformed
+ * by gdk_keymap_add_virtual_modifiers() in order to contain the
+ * expected result.
+ *
+ * Returns: the modifier mask used for @intent.
+ *
+ * Since: 3.4
+ **/
+GdkModifierType
+gdk_keymap_get_modifier_mask (GdkKeymap *keymap,
+ GdkModifierIntent intent)
+{
+ g_return_val_if_fail (GDK_IS_KEYMAP (keymap), 0);
+
+ return GDK_KEYMAP_GET_CLASS (keymap)->get_modifier_mask (keymap, intent);
+}
+
+
/**
* gdk_keyval_name:
- * @keyval: a key value.
+ * @keyval: a key value
*
* Converts a key value into a symbolic name.
+ *
* The names are the same as those in the
* <filename><gdk/gdkkeysyms.h></filename> header file
* but without the leading "GDK_KEY_".
* or %NULL if @keyval is not a valid key. The string should not be
* modified.
*/
-gchar*
+gchar *
gdk_keyval_name (guint keyval)
{
GdkDisplayManager *manager = gdk_display_manager_get ();
- return GDK_DISPLAY_MANAGER_GET_CLASS (manager)->get_keyval_name (manager, keyval);
+ return GDK_DISPLAY_MANAGER_GET_CLASS (manager)->get_keyval_name (manager,
+ keyval);
}
+/**
+ * gdk_keyval_from_name:
+ * @keyval_name: a key name
+ *
+ * Converts a key name to a key value.
+ *
+ * The names are the same as those in the
+ * <filename><gdk/gdkkeysyms.h></filename> header file
+ * but without the leading "GDK_KEY_".
+ *
+ * Returns: the corresponding key value, or %GDK_KEY_VoidSymbol
+ * if the key name is not a valid key
+ */
guint
gdk_keyval_from_name (const gchar *keyval_name)
{
GdkDisplayManager *manager = gdk_display_manager_get ();
- return GDK_DISPLAY_MANAGER_GET_CLASS (manager)->lookup_keyval (manager, keyval_name);
+ return GDK_DISPLAY_MANAGER_GET_CLASS (manager)->lookup_keyval (manager,
+ keyval_name);
+}
+
+void
+_gdk_display_manager_real_keyval_convert_case (GdkDisplayManager *manager,
+ guint symbol,
+ guint *lower,
+ guint *upper)
+{
+ guint xlower = symbol;
+ guint xupper = symbol;
+
+ /* Check for directly encoded 24-bit UCS characters: */
+ if ((symbol & 0xff000000) == 0x01000000)
+ {
+ if (lower)
+ *lower = gdk_unicode_to_keyval (g_unichar_tolower (symbol & 0x00ffffff));
+ if (upper)
+ *upper = gdk_unicode_to_keyval (g_unichar_toupper (symbol & 0x00ffffff));
+ return;
+ }
+
+ switch (symbol >> 8)
+ {
+ case 0: /* Latin 1 */
+ if ((symbol >= GDK_KEY_A) && (symbol <= GDK_KEY_Z))
+ xlower += (GDK_KEY_a - GDK_KEY_A);
+ else if ((symbol >= GDK_KEY_a) && (symbol <= GDK_KEY_z))
+ xupper -= (GDK_KEY_a - GDK_KEY_A);
+ else if ((symbol >= GDK_KEY_Agrave) && (symbol <= GDK_KEY_Odiaeresis))
+ xlower += (GDK_KEY_agrave - GDK_KEY_Agrave);
+ else if ((symbol >= GDK_KEY_agrave) && (symbol <= GDK_KEY_odiaeresis))
+ xupper -= (GDK_KEY_agrave - GDK_KEY_Agrave);
+ else if ((symbol >= GDK_KEY_Ooblique) && (symbol <= GDK_KEY_Thorn))
+ xlower += (GDK_KEY_oslash - GDK_KEY_Ooblique);
+ else if ((symbol >= GDK_KEY_oslash) && (symbol <= GDK_KEY_thorn))
+ xupper -= (GDK_KEY_oslash - GDK_KEY_Ooblique);
+ break;
+
+ case 1: /* Latin 2 */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (symbol == GDK_KEY_Aogonek)
+ xlower = GDK_KEY_aogonek;
+ else if (symbol >= GDK_KEY_Lstroke && symbol <= GDK_KEY_Sacute)
+ xlower += (GDK_KEY_lstroke - GDK_KEY_Lstroke);
+ else if (symbol >= GDK_KEY_Scaron && symbol <= GDK_KEY_Zacute)
+ xlower += (GDK_KEY_scaron - GDK_KEY_Scaron);
+ else if (symbol >= GDK_KEY_Zcaron && symbol <= GDK_KEY_Zabovedot)
+ xlower += (GDK_KEY_zcaron - GDK_KEY_Zcaron);
+ else if (symbol == GDK_KEY_aogonek)
+ xupper = GDK_KEY_Aogonek;
+ else if (symbol >= GDK_KEY_lstroke && symbol <= GDK_KEY_sacute)
+ xupper -= (GDK_KEY_lstroke - GDK_KEY_Lstroke);
+ else if (symbol >= GDK_KEY_scaron && symbol <= GDK_KEY_zacute)
+ xupper -= (GDK_KEY_scaron - GDK_KEY_Scaron);
+ else if (symbol >= GDK_KEY_zcaron && symbol <= GDK_KEY_zabovedot)
+ xupper -= (GDK_KEY_zcaron - GDK_KEY_Zcaron);
+ else if (symbol >= GDK_KEY_Racute && symbol <= GDK_KEY_Tcedilla)
+ xlower += (GDK_KEY_racute - GDK_KEY_Racute);
+ else if (symbol >= GDK_KEY_racute && symbol <= GDK_KEY_tcedilla)
+ xupper -= (GDK_KEY_racute - GDK_KEY_Racute);
+ break;
+
+ case 2: /* Latin 3 */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (symbol >= GDK_KEY_Hstroke && symbol <= GDK_KEY_Hcircumflex)
+ xlower += (GDK_KEY_hstroke - GDK_KEY_Hstroke);
+ else if (symbol >= GDK_KEY_Gbreve && symbol <= GDK_KEY_Jcircumflex)
+ xlower += (GDK_KEY_gbreve - GDK_KEY_Gbreve);
+ else if (symbol >= GDK_KEY_hstroke && symbol <= GDK_KEY_hcircumflex)
+ xupper -= (GDK_KEY_hstroke - GDK_KEY_Hstroke);
+ else if (symbol >= GDK_KEY_gbreve && symbol <= GDK_KEY_jcircumflex)
+ xupper -= (GDK_KEY_gbreve - GDK_KEY_Gbreve);
+ else if (symbol >= GDK_KEY_Cabovedot && symbol <= GDK_KEY_Scircumflex)
+ xlower += (GDK_KEY_cabovedot - GDK_KEY_Cabovedot);
+ else if (symbol >= GDK_KEY_cabovedot && symbol <= GDK_KEY_scircumflex)
+ xupper -= (GDK_KEY_cabovedot - GDK_KEY_Cabovedot);
+ break;
+
+ case 3: /* Latin 4 */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (symbol >= GDK_KEY_Rcedilla && symbol <= GDK_KEY_Tslash)
+ xlower += (GDK_KEY_rcedilla - GDK_KEY_Rcedilla);
+ else if (symbol >= GDK_KEY_rcedilla && symbol <= GDK_KEY_tslash)
+ xupper -= (GDK_KEY_rcedilla - GDK_KEY_Rcedilla);
+ else if (symbol == GDK_KEY_ENG)
+ xlower = GDK_KEY_eng;
+ else if (symbol == GDK_KEY_eng)
+ xupper = GDK_KEY_ENG;
+ else if (symbol >= GDK_KEY_Amacron && symbol <= GDK_KEY_Umacron)
+ xlower += (GDK_KEY_amacron - GDK_KEY_Amacron);
+ else if (symbol >= GDK_KEY_amacron && symbol <= GDK_KEY_umacron)
+ xupper -= (GDK_KEY_amacron - GDK_KEY_Amacron);
+ break;
+
+ case 6: /* Cyrillic */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (symbol >= GDK_KEY_Serbian_DJE && symbol <= GDK_KEY_Serbian_DZE)
+ xlower -= (GDK_KEY_Serbian_DJE - GDK_KEY_Serbian_dje);
+ else if (symbol >= GDK_KEY_Serbian_dje && symbol <= GDK_KEY_Serbian_dze)
+ xupper += (GDK_KEY_Serbian_DJE - GDK_KEY_Serbian_dje);
+ else if (symbol >= GDK_KEY_Cyrillic_YU && symbol <= GDK_KEY_Cyrillic_HARDSIGN)
+ xlower -= (GDK_KEY_Cyrillic_YU - GDK_KEY_Cyrillic_yu);
+ else if (symbol >= GDK_KEY_Cyrillic_yu && symbol <= GDK_KEY_Cyrillic_hardsign)
+ xupper += (GDK_KEY_Cyrillic_YU - GDK_KEY_Cyrillic_yu);
+ break;
+
+ case 7: /* Greek */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (symbol >= GDK_KEY_Greek_ALPHAaccent && symbol <= GDK_KEY_Greek_OMEGAaccent)
+ xlower += (GDK_KEY_Greek_alphaaccent - GDK_KEY_Greek_ALPHAaccent);
+ else if (symbol >= GDK_KEY_Greek_alphaaccent && symbol <= GDK_KEY_Greek_omegaaccent &&
+ symbol != GDK_KEY_Greek_iotaaccentdieresis &&
+ symbol != GDK_KEY_Greek_upsilonaccentdieresis)
+ xupper -= (GDK_KEY_Greek_alphaaccent - GDK_KEY_Greek_ALPHAaccent);
+ else if (symbol >= GDK_KEY_Greek_ALPHA && symbol <= GDK_KEY_Greek_OMEGA)
+ xlower += (GDK_KEY_Greek_alpha - GDK_KEY_Greek_ALPHA);
+ else if (symbol >= GDK_KEY_Greek_alpha && symbol <= GDK_KEY_Greek_omega &&
+ symbol != GDK_KEY_Greek_finalsmallsigma)
+ xupper -= (GDK_KEY_Greek_alpha - GDK_KEY_Greek_ALPHA);
+ break;
+ }
+
+ if (lower)
+ *lower = xlower;
+ if (upper)
+ *upper = xupper;
}