/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * 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, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include "xklavier_private.h" #include "xklavier_private_xmm.h" static gint xkl_xmm_process_keypress_event(XklEngine * engine, XKeyPressedEvent * kpe) { if (xkl_engine_is_listening_for(engine, XKLL_MANAGE_LAYOUTS)) { gint current_shortcut = 0; const XmmSwitchOption *sop; xkl_debug(200, "Processing the KeyPress event\n"); sop = xkl_xmm_find_switch_option(engine, kpe->keycode, kpe->state, ¤t_shortcut); if (sop != NULL) { XklState state; xkl_debug(150, "It is THE shortcut\n"); xkl_xmm_get_server_state(engine, &state); if (state.group != -1) { gint new_group = (state.group + sop->shortcut_steps[current_shortcut]) % g_strv_length(xkl_engine_backend (engine, XklXmm, current_config).layouts); xkl_debug(150, "Setting new xmm group %d\n", new_group); xkl_xmm_lock_group(engine, new_group); return 1; } } } return 0; } static gint xkl_xmm_process_property_event(XklEngine * engine, XPropertyEvent * kpe) { Atom state_atom = xkl_engine_backend(engine, XklXmm, state_atom); xkl_debug(200, "Processing the PropertyNotify event: %d/%d\n", kpe->atom, state_atom); /* * Group is changed! */ if (kpe->atom == state_atom) { XklState state; xkl_xmm_get_server_state(engine, &state); if (xkl_engine_is_listening_for (engine, XKLL_MANAGE_LAYOUTS)) { xkl_debug(150, "Current group from the root window property %d\n", state.group); xkl_xmm_shortcuts_ungrab(engine); xkl_xmm_actualize_group(engine, state.group); xkl_xmm_shortcuts_grab(engine); return 1; } if (xkl_engine_is_listening_for (engine, XKLL_MANAGE_WINDOW_STATES) | xkl_engine_is_listening_for(engine, XKLL_TRACK_KEYBOARD_STATE)) { xkl_debug(150, "XMM state changed, new 'group' %d\n", state.group); xkl_engine_process_state_modification(engine, GROUP_CHANGED, state.group, 0, False); } } else /* * Configuration is changed! */ if (kpe->atom == xkl_engine_priv(engine, base_config_atom)) { xkl_engine_reset_all_info(engine, TRUE, "base config atom changed"); } return 0; } /* * XMM event handler */ gint xkl_xmm_process_x_event(XklEngine * engine, XEvent * xev) { switch (xev->type) { case KeyPress: return xkl_xmm_process_keypress_event(engine, (XKeyPressedEvent *) xev); case PropertyNotify: return xkl_xmm_process_property_event(engine, (XPropertyEvent *) xev); } return 0; } /* * We have to find which of Shift/Lock/Control/ModX masks * belong to Caps/Num/Scroll lock */ static void xkl_xmm_init_xmm_indicators_map(XklEngine * engine, guint * p_caps_lock_mask, guint * p_num_lock_mask, guint * p_scroll_lock_mask) { XModifierKeymap *xmkm = NULL; KeyCode *kcmap, nlkc, clkc, slkc; int m, k, mask; Display *display = xkl_engine_get_display(engine); xmkm = XGetModifierMapping(display); if (xmkm) { clkc = XKeysymToKeycode(display, XK_Num_Lock); nlkc = XKeysymToKeycode(display, XK_Caps_Lock); slkc = XKeysymToKeycode(display, XK_Scroll_Lock); kcmap = xmkm->modifiermap; mask = 1; for (m = 8; --m >= 0; mask <<= 1) for (k = xmkm->max_keypermod; --k >= 0; kcmap++) { if (*kcmap == clkc) *p_caps_lock_mask = mask; if (*kcmap == slkc) *p_scroll_lock_mask = mask; if (*kcmap == nlkc) *p_num_lock_mask = mask; } XFreeModifiermap(xmkm); } } void xkl_xmm_grab_ignoring_indicators(XklEngine * engine, gint keycode, guint modifiers) { guint caps_lock_mask = 0, num_lock_mask = 0, scroll_lock_mask = 0; xkl_xmm_init_xmm_indicators_map(engine, &caps_lock_mask, &num_lock_mask, &scroll_lock_mask); #define GRAB(mods) \ xkl_engine_grab_key(engine, keycode, modifiers|(mods)) GRAB(0); GRAB(caps_lock_mask); GRAB(num_lock_mask); GRAB(scroll_lock_mask); GRAB(caps_lock_mask | num_lock_mask); GRAB(caps_lock_mask | scroll_lock_mask); GRAB(num_lock_mask | scroll_lock_mask); GRAB(caps_lock_mask | num_lock_mask | scroll_lock_mask); #undef GRAB } void xkl_xmm_ungrab_ignoring_indicators(XklEngine * engine, gint keycode, guint modifiers) { guint caps_lock_mask = 0, num_lock_mask = 0, scroll_lock_mask = 0; xkl_xmm_init_xmm_indicators_map(engine, &caps_lock_mask, &num_lock_mask, &scroll_lock_mask); #define UNGRAB(mods) \ xkl_engine_ungrab_key(engine, keycode, modifiers|(mods)) UNGRAB(0); UNGRAB(caps_lock_mask); UNGRAB(num_lock_mask); UNGRAB(scroll_lock_mask); UNGRAB(caps_lock_mask | num_lock_mask); UNGRAB(caps_lock_mask | scroll_lock_mask); UNGRAB(num_lock_mask | scroll_lock_mask); UNGRAB(caps_lock_mask | num_lock_mask | scroll_lock_mask); #undef UNGRAB }