changeset 1137:f10904ac58b4

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.
author Johannes Hofmann <Johannes.Hofmann@gmx.de>
date Wed, 27 May 2009 17:52:45 +0200
parents 6707fde200f7
children 227999b86d9b
files src/uicmd.cc src/xembed.cc src/xembed.hh
diffstat 3 files changed, 160 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/src/uicmd.cc	Wed May 27 17:48:57 2009 +0200
+++ b/src/uicmd.cc	Wed May 27 17:52:45 2009 +0200
@@ -393,7 +393,7 @@
 {
    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 @@
       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 @@
    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) {
--- a/src/xembed.cc	Wed May 27 17:48:57 2009 +0200
+++ b/src/xembed.cc	Wed May 27 17:52:45 2009 +0200
@@ -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);
+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
-}
--- a/src/xembed.hh	Wed May 27 17:48:57 2009 +0200
+++ b/src/xembed.hh	Wed May 27 17:52:45 2009 +0200
@@ -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