diff options
Diffstat (limited to 'src/xembed.cc')
-rw-r--r-- | src/xembed.cc | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/src/xembed.cc b/src/xembed.cc new file mode 100644 index 00000000..04a4362a --- /dev/null +++ b/src/xembed.cc @@ -0,0 +1,165 @@ +/* + * File: xembed.cc + * + * Copyright (C) 2009 Jorge Arellano Cid <jcid@dillo.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + */ + +#include <string.h> +#include <ctype.h> + +#include <fltk/Window.h> +#include <fltk/run.h> +#include <fltk/events.h> +#include <fltk/x.h> + +#include "xembed.hh" + +#if USE_X11 + +typedef enum { + XEMBED_EMBEDDED_NOTIFY = 0, + XEMBED_WINDOW_ACTIVATE = 1, + XEMBED_WINDOW_DEACTIVATE = 2, + XEMBED_REQUEST_FOCUS = 3, + XEMBED_FOCUS_IN = 4, + XEMBED_FOCUS_OUT = 5, + XEMBED_FOCUS_NEXT = 6, + XEMBED_FOCUS_PREV = 7, + XEMBED_GRAB_KEY = 8, + XEMBED_UNGRAB_KEY = 9, + XEMBED_MODALITY_ON = 10, + XEMBED_MODALITY_OFF = 11, +} XEmbedMessageType; + +void +Xembed::setXembedInfo(unsigned long flags) +{ + unsigned long buffer[2]; + + Atom xembed_info_atom = XInternAtom (fltk::xdisplay, "_XEMBED_INFO", false); + + buffer[0] = 1; + buffer[1] = flags; + + XChangeProperty (fltk::xdisplay, + xid, + xembed_info_atom, xembed_info_atom, 32, + PropModeReplace, + (unsigned char *)buffer, 2); +} + +void +Xembed::sendXembedEvent(uint32_t message) { + XClientMessageEvent xclient; + + memset (&xclient, 0, sizeof (xclient)); + xclient.window = xid; + xclient.type = ClientMessage; + xclient.message_type = XInternAtom (fltk::xdisplay, "_XEMBED", false); + xclient.format = 32; + xclient.data.l[0] = fltk::event_time; + xclient.data.l[1] = message; + + XSendEvent(fltk::xdisplay, xid, False, NoEventMask, (XEvent *)&xclient); + XSync(fltk::xdisplay, False); +} + +int +Xembed::handle(int e) { + if (e == fltk::PUSH) + sendXembedEvent(XEMBED_REQUEST_FOCUS); + + return Window::handle(e); +} + +static int event_handler(int e, fltk::Window *w) { + Atom xembed_atom = XInternAtom (fltk::xdisplay, "_XEMBED", false); + + if (fltk::xevent.type == ClientMessage) { + if (fltk::xevent.xclient.message_type == xembed_atom) { + long message = fltk::xevent.xclient.data.l[1]; + + switch (message) { + case XEMBED_WINDOW_ACTIVATE: + // Force a ConfigureNotify message so fltk can get the new + // coordinates after a move of the embedder window. + w->resize(0, 0, w->w(), w->h()); + break; + case XEMBED_WINDOW_DEACTIVATE: + break; + default: + break; + } + } + } + + return 0; +} + +// TODO: Implement more XEMBED support; + +void Xembed::create() { + createInternal(xid); + setXembedInfo(1); + fltk::add_event_handler(event_handler); +} + +void Xembed::createInternal(uint32_t parent) { + fltk::Window *window = this; + Colormap colormap = fltk::xcolormap; + + XSetWindowAttributes attr; + attr.border_pixel = 0; + attr.colormap = colormap; + attr.bit_gravity = 0; // StaticGravity; + int mask = CWBorderPixel|CWColormap|CWEventMask|CWBitGravity; + + int W = window->w(); + if (W <= 0) W = 1; // X don't like zero... + int H = window->h(); + if (H <= 0) H = 1; // X don't like zero... + int X = window->x(); + int Y = window->y(); + + attr.event_mask = + ExposureMask | StructureNotifyMask + | KeyPressMask | KeyReleaseMask | KeymapStateMask | FocusChangeMask + | ButtonPressMask | ButtonReleaseMask + | EnterWindowMask | LeaveWindowMask + | PointerMotionMask; + + fltk::CreatedWindow::set_xid(window, + XCreateWindow(fltk::xdisplay, + parent, + X, Y, W, H, + 0, // borderwidth + fltk::xvisual->depth, + InputOutput, + fltk::xvisual->visual, + mask, &attr)); +} + +#else // USE_X11 + +void +Xembed::setXembedInfo(unsigned long flags) {}; + +void +Xembed::sendXembedEvent(uint32_t message) {}; + +int +Xembed::handle(int e) { + return Window::handle(e); +} + +void +Xembed::create() { + Window::create(); +} + +#endif |