Implementors of the XEmbed protocol should handle the other
party disappearing at any point. For this reason X errors
must be trapped when performing any operation with a window
not created by the application. This is done by using
XSetErrorHandler()
.
A sample implementation of trapping errors in C looks like:
#include <X11/Xlib.h> static int trapped_error_code = 0; static int (*old_error_handler) (Display *, XErrorEvent *); static int error_handler(Display *display, XErrorEvent *error) { trapped_error_code = error->error_code; return 0; } void trap_errors(void) { trapped_error_code = 0; old_error_handler = XSetErrorHandler(error_handler); } int untrap_errors(void) { XSetErrorHandler(old_error_handler); return trapped_error_code; }
An XEmbed embedder has to forward key-press and key-release events to its respective client.
Key events are forwarded by changing the event's window field
to the window handle of the client and sending the modified
message via XSendEvent()
to the embedder,
with no event mask and propagation turned off.
Note: XEmbed requires toolkits to handle key-events that come
from a SendEvent request. That means, if somebody can access
your X-Server, it's possible to fake keyboard input. Given
that most toolkits accept sent key events today anyway and the
X Server is typically protected through magic cookie
authorization, this is not considered to be an
issue. Applications with higher security requirements may
choose not to use embedded components, though, and to filter
out any events coming from XSendEvent()
.
Given that Window client is the client's window handle, here is a piece of code of an imaginary event-loop in C that does the forwarding.
#include <X11/Xlib.h> void handle_event( Display* dpy, /* display */ XEvent* ev /* event */ ){ if ( ev->type == KeyPress || ev->type == KeyRelease ) { ev->xkey.window = client; trap_errors(); XSendEvent( dpy, client, False, NoEventMask, ev ); XSync( dpy, False ); if (untrap_errors()) { /* Handle failure */ } return; } ... /* normal event handling */ }
Given that Time x_time contains the timestamp from the event currently being processed. (CurrentTime is generally the best choice if no event is being processed), here is a valid implementation in C of sending an XEMBED message:
#include <X11/Xlib.h> void send_xembed_message( Display* dpy, /* display */ Window w, /* receiver */ long message, /* message opcode */ long detail /* message detail */ long data1 /* message data 1 */ long data2 /* message data 2 */ ){ XEvent ev; memset(&ev, 0, sizeof(ev)); ev.xclient.type = ClientMessage; ev.xclient.window = w; ev.xclient.message_type = XInternAtom( dpy, "_XEMBED", False ); ev.xclient.format = 32; ev.xclient.data.l[0] = x_time; ev.xclient.data.l[1] = message; ev.xclient.data.l[2] = detail; ev.xclient.data.l[3] = data1; ev.xclient.data.l[4] = data2; trap_errors(); XSendEvent(dpy, w, False, NoEventMask, &ev); XSync(dpy, False); if (untrap_errors()) { /* Handle failure */ } }