/* Given a hardware keycode, return the keyval which would have been returned if the key were unshifted */ static guint unshift_keysym( guint keycode, gint group ) { GdkKeymapKey *maps; guint *keyvals, i, r = GDK_KEY_VoidSymbol, r2 = GDK_KEY_VoidSymbol; gint count; gdk_keymap_get_entries_for_keycode( gdk_keymap_get_default(), keycode, &maps, &keyvals, &count ); for( i = 0; i < count; i++ ) { if( maps[i].group == group && maps[i].level == 0 ) { r = keyvals[i]; break; } if( maps[i].group == 0 && maps[i].level == 0 ) { r2 = keyvals[i]; } } if (i == count) r = r2; g_free( keyvals ); g_free( maps ); return r; }
static VALUE rg_get_entries_for_keycode(VALUE self, VALUE hardware_keycode) { GdkKeymapKey* keys; guint* keyvals; gint n_entries; gboolean ret = gdk_keymap_get_entries_for_keycode(_SELF(self), NUM2UINT(hardware_keycode), &keys, &keyvals, &n_entries); if (ret){ VALUE key; VALUE ary = rb_ary_new(); gint i; for (i = 0; i < n_entries; i++){ key = rb_ary_new3(4, UINT2NUM(keys[i].keycode), INT2NUM(keys[i].group), INT2NUM(keys[i].level), UINT2NUM(keyvals[i])); rb_ary_push(ary, key); } g_free(keys); g_free(keyvals); return ary; } else { return Qnil; } }
/* Get the first keyval in the keymap for this event's keycode. The first keyval corresponds roughly to Java's notion of a virtual key. Returns the uppercase version of the first keyval. */ static guint get_first_keyval_from_keymap (GdkEvent *event) { guint keyval; guint *keyvals; gint n_entries; if (!gdk_keymap_get_entries_for_keycode (NULL, event->key.hardware_keycode, NULL, &keyvals, &n_entries)) { g_warning ("No keyval found for hardware keycode %d\n", event->key.hardware_keycode); /* Try to recover by using the keyval in the event structure. */ keyvals = &(event->key.keyval); } keyval = keyvals[0]; g_free (keyvals); return gdk_keyval_to_upper (keyval); }
gchar* keycode_to_string(KeyCode keycode, GtkWidget* widget) { guint *keyvals; gint n; gboolean retval; gchar *keystr = NULL; GdkDisplay* display; display = widget ? gtk_widget_get_display(widget) : gdk_display_get_default(); if (!display) return FALSE; retval = gdk_keymap_get_entries_for_keycode( gdk_keymap_get_for_display(display), keycode, NULL, &keyvals, &n); if (!retval || !n) return NULL; keystr = gdk_keyval_name(keyvals[0]); g_free(keyvals); return keystr; }
static GdkNativeWindow select_window_x11 (GdkScreen *screen) { Display *x_dpy = GDK_SCREEN_XDISPLAY (screen); gint x_scr = GDK_SCREEN_XNUMBER (screen); Window x_root = RootWindow (x_dpy, x_scr); Window x_win = None; GC x_gc = None; Cursor x_cursor = XCreateFontCursor (x_dpy, GDK_CROSSHAIR); GdkKeymapKey *keys = NULL; gint status; gint i, num_keys; gint buttons = 0; gint mask = ButtonPressMask | ButtonReleaseMask; gboolean cancel = FALSE; if (shootvals.shoot_type == SHOOT_REGION) mask |= PointerMotionMask; status = XGrabPointer (x_dpy, x_root, False, mask, GrabModeSync, GrabModeAsync, x_root, x_cursor, CurrentTime); if (status != GrabSuccess) { gint x, y; guint xmask; /* if we can't grab the pointer, return the window under the pointer */ XQueryPointer (x_dpy, x_root, &x_root, &x_win, &x, &y, &x, &y, &xmask); if (x_win == None || x_win == x_root) g_message (_("Error selecting the window")); } if (shootvals.shoot_type == SHOOT_REGION) { XGCValues gc_values; gc_values.function = GXxor; gc_values.plane_mask = AllPlanes; gc_values.foreground = WhitePixel (x_dpy, x_scr); gc_values.background = BlackPixel (x_dpy, x_scr); gc_values.line_width = 0; gc_values.line_style = LineSolid; gc_values.fill_style = FillSolid; gc_values.cap_style = CapButt; gc_values.join_style = JoinMiter; gc_values.graphics_exposures = FALSE; gc_values.clip_x_origin = 0; gc_values.clip_y_origin = 0; gc_values.clip_mask = None; gc_values.subwindow_mode = IncludeInferiors; x_gc = XCreateGC (x_dpy, x_root, GCFunction | GCPlaneMask | GCForeground | GCLineWidth | GCLineStyle | GCCapStyle | GCJoinStyle | GCGraphicsExposures | GCBackground | GCFillStyle | GCClipXOrigin | GCClipYOrigin | GCClipMask | GCSubwindowMode, &gc_values); } if (gdk_keymap_get_entries_for_keyval (NULL, GDK_Escape, &keys, &num_keys)) { gdk_error_trap_push (); #define X_GRAB_KEY(index, modifiers) \ XGrabKey (x_dpy, keys[index].keycode, modifiers, x_root, False, \ GrabModeAsync, GrabModeAsync) for (i = 0; i < num_keys; i++) { X_GRAB_KEY (i, 0); X_GRAB_KEY (i, LockMask); /* CapsLock */ X_GRAB_KEY (i, Mod2Mask); /* NumLock */ X_GRAB_KEY (i, Mod5Mask); /* ScrollLock */ X_GRAB_KEY (i, LockMask | Mod2Mask); /* CapsLock + NumLock */ X_GRAB_KEY (i, LockMask | Mod5Mask); /* CapsLock + ScrollLock */ X_GRAB_KEY (i, Mod2Mask | Mod5Mask); /* NumLock + ScrollLock */ X_GRAB_KEY (i, LockMask | Mod2Mask | Mod5Mask); /* all */ } #undef X_GRAB_KEY gdk_flush (); gdk_error_trap_pop (); } while (! cancel && ((x_win == None) || (buttons != 0))) { XEvent x_event; gint x, y, w, h; XAllowEvents (x_dpy, SyncPointer, CurrentTime); XWindowEvent (x_dpy, x_root, mask | KeyPressMask, &x_event); switch (x_event.type) { case ButtonPress: if (x_win == None) { x_win = x_event.xbutton.subwindow; if (x_win == None) x_win = x_root; #ifdef HAVE_X11_XMU_WINUTIL_H else if (! shootvals.decorate) x_win = XmuClientWindow (x_dpy, x_win); #endif shootvals.x2 = shootvals.x1 = x_event.xbutton.x_root; shootvals.y2 = shootvals.y1 = x_event.xbutton.y_root; } buttons++; break; case ButtonRelease: if (buttons > 0) buttons--; if (! buttons && shootvals.shoot_type == SHOOT_REGION) { x = MIN (shootvals.x1, shootvals.x2); y = MIN (shootvals.y1, shootvals.y2); w = ABS (shootvals.x2 - shootvals.x1); h = ABS (shootvals.y2 - shootvals.y1); if (w > 0 && h > 0) XDrawRectangle (x_dpy, x_root, x_gc, x, y, w, h); shootvals.x2 = x_event.xbutton.x_root; shootvals.y2 = x_event.xbutton.y_root; } break; case MotionNotify: if (buttons > 0) { x = MIN (shootvals.x1, shootvals.x2); y = MIN (shootvals.y1, shootvals.y2); w = ABS (shootvals.x2 - shootvals.x1); h = ABS (shootvals.y2 - shootvals.y1); if (w > 0 && h > 0) XDrawRectangle (x_dpy, x_root, x_gc, x, y, w, h); shootvals.x2 = x_event.xmotion.x_root; shootvals.y2 = x_event.xmotion.y_root; x = MIN (shootvals.x1, shootvals.x2); y = MIN (shootvals.y1, shootvals.y2); w = ABS (shootvals.x2 - shootvals.x1); h = ABS (shootvals.y2 - shootvals.y1); if (w > 0 && h > 0) XDrawRectangle (x_dpy, x_root, x_gc, x, y, w, h); } break; case KeyPress: { guint *keyvals; gint n; if (gdk_keymap_get_entries_for_keycode (NULL, x_event.xkey.keycode, NULL, &keyvals, &n)) { gint i; for (i = 0; i < n && ! cancel; i++) if (keyvals[i] == GDK_Escape) cancel = TRUE; g_free (keyvals); } } break; default: break; } } if (keys) { #define X_UNGRAB_KEY(index, modifiers) \ XUngrabKey (x_dpy, keys[index].keycode, modifiers, x_root) for (i = 0; i < num_keys; i++) { X_UNGRAB_KEY (i, 0); X_UNGRAB_KEY (i, LockMask); /* CapsLock */ X_UNGRAB_KEY (i, Mod2Mask); /* NumLock */ X_UNGRAB_KEY (i, Mod5Mask); /* ScrollLock */ X_UNGRAB_KEY (i, LockMask | Mod2Mask); /* CapsLock + NumLock */ X_UNGRAB_KEY (i, LockMask | Mod5Mask); /* CapsLock + ScrollLock */ X_UNGRAB_KEY (i, Mod2Mask | Mod5Mask); /* NumLock + ScrollLock */ X_UNGRAB_KEY (i, LockMask | Mod2Mask | Mod5Mask); /* all */ } #undef X_UNGRAB_KEY g_free (keys); } if (status == GrabSuccess) XUngrabPointer (x_dpy, CurrentTime); XFreeCursor (x_dpy, x_cursor); if (x_gc != None) XFreeGC (x_dpy, x_gc); return x_win; }
static void reload_modmap (GdkKeymap *keymap, EggModmap *modmap) { XModifierKeymap *xmodmap; int map_size; int i; /* FIXME multihead */ xmodmap = XGetModifierMapping (gdk_x11_get_default_xdisplay ()); memset (modmap->mapping, 0, sizeof (modmap->mapping)); /* there are 8 modifiers, and the first 3 are shift, shift lock, * and control */ map_size = 8 * xmodmap->max_keypermod; i = 3 * xmodmap->max_keypermod; while (i < map_size) { /* get the key code at this point in the map, * see if its keysym is one we're interested in */ int keycode = xmodmap->modifiermap[i]; GdkKeymapKey *keys; guint *keyvals; int n_entries; int j; unsigned mask; keys = NULL; keyvals = NULL; n_entries = 0; gdk_keymap_get_entries_for_keycode (keymap, keycode, &keys, &keyvals, &n_entries); mask = 0; j = 0; while (j < n_entries) { if (keyvals[j] == GDK_Num_Lock) mask |= EGG_VIRTUAL_NUM_LOCK_MASK; else if (keyvals[j] == GDK_Scroll_Lock) mask |= EGG_VIRTUAL_SCROLL_LOCK_MASK; else if (keyvals[j] == GDK_Meta_L || keyvals[j] == GDK_Meta_R) mask |= EGG_VIRTUAL_META_MASK; else if (keyvals[j] == GDK_Hyper_L || keyvals[j] == GDK_Hyper_R) mask |= EGG_VIRTUAL_HYPER_MASK; else if (keyvals[j] == GDK_Super_L || keyvals[j] == GDK_Super_R) mask |= EGG_VIRTUAL_SUPER_MASK; else if (keyvals[j] == GDK_Mode_switch) mask |= EGG_VIRTUAL_MODE_SWITCH_MASK; ++j; } /* Mod1Mask is 1 << 3 for example, i.e. the * fourth modifier, i / keyspermod is the modifier * index */ EggVirtualModifierType *p = &modmap->mapping[i/xmodmap->max_keypermod]; *p = (EggVirtualModifierType)(*p | mask); g_free (keyvals); g_free (keys); ++i; } /* Add in the not-really-virtual fixed entries */ modmap->mapping[EGG_MODMAP_ENTRY_SHIFT] = (EggVirtualModifierType)(modmap->mapping[EGG_MODMAP_ENTRY_SHIFT] | EGG_VIRTUAL_SHIFT_MASK); modmap->mapping[EGG_MODMAP_ENTRY_CONTROL] = (EggVirtualModifierType)(modmap->mapping[EGG_MODMAP_ENTRY_CONTROL] | EGG_VIRTUAL_CONTROL_MASK); modmap->mapping[EGG_MODMAP_ENTRY_LOCK] = (EggVirtualModifierType)(modmap->mapping[EGG_MODMAP_ENTRY_LOCK] | EGG_VIRTUAL_LOCK_MASK); modmap->mapping[EGG_MODMAP_ENTRY_MOD1] = (EggVirtualModifierType)(modmap->mapping[EGG_MODMAP_ENTRY_MOD1] | EGG_VIRTUAL_ALT_MASK); modmap->mapping[EGG_MODMAP_ENTRY_MOD2] = (EggVirtualModifierType)(modmap->mapping[EGG_MODMAP_ENTRY_MOD2] | EGG_VIRTUAL_MOD2_MASK); modmap->mapping[EGG_MODMAP_ENTRY_MOD3] = (EggVirtualModifierType)(modmap->mapping[EGG_MODMAP_ENTRY_MOD3] | EGG_VIRTUAL_MOD3_MASK); modmap->mapping[EGG_MODMAP_ENTRY_MOD4] = (EggVirtualModifierType)(modmap->mapping[EGG_MODMAP_ENTRY_MOD4] | EGG_VIRTUAL_MOD4_MASK); modmap->mapping[EGG_MODMAP_ENTRY_MOD5] = (EggVirtualModifierType)(modmap->mapping[EGG_MODMAP_ENTRY_MOD5] | EGG_VIRTUAL_MOD5_MASK); XFreeModifiermap (xmodmap); }
gboolean cd_do_key_pressed (gpointer pUserData, GldiContainer *pContainer, guint iKeyVal, guint iModifierType, const gchar *string, int iKeyCode) { g_return_val_if_fail (cd_do_session_is_running (), GLDI_NOTIFICATION_LET_PASS); g_return_val_if_fail (myData.pCurrentDock != NULL, GLDI_NOTIFICATION_LET_PASS); const gchar *cKeyName = gdk_keyval_name (iKeyVal); guint32 iUnicodeChar = gdk_keyval_to_unicode (iKeyVal); cd_debug ("+ cKeyName : %s (%c, %s, %d)", cKeyName, iUnicodeChar, string, iKeyCode); if (myData.sCurrentText->len == 0) { GdkKeymapKey *keys = NULL; guint *keyvals = NULL; int i, n_entries = 0; int iKeyVal2; gdk_keymap_get_entries_for_keycode (gdk_keymap_get_default (), iKeyCode, &keys, &keyvals, &n_entries); for (i = 0; i < n_entries; i ++) { iKeyVal2 = keyvals[i]; if ((iKeyVal2 >= GDK_KEY_0 && iKeyVal2 <= GDK_KEY_9) || (iKeyVal2 >= GDK_KEY_KP_0 && iKeyVal2 <= GDK_KEY_KP_9)) { iKeyVal = iKeyVal2; break; } } g_free (keys); g_free (keyvals); } if (iKeyVal == GDK_KEY_Escape) // on clot la session. { // give the focus back to the window that had it before the user opened this session. if (myData.pPreviouslyActiveWindow != NULL) { gldi_window_show (myData.pPreviouslyActiveWindow); } cd_do_close_session (); } else if (iKeyVal == GDK_KEY_space && myData.sCurrentText->len == 0) // pas d'espace en debut de chaine. { // on rejette. } else if (iKeyVal >= GDK_KEY_Shift_L && iKeyVal <= GDK_KEY_Hyper_R) // on n'ecrit pas les modificateurs. { // on rejette. } else if (iKeyVal == GDK_KEY_Menu) // emulation du clic droit. { if (myData.pCurrentIcon != NULL) { myData.bIgnoreIconState = TRUE; gldi_icon_stop_animation (myData.pCurrentIcon); // car on va perdre le focus. myData.bIgnoreIconState = FALSE; GtkWidget *menu = gldi_container_build_menu (CAIRO_CONTAINER (myData.pCurrentDock), myData.pCurrentIcon); gldi_menu_popup (menu); } } else if (iKeyVal == GDK_KEY_BackSpace) // on efface la derniere lettre. { if (myData.sCurrentText->len > 0) { cd_debug ("we remove the last letter of %s (%d)", myData.sCurrentText->str, myData.sCurrentText->len); g_string_truncate (myData.sCurrentText, myData.sCurrentText->len-1); // on relance la recherche. if (myData.pCurrentIcon == NULL) // sinon l'icone actuelle convient toujours. cd_do_search_current_icon (FALSE); } } else if (iKeyVal == GDK_KEY_Tab) // jump to next icon. { if (myData.sCurrentText->len > 0) { //gboolean bPrevious = iModifierType & GDK_SHIFT_MASK; // on cherche l'icone suivante. cd_do_search_current_icon (TRUE); // pCurrentIcon peut etre NULL si elle s'est faite detruire pendant la recherche, auquel cas on cherchera juste normalement. } } else if (iKeyVal == GDK_KEY_Return) { if (myData.pCurrentIcon != NULL) { cd_debug ("we click on the icon '%s' [%d, %d]", myData.pCurrentIcon->cName, iModifierType, GDK_SHIFT_MASK); myData.bIgnoreIconState = TRUE; if (iModifierType & GDK_MOD1_MASK) // ALT { myData.bIgnoreIconState = TRUE; gldi_icon_stop_animation (myData.pCurrentIcon); // car aucune animation ne va la remplacer. myData.bIgnoreIconState = FALSE; gldi_object_notify (CAIRO_CONTAINER (myData.pCurrentDock), NOTIFICATION_MIDDLE_CLICK_ICON, myData.pCurrentIcon, myData.pCurrentDock); } else if (iModifierType & GDK_CONTROL_MASK) // CTRL { myData.bIgnoreIconState = TRUE; gldi_icon_stop_animation (myData.pCurrentIcon); // car on va perdre le focus. myData.bIgnoreIconState = FALSE; GtkWidget *menu = gldi_container_build_menu (CAIRO_CONTAINER (myData.pCurrentDock), myData.pCurrentIcon); gldi_menu_popup (menu); } else { cd_do_simulate_click (CAIRO_CONTAINER (myData.pCurrentDock), myData.pCurrentIcon, iModifierType); } gldi_icon_start_animation (myData.pCurrentIcon); myData.bIgnoreIconState = FALSE; myData.pCurrentIcon = NULL; // sinon on va interrompre l'animation en fermant la session. } cd_do_close_session (); } else if (iKeyVal == GDK_KEY_Left || iKeyVal == GDK_KEY_Right || iKeyVal == GDK_KEY_Up || iKeyVal == GDK_KEY_Down) { iKeyVal = _orient_arrow (pContainer, iKeyVal); if (iKeyVal == GDK_KEY_Up) { if (myData.pCurrentIcon != NULL && myData.pCurrentIcon->pSubDock != NULL) { cd_debug ("on monte dans le sous-dock %s", myData.pCurrentIcon->cName); Icon *pIcon = cairo_dock_get_first_icon (myData.pCurrentIcon->pSubDock->icons); cd_do_change_current_icon (pIcon, myData.pCurrentIcon->pSubDock); } } else if (iKeyVal == GDK_KEY_Down) { if (myData.pCurrentDock->iRefCount > 0) { CairoDock *pParentDock = NULL; Icon *pPointingIcon = cairo_dock_search_icon_pointing_on_dock (myData.pCurrentDock, &pParentDock); if (pPointingIcon != NULL) { cd_debug ("on redescend dans le dock parent via %s", pPointingIcon->cName); cd_do_change_current_icon (pPointingIcon, pParentDock); } } } else if (iKeyVal == GDK_KEY_Left) { if (myData.pCurrentDock->icons != NULL) { Icon *pPrevIcon = cairo_dock_get_previous_icon (myData.pCurrentDock->icons, myData.pCurrentIcon); if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pPrevIcon)) pPrevIcon = cairo_dock_get_previous_icon (myData.pCurrentDock->icons, pPrevIcon); if (pPrevIcon == NULL) // pas trouve ou bien 1ere icone. { pPrevIcon = cairo_dock_get_last_icon (myData.pCurrentDock->icons); } cd_debug ("on se deplace a gauche sur %s", pPrevIcon ? pPrevIcon->cName : "none"); cd_do_change_current_icon (pPrevIcon, myData.pCurrentDock); } } else // Gdk_Right. { if (myData.pCurrentDock->icons != NULL) { Icon *pNextIcon = cairo_dock_get_next_icon (myData.pCurrentDock->icons, myData.pCurrentIcon); if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pNextIcon)) pNextIcon = cairo_dock_get_next_icon (myData.pCurrentDock->icons, pNextIcon); if (pNextIcon == NULL) // pas trouve ou bien 1ere icone. { pNextIcon = cairo_dock_get_first_icon (myData.pCurrentDock->icons); } cd_debug ("on se deplace a gauche sur %s", pNextIcon ? pNextIcon->cName : "none"); cd_do_change_current_icon (pNextIcon, myData.pCurrentDock); } } } else if (iKeyVal == GDK_KEY_Page_Down || iKeyVal == GDK_KEY_Page_Up || iKeyVal == GDK_KEY_Home || iKeyVal == GDK_KEY_End) { if (iModifierType & GDK_CONTROL_MASK) // changement de dock principal { gpointer data[4] = {myData.pCurrentDock, NULL, GINT_TO_POINTER (FALSE), NULL}; gldi_docks_foreach_root ((GFunc) _find_next_dock, data); CairoDock *pNextDock = data[1]; if (pNextDock == NULL) pNextDock = data[3]; if (pNextDock != NULL) { Icon *pNextIcon = NULL; int n = g_list_length (pNextDock->icons); if (n > 0) { pNextIcon = g_list_nth_data (pNextDock->icons, (n-1) / 2); if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pNextIcon) && n > 1) pNextIcon = g_list_nth_data (pNextDock->icons, (n+1) / 2); } cd_do_change_current_icon (pNextIcon, pNextDock); } } Icon *pIcon = (iKeyVal == GDK_KEY_Page_Up || iKeyVal == GDK_KEY_Home ? cairo_dock_get_first_icon (myData.pCurrentDock->icons) : cairo_dock_get_last_icon (myData.pCurrentDock->icons)); cd_debug ("on se deplace a l'extremite sur %s", pIcon ? pIcon->cName : "none"); cd_do_change_current_icon (pIcon, myData.pCurrentDock); } else if ( ((iKeyVal >= GDK_KEY_0 && iKeyVal <= GDK_KEY_9) || (iKeyVal >= GDK_KEY_KP_0 && iKeyVal <= GDK_KEY_KP_9)) && myData.sCurrentText->len == 0) { _activate_nth_icon (iKeyVal, iModifierType); } else if (string) /// utiliser l'unichar ... { cd_debug ("string:'%s'", string); g_string_append_c (myData.sCurrentText, *string); cd_do_search_current_icon (FALSE); } return GLDI_NOTIFICATION_INTERCEPT; }