Example #1
0
File: textbox.c Project: bjauy/xoat
// 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;
}
Example #2
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;
}
Example #3
0
File: terma.c Project: halhen/terma
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);
    }
}
Example #4
0
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));
}
Example #5
0
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;
}
Example #6
0
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") ;
}
Example #7
0
File: nenu.c Project: mytchel/nenu
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();
	}
}
Example #8
0
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;
	}

    }
Example #9
0
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);
}
Example #10
0
	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;
			}
		}
	}
Example #11
0
/* 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);
}
Example #12
0
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);
}
Example #13
0
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;
	}
}
Example #14
0
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;
    }
Example #15
0
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);

	
}
Example #16
0
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();
}
Example #17
0
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();
}
Example #18
0
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;
	}
	}
}