Monday, August 14, 2006

X level solution for VKB and Minimo interaction

These days I have been in touch with some low level (at least in my option) code. I've gone deeply down toward the "ugly" X level programming. Lots of Display, Window, RootWindow, Atom , blablabla ...

Anyways, it was good to have an idea about it , and mainly because through this I got the built-in maemo's virtual keyboard popping up/hiding when focus in/out event occur on minimo, without any gtk-based stuff.

Follows some lines of code that popup vbk manually for you:

(...)
// same as XOpenDisplay (0)?
Display *display = GDK_DISPLAY ();
if (!display) return ;

Atom hildonWindow;

hildonWindow = XInternAtom (display, "_HILDON_IM_WINDOW", true); // original code from Tim.

static char *XAtomNames[] = {"WINDOW"};
static Atom XAtoms[ARRAY_LENGTH(XAtomNames)];

// get needed atoms
XInternAtoms(display, XAtomNames, ARRAY_LENGTH(XAtomNames), False, XAtoms);

if (hildonWindow != None) {
Atom atomType;
int atomFormat;
int res;
unsigned long atomItems;
unsigned long atomBytes;
unsigned char* atomProperties;
::Window imWindow;

// this code fragment, I can get from widget/src/gtksuperwin/gtkmozarea.c:310
// gdk_property_get ?????
res=XGetWindowProperty(display,
RootWindow (display,XDefaultScreen(display)), hildonWindow, 0, 1, false, XAtoms[0],
&atomType, &atomFormat, &atomItems, &atomBytes, &atomProperties);

if (res!=Success || atomProperties==NULL) {
std::cout << "Cannot get IM window" <<>

imWindow=reinterpret_cast< ::Window*>(atomProperties)[0];
std::cout << "Acquire " <<>window << " " <<>

::XEvent event;

memset(&event,0,sizeof(event));
event.xclient.type=ClientMessage;
event.xclient.window=imWindow;
event.xclient.message_type=XInternAtom(display,"_HILDON_IM_ACTIVATE",False);
event.xclient.format=8;
// event.xclient.data.l[0]=RootWindow (display,XDefaultScreen(display));
// event.xclient.data.l[1]=RootWindow (display,XDefaultScreen(display));
event.xclient.data.l[2]=0x08;
event.xclient.data.l[3]=0x00400007;
event.xclient.data.l[4]=0;
if (XSendEvent(display,imWindow,False,NoEventMask,&event)==0) {
std::cerr << "Error while sending vk-1" <<>

event.xclient.message_type= XInternAtom(display,"_HILDON_IM_ACTIVATE",False);
event.xclient.data.l[2]=0x09;

if (XSendEvent(display,imWindow,False,NoEventMask,&event)==0) {
std::cerr << "Error while sending vk-7" <<>
} // end

(...)

ps: I got great support on this coming from Tim (nice German guy) who is also porting a non-gtk application to maemo 2.0. Most of the code above comes from his Illumination app.

--Antonio Gomes

4 comments:

Anonymous said...

great! I'm hoping there will be new builds soon. Great software/port!

Will said...

While your code will display the virtual keyboard, if you try clicking on any of the keys you'll see that none of the input is registered in the input area. This is because you didn't reference the correct xwindow in the l[0] data member of your client message. The virtual keyboard uses that member to send client messages containing values of each keypress on the keyboard.

Check out the maemo wiki article, even though its a little out of date with OS 2006.

Antonio said...

yeap,


these lines were wrong in my code !

// event.xclient.data.l[0]=RootWindow (display,XDefaultScreen(display));
// event.xclient.data.l[1]=RootWindow (display,XDefaultScreen(display));

fixed

Will said...

I don't suppose you'd be willing to update your blog post with the correct code would ya? I'm assuming its more than just uncommenting those lines. I'd be very interested in seeing how you found the appropriate window the virtual keyboard sends its _HILDON_IM_INSERT_UTF8 XClientMessageEvents to in order to get those key presses displayed on the active app.