/** \file * \brief GTK Driver keyboard mapping * * See Copyright Notice in "iup.h" */ #include #include #include #include #include "iup.h" #include "iupcbs.h" #include "iupkey.h" #include "iup_object.h" #include "iup_key.h" #include "iupgtk_drv.h" typedef struct _Igtk2iupkey { guint gtkcode; int iupcode; int s_iupcode; int c_iupcode; int m_iupcode; int y_iupcode; } Igtk2iupkey; static Igtk2iupkey gtkkey_map[] = { { GDK_Escape, K_ESC, K_sESC, K_cESC, K_mESC ,K_yESC }, { GDK_Pause, K_PAUSE, K_sPAUSE, K_cPAUSE, K_mPAUSE ,K_yPAUSE }, { GDK_Print, K_Print, K_sPrint, K_cPrint, K_mPrint ,K_yPrint }, { GDK_Menu, K_Menu, K_sMenu, K_cMenu, K_mMenu ,K_yMenu }, { GDK_Home, K_HOME, K_sHOME, K_cHOME, K_mHOME ,K_yHOME }, { GDK_Up, K_UP, K_sUP, K_cUP, K_mUP ,K_yUP }, { GDK_Prior, K_PGUP, K_sPGUP, K_cPGUP, K_mPGUP ,K_yPGUP }, { GDK_Left, K_LEFT, K_sLEFT, K_cLEFT, K_mLEFT ,K_yLEFT }, { GDK_Begin, K_MIDDLE,K_sMIDDLE, K_cMIDDLE,K_mMIDDLE,K_yMIDDLE}, { GDK_Right, K_RIGHT, K_sRIGHT, K_cRIGHT, K_mRIGHT ,K_yRIGHT }, { GDK_End, K_END, K_sEND, K_cEND, K_mEND ,K_yEND }, { GDK_Down, K_DOWN, K_sDOWN, K_cDOWN, K_mDOWN ,K_yDOWN }, { GDK_Next, K_PGDN, K_sPGDN, K_cPGDN, K_mPGDN ,K_yPGDN }, { GDK_Insert, K_INS, K_sINS, K_cINS, K_mINS ,K_yINS }, { GDK_Delete, K_DEL, K_sDEL, K_cDEL, K_mDEL ,K_yDEL }, { GDK_space, K_SP, K_sSP, K_cSP, K_mSP ,K_ySP }, { GDK_Tab, K_TAB, K_sTAB, K_cTAB, K_mTAB ,K_yTAB }, { GDK_Return, K_CR, K_sCR, K_cCR, K_mCR ,K_yCR }, { GDK_BackSpace, K_BS, K_sBS, K_cBS, K_mBS ,K_yBS }, { GDK_1, K_1, K_exclam, K_c1, K_m1, K_y1 }, { GDK_2, K_2, K_at, K_c2, K_m2, K_y2 }, { GDK_3, K_3, K_numbersign, K_c3, K_m3, K_y3 }, { GDK_4, K_4, K_dollar, K_c4, K_m4, K_y4 }, { GDK_5, K_5, K_percent, K_c5, K_m5, K_y5 }, { GDK_6, K_6, K_circum, K_c6, K_m6, K_y6 }, { GDK_7, K_7, K_ampersand, K_c7, K_m7, K_y7 }, { GDK_8, K_8, K_asterisk, K_c8, K_m8, K_y8 }, { GDK_9, K_9, K_parentleft, K_c9, K_m9, K_y9 }, { GDK_0, K_0, K_parentright, K_c0, K_m0, K_y0 }, /* Shift will be flaged so s_iupcode will contain the right code */ { GDK_exclam, K_1, K_exclam, K_c1, K_m1, K_y1 }, { GDK_at, K_2, K_at, K_c2, K_m2, K_y2 }, { GDK_numbersign, K_3, K_numbersign, K_c3, K_m3, K_y3 }, { GDK_dollar, K_4, K_dollar, K_c4, K_m4, K_y4 }, { GDK_percent, K_5, K_percent, K_c5, K_m5, K_y5 }, { GDK_dead_diaeresis, K_6, K_circum, K_c6, K_m6, K_y6 }, { GDK_ampersand, K_7, K_ampersand, K_c7, K_m7, K_y7 }, { GDK_asterisk, K_8, K_asterisk, K_c8, K_m8, K_y8 }, { GDK_parenleft, K_9, K_parentleft, K_c9, K_m9, K_y9 }, { GDK_parenright, K_0, K_parentright, K_c0, K_m0, K_y0 }, { GDK_a, K_a, K_A, K_cA, K_mA, K_yA }, { GDK_b, K_b, K_B, K_cB, K_mB, K_yB }, { GDK_c, K_c, K_C, K_cC, K_mC, K_yC }, { GDK_d, K_d, K_D, K_cD, K_mD, K_yD }, { GDK_e, K_e, K_E, K_cE, K_mE, K_yE }, { GDK_f, K_f, K_F, K_cF, K_mF, K_yF }, { GDK_g, K_g, K_G, K_cG, K_mG, K_yG }, { GDK_h, K_h, K_H, K_cH, K_mH, K_yH }, { GDK_i, K_i, K_I, K_cI, K_mI, K_yI }, { GDK_j, K_j, K_J, K_cJ, K_mJ, K_yJ }, { GDK_k, K_k, K_K, K_cK, K_mK, K_yK }, { GDK_l, K_l, K_L, K_cL, K_mL, K_yL }, { GDK_m, K_m, K_M, K_cM, K_mM, K_yM }, { GDK_n, K_n, K_N, K_cN, K_mN, K_yN }, { GDK_o, K_o, K_O, K_cO, K_mO, K_yO }, { GDK_p, K_p, K_P, K_cP, K_mP, K_yP }, { GDK_q, K_q, K_Q, K_cQ, K_mQ, K_yQ }, { GDK_r, K_r, K_R, K_cR, K_mR, K_yR }, { GDK_s, K_s, K_S, K_cS, K_mS, K_yS }, { GDK_t, K_t, K_T, K_cT, K_mT, K_yT }, { GDK_u, K_u, K_U, K_cU, K_mU, K_yU }, { GDK_v, K_v, K_V, K_cV, K_mV, K_yV }, { GDK_w, K_w, K_W, K_cW, K_mW, K_yW }, { GDK_x, K_x, K_X, K_cX, K_mX, K_yX }, { GDK_y, K_y, K_Y, K_cY, K_mY, K_yY }, { GDK_z, K_z, K_Z, K_cZ, K_mZ, K_yZ }, /* Shift will be flaged so s_iupcode will contain the right code */ { GDK_A, K_a, K_A, K_cA, K_mA, K_yA }, { GDK_B, K_b, K_B, K_cB, K_mB, K_yB }, { GDK_C, K_c, K_C, K_cC, K_mC, K_yC }, { GDK_D, K_d, K_D, K_cD, K_mD, K_yD }, { GDK_E, K_e, K_E, K_cE, K_mE, K_yE }, { GDK_F, K_f, K_F, K_cF, K_mF, K_yF }, { GDK_G, K_g, K_G, K_cG, K_mG, K_yG }, { GDK_H, K_h, K_H, K_cH, K_mH, K_yH }, { GDK_I, K_i, K_I, K_cI, K_mI, K_yI }, { GDK_J, K_j, K_J, K_cJ, K_mJ, K_yJ }, { GDK_K, K_k, K_K, K_cK, K_mK, K_yK }, { GDK_L, K_l, K_L, K_cL, K_mL, K_yL }, { GDK_M, K_m, K_M, K_cM, K_mM, K_yM }, { GDK_N, K_n, K_N, K_cN, K_mN, K_yN }, { GDK_O, K_o, K_O, K_cO, K_mO, K_yO }, { GDK_P, K_p, K_P, K_cP, K_mP, K_yP }, { GDK_Q, K_q, K_Q, K_cQ, K_mQ, K_yQ }, { GDK_R, K_r, K_R, K_cR, K_mR, K_yR }, { GDK_S, K_s, K_S, K_cS, K_mS, K_yS }, { GDK_T, K_t, K_T, K_cT, K_mT, K_yT }, { GDK_U, K_u, K_U, K_cU, K_mU, K_yU }, { GDK_V, K_v, K_V, K_cV, K_mV, K_yV }, { GDK_W, K_w, K_W, K_cW, K_mW, K_yW }, { GDK_X, K_x, K_X, K_cX, K_mX, K_yX }, { GDK_Y, K_y, K_Y, K_cY, K_mY, K_yY }, { GDK_Z, K_z, K_Z, K_cZ, K_mZ, K_yZ }, { GDK_F1, K_F1, K_sF1, K_cF1, K_mF1, K_yF1 }, { GDK_F2, K_F2, K_sF2, K_cF2, K_mF2, K_yF2 }, { GDK_F3, K_F3, K_sF3, K_cF3, K_mF3, K_yF3 }, { GDK_F4, K_F4, K_sF4, K_cF4, K_mF4, K_yF4 }, { GDK_F5, K_F5, K_sF5, K_cF5, K_mF5, K_yF5 }, { GDK_F6, K_F6, K_sF6, K_cF6, K_mF6, K_yF6 }, { GDK_F7, K_F7, K_sF7, K_cF7, K_mF7, K_yF7 }, { GDK_F8, K_F8, K_sF8, K_cF8, K_mF8, K_yF8 }, { GDK_F9, K_F9, K_sF9, K_cF9, K_mF9, K_yF9 }, { GDK_F10, K_F10, K_sF10, K_cF10, K_mF10, K_yF10 }, { GDK_F11, K_F11, K_sF11, K_cF11, K_mF11, K_yF11 }, { GDK_F12, K_F12, K_sF12, K_cF12, K_mF12, K_yF12 }, { GDK_semicolon, K_semicolon, K_colon, K_cSemicolon, K_mSemicolon, K_ySemicolon }, { GDK_equal, K_equal, K_plus, K_cEqual, K_mEqual, K_yEqual }, { GDK_comma, K_comma, K_less, K_cComma, K_mComma, K_yComma }, { GDK_minus, K_minus, K_underscore, K_cMinus, K_mMinus, K_yMinus }, { GDK_period, K_period, K_greater, K_cPeriod, K_mPeriod, K_yPeriod }, { GDK_slash, K_slash, K_question, K_cSlash, K_mSlash, K_ySlash }, { GDK_grave, K_grave, K_tilde, 0, 0, 0 }, { GDK_bracketleft, K_bracketleft, K_braceleft, K_cBracketleft, K_mBracketleft, K_yBracketleft }, { GDK_backslash, K_backslash, K_bar, K_cBackslash, K_mBackslash, K_yBackslash }, { GDK_bracketright,K_bracketright, K_braceright, K_cBracketright,K_mBracketright,K_yBracketright }, { GDK_apostrophe, K_apostrophe, K_quotedbl, 0, 0, 0 }, /* Shift will be flaged so s_iupcode will contain the right code */ { GDK_colon, K_semicolon, K_colon, K_cSemicolon, K_mSemicolon, K_ySemicolon }, { GDK_plus, K_equal, K_plus, K_cEqual, K_mEqual, K_yEqual }, { GDK_less, K_comma, K_less, K_cComma, K_mComma, K_yComma }, { GDK_underscore, K_minus, K_underscore, K_cMinus, K_mMinus, K_yMinus }, { GDK_greater, K_period, K_greater, K_cPeriod, K_mPeriod, K_yPeriod }, { GDK_question, K_slash, K_question, K_cSlash, K_mSlash, K_ySlash }, { GDK_braceleft, K_bracketleft, K_braceleft, K_cBracketleft, K_mBracketleft, K_yBracketleft }, { GDK_bar, K_backslash, K_bar, K_cBackslash, K_mBackslash, K_yBackslash }, { GDK_braceright, K_bracketright, K_braceright, K_cBracketright,K_mBracketright,K_yBracketright }, { GDK_quotedbl, K_apostrophe, K_quotedbl, 0, 0, 0 }, { GDK_KP_0, K_0, K_0, K_c0, K_m0, K_y0 }, { GDK_KP_1, K_1, K_1, K_c1, K_m1, K_y1 }, { GDK_KP_2, K_2, K_2, K_c2, K_m2, K_y2 }, { GDK_KP_3, K_3, K_3, K_c3, K_m3, K_y3 }, { GDK_KP_4, K_4, K_4, K_c4, K_m4, K_y4 }, { GDK_KP_5, K_5, K_5, K_c5, K_m5, K_y5 }, { GDK_KP_6, K_6, K_6, K_c6, K_m6, K_y6 }, { GDK_KP_7, K_7, K_7, K_c7, K_m7, K_y7 }, { GDK_KP_8, K_8, K_8, K_c8, K_m8, K_y8 }, { GDK_KP_9, K_9, K_9, K_c9, K_m9, K_y9 }, { GDK_KP_Multiply, K_asterisk, K_sAsterisk, K_cAsterisk, K_mAsterisk, K_yAsterisk }, { GDK_KP_Add, K_plus, K_sPlus, K_cPlus, K_mPlus, K_yPlus }, { GDK_KP_Subtract, K_minus, K_sMinus, K_cMinus, K_mMinus, K_yMinus }, { GDK_KP_Decimal, K_period, K_sPeriod, K_cPeriod, K_mPeriod, K_yPeriod }, { GDK_KP_Divide, K_slash, K_sSlash, K_cSlash, K_mSlash, K_ySlash }, { GDK_KP_Separator, K_comma, K_sComma, K_cComma, K_mComma, K_yComma }, { GDK_ccedilla, K_ccedilla, K_Ccedilla, K_cCcedilla, K_mCcedilla, K_yCcedilla }, { GDK_Ccedilla, K_ccedilla, K_Ccedilla, K_cCcedilla, K_mCcedilla, K_yCcedilla }, { GDK_dead_tilde, K_tilde, K_circum, 0, 0, 0 }, { GDK_dead_acute, K_acute, K_grave, 0, 0, 0 }, { GDK_dead_grave, K_grave, K_tilde, 0, 0, 0 }, { GDK_dead_circumflex, K_tilde, K_circum, 0, 0, 0 }, { GDK_KP_F1, K_F1, K_sF1, K_cF1, K_mF1, K_yF1 }, { GDK_KP_F2, K_F2, K_sF2, K_cF2, K_mF2, K_yF2 }, { GDK_KP_F3, K_F3, K_sF3, K_cF3, K_mF3, K_yF3 }, { GDK_KP_F4, K_F4, K_sF4, K_cF4, K_mF4, K_yF4 }, { GDK_KP_Space, K_SP, K_sSP, K_cSP, K_mSP ,K_ySP }, { GDK_KP_Tab, K_TAB, K_sTAB, K_cTAB, K_mTAB ,K_yTAB }, { GDK_KP_Equal, K_equal, 0, K_cEqual, K_mEqual, K_yEqual }, { GDK_KP_Enter, K_CR, K_sCR, K_cCR, K_mCR, K_yCR }, { GDK_KP_Home, K_HOME, K_sHOME, K_cHOME, K_mHOME, K_yHOME }, { GDK_KP_Up, K_UP, K_sUP, K_cUP, K_mUP, K_yUP }, { GDK_KP_Page_Up, K_PGUP, K_sPGUP, K_cPGUP, K_mPGUP, K_yPGUP }, { GDK_KP_Left, K_LEFT, K_sLEFT, K_cLEFT, K_mLEFT, K_yLEFT }, { GDK_KP_Begin, K_MIDDLE,K_sMIDDLE, K_cMIDDLE,K_mMIDDLE,K_yMIDDLE}, { GDK_KP_Right, K_RIGHT, K_sRIGHT, K_cRIGHT, K_mRIGHT, K_yRIGHT }, { GDK_KP_End, K_END, K_sEND, K_cEND, K_mEND, K_yEND }, { GDK_KP_Down, K_DOWN, K_sDOWN, K_cDOWN, K_mDOWN, K_yDOWN }, { GDK_KP_Page_Down, K_PGDN, K_sPGDN, K_cPGDN, K_mPGDN, K_yPGDN }, { GDK_KP_Insert, K_INS, K_sINS, K_cINS, K_mINS, K_yINS }, { GDK_KP_Delete, K_DEL, K_sDEL, K_cDEL, K_mDEL, K_yDEL } }; void iupgtkKeyEncode(int key, guint *keyval, guint *state) { int i, iupcode = key & 0xFF; /* 0-255 interval */ int count = sizeof(gtkkey_map)/sizeof(gtkkey_map[0]); for (i = 0; i < count; i++) { Igtk2iupkey* key_map = &(gtkkey_map[i]); if (key_map->iupcode == iupcode) { *keyval = key_map->gtkcode; *state = 0; if (iupcode != key) { if (key_map->c_iupcode == key) *state = GDK_CONTROL_MASK; else if (key_map->m_iupcode == key) *state = GDK_MOD1_MASK; else if (key_map->y_iupcode == key) *state = GDK_MOD4_MASK; else if (key_map->s_iupcode == key) *state = GDK_SHIFT_MASK; } return; } else if (key_map->s_iupcode == key) /* There are Shift keys bellow 256 */ { *keyval = key_map->gtkcode; *state = GDK_SHIFT_MASK; if ((*keyval >= GDK_a) && (*keyval <= GDK_z)) { /* remap to upper case */ *keyval -= GDK_a-GDK_A; } return; } } } static int gtkKeyMap2Iup(int state, int i) { int code = 0; if (state & GDK_CONTROL_MASK) /* Ctrl */ code = gtkkey_map[i].c_iupcode; else if (state & GDK_MOD1_MASK || state & GDK_MOD5_MASK) /* Alt */ code = gtkkey_map[i].m_iupcode; else if (state & GDK_MOD4_MASK) /* Apple/Win */ code = gtkkey_map[i].y_iupcode; else if (state & GDK_LOCK_MASK) /* CapsLock */ { if ((state & GDK_SHIFT_MASK) || !iupKeyCanCaps(gtkkey_map[i].iupcode)) return gtkkey_map[i].iupcode; else code = gtkkey_map[i].s_iupcode; } else if (state & GDK_SHIFT_MASK) /* Shift */ code = gtkkey_map[i].s_iupcode; else return gtkkey_map[i].iupcode; if (!code) code = gtkkey_map[i].iupcode; return code; } static int gtkKeyDecode(GdkEventKey *evt) { int i; int count = sizeof(gtkkey_map)/sizeof(gtkkey_map[0]); guint keyval = evt->keyval; if ((evt->state & GDK_MOD2_MASK) && /* NumLock */ (keyval >= GDK_KP_Home) && (keyval <= GDK_KP_Delete)) { /* remap to numeric keys */ guint remap_numkey[] = {GDK_KP_7, GDK_KP_4, GDK_KP_8, GDK_KP_6, GDK_KP_2, GDK_KP_9, GDK_KP_3, GDK_KP_1, GDK_KP_5, GDK_KP_0, GDK_KP_Decimal}; keyval = remap_numkey[keyval-GDK_KP_Home]; } for (i = 0; i < count; i++) { if (gtkkey_map[i].gtkcode == keyval) return gtkKeyMap2Iup(evt->state, i); } return 0; } gboolean iupgtkKeyPressEvent(GtkWidget *widget, GdkEventKey *evt, Ihandle *ih) { int result; int code = gtkKeyDecode(evt); if (code == 0) return FALSE; /* Avoid duplicate calls if a child of a native container contains the focus. GTK will call the callback for the child and for the container. */ if (ih->iclass->childtype != IUP_CHILDNONE && ih != IupGetFocus()) return FALSE; result = iupKeyCallKeyCb(ih, code); if (result == IUP_CLOSE) { IupExitLoop(); return FALSE; } if (result == IUP_IGNORE) return TRUE; /* in the previous callback the dialog could be destroyed */ if (iupObjectCheck(ih)) { /* this is called only for canvas */ if (ih->iclass->nativetype == IUP_TYPECANVAS) { result = iupKeyCallKeyPressCb(ih, code, 1); if (result == IUP_CLOSE) { IupExitLoop(); return FALSE; } if (result == IUP_IGNORE) return TRUE; } if (!iupKeyProcessNavigation(ih, code, evt->state & GDK_SHIFT_MASK)) return TRUE; /* compensate the show-help limitation. * It is not called on F1, only on Shift+F1 and Ctrl+F1. */ if (code == K_F1) { Icallback cb = IupGetCallback(ih, "HELP_CB"); if (cb) { if (cb(ih) == IUP_CLOSE) IupExitLoop(); } } } (void)widget; return FALSE; } gboolean iupgtkKeyReleaseEvent(GtkWidget *widget, GdkEventKey *evt, Ihandle *ih) { /* this is called only for canvas */ int result; int code = gtkKeyDecode(evt); if (code == 0) return FALSE; result = iupKeyCallKeyPressCb(ih, code, 0); if (result == IUP_CLOSE) { IupExitLoop(); return FALSE; } if (result == IUP_IGNORE) return TRUE; (void)widget; return FALSE; } void iupgtkButtonKeySetStatus(guint state, unsigned int but, char* status, int doubleclick) { if (state & GDK_SHIFT_MASK) iupKEY_SETSHIFT(status); if (state & GDK_CONTROL_MASK) iupKEY_SETCONTROL(status); if ((state & GDK_BUTTON1_MASK) || but==1) iupKEY_SETBUTTON1(status); if ((state & GDK_BUTTON2_MASK) || but==2) iupKEY_SETBUTTON2(status); if ((state & GDK_BUTTON3_MASK) || but==3) iupKEY_SETBUTTON3(status); if ((state & GDK_BUTTON4_MASK) || but==4) iupKEY_SETBUTTON4(status); if ((state & GDK_BUTTON5_MASK) || but==5) iupKEY_SETBUTTON5(status); if (state & GDK_MOD1_MASK || state & GDK_MOD5_MASK) /* Alt */ iupKEY_SETALT(status); if (state & GDK_MOD4_MASK) /* Apple/Win */ iupKEY_SETSYS(status); if (doubleclick) iupKEY_SETDOUBLE(status); }