diff options
author | Johannes Hofmann <Johannes.Hofmann@gmx.de> | 2009-05-27 17:52:45 +0200 |
---|---|---|
committer | Johannes Hofmann <Johannes.Hofmann@gmx.de> | 2009-05-27 17:52:45 +0200 |
commit | 283524e074d09bd626a049fe9f8e7ea02d002dbc (patch) | |
tree | 708c8e6c01a56c4e2f405f5e3e375cf139d001c1 | |
parent | 77d8a7bef39cc0ec3d20dad6d877cc2d7c67ae41 (diff) |
more xembed work
* Create Xembed windows directly as child windows instead of
reparenting them to avoid races with reparenting WMs.
* Set _XEMBED_INFO property as required by XEMBED.
* Send XEMBED_REQUEST_FOCUS to get focus when user clicks
on the dillo window.
-rw-r--r-- | src/uicmd.cc | 9 | ||||
-rw-r--r-- | src/xembed.cc | 159 | ||||
-rw-r--r-- | src/xembed.hh | 12 |
3 files changed, 160 insertions, 20 deletions
diff --git a/src/uicmd.cc b/src/uicmd.cc index 22827d7a..e3465e92 100644 --- a/src/uicmd.cc +++ b/src/uicmd.cc @@ -393,7 +393,7 @@ BrowserWindow *a_UIcmd_browser_window_new(int ww, int wh, uint32_t xid, const vo { BrowserWindow *old_bw = (BrowserWindow*)vbw; BrowserWindow *new_bw = NULL; - Xembed *win; + Window *win; if (ww <= 0 || wh <= 0) { // Set default geometry from dillorc. @@ -401,7 +401,10 @@ BrowserWindow *a_UIcmd_browser_window_new(int ww, int wh, uint32_t xid, const vo wh = prefs.height; } - win = new Xembed(ww, wh); + if (xid) + win = new Xembed(xid, ww, wh); + else + win = new Window(ww, wh); win->shortcut(0); // Ignore Escape if (prefs.buffered_drawing != 2) @@ -421,8 +424,6 @@ BrowserWindow *a_UIcmd_browser_window_new(int ww, int wh, uint32_t xid, const vo DilloTabs->add(new_ui); DilloTabs->resizable(new_ui); DilloTabs->window()->resizable(new_ui); - if (xid) - win->embed(xid); DilloTabs->window()->show(); if (old_bw == NULL && prefs.xpos >= 0 && prefs.ypos >= 0) { diff --git a/src/xembed.cc b/src/xembed.cc index bd3be592..db2bdd4b 100644 --- a/src/xembed.cc +++ b/src/xembed.cc @@ -1,23 +1,154 @@ +#include <stdio.h> +#include <string.h> +#include <ctype.h> + #include <fltk/Window.h> #include <fltk/x11.h> #include <fltk/run.h> +#include <fltk/events.h> #include <fltk/x.h> #include "xembed.hh" -using namespace fltk; -// TODO; Implement proper XEMBED support; -// http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html -void Xembed::embed (uint32_t xid) { #if USE_X11 - fltk::Widget *r = resizable(); - // WORKAROUND: Avoid jumping windows with tiling window managers (e.g. dwm) - resize(1, 1); - resizable(NULL); - fltk::Window::show(); - fltk::Widget::hide(); - resizable(r); - fltk::flush(); - XReparentWindow (fltk::xdisplay, fltk::xid(this), xid, 0, 0); -#endif +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) { + + fprintf(stderr, "====> %s\n", XGetAtomName(fltk::xdisplay, fltk::xevent.xclient.message_type)); + + if (fltk::xevent.xclient.message_type == xembed_atom) { + long message = fltk::xevent.xclient.data.l[1]; + + switch (message) { + case XEMBED_WINDOW_ACTIVATE: + 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() { + create_internal(xid); + setXembedInfo(1); + fltk::add_event_handler(event_handler); +} + +void Xembed::create_internal(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 *x = 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 diff --git a/src/xembed.hh b/src/xembed.hh index 72fbf887..0bb5e790 100644 --- a/src/xembed.hh +++ b/src/xembed.hh @@ -6,9 +6,17 @@ #include "d_size.h" class Xembed : public fltk::Window { + uint32_t xid; + void create_internal(uint32_t parent); + void setXembedInfo(unsigned long flags); + void sendXembedEvent(uint32_t message); + public: - Xembed(int _w, int _h) : fltk::Window(_w, _h) {}; - void embed(uint32_t xid); + Xembed(uint32_t xid, int _w, int _h) : fltk::Window(_w, _h) { + this->xid = xid; + }; + void create(); + int handle(int event); }; #endif |