aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/uicmd.cc9
-rw-r--r--src/xembed.cc159
-rw-r--r--src/xembed.hh12
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