// handle a keypress in edit mode // 0 = unhandled // 1 = handled // -1 = handled and return pressed (finished) int textbox_keypress(textbox *tb, XEvent *ev) { if (!(tb->flags & TB_EDITABLE)) return 0; KeySym key; Status stat; char pad[32]; int len = XmbLookupString(tb->xic, &ev->xkey, pad, sizeof(pad), &key, &stat); pad[len] = 0; switch (key) { case XK_Left : textbox_cursor_dec(tb); return 1; case XK_Right : textbox_cursor_inc(tb); return 1; case XK_Home : textbox_cursor_home(tb); return 1; case XK_End : textbox_cursor_end(tb); return 1; case XK_Delete : textbox_cursor_del(tb); return 1; case XK_BackSpace : textbox_cursor_bkspc(tb); return 1; case XK_Return : return -1; default: if (!iscntrl(*pad)) { textbox_insert(tb, tb->cursor, pad); textbox_cursor_inc(tb); return 1; } } return 0; }
// handle a keypress in edit mode // 0 = unhandled // 1 = handled // -1 = handled and return pressed (finished) int textbox_keypress(textbox *tb, XEvent *ev) { KeySym key; Status stat; char pad[32]; int len; if (!(tb->flags & TB_EDITABLE)) return 0; len = XmbLookupString(tb->xic, &ev->xkey, pad, sizeof(pad), &key, &stat); pad[len] = 0; if (key == XK_Left) { textbox_cursor_dec(tb); return 1; } else if (key == XK_Right) { textbox_cursor_inc(tb); return 1; } else if (key == XK_Home) { textbox_cursor_home(tb); return 1; } else if (key == XK_End) { textbox_cursor_end(tb); return 1; } else if (key == XK_Delete) { textbox_cursor_del(tb); return 1; } else if (key == XK_BackSpace) { textbox_cursor_bkspc(tb); return 1; } else if (key == XK_Return) { return -1; } else if (!iscntrl(*pad)) { textbox_insert(tb, tb->cursor, pad); textbox_cursor_inc(tb); return 1; } return 0; }
void x_on_keypress(XEvent *event) { XKeyEvent *e = &event->xkey; KeySym ksym; char buf[32]; int len; Status status; len = XmbLookupString(X.xic, e, buf, sizeof(buf)-1, &ksym, &status); if (!term_handle_keypress(ksym, e->state) && len > 0) { sh_write(buf, len); } }
int _XawLookupString(Widget w, XKeyEvent *event, char *buffer_return, int buffer_size, KeySym *keysym_return) { XawVendorShellExtPart *ve; VendorShellWidget vw; XawIcTableList p; if ((vw = SearchVendorShell(w)) && (ve = GetExtPart(vw)) && ve->im.xim && (p = GetIcTableShared(w, ve)) && p->xic) return (XmbLookupString(p->xic, event, buffer_return, buffer_size, keysym_return, NULL)); return (XLookupString(event, buffer_return, buffer_size, keysym_return, NULL)); }
int XUtf8LookupString(XIC ic, XKeyPressedEvent* event, char* buffer_return, int bytes_buffer, KeySym* keysym, Status* status_return) { long ucs = -1; int len; len = XmbLookupString(ic, event, buffer_return, bytes_buffer / 5, keysym, status_return); if (*status_return == XBufferOverflow) { return len * 5; } if (*keysym > 0 && *keysym < 0x100 && len == 1) { if (*keysym < 0x80) { ucs = (unsigned char)buffer_return[0]; } else { ucs = *keysym; } } else if (((*keysym >= 0x100 && *keysym <= 0xf000) || (*keysym & 0xff000000U) == 0x01000000)) { ucs = XKeysymToUcs(*keysym); } else { ucs = -2; } if (ucs > 0) { len = XConvertUcsToUtf8((unsigned)ucs, (char *)buffer_return); } else if (len > 0) { XIM im; if (!ic) return 0; im = XIMOfIC(ic); if (!im) return 0; len = XConvertEucToUtf8(XLocaleOfIM(im), buffer_return, len, bytes_buffer); } return len; }
value caml_next_event(value unit) { CAMLparam1(unit); CAMLlocal1(mlev); XEvent ev; char buf[32]; KeySym ksym = NoSymbol; Status status; size_t len; while(!XNextEvent(dc->dpy, &ev)) { if(XFilterEvent(&ev, win)) continue; switch(ev.type) { case Expose: if(ev.xexpose.count == 0) mapdc(dc, win, mw, mh); break; case KeyPress: len = XmbLookupString(xic, &ev.xkey, buf, sizeof buf, &ksym, &status); buf[len] = '\0'; mlev = caml_alloc_tuple(2); Field(mlev, 0) = Val_int(ksym); Field(mlev, 1) = caml_copy_string (buf); CAMLreturn (mlev); break; case SelectionNotify: /* if(ev.xselection.property == utf8) paste(); */ break; case VisibilityNotify: if(ev.xvisibility.state != VisibilityUnobscured) XRaiseWindow(dc->dpy, win); break; } } caml_failwith("unexpected return from XNextEvent") ; }
void handle_key(XKeyEvent ke) { FcChar8 buf[32]; int len, n; KeySym keysym = NoSymbol; Status status; option *o; len = XmbLookupString(xic, &ke, buf, sizeof(buf), &keysym, &status); if (status == XBufferOverflow) return; if (ke.state & ControlMask) { switch(keysym) { case XK_a: keysym = XK_Home; break; case XK_e: keysym = XK_End; break; case XK_p: keysym = XK_Up; break; case XK_n: keysym = XK_Down; break; case XK_f: keysym = XK_Right; break; case XK_b: keysym = XK_Left; break; case XK_d: keysym = XK_Delete; break; case XK_bracketleft: keysym = XK_Escape; break; case XK_k: text[cursor] = '\0'; break; case XK_u: for (n = cursor; cursor < MAX_LEN; cursor++) text[cursor - n] = text[cursor]; cursor = 0; update_valid_options(); return; } } if (text_input) { switch(keysym) { default: if (!iscntrl(*buf)) { insert(buf, len); update_valid_options(); } break; case XK_Delete: if (text[cursor] == '\0') break; cursor = nextrune(+1); /* Fall through to backspace */ case XK_BackSpace: if (cursor == 0) exit(0); insert(NULL, nextrune(-1) - cursor); update_valid_options(); break; case XK_Tab: copy_first(); break; case XK_Left: if (cursor != 0) cursor = nextrune(-1); break; case XK_Right: if (text[cursor] != '\0') cursor = nextrune(+1); break; case XK_Home: cursor = 0; break; case XK_End: while (text[cursor] != '\0') cursor = nextrune(+1); } } switch(keysym) { case XK_Up: if (valid->prev) valid = valid->prev; else for (; valid && valid->next; valid = valid->next); break; case XK_Down: if (valid->next) valid = valid->next; else for (; valid && valid->prev; valid = valid->prev); break; case XK_Return: finish(); break; case XK_Escape: exit(1); break; } if (exit_on_one) { for (n = 0, o = valid; o; o = o->next) n++; if (n == 1) finish(); } }
void appGuiGetStringFromKeyboardEvent( APP_INPUT_CONTEXT ic, APP_WIDGET w, APP_EVENT * event, int * pGotString, int * pGotKey, unsigned int * pState, unsigned char * buf, int capacity, APP_KEY_VALUE * pKey ) { int gotString; XKeyPressedEvent * keyEvent= &(event->xkey); if ( event->type != KeyPress ) { LLDEB(event->type,KeyPress); *pGotString= 0; return; } if ( ic ) { Status status; gotString= XmbLookupString( ic, keyEvent, (char *)buf, capacity- 1, pKey, &status ); switch( status ) { case XBufferOverflow: LDEB(status); *pGotString= 0; *pGotKey= 0; return; case XLookupNone: *pGotString= 0; *pGotKey= 0; return; case XLookupBoth: buf[gotString]= '\0'; *pGotString= gotString; *pGotKey= 1; *pState= keyEvent->state; return; case XLookupChars: buf[gotString]= '\0'; *pGotString= gotString; *pGotKey= 0; *pState= keyEvent->state; return; case XLookupKeySym: *pGotString= 0; *pGotKey= 1; *pState= keyEvent->state; if ( appGuiKeysymCludge( buf, *pKey ) ) { *pGotString= 1; } return; } } else{ gotString= XLookupString( keyEvent, (char *)buf, capacity- 1, pKey, (XComposeStatus *)0 ); if ( gotString > 0 ) { buf[gotString]= '\0'; } *pGotString= gotString; *pGotKey= 1; *pState= keyEvent->state; if ( ! gotString && appGuiKeysymCludge( buf, *pKey ) ) { *pGotString= 1; } return; } }
void keypress(Input *i, XKeyEvent *ev) { char buf[32]; int len; KeySym ksym = NoSymbol; Status status; len = XmbLookupString(ic, ev, buf, sizeof(buf), &ksym, &status); if (status == XBufferOverflow) return; if (ev->state & ControlMask) switch (ksym) { case XK_a: ksym = XK_Home; break; case XK_b: ksym = XK_Left; break; case XK_d: ksym = XK_Delete; break; case XK_e: ksym = XK_End; break; case XK_f: ksym = XK_Right; break; case XK_h: ksym = XK_BackSpace; break; case XK_i: ksym = XK_Tab; break; case XK_j: case XK_m: ksym = XK_Return; break; default: return; } else if (ev->state & Mod1Mask) switch (ksym) { case XK_g: ksym = XK_Home; break; case XK_G: ksym = XK_End; break; default: return; } switch (ksym) { default: if (!iscntrl(*buf)) insert(i, buf, len); break; case XK_Delete: if (i->text[i->cursor] == 0) return; i->cursor = nextrune(i, +1); /* fallthrough */ case XK_BackSpace: if (i->cursor == 0) return; insert(i, NULL, nextrune(i, -1) - i->cursor); break; case XK_Home: if (i->cursor == 0) return; i->cursor = 0; break; case XK_End: if (i->text[i->cursor] == 0) return; i->cursor = strlen(i->text); break; case XK_Left: if (i->cursor == 0) return; i->cursor = nextrune(i, -1); break; case XK_Right: if (i->text[i->cursor] == 0) return; i->cursor = nextrune(i, +1); break; case XK_Return: case XK_KP_Enter: if (!i->next) { running = False; return; } /* fallthrough */ case XK_Tab: XSetInputFocus(dpy, i->next ? i->next->win : inputs->win, RevertToPointerRoot, CurrentTime); return; } drawinput(i); }
int main(int argc, char **argv) { Display *display; int screen_num; Window win; //窗口ID unsigned int width, height; //窗口尺寸 unsigned int border_width = 4; //边界空白 unsigned int display_width, display_height;//屏幕尺寸 XEvent report; GC gc; unsigned long valuemask = 0; XGCValues values; char *display_name = NULL; Atom protocols; //edit int len = 127; unsigned char string[128], s_tab[ROW][127]; KeySym keysym; int row = 0, col = 0; int i, count = 0; Status status; //字体集 XFontSet fontset; char **missing_charsets; int num_missing_charsets; char *default_string; XFontSetExtents *fs_ext; int dec; //XIM XIM im; XIC ic; //overspot XRectangle spot, s_rect; XVaNestedList preedit_attr, status_attr; //设置locale if((setlocale(LC_ALL, "")) == NULL){ printf("cannot set locale\n"); exit(1); } //判断X是否支持locale if(!XSupportsLocale()){ printf("X does not support current locale\n"); exit(1); } //设置locale修饰 if(XSetLocaleModifiers(NULL)){ printf("Cannot set locale modifiers\n"); exit(1); } // 和X 服务器连接 if ( (display=XOpenDisplay(display_name)) == NULL ) { printf("Cannot connect to X server %s\n", XDisplayName(display_name)); exit(-1); } //获得缺省的 screen_num screen_num = DefaultScreen(display); //获得屏幕的宽度和高度 display_width = DisplayWidth(display, screen_num); display_height = DisplayHeight(display, screen_num); //建立字体集 fontset = XCreateFontSet(display, "8x16,-*-song-medium-r-normal--16-*-*-*-*-*-gb2312.1980-0", &missing_charsets, &num_missing_charsets, &default_string); if(num_missing_charsets > 0){ int i; printf("Following charsets are missing:\n"); for(i=0; i<num_missing_charsets; i++){ printf("Missing %d: %s\n", i, missing_charsets[i]); } printf("\nDefault string:%s\n", default_string); XFreeStringList(missing_charsets); } //字体的Extents fs_ext = XExtentsOfFontSet(fontset); dec = fs_ext->max_logical_extent.height + fs_ext->max_logical_extent.y; width = W_WIDTH; height = W_HEIGHT + dec; //建立窗口 win = XCreateSimpleWindow(display, //display RootWindow(display,screen_num), //父窗口 0, 0, width, height, //位置和大小 border_width, //边界宽度 BlackPixel(display,screen_num), //前景色 WhitePixel(display,screen_num));//背景色 //选择窗口感兴趣的事件掩码 XSelectInput(display, win, ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask); //建立GC gc = XCreateGC(display, win, valuemask, &values); protocols = XInternAtom(display, "WM_DELETE_WINDOW", True); XSetWMProtocols(display, win, &protocols, 1); //显示窗口 XMapWindow(display, win); //联接输入服务器 if((im = XOpenIM(display, NULL, NULL, NULL)) == NULL){ printf("Error : XOpenIM !\n"); exit(1); } //设置输入服务器的位置 spot.x = F_SIZE / 2 * col; spot.y = F_SIZE * (row + 1) - dec; preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, XNFontSet, fontset, NULL); s_rect.x = 0; s_rect.y = F_SIZE * ROW + dec + 2; s_rect.width = W_WIDTH; s_rect.height = F_SIZE; status_attr = XVaCreateNestedList(0, XNArea, &s_rect, XNFontSet, fontset, NULL); //建立IC if((ic = XCreateIC(im, XNInputStyle, XIMPreeditPosition | XIMStatusNothing, XNClientWindow, win, XNPreeditAttributes, preedit_attr, XNStatusAttributes, status_attr, NULL)) == NULL){ printf("Error : XCreateIC() ! \n"); XCloseIM(im); exit(0); } //释放内存 XFree(preedit_attr); XFree(status_attr); //写屏缓冲区初始化 for(i = 0; i < ROW; i++)s_tab[i][0] = 0; //进入事件循环 while (1) { //取得队列中的事件 XNextEvent(display, &report); //过滤事件 if(XFilterEvent(&report, None) == True) continue; switch (report.type) { //聚焦发声变化 case FocusIn: XSetICFocus(ic); break; case FocusOut: XUnsetICFocus(ic); break; //曝光事件, 窗口应重绘 case Expose: //取得最后一个曝光事件 if (report.xexpose.count != 0) break; for ( i=0; i < ROW; i++) XmbDrawString(display, win, fontset,gc, 0, F_SIZE * (i +1), s_tab[i], strlen(s_tab[i])); break; //窗口尺寸改变, 重新取得窗口的宽度和高度 case ConfigureNotify: width = report.xconfigure.width; height = report.xconfigure.height; break; //鼠标点击或有按键, 释放资源则退出 case KeyPress: count = XmbLookupString(ic, (XKeyPressedEvent *) &report, string, len, &keysym, &status); string[count] = 0; if (status == XLookupBoth&&keysym == XK_Return){ row = (++row) % ROW; col = 0; s_tab[row][0] = 0; XClearArea(display, win, 0, F_SIZE * row + dec, W_WIDTH, F_SIZE, False); } else if (status = XLookupChars || status == XLookupBoth){ XmbDrawString(display, win, fontset, gc, F_SIZE / 2 * col, F_SIZE * (row + 1), string, count); for (i = 0; i < count && col < len && string[i]; i++, col++) s_tab[row][col] = string[i]; s_tab[row][col] = 0; } //更新输入服务器位置 spot.x = F_SIZE / 2 * col; spot.y = F_SIZE * (row + 1); preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL); XSetICValues(ic, XNPreeditAttributes, preedit_attr, NULL); XFree(preedit_attr); break; case ClientMessage: if (report.xclient.data.l[0] == protocols) { XDestroyIC(ic); XCloseIM(im); XDestroyWindow(display, win); XCloseDisplay(display); exit(0); } break; default: break; } } }
/* ARGSUSED */ static void InsertChar ( Widget ctxw, XEvent *event, String *params, Cardinal *num_params) { LoginWidget ctx = (LoginWidget)ctxw; char strbuf[128]; #ifndef XPM int len; #else int len,pixels; #endif /* XPM */ KeySym keysym = 0; if (ctx->login.xic) { static Status status; len = XmbLookupString(ctx->login.xic, &event->xkey, strbuf, sizeof (strbuf), &keysym, &status); } else { static XComposeStatus compose_status = {NULL, 0}; len = XLookupString (&event->xkey, strbuf, sizeof (strbuf), &keysym, &compose_status); } strbuf[len] = '\0'; #ifdef XPM pixels = 3 + ctx->login.font->max_bounds.width * len + XTextWidth(ctx->login.font, ctx->login.data.name, strlen(ctx->login.data.name)); /* pixels to be added */ #endif /* XPM */ /* * Note: You can override this default key handling * by the settings in the translation table * loginActionsTable at the end of this file. */ switch (keysym) { case XK_Return: case XK_KP_Enter: case XK_Linefeed: case XK_Execute: FinishField(ctxw, event, params, num_params); return; case XK_BackSpace: DeleteBackwardChar(ctxw, event, params, num_params); return; case XK_Delete: case XK_KP_Delete: case DXK_Remove: /* Sorry, it's not a telex machine, it's a terminal */ DeleteForwardChar(ctxw, event, params, num_params); return; case XK_Left: case XK_KP_Left: MoveBackwardChar(ctxw, event, params, num_params); return; case XK_Right: case XK_KP_Right: MoveForwardChar(ctxw, event, params, num_params); return; case XK_End: case XK_KP_End: MoveToEnd(ctxw, event, params, num_params); return; case XK_Home: case XK_KP_Home: MoveToBegining(ctxw, event, params, num_params); return; default: if (len == 0) { if (!IsModifierKey(keysym)) /* it's not a modifier */ XBell(XtDisplay(ctxw), 60); return; } else break; } switch (ctx->login.state) { case GET_NAME: #ifndef XPM if (len + (int)strlen(ctx->login.data.name) >= NAME_LEN - 1) #else if ( (len + (int)strlen(ctx->login.data.name) >= NAME_LEN - 1)/* && (pixels <= LOGIN_W(ctx) - PROMPT_W(ctx))*/ ) #endif /* XPM */ len = NAME_LEN - strlen(ctx->login.data.name) - 2; case GET_PASSWD: if (len + (int)strlen(ctx->login.data.passwd) >= PASSWORD_LEN - 1) len = PASSWORD_LEN - strlen(ctx->login.data.passwd) - 2; } #ifndef XPM if (len == 0) #else if (len == 0 || pixels >= LOGIN_W(ctx) - PROMPT_W(ctx)) #endif /* XPM */ return; XorCursor (ctx); RemoveFail (ctx); switch (ctx->login.state) { case GET_NAME: EraseName (ctx, ctx->login.cursor); memmove( ctx->login.data.name + ctx->login.cursor + len, ctx->login.data.name + ctx->login.cursor, strlen (ctx->login.data.name + ctx->login.cursor) + 1); memmove( ctx->login.data.name + ctx->login.cursor, strbuf, len); DrawName (ctx, ctx->login.cursor); ctx->login.cursor += len; break; case GET_PASSWD: memmove( ctx->login.data.passwd + ctx->login.cursor + len, ctx->login.data.passwd + ctx->login.cursor, strlen (ctx->login.data.passwd + ctx->login.cursor) + 1); memmove( ctx->login.data.passwd + ctx->login.cursor, strbuf, len); ctx->login.cursor += len; #ifdef XPM /*as good a place as any Caolan begin*/ ctx->login.lastEventTime = time(NULL); /*as good a place as any Caolan end*/ #endif /* XPM */ break; } XorCursor (ctx); }
const char * TkpGetString( TkWindow *winPtr, /* Window where event occurred */ XEvent *eventPtr, /* X keyboard event. */ Tcl_DString *dsPtr) /* Initialized, empty string to hold result. */ { int len; Tcl_DString buf; TkKeyEvent *kePtr = (TkKeyEvent *) eventPtr; /* * If we have the value cached already, use it now. [Bug 1373712] */ if (kePtr->charValuePtr != NULL) { Tcl_DStringSetLength(dsPtr, kePtr->charValueLen); memcpy(Tcl_DStringValue(dsPtr), kePtr->charValuePtr, (unsigned) kePtr->charValueLen+1); return Tcl_DStringValue(dsPtr); } #ifdef TK_USE_INPUT_METHODS if ((winPtr->dispPtr->flags & TK_DISPLAY_USE_IM) && (winPtr->inputContext != NULL) && (eventPtr->type == KeyPress)) { Status status; #if X_HAVE_UTF8_STRING Tcl_DStringSetLength(dsPtr, TCL_DSTRING_STATIC_SIZE-1); len = Xutf8LookupString(winPtr->inputContext, &eventPtr->xkey, Tcl_DStringValue(dsPtr), Tcl_DStringLength(dsPtr), &kePtr->keysym, &status); if (status == XBufferOverflow) { /* * Expand buffer and try again. */ Tcl_DStringSetLength(dsPtr, len); len = Xutf8LookupString(winPtr->inputContext, &eventPtr->xkey, Tcl_DStringValue(dsPtr), Tcl_DStringLength(dsPtr), &kePtr->keysym, &status); } if ((status != XLookupChars) && (status != XLookupBoth)) { len = 0; } Tcl_DStringSetLength(dsPtr, len); #else /* !X_HAVE_UTF8_STRING */ /* * Overallocate the dstring to the maximum stack amount. */ Tcl_DStringInit(&buf); Tcl_DStringSetLength(&buf, TCL_DSTRING_STATIC_SIZE-1); len = XmbLookupString(winPtr->inputContext, &eventPtr->xkey, Tcl_DStringValue(&buf), Tcl_DStringLength(&buf), &kePtr->keysym, &status); /* * If the buffer wasn't big enough, grow the buffer and try again. */ if (status == XBufferOverflow) { Tcl_DStringSetLength(&buf, len); len = XmbLookupString(winPtr->inputContext, &eventPtr->xkey, Tcl_DStringValue(&buf), len, &kePtr->keysym, &status); } if ((status != XLookupChars) && (status != XLookupBoth)) { len = 0; } Tcl_DStringSetLength(&buf, len); Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(&buf), len, dsPtr); Tcl_DStringFree(&buf); #endif /* X_HAVE_UTF8_STRING */ } else #endif /* TK_USE_INPUT_METHODS */ { /* * Fall back to convert a keyboard event to a UTF-8 string using * XLookupString. This is used when input methods are turned off and * for KeyRelease events. * * Note: XLookupString() normally returns a single ISO Latin 1 or * ASCII control character. */ Tcl_DStringInit(&buf); Tcl_DStringSetLength(&buf, TCL_DSTRING_STATIC_SIZE-1); len = XLookupString(&eventPtr->xkey, Tcl_DStringValue(&buf), TCL_DSTRING_STATIC_SIZE, &kePtr->keysym, 0); Tcl_DStringValue(&buf)[len] = '\0'; if (len == 1) { len = Tcl_UniCharToUtf((unsigned char) Tcl_DStringValue(&buf)[0], Tcl_DStringValue(dsPtr)); Tcl_DStringSetLength(dsPtr, len); } else { /* * len > 1 should only happen if someone has called XRebindKeysym. * Assume UTF-8. */ Tcl_DStringSetLength(dsPtr, len); strncpy(Tcl_DStringValue(dsPtr), Tcl_DStringValue(&buf), len); } } /* * Cache the string in the event so that if/when we return to this * function, we will be able to produce it without asking X. This stops us * from having to reenter the XIM engine. [Bug 1373712] */ kePtr->charValuePtr = ckalloc(len + 1); kePtr->charValueLen = len; memcpy(kePtr->charValuePtr, Tcl_DStringValue(dsPtr), (unsigned) len + 1); return Tcl_DStringValue(dsPtr); }
void emX11WindowPort::HandleEvent(XEvent & event) { emInputEvent inputEvent; emX11WindowPort * wp; char tmp[256]; char keymap[32]; KeySym ks; emInputKey key; Status status; int i,x,y,w,h,mask,repeat,variant,len; double mx,my; bool inside; // Remember: // - Calling InputToView may delete this window port. // - The grab stuff is very very tricky. switch (event.type) { case MotionNotify: mx=PaneX+event.xmotion.x+Screen.MouseWarpX; my=PaneY+event.xmotion.y+Screen.MouseWarpY; if ( Screen.InputState.GetMouseX()!=mx || Screen.InputState.GetMouseY()!=my ) { Screen.InputState.SetMouse(mx,my); Screen.InputStateClock++; } for (i=0; i<3; i++) { if (i==0) { key=EM_KEY_LEFT_BUTTON ; mask=Button1Mask; } else if (i==1) { key=EM_KEY_MIDDLE_BUTTON; mask=Button2Mask; } else { key=EM_KEY_RIGHT_BUTTON ; mask=Button3Mask; } if (Screen.InputState.Get(key) && (event.xmotion.state&mask)==0) { Screen.InputState.Set(key,false); Screen.InputStateClock++; } } return; case ButtonPress: mx=PaneX+event.xbutton.x+Screen.MouseWarpX; my=PaneY+event.xbutton.y+Screen.MouseWarpY; if ( Screen.InputState.GetMouseX()!=mx || Screen.InputState.GetMouseY()!=my ) { Screen.InputState.SetMouse(mx,my); Screen.InputStateClock++; } wp=SearchOwnedPopupAt(mx,my); if (wp) { if (wp->Mapped) { event.xbutton.x+=PaneX-wp->PaneX; event.xbutton.y+=PaneY-wp->PaneY; wp->HandleEvent(event); } return; } if (ModalDescendants>0) { FocusModalDescendant(true); return; } inside=( mx>=PaneX && mx<PaneX+PaneW && my>=PaneY && my<PaneY+PaneH ); if ( !inside && Screen.GrabbingWinPort==this && (GetWindowFlags()&emWindow::WF_POPUP)!=0 ) { XMutex.Lock(); XAllowEvents(Disp,ReplayPointer,CurrentTime); XMutex.Unlock(); Screen.GrabbingWinPort=NULL; LastButtonPress=EM_KEY_NONE; SignalWindowClosing(); } for (i=Screen.WinPorts.GetCount()-1; i>=0; i--) { wp=Screen.WinPorts[i]; if ( (wp->GetWindowFlags()&emWindow::WF_POPUP)!=0 && wp!=this && !wp->IsAncestorOf(this) ) { wp->SignalWindowClosing(); } } if (!inside) return; if (!Focused && event.xbutton.button>=1 && event.xbutton.button<=5) { RequestFocus(); Screen.UpdateKeymapAndInputState(); } if (event.xbutton.button>=1 && event.xbutton.button<=3) { if (event.xbutton.button==1) key=EM_KEY_LEFT_BUTTON; else if (event.xbutton.button==2) key=EM_KEY_MIDDLE_BUTTON; else key=EM_KEY_RIGHT_BUTTON; if (!Screen.InputState.Get(key)) { Screen.InputState.Set(key,true); Screen.InputStateClock++; if ( key==LastButtonPress && event.xbutton.time>LastButtonPressTime && event.xbutton.time-LastButtonPressTime<=330 && event.xbutton.x>=LastButtonPressX-10 && event.xbutton.x<=LastButtonPressX+10 && event.xbutton.y>=LastButtonPressY-10 && event.xbutton.y<=LastButtonPressY+10 ) { repeat=LastButtonPressRepeat+1; } else { repeat=0; } LastButtonPress=key; LastButtonPressTime=event.xbutton.time; LastButtonPressX=event.xbutton.x; LastButtonPressY=event.xbutton.y; LastButtonPressRepeat=repeat; inputEvent.Setup(key,"",repeat,0); InputStateClock=Screen.InputStateClock; InputToView(inputEvent,Screen.InputState); return; } } else if (event.xbutton.button==4) { inputEvent.Setup(EM_KEY_WHEEL_UP,"",0,0); InputStateClock=Screen.InputStateClock; InputToView(inputEvent,Screen.InputState); return; } else if (event.xbutton.button==5) { inputEvent.Setup(EM_KEY_WHEEL_DOWN,"",0,0); InputStateClock=Screen.InputStateClock; InputToView(inputEvent,Screen.InputState); return; } return; case ButtonRelease: mx=PaneX+event.xbutton.x+Screen.MouseWarpX; my=PaneY+event.xbutton.y+Screen.MouseWarpY; if ( Screen.InputState.GetMouseX()!=mx || Screen.InputState.GetMouseY()!=my ) { Screen.InputState.SetMouse(mx,my); Screen.InputStateClock++; } if (event.xbutton.button>=1 && event.xbutton.button<=3) { if (event.xbutton.button==1) key=EM_KEY_LEFT_BUTTON; else if (event.xbutton.button==2) key=EM_KEY_MIDDLE_BUTTON; else key=EM_KEY_RIGHT_BUTTON; if (Screen.InputState.Get(key)) { Screen.InputState.Set(key,false); Screen.InputStateClock++; inputEvent.Eat(); InputStateClock=Screen.InputStateClock; InputToView(inputEvent,Screen.InputState); return; } } return; case KeyPress: i=event.xkey.keycode/8; mask=1<<(event.xkey.keycode&7); if (i<32 && (Screen.Keymap[i]&mask)==0) { Screen.Keymap[i]|=mask; Screen.UpdateInputStateFromKeymap(); } if (InputContext) { XMutex.Lock(); len=XmbLookupString( InputContext, &event.xkey, tmp, sizeof(tmp)-1, &ks, &status ); XMutex.Unlock(); if (status!=XLookupChars && status!=XLookupBoth) len=0; if (status!=XLookupKeySym && status!=XLookupBoth) ks=0; } else { XMutex.Lock(); len=XLookupString( &event.xkey, tmp, sizeof(tmp)-1, &ks, &ComposeStatus ); XMutex.Unlock(); } tmp[len]=0; key=emX11Screen::ConvertKey(ks,&variant); if (key==EM_KEY_NONE && !tmp[0]) return; repeat=0; if ( key!=EM_KEY_NONE && Screen.InputState.Get(key) && RepeatKey==key ) { repeat=KeyRepeat+1; } if (ModalDescendants>0) return; RepeatKey=key; KeyRepeat=repeat; inputEvent.Setup(key,tmp,repeat,variant); InputStateClock=Screen.InputStateClock; InputToView(inputEvent,Screen.InputState); return; case KeyRelease: memset(keymap,0,sizeof(keymap)); XMutex.Lock(); XQueryKeymap(Disp,keymap); XMutex.Unlock(); i=event.xkey.keycode/8; mask=1<<(event.xkey.keycode&7); if (i<32 && (keymap[i]&mask)==0) { RepeatKey=EM_KEY_NONE; if ((Screen.Keymap[i]&mask)!=0) { Screen.Keymap[i]&=~mask; Screen.UpdateInputStateFromKeymap(); } } return; case Expose: x=event.xexpose.x; y=event.xexpose.y; w=event.xexpose.width; h=event.xexpose.height; InvalidatePainting(PaneX+x,PaneY+y,w,h); return; case FocusIn: if ( event.xfocus.mode==NotifyNormal || event.xfocus.mode==NotifyWhileGrabbed ) { if (InputContext) { XMutex.Lock(); XSetICFocus(InputContext); XMutex.Unlock(); } Screen.UpdateKeymapAndInputState(); RepeatKey=EM_KEY_NONE; if (!Focused) { Focused=true; SetViewFocused(true); } if (ModalDescendants>0) FocusModalDescendant(); } return; case FocusOut: if ( event.xfocus.mode==NotifyNormal || event.xfocus.mode==NotifyWhileGrabbed ) { if (InputContext) { XMutex.Lock(); XUnsetICFocus(InputContext); XMutex.Unlock(); } if (Focused) { Focused=false; SetViewFocused(false); } LastButtonPress=EM_KEY_NONE; RepeatKey=EM_KEY_NONE; } return; case ConfigureNotify: // The meaning of the coordinates from event.xconfigure depends on // the window manager. Therefore: GetAbsWinGeometry(Disp,Win,&x,&y,&w,&h); if (PaneX!=x || PaneY!=y || PaneW!=w || PaneH!=h) { PaneX=x; PaneY=y; PaneW=w; PaneH=h; ClipX1=PaneX; ClipY1=PaneY; ClipX2=PaneX+PaneW; ClipY2=PaneY+PaneH; InvalidRects.Set(PaneX,PaneY,PaneX+PaneW,PaneY+PaneH); WakeUp(); if (!PosPending && !SizePending) { SetViewGeometry( PaneX,PaneY, PaneW,PaneH, Screen.PixelTallness ); } else if (!PosPending) { SetViewGeometry( PaneX,PaneY, GetViewWidth(),GetViewHeight(), Screen.PixelTallness ); } else if (!SizePending) { SetViewGeometry( GetViewX(),GetViewY(), PaneW,PaneH, Screen.PixelTallness ); } Screen.InputStateClock++; } return; case MapNotify: if (event.xmap.window==Win && !Mapped) { Mapped=true; WakeUp(); } return; case UnmapNotify: if (event.xmap.window==Win && Mapped) { Mapped=false; } return; case ClientMessage: if (event.xclient.data.l[0]==(long)Screen.WM_DELETE_WINDOW) { if (ModalDescendants<=0) SignalWindowClosing(); else FocusModalDescendant(true); } return; } }
Bool awt_x11inputmethod_lookupString(XKeyPressedEvent *event, KeySym *keysymp) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); X11InputMethodData *pX11IMData; KeySym keysym = NoSymbol; Status status; int mblen; jstring javastr; XIC ic; Bool result = True; static Bool composing = False; /* printf("lookupString: entering...\n"); */ pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance); if (pX11IMData == NULL) { #ifdef __linux__ return False; #else return result; #endif } if ((ic = pX11IMData->current_ic) == (XIC)0){ #ifdef __linux__ return False; #else return result; #endif } /* allocate the lookup buffer at the first invocation */ if (pX11IMData->lookup_buf_len == 0) { pX11IMData->lookup_buf = (char *)malloc(INITIAL_LOOKUP_BUF_SIZE); if (pX11IMData->lookup_buf == NULL) { THROW_OUT_OF_MEMORY_ERROR(); return result; } pX11IMData->lookup_buf_len = INITIAL_LOOKUP_BUF_SIZE; } mblen = XmbLookupString(ic, event, pX11IMData->lookup_buf, pX11IMData->lookup_buf_len - 1, &keysym, &status); /* * In case of overflow, a buffer is allocated and it retries * XmbLookupString(). */ if (status == XBufferOverflow) { free((void *)pX11IMData->lookup_buf); pX11IMData->lookup_buf_len = 0; pX11IMData->lookup_buf = (char *)malloc(mblen + 1); if (pX11IMData->lookup_buf == NULL) { THROW_OUT_OF_MEMORY_ERROR(); return result; } pX11IMData->lookup_buf_len = mblen + 1; mblen = XmbLookupString(ic, event, pX11IMData->lookup_buf, pX11IMData->lookup_buf_len - 1, &keysym, &status); } pX11IMData->lookup_buf[mblen] = 0; /* Get keysym without taking modifiers into account first to map * to AWT keyCode table. */ if (((event->state & ShiftMask) || (event->state & LockMask)) && keysym >= 'A' && keysym <= 'Z') { keysym = XLookupKeysym(event, 0); } switch (status) { case XLookupBoth: if (!composing) { if (keysym < 128 || ((keysym & 0xff00) == 0xff00)) { *keysymp = keysym; result = False; break; } } composing = False; /*FALLTHRU*/ case XLookupChars: /* printf("lookupString: status=XLookupChars, type=%d, state=%x, keycode=%x, keysym=%x\n", event->type, event->state, event->keycode, keysym); */ javastr = JNU_NewStringPlatform(env, (const char *)pX11IMData->lookup_buf); if (javastr != NULL) { JNU_CallMethodByName(env, NULL, currentX11InputMethodInstance, "dispatchCommittedText", "(Ljava/lang/String;J)V", javastr, #ifndef XAWT_HACK awt_util_nowMillisUTC_offset(event->time)); #else event->time); #endif } break; case XLookupKeySym: /* printf("lookupString: status=XLookupKeySym, type=%d, state=%x, keycode=%x, keysym=%x\n", event->type, event->state, event->keycode, keysym); */ if (keysym == XK_Multi_key) composing = True; if (! composing) { *keysymp = keysym; result = False; } break; case XLookupNone: /* printf("lookupString: status=XLookupNone, type=%d, state=%x, keycode=%x, keysym=%x\n", event->type, event->state, event->keycode, keysym); */ break; }
void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { // X11 functions don't know what const is XKeyEvent *xkeyevent = p_event; // This code was pretty difficult to write. // The docs stink and every toolkit seems to // do it in a different way. /* Phase 1, obtain a proper keysym */ // This was also very difficult to figure out. // You'd expect you could just use Keysym provided by // XKeycodeToKeysym to obtain internationalized // input.. WRONG!! // you must use XLookupString (???) which not only wastes // cycles generating an unnecesary string, but also // still works in half the cases. (won't handle deadkeys) // For more complex input methods (deadkeys and more advanced) // you have to use XmbLookupString (??). // So.. then you have to chosse which of both results // you want to keep. // This is a real bizarreness and cpu waster. KeySym keysym_keycode=0; // keysym used to find a keycode KeySym keysym_unicode=0; // keysym used to find unicode int nbytes=0; // bytes the string takes // XLookupString returns keysyms usable as nice scancodes/ char str[256+1]; nbytes=XLookupString(xkeyevent, str, 256, &keysym_keycode, NULL); // Meanwhile, XLookupString returns keysyms useful for unicode. if (!xmbstring) { // keep a temporary buffer for the string xmbstring=(char*)memalloc(sizeof(char)*8); xmblen=8; } if (xkeyevent->type == KeyPress && xic) { Status status; do { int mnbytes = XmbLookupString (xic, xkeyevent, xmbstring, xmblen - 1, &keysym_unicode, &status); xmbstring[mnbytes] = '\0'; if (status == XBufferOverflow) { xmblen = mnbytes + 1; xmbstring = (char*)memrealloc (xmbstring, xmblen); } } while (status == XBufferOverflow); } /* Phase 2, obtain a pigui keycode from the keysym */ // KeyMappingX11 just translated the X11 keysym to a PIGUI // keysym, so it works in all platforms the same. unsigned int keycode = KeyMappingX11::get_keycode(keysym_keycode); /* Phase 3, obtain an unicode character from the keysym */ // KeyMappingX11 also translates keysym to unicode. // It does a binary search on a table to translate // most properly. //print_line("keysym_unicode: "+rtos(keysym_unicode)); unsigned int unicode = keysym_unicode>0? KeyMappingX11::get_unicode_from_keysym(keysym_unicode):0; /* Phase 4, determine if event must be filtered */ // This seems to be a side-effect of using XIM. // XEventFilter looks like a core X11 funciton, // but it's actually just used to see if we must // ignore a deadkey, or events XIM determines // must not reach the actual gui. // Guess it was a design problem of the extension bool keypress = xkeyevent->type == KeyPress; if (xkeyevent->type == KeyPress && xic) { if (XFilterEvent((XEvent*)xkeyevent, x11_window)) return; } if (keycode==0 && unicode==0) return; /* Phase 5, determine modifier mask */ // No problems here, except I had no way to // know Mod1 was ALT and Mod4 was META (applekey/winkey) // just tried Mods until i found them. //print_line("mod1: "+itos(xkeyevent->state&Mod1Mask)+" mod 5: "+itos(xkeyevent->state&Mod5Mask)); InputModifierState state = get_key_modifier_state(xkeyevent->state); /* Phase 6, determine echo character */ // Echo characters in X11 are a keyrelease and a keypress // one after the other with the (almot) same timestamp. // To detect them, i use XPeekEvent and check that their // difference in time is below a treshold. if (xkeyevent->type != KeyPress) { // make sure there are events pending, // so this call won't block. if (XPending(x11_display)>0) { XEvent peek_event; XPeekEvent(x11_display, &peek_event); // I'm using a treshold of 5 msecs, // since sometimes there seems to be a little // jitter. I'm still not convinced that all this approach // is correct, but the xorg developers are // not very helpful today. ::Time tresh=ABS(peek_event.xkey.time-xkeyevent->time); if (peek_event.type == KeyPress && tresh<5 ) { KeySym rk; nbytes=XLookupString((XKeyEvent*)&peek_event, str, 256, &rk, NULL); if (rk==keysym_keycode) { XEvent event; XNextEvent(x11_display, &event); //erase next event handle_key_event( (XKeyEvent*)&event,true ); return; //ignore current, echo next } } // use the time from peek_event so it always works } // save the time to check for echo when keypress happens } /* Phase 7, send event to Window */ InputEvent event; event.ID=++event_id; event.type = InputEvent::KEY; event.device=0; event.key.mod=state; event.key.pressed=keypress; if (keycode>='a' && keycode<='z') keycode-='a'-'A'; event.key.scancode=keycode; event.key.unicode=unicode; event.key.echo=p_echo; if (event.key.scancode==KEY_BACKTAB) { //make it consistent accross platforms. event.key.scancode=KEY_TAB; event.key.mod.shift=true; } //printf("key: %x\n",event.key.scancode); input->parse_input_event( event); }
void keypress(XKeyEvent *ev) { char buf[32]; int len; KeySym ksym = NoSymbol; Status status; len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status); if(status == XBufferOverflow) return; if(ev->state & ControlMask) switch(ksym) { case XK_a: ksym = XK_Home; break; case XK_b: ksym = XK_Left; break; case XK_c: ksym = XK_Escape; break; case XK_d: ksym = XK_Delete; break; case XK_e: ksym = XK_End; break; case XK_f: ksym = XK_Right; break; case XK_g: ksym = XK_Escape; break; case XK_h: ksym = XK_BackSpace; break; case XK_i: ksym = XK_Tab; break; case XK_j: /* fallthrough */ case XK_J: ksym = XK_Return; break; case XK_m: /* fallthrough */ case XK_M: ksym = XK_Return; break; case XK_n: ksym = XK_Down; break; case XK_p: ksym = XK_Up; break; case XK_k: /* delete right */ text[cursor] = '\0'; match(); break; case XK_u: /* delete left */ insert(NULL, 0 - cursor); break; case XK_w: /* delete word */ while(cursor > 0 && text[nextrune(-1)] == ' ') insert(NULL, nextrune(-1) - cursor); while(cursor > 0 && text[nextrune(-1)] != ' ' && text[nextrune(-1)] != '/') insert(NULL, nextrune(-1) - cursor); break; case XK_y: /* paste selection */ XConvertSelection(dc->dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY, utf8, utf8, win, CurrentTime); return; default: return; } else if(ev->state & Mod1Mask) switch(ksym) { case XK_g: ksym = XK_Home; break; case XK_G: ksym = XK_End; break; case XK_h: ksym = XK_Up; break; case XK_j: ksym = XK_Next; break; case XK_k: ksym = XK_Prior; break; case XK_l: ksym = XK_Down; break; default: return; } switch(ksym) { default: if(!iscntrl(*buf)) insert(buf, len); break; case XK_Delete: if(text[cursor] == '\0') return; cursor = nextrune(+1); /* fallthrough */ case XK_BackSpace: if(cursor == 0) return; insert(NULL, nextrune(-1) - cursor); break; case XK_End: if(text[cursor] != '\0') { cursor = strlen(text); break; } if(next) { /* jump to end of list and position items in reverse */ curr = matchend; calcoffsets(); curr = prev; calcoffsets(); while(next && (curr = curr->right)) calcoffsets(); } sel = matchend; break; case XK_Escape: ret = EXIT_FAILURE; running = False; case XK_Home: if(sel == matches) { cursor = 0; break; } sel = curr = matches; calcoffsets(); break; case XK_Left: if(cursor > 0 && (!sel || !sel->left || lines > 0)) { cursor = nextrune(-1); break; } if(lines > 0) return; /* fallthrough */ case XK_Up: if(sel && sel->left && (sel = sel->left)->right == curr) { curr = prev; calcoffsets(); } break; case XK_Next: if(!next) return; sel = curr = next; calcoffsets(); break; case XK_Prior: if(!prev) return; sel = curr = prev; calcoffsets(); break; case XK_Return: case XK_KP_Enter: puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); ret = EXIT_SUCCESS; running = False; case XK_Right: if(text[cursor] != '\0') { cursor = nextrune(+1); break; } if(lines > 0) return; /* fallthrough */ case XK_Down: if(sel && sel->right && (sel = sel->right) == next) { curr = next; calcoffsets(); } break; case XK_Tab: if(!sel) return; strncpy(text, sel->text, sizeof text); cursor = strlen(text); match(); break; } drawmenu(); }
void X11Window::poll() { bool needsResizeUpdate = false; XEvent event, peekEvent; while(XPending(m_display) > 0) { XNextEvent(m_display, &event); // check for repeated key releases bool repatedKeyRelease = false; if(event.type == KeyRelease && XPending(m_display)) { XPeekEvent(m_display, &peekEvent); if((peekEvent.type == KeyPress) && (peekEvent.xkey.keycode == event.xkey.keycode) && ((peekEvent.xkey.time-event.xkey.time) < 2)) repatedKeyRelease = true; } // process keydown and keyrelease events first if(event.type == KeyPress || (event.type == KeyRelease && !repatedKeyRelease)) { // remove caps lock and shift maks XKeyEvent xkey = event.xkey; xkey.state &= ~(ShiftMask | LockMask); // lookup keysym and translate it KeySym keysym; char buf[32]; XLookupString(&xkey, buf, sizeof(buf), &keysym, 0); Fw::Key keyCode = Fw::KeyUnknown; if(m_keyMap.find(keysym) != m_keyMap.end()) keyCode = m_keyMap[keysym]; if(event.type == KeyPress) processKeyDown(keyCode); else if(event.type == KeyRelease) processKeyUp(keyCode); } // call filter because xim will discard KeyPress events when keys still composing if(XFilterEvent(&event, m_window)) continue; // discard repated key releases if(repatedKeyRelease) continue; switch(event.type) { case ClientMessage: { // close event if((Atom)event.xclient.data.l[0] == m_wmDelete && m_onClose) m_onClose(); break; } case ConfigureNotify: { Size newSize(event.xconfigure.width, event.xconfigure.height); Point newPos(event.xconfigure.x, event.xconfigure.y); // updates window size if(m_size != newSize) { m_size = newSize; needsResizeUpdate = true; } // checks if the window is maximized if(m_visible) { m_maximized = false; Atom wmState = XInternAtom(m_display, "_NET_WM_STATE", False); Atom wmStateMaximizedVert = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_VERT", False); Atom wmStateMaximizedHorz = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); Atom actualType; ulong i, numItems, bytesAfter; uchar *propertyValue = NULL; int actualFormat; if(XGetWindowProperty(m_display, m_window, wmState, 0, 1024, False, XA_ATOM, &actualType, &actualFormat, &numItems, &bytesAfter, &propertyValue) == Success) { Atom *atoms = (Atom*)propertyValue; int maximizedMask = 0; for(i=0; i<numItems; ++i) { if(atoms[i] == wmStateMaximizedVert) maximizedMask |= 1; else if(atoms[i] == wmStateMaximizedHorz) maximizedMask |= 2; } if(maximizedMask == 3) m_maximized = true; XFree(propertyValue); } } // updates window pos if(m_visible) m_position = newPos; updateUnmaximizedCoords(); break; } case SelectionRequest: { XEvent respond; XSelectionRequestEvent *req = &(event.xselectionrequest); Atom targets = XInternAtom(m_display, "TARGETS", False); if(req->target == targets) { Atom typeList[] = { XInternAtom(m_display, "UTF8_STRING", False), XInternAtom(m_display, "TEXT", False), XInternAtom(m_display, "STRING", False), XInternAtom(m_display, "text/plain", False), XInternAtom(m_display, "COMPOUND_TEXT", False), XA_STRING }; XChangeProperty(m_display, req->requestor, req->property, req->target, 8, PropModeReplace, (uchar *)&typeList, sizeof(typeList)); respond.xselection.property = req->property; } else { XChangeProperty(m_display, req->requestor, req->property, req->target, 8, PropModeReplace, (uchar *)m_clipboardText.c_str(), m_clipboardText.length()); respond.xselection.property = req->property; } respond.xselection.type = SelectionNotify; respond.xselection.display = req->display; respond.xselection.requestor = req->requestor; respond.xselection.selection = req->selection; respond.xselection.target = req->target; respond.xselection.time = req->time; XSendEvent(m_display, req->requestor, 0, 0, &respond); XFlush(m_display); break; } // process text events case KeyPress: { // text cant be insert while holding ctrl or alt if(event.xkey.state & ControlMask || event.xkey.state & Mod1Mask) break; // process key text events KeySym keysym; char buf[32]; memset(buf, 0, 32); int len; // lookup for keyText if(m_xic) { // with xim we can get latin1 input correctly Status status; len = XmbLookupString(m_xic, &event.xkey, buf, sizeof(buf), &keysym, &status); } else { // otherwise use XLookupString, but often it doesn't work right with dead keys static XComposeStatus compose = {NULL, 0}; len = XLookupString(&event.xkey, buf, sizeof(buf), &keysym, &compose); } // filter unwanted characters if(len == 0 || (uchar)(buf[0]) < 32 || keysym == XK_BackSpace || keysym == XK_Return || keysym == XK_Delete || keysym == XK_Escape) break; std::string text = buf; //g_logger.debug("char: ", buf[0], " code: ", (int)((uchar)buf[0])); if(m_onInputEvent && text.length() > 0) { m_inputEvent.reset(Fw::KeyTextInputEvent); m_inputEvent.keyText = text; m_onInputEvent(m_inputEvent); } break; } case ButtonPress: case ButtonRelease: { m_inputEvent.reset(); m_inputEvent.type = (event.type == ButtonPress) ? Fw::MousePressInputEvent : Fw::MouseReleaseInputEvent; switch(event.xbutton.button) { case Button1: m_inputEvent.mouseButton = Fw::MouseLeftButton; m_mouseButtonStates[Fw::MouseLeftButton] = (event.type == ButtonPress); break; case Button3: m_inputEvent.mouseButton = Fw::MouseRightButton; m_mouseButtonStates[Fw::MouseRightButton] = (event.type == ButtonPress); break; case Button2: m_inputEvent.mouseButton = Fw::MouseMidButton; m_mouseButtonStates[Fw::MouseMidButton] = (event.type == ButtonPress); break; case Button4: if(event.type == ButtonPress) { m_inputEvent.type = Fw::MouseWheelInputEvent; m_inputEvent.mouseButton = Fw::MouseMidButton; m_inputEvent.wheelDirection = Fw::MouseWheelUp; } break; case Button5: if(event.type == ButtonPress) { m_inputEvent.type = Fw::MouseWheelInputEvent; m_inputEvent.mouseButton = Fw::MouseMidButton; m_inputEvent.wheelDirection = Fw::MouseWheelDown; } break; default: m_inputEvent.type = Fw::NoInputEvent; break; } if(m_inputEvent.type != Fw::NoInputEvent && m_onInputEvent) m_onInputEvent(m_inputEvent); break; } case MotionNotify: { m_inputEvent.reset(); m_inputEvent.type = Fw::MouseMoveInputEvent; Point newMousePos(event.xbutton.x, event.xbutton.y); m_inputEvent.mouseMoved = newMousePos - m_inputEvent.mousePos; m_inputEvent.mousePos = newMousePos; if(m_onInputEvent) m_onInputEvent(m_inputEvent); break; } case MapNotify: m_visible = true; needsResizeUpdate = true; break; case UnmapNotify: m_visible = false; releaseAllKeys(); break; case FocusIn: m_focused = true; releaseAllKeys(); break; case FocusOut: m_focused = false; releaseAllKeys(); break; case Expose: // window needs redraw break; } } if(needsResizeUpdate && m_onResize) m_onResize(m_size); fireKeysPress(); }
static Eina_Bool _ecore_imf_context_xim_filter_event(Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event) { EINA_LOG_DBG("%s in", __FUNCTION__); #ifdef ENABLE_XIM Ecore_IMF_Context_Data *imf_context_data; XIC ic; Ecore_X_Display *dsp; Ecore_X_Window win; int val; char compose_buffer[256]; KeySym sym; char *compose = NULL; char *tmp = NULL; Eina_Bool result = EINA_FALSE; imf_context_data = ecore_imf_context_data_get(ctx); if (!imf_context_data) return EINA_FALSE; ic = imf_context_data->ic; if (!ic) ic = get_ic(ctx); if (type == ECORE_IMF_EVENT_KEY_DOWN) { XKeyPressedEvent xev; Ecore_IMF_Event_Key_Down *ev = (Ecore_IMF_Event_Key_Down *)event; EINA_LOG_DBG("ECORE_IMF_EVENT_KEY_DOWN"); dsp = ecore_x_display_get(); win = imf_context_data->win; xev.type = KeyPress; xev.serial = 0; /* hope it doesn't matter */ xev.send_event = 0; xev.display = dsp; xev.window = win; xev.root = ecore_x_window_root_get(win); xev.subwindow = win; xev.time = ev->timestamp; xev.x = xev.x_root = 0; xev.y = xev.y_root = 0; xev.state = 0; xev.state |= _ecore_x_event_reverse_modifiers(ev->modifiers); xev.state |= _ecore_x_event_reverse_locks(ev->locks); xev.keycode = _keycode_get(dsp, ev->keyname); xev.same_screen = True; if (ic) { Status mbstatus; #ifdef X_HAVE_UTF8_STRING val = Xutf8LookupString(ic, &xev, compose_buffer, sizeof(compose_buffer) - 1, &sym, &mbstatus); #else /* ifdef X_HAVE_UTF8_STRING */ val = XmbLookupString(ic, &xev, compose_buffer, sizeof(compose_buffer) - 1, &sym, &mbstatus); #endif /* ifdef X_HAVE_UTF8_STRING */ if (mbstatus == XBufferOverflow) { tmp = malloc(sizeof (char) * (val + 1)); if (!tmp) return EINA_FALSE; compose = tmp; #ifdef X_HAVE_UTF8_STRING val = Xutf8LookupString(ic, &xev, tmp, val, &sym, &mbstatus); #else /* ifdef X_HAVE_UTF8_STRING */ val = XmbLookupString(ic, &xev, tmp, val, &sym, &mbstatus); #endif /* ifdef X_HAVE_UTF8_STRING */ if (val > 0) { tmp[val] = '\0'; #ifndef X_HAVE_UTF8_STRING compose = eina_str_convert(nl_langinfo(CODESET), "UTF-8", tmp); free(tmp); tmp = compose; #endif /* ifndef X_HAVE_UTF8_STRING */ } else compose = NULL; } else if (val > 0) { compose_buffer[val] = '\0'; #ifdef X_HAVE_UTF8_STRING compose = strdup(compose_buffer); #else /* ifdef X_HAVE_UTF8_STRING */ compose = eina_str_convert(nl_langinfo(CODESET), "UTF-8", compose_buffer); #endif /* ifdef X_HAVE_UTF8_STRING */ } } else { compose = strdup(ev->compose); } if (compose) { Eina_Unicode *unicode; int len; unicode = eina_unicode_utf8_to_unicode(compose, &len); if (!unicode) abort(); if (unicode[0] >= 0x20 && unicode[0] != 0x7f) { ecore_imf_context_commit_event_add(ctx, compose); ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_COMMIT, compose); result = EINA_TRUE; } free(compose); free(unicode); } } return result; #else (void)ctx; (void)type; (void)event; return EINA_FALSE; #endif }
KeyID CXWindowsPrimaryScreen::mapKey(XKeyEvent* event) const { CDisplayLock display(m_screen); // convert to a keysym KeySym keysym; if (event->type == KeyPress && m_ic != NULL) { // do multibyte lookup. can only call XmbLookupString with a // key press event and a valid XIC so we checked those above. char scratch[32]; int n = sizeof(scratch) / sizeof(scratch[0]); char* buffer = scratch; int status; n = XmbLookupString(m_ic, event, buffer, n, &keysym, &status); if (status == XBufferOverflow) { // not enough space. grow buffer and try again. buffer = new char[n]; n = XmbLookupString(m_ic, event, buffer, n, &keysym, &status); delete[] buffer; } // see what we got. since we don't care about the string // we'll just look for a keysym. switch (status) { default: case XLookupNone: case XLookupChars: keysym = 0; break; case XLookupKeySym: case XLookupBoth: break; } } else { // plain old lookup char dummy[1]; XLookupString(event, dummy, 0, &keysym, NULL); } // convert key switch (keysym & 0xffffff00) { case 0x0000: // Latin-1 return static_cast<KeyID>(keysym); case 0xfe00: // ISO 9995 Function and Modifier Keys if (keysym == XK_ISO_Left_Tab) { return kKeyLeftTab; } return kKeyNone; case 0xff00: // MISCELLANY return static_cast<KeyID>(keysym - 0xff00 + 0xef00); case 0x1008ff00: // "Internet" keys return g_map1008FF[keysym & 0xff]; default: { // lookup character in table UInt32 key = CXWindowsUtil::mapKeySymToUCS4(keysym); if (key != 0x0000ffff) { return static_cast<KeyID>(key); } // unknown character return kKeyNone; } } }