[rkward-cvs] SF.net SVN: rkward: [935] trunk/rkward

tfry at users.sourceforge.net tfry at users.sourceforge.net
Sat Nov 25 20:09:57 UTC 2006


Revision: 935
          http://svn.sourceforge.net/rkward/?rev=935&view=rev
Author:   tfry
Date:     2006-11-25 12:09:57 -0800 (Sat, 25 Nov 2006)

Log Message:
-----------
window catching is working in principle, now (but everything's still messy and bogus)

Modified Paths:
--------------
    trunk/rkward/TODO
    trunk/rkward/rkward/rbackend/rembedinternal.cpp
    trunk/rkward/rkward/rbackend/rembedinternal.h
    trunk/rkward/rkward/rbackend/rkwindowcatcher.cpp
    trunk/rkward/rkward/rbackend/rkwindowcatcher.h
    trunk/rkward/rkward/rbackend/rthread.cpp
    trunk/rkward/rkward/rkward.cpp
    trunk/rkward/rkward/windows/Makefile.am

Added Paths:
-----------
    trunk/rkward/rkward/windows/qxembedcopy.cpp
    trunk/rkward/rkward/windows/qxembedcopy.h

Modified: trunk/rkward/TODO
===================================================================
--- trunk/rkward/TODO	2006-11-25 20:08:29 UTC (rev 934)
+++ trunk/rkward/TODO	2006-11-25 20:09:57 UTC (rev 935)
@@ -26,9 +26,9 @@
 UI-stuff
 	- Access to dev.copy (), dev.print (), and a function to copy gaphics to rkward output
 		- probably in Windows-menu for now
+		- also allow scroll-bar mode
 	- Output window should gain some sort of auto-update functionality:
 		- After user commands, should check, whether the output file was modified. If so, reload
-	- Script editor should not open the same file multiple times, rather raise the window, if opening an already open URL
 	- Option to save workplace per session instead of per workspace
 	"First-run wizard"
 		- pre-install R packages

Modified: trunk/rkward/rkward/rbackend/rembedinternal.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rembedinternal.cpp	2006-11-25 20:08:29 UTC (rev 934)
+++ trunk/rkward/rkward/rbackend/rembedinternal.cpp	2006-11-25 20:09:57 UTC (rev 935)
@@ -224,6 +224,7 @@
 // ############## R Standard callback overrides END ####################
 
 char *REmbedInternal::na_char_internal = new char;
+bool REmbedInternal::x11events_disabled = false;
 
 REmbedInternal::REmbedInternal () {
 }
@@ -288,6 +289,8 @@
 void REmbedInternal::processX11Events () {
 /* what we do here is walk the list of objects, that have told R, they're listening for events.
 We figure out which ones look for X11-events and tell those to do their stuff (regardless of whether events actually occurred) */
+	if (x11events_disabled) return;
+
 	extern InputHandler *R_InputHandlers;
 	InputHandler *handler = R_InputHandlers;
 	while (handler) {
@@ -297,7 +300,7 @@
 		handler = handler->next;
 	}
 
-/* I don't really understand what I'm doing here, but apparently this is necessary for Tcl-Tk windows to function properly. */
+	/* I don't really understand what I'm doing here, but apparently this is necessary for Tcl-Tk windows to function properly. */
 	R_PolledEvents ();
 	
 /* Maybe we also need to also call R_timeout_handler once in a while? Obviously this is extremely crude code! 

Modified: trunk/rkward/rkward/rbackend/rembedinternal.h
===================================================================
--- trunk/rkward/rkward/rbackend/rembedinternal.h	2006-11-25 20:08:29 UTC (rev 934)
+++ trunk/rkward/rkward/rbackend/rembedinternal.h	2006-11-25 20:09:57 UTC (rev 935)
@@ -154,6 +154,7 @@
 /** only one instance of this class may be around. This pointer keeps the reference to it, for interfacing to from C to C++ */
 	static REmbedInternal *this_pointer;
 	static char *na_char_internal;
+	static bool x11events_disabled;
 
 /** Flags used to classify output. */
 //	static bool output_is_warning;

Modified: trunk/rkward/rkward/rbackend/rkwindowcatcher.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rkwindowcatcher.cpp	2006-11-25 20:08:29 UTC (rev 934)
+++ trunk/rkward/rkward/rbackend/rkwindowcatcher.cpp	2006-11-25 20:09:57 UTC (rev 935)
@@ -20,16 +20,29 @@
 #ifndef DISABLE_RKWINDOWCATCHER
 
 #include <kapplication.h>
-#include <qxembed.h>
+#include <qlayout.h>
+#include <qvbox.h>
 
 #include <X11/X.h>
 #include <X11/Xlib.h>
 
+#include "../windows/qxembedcopy.h"
 #include "../debug.h"
 
+static int get_parent(WId winid, Window *out_parent)
+{
+    Window root, *children=0;
+    unsigned int nchildren;
+    int st = XQueryTree(qt_xdisplay(), winid, &root, out_parent, &children, &nchildren);
+    if (st && children) 
+        XFree(children);
+    return st;
+}
+
 // function below is a slightly adapted copy from http://lists.trolltech.com/qt-interest/1999-10/msg00224.html
 // this could be tweaked a little more, since for instance we know we're only looking for toplevel windows
-Window Window_With_Name (Display *dp, Window top, const char *name) {
+Window Window_With_Name (Display *dp, Window top, const char *name, int level=10) {
+    if (level < 0) return (0);
     Window *children, dummy;
     unsigned int nchildren;
     int i;
@@ -37,14 +50,21 @@
     char *window_name;
 
     if (XFetchName(dp, top, &window_name)) {
-		if (QString (window_name).startsWith (name)) return(top);
+		if (QString (window_name).startsWith (name)) {
+			Window parent=0;
+			if (get_parent (top, &parent)) {
+				XFetchName (dp, parent, &window_name);
+				qDebug ("parent %x, name: %s", parent, window_name);
+			}
+			return (top);
+		}
 	}
 
     if (!XQueryTree(dp, top, &dummy, &dummy, &children, &nchildren))
         return(0);
 
     for (i=0; i<nchildren; i++) {
-        w = Window_With_Name(dp, children[i], name);
+        w = Window_With_Name(dp, children[i], name, level-1);
         if (w)
             break;
     }
@@ -59,31 +79,29 @@
 RKWindowCatcher::~RKWindowCatcher () {
 }
 
+void RKWindowCatcher::windowLost () {
+	qDebug ("lost");
+	deleteLater ();
+}
+
 void RKWindowCatcher::catchWindow (const QString &title_start, int corresponding_device_number) {
-	Window w = Window_With_Name (qt_xdisplay (), qApp->desktop ()->winId (), title_start.latin1 ());
-	qDebug ("Window id is: %x", w);
+	Window w = Window_With_Name (qt_xdisplay (), DefaultRootWindow (qt_xdisplay()), title_start.latin1 ());
+	qDebug ("Window id is: %x (root: %x)", w, DefaultRootWindow (qt_xdisplay()));
 	if (w) {
-		QXEmbed *capture = new QXEmbed (); // (0, 0, Qt::WDestructiveClose);
-		capture->setProtocol (QXEmbed::XPLAIN);
-// (trying to) work around buggy R X11 event handling (see http://www.ens.gu.edu.au/robertk/R/devel/01a/0077.html)
-/*		extern Display *Rf_getX11Display (); // now, how to link this?
-
-		qDebug ("qt disp: %x r disp: %x", qt_xdisplay (), Rf_getX11Display ()); */
-		
-/*		Atom *old_prots;
-		int num_old_prots;
-		if (!XGetWMProtocols (Rf_getX11Display (), w, &old_prots, &num_old_prots)) qDebug ("fail 1");
-		if (!XSetWMProtocols (Rf_getX11Display (), w, 0, 0)) qDebug ("fail2");
-//		capture->embed (w);
-		XEvent dummy;
-		while (XPending (Rf_getX11Display ())) {
-			XNextEvent (Rf_getX11Display (), &dummy);
-			qDebug ("event for window: %x", dummy.xany.window);
-		}
-		XSetWMProtocols (Rf_getX11Display (), w, old_prots, num_old_prots);
-		capture->show (); */
+		QWidget *test1 = new QWidget (0);
+		test1->setCaption ("1");
+		QVBoxLayout *layout = new QVBoxLayout (test1);
+		QXEmbedCopy *capture = new QXEmbedCopy (test1, 0, Qt::WDestructiveClose);
+		connect (capture, SIGNAL (embeddedWindowDestroyed ()), this, SLOT (windowLost ()));
+		capture->setProtocol (QXEmbedCopy::XPLAIN);
 		capture->embed (w);
 		capture->show ();
+		layout->addWidget (capture);
+		test1->show ();
+		QVBox *test2 = new QVBox (0);
+		test2->setCaption ("2");
+		test1->reparent (test2, QPoint (0, 0), true);
+		test2->show ();
 	}
 }
 

Modified: trunk/rkward/rkward/rbackend/rkwindowcatcher.h
===================================================================
--- trunk/rkward/rkward/rbackend/rkwindowcatcher.h	2006-11-25 20:08:29 UTC (rev 934)
+++ trunk/rkward/rkward/rbackend/rkwindowcatcher.h	2006-11-25 20:09:57 UTC (rev 935)
@@ -18,7 +18,7 @@
 #ifndef RKWINDOWCATCHER_H
 #define RKWINDOWCATCHER_H
 
-#define DISABLE_RKWINDOWCATCHER
+//#define DISABLE_RKWINDOWCATCHER
 #ifndef DISABLE_RKWINDOWCATCHER
 
 #include <qwidget.h>
@@ -69,6 +69,8 @@
 /*	void start (int prev_cur_device);
 	void stop (int new_cur_device); */
 	void catchWindow (const QString &title_start, int corresponding_device_number);
+public slots:
+	void windowLost ();
 private:
 //	int last_cur_device;
 };

Modified: trunk/rkward/rkward/rbackend/rthread.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rthread.cpp	2006-11-25 20:08:29 UTC (rev 934)
+++ trunk/rkward/rkward/rbackend/rthread.cpp	2006-11-25 20:09:57 UTC (rev 935)
@@ -323,6 +323,10 @@
 			return;
 		}
 	}
+	if (call[0] == "catchWindow") {
+		qDebug ("here");
+		x11events_disabled = true;
+	}
 
 	RCommand *prev_command = current_command;
 	REvalRequest *request = new REvalRequest;
@@ -363,6 +367,7 @@
 		msleep (10);
 	}
 
+	x11events_disabled = false;
 	delete reply_stack;
 }
 

Modified: trunk/rkward/rkward/rkward.cpp
===================================================================
--- trunk/rkward/rkward/rkward.cpp	2006-11-25 20:08:29 UTC (rev 934)
+++ trunk/rkward/rkward/rkward.cpp	2006-11-25 20:09:57 UTC (rev 935)
@@ -78,6 +78,7 @@
 #include "agents/showedittextfileagent.h"	// TODO: see below: needed purely for linking!
 #include "dialogs/rkreadlinedialog.h"	// TODO: see below: needed purely for linking!
 #include "windows/detachedwindowcontainer.h"	// TODO: see below: needed purely for linking!
+#include "windows/qxembedcopy.h"	// TODO: see below: needed purely for linking!
 #include "dataeditor/rkeditordataframepart.h"	// TODO: see below: needed purely for linking!
 
 // This nevers gets called. It's needed to trick ld into linking correctly. Nothing else.
@@ -87,6 +88,7 @@
 	new RKEditorDataFramePart (0);
 	DetachedWindowContainer (0);
 	new RKWorkplaceView (0);
+	new QXEmbedCopy (0);
 }
 
 //static

Modified: trunk/rkward/rkward/windows/Makefile.am
===================================================================
--- trunk/rkward/rkward/windows/Makefile.am	2006-11-25 20:08:29 UTC (rev 934)
+++ trunk/rkward/rkward/windows/Makefile.am	2006-11-25 20:09:57 UTC (rev 935)
@@ -3,9 +3,9 @@
 noinst_LIBRARIES =  libwindows.a
 noinst_HEADERS = rkcommandeditorwindow.h rkcommandeditorwindowpart.h \
 	rkhtmlwindow.h rcontrolwindow.h detachedwindowcontainer.h rkmdiwindow.h \
-	rkworkplaceview.h  rkworkplace.h
+	rkworkplaceview.h rkworkplace.h qxembedcopy.h
 libwindows_a_SOURCES = rkcommandeditorwindow.cpp rkcommandeditorwindowpart.cpp \
 	rkhtmlwindow.cpp rcontrolwindow.cpp detachedwindowcontainer.cpp rkmdiwindow.cpp \
-	rkworkplaceview.cpp rkworkplace.cpp
+	rkworkplaceview.cpp rkworkplace.cpp qxembedcopy.cpp
 rcdir = $(kde_datadir)/rkward
 rc_DATA = rkcommandeditorwindowpart.rc rkoutputwindow.rc rkhelpwindow.rc detachedwindowcontainer.rc

Added: trunk/rkward/rkward/windows/qxembedcopy.cpp
===================================================================
--- trunk/rkward/rkward/windows/qxembedcopy.cpp	                        (rev 0)
+++ trunk/rkward/rkward/windows/qxembedcopy.cpp	2006-11-25 20:09:57 UTC (rev 935)
@@ -0,0 +1,1372 @@
+/****************************************************************************
+    Implementation of QXEmbedCopy class
+
+    Copyright (C) 1999-2002 Trolltech AS
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*****************************************************************************/
+
+
+// L-000: About comments marked with Lxxxx.
+// 
+//    These comments represent an attempt to provide a more adequate
+//    documentation to KDE developpers willing to modify QXEmbedCopy.  Keep in
+//    mind that these comments were written long after most of the code.
+//    Please improve them if you spot something wrong or missing 
+//    (Leon Bottou, 26-10-2003).
+//
+//    Relevant documents:
+//    - QXEmbedCopy developper documentation
+//        (see comments in qxembed.h)
+//    - Xlib Reference Manual  
+//        (sections about focus, reparenting, window management)
+//    - ICCCM Manual
+//        (window management)
+//    - XEMBED specification 
+//        (http://www.freedesktop.org/Standards/xembed-spec)
+//    - XPLAIN and XEMBED.
+//        <http://lists.kde.org/?w=2&r=1&s=qxembed+variants&q=t>
+//    - Accumulated community knowledge.
+//        <http://lists.kde.org/?w=2&r=1&s=qxembed&q=t>
+//        <http://lists.kde.org/?l=kde-devel&w=2&r=1&s=qxembed&q=b>
+//        <http://lists.kde.org/?l=kfm-devel&w=2&r=1&s=qxembed&q=b>
+// 
+
+
+#include <qapplication.h>
+#include <qptrlist.h>
+#include <qptrdict.h>
+#include <qguardedptr.h>
+#include <qwhatsthis.h>
+#include <qfocusdata.h>
+
+// L0001: QXEmbedCopy works only under X windows.
+#ifdef Q_WS_X11
+
+# include <X11/X.h>
+# include <X11/Xlib.h>
+# include <X11/Xutil.h>
+# include <X11/Xatom.h>
+# define XK_MISCELLANY
+# define XK_LATIN1
+# include <X11/keysymdef.h>
+# include <kdebug.h>
+# include <kxerrorhandler.h>
+
+// L0002: Is file config.h KDE specific?
+# include <config.h>
+# ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+#  ifdef HAVE_USLEEP
+#   define USLEEP(x) usleep(x)
+#  else
+#   define USLEEP(x) sleep(0)
+#  endif
+# else
+#  define USLEEP(x) sleep(0)
+# endif
+
+# include "qxembedcopy.h"
+
+// L0003: This keysym is used for focus navigation.
+# ifndef XK_ISO_Left_Tab
+#  define XK_ISO_Left_Tab 0xFE20
+# endif
+
+// L0004: Conflicts between X11 and Qt definitions.
+const int XFocusOut = FocusOut;
+const int XFocusIn = FocusIn;
+const int XKeyPress = KeyPress;
+const int XKeyRelease = KeyRelease;
+# undef KeyRelease
+# undef KeyPress
+# undef FocusOut
+# undef FocusIn
+
+// L0005: Variables defined in qapplication_x11.cpp
+extern Atom qt_wm_protocols;
+extern Atom qt_wm_delete_window;
+extern Atom qt_wm_take_focus;
+extern Atom qt_wm_state;
+extern Time qt_x_time;
+
+// L0006: X11 atoms private to QXEmbedCopy
+static Atom xembed = 0;
+static Atom context_help = 0;
+
+// L0007: Xembed message codes (see XEmbed spec)
+#define XEMBED_EMBEDDED_NOTIFY          0
+#define XEMBED_WINDOW_ACTIVATE          1
+#define XEMBED_WINDOW_DEACTIVATE        2
+#define XEMBED_REQUEST_FOCUS            3
+#define XEMBED_FOCUS_IN                 4
+#define XEMBED_FOCUS_OUT                5
+#define XEMBED_FOCUS_NEXT               6
+#define XEMBED_FOCUS_PREV               7
+
+// L0008: Xembed message details (see XEmbed spec)
+// -- XEMBED_FOCUS_IN:
+#define XEMBED_FOCUS_CURRENT            0
+#define XEMBED_FOCUS_FIRST              1
+#define XEMBED_FOCUS_LAST               2
+
+
+// L0100: Private data held by the QXEmbedCopy object.
+//        This belongs to the embedder side.
+class QXEmbedCopyData
+{
+public:
+    QXEmbedCopyData(){ 
+        autoDelete = true;
+        xplain = false;
+        xgrab = false;
+        mapAfterRelease = false;
+        lastPos = QPoint(0,0);
+    }
+    ~QXEmbedCopyData(){};
+
+    bool autoDelete;      // L0101: See L2600
+    bool xplain;          // L0102: See L1100
+    bool xgrab;           // L0103: See L2800
+    bool mapAfterRelease;
+    QWidget* focusProxy;  // L0104: See XEmbed spec
+    QPoint lastPos;       // L0105: See L1390
+};
+
+namespace
+{
+    // L0200: This application wide event filter handles focus
+    //        issues in the embedded client.
+    class QXEmbedCopyAppFilter : public QObject
+    {
+    public:
+        QXEmbedCopyAppFilter()  { qApp->installEventFilter( this ); } 
+        ~QXEmbedCopyAppFilter() { };
+        bool eventFilter( QObject *, QEvent * );
+    };
+}
+
+// L0201: See L0200, L0740
+static QXEmbedCopyAppFilter* filter = 0;
+// L0202: See L0610, L0730
+static QPtrDict<QGuardedPtr<QWidget> > *focusMap = 0;
+// L0203: See L0660, L1400, L1450
+static XKeyEvent last_key_event;
+
+// L0300: This class gives access protected members of class QWidget.
+//        Function focusData() is useful to reimplement tab focus management
+//        (L0620) Function topData() returns a structure QTLWExtra containing
+//        information unique to toplevel windows.  This structure contains two
+//        members for the sole use of QXEmbedCopy. Flag `embedded' indicates whether
+//        the toplevel window is embedded using the XEMBED protocol (L0680). 
+//        Handle `parentWinId' then records the id of the embedding window.
+
+class QPublicWidget : public QWidget
+{
+public:
+    QTLWExtra* topData() { return QWidget::topData(); }
+    QFocusData *focusData(){ return QWidget::focusData(); }
+    bool focusNextPrev(bool b) { return focusNextPrevChild(b); }
+};
+
+// L0400: This sets a very low level filter for X11 messages.
+//        See qapplication_x11.cpp
+typedef int (*QX11EventFilter) (XEvent*);
+extern QX11EventFilter qt_set_x11_event_filter (QX11EventFilter filter);
+static QX11EventFilter oldFilter = 0;
+
+
+// L0500: Helper to send XEmbed messages.
+static void sendXEmbedMessage( WId window, long message, long detail = 0,
+                               long data1 = 0, long data2 = 0)
+{
+    if (!window) return;
+    XEvent ev;
+    memset(&ev, 0, sizeof(ev));
+    ev.xclient.type = ClientMessage;
+    ev.xclient.window = window;
+    ev.xclient.message_type = xembed;
+    ev.xclient.format = 32;
+    ev.xclient.data.l[0] = qt_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;
+    XSendEvent(qt_xdisplay(), window, false, NoEventMask, &ev);
+}
+
+// L0501: Helper to send ICCCM Client messages. 
+//        See X11 ICCCM Specification.
+static void sendClientMessage(Window window, Atom a, long x)
+{
+  if (!window) return;
+  XEvent ev;
+  memset(&ev, 0, sizeof(ev));
+  ev.xclient.type = ClientMessage;
+  ev.xclient.window = window;
+  ev.xclient.message_type = a;
+  ev.xclient.format = 32;
+  ev.xclient.data.l[0] = x;
+  ev.xclient.data.l[1] = qt_x_time;
+  XSendEvent(qt_xdisplay(), window, false, NoEventMask, &ev);
+}
+
+// L0502: Helper to send fake X11 focus messages.
+//        See X11 Reference Manual and Window Management stuff.
+static void sendFocusMessage(Window window, int type, int mode, int detail)
+{
+  if (!window) return;
+  XEvent ev;
+  memset(&ev, 0, sizeof(ev));
+  ev.xfocus.type = type;
+  ev.xfocus.window = window;
+  ev.xfocus.mode = mode;
+  ev.xfocus.detail = detail;
+  XSendEvent(qt_xdisplay(), window, false, FocusChangeMask, &ev);
+}
+
+
+// ------------------------------------------------------------
+// L0600: MOST OF WHAT FOLLOWS CONCERNS THE CLIENT SIDE.
+//        The following code mostly executes inside a Qt application swallowed
+//        by QXEmbedCopy widget.  It mostly consists of event filters that fight
+//        the normal Qt mechanisms in order to implement the XEMBED protocol.
+//        All this would be a lot simpler if it was implemented by Qt itself.
+
+
+
+// L0610: This event filter receives all Qt events.  Its main purpose is to
+//        capture the Qt focus events in the embedded client in order to
+//        implement the XEMBED protocol. 
+//
+//        Let's start with a few reminders:
+//
+//        - X11 only has the concept of the "X11 focus window".  This window
+//          basically receives all key events.  The ICCCM conventions define
+//          how the window manager and the applications must cooperate to
+//          choose the X11 focus window.
+//
+//        - Most toolkits, including Qt, maintain the concepts of 'active
+//          widget' and 'Qt focus widget'.  A toplevel widget is active when
+//          the X11 focus is set to one of its children.  By extension a
+//          widget is active when its toplevel widget is active.  There is one
+//          Qt focus widget for each toplevel widget.  When the toplevel
+//          widget is active, all key events are sent to the Qt focus widget,
+//          regardless of which descendant of the toplevel window has the X11
+//          focus.  Widgets can adjust their appearance according to both 
+//          their activation and focus states.  The Qt FocusIn and FocusOut 
+//          events indicate when a widget simultaneously is active and has
+//          the Qt focus. 
+//
+//        The XEMBED protocol defines ways to communicate abouth both
+//        activation and focus. The embedded client is active as soon as the
+//        embedding window is active (L0676, L0677).  A widget in the embedded
+//        client receives key events when (1) it has the Qt focus in the
+//        embedded application, and (2) the QXEmbedCopy widget in the embedding
+//        application is active and has the Qt focus.  The Qt library in the
+//        embedded application is unaware of the focus status of the QXEmbedCopy
+//        widget.  We must make sure it does the right thing regarding the
+//        sending of focus events and the visual appearance of the focussed 
+//        widgets.  When the QXEmbedCopy widget looses the Qt focus, we clear the 
+//        focus in the embedded client (L1570, L0688). Conversely, when
+//        the QXEmbedCopy widget gains the Qt focus, we restore the Qt focus 
+//        window in the embedded client (L1530, L0680, L0683). 
+//        Variable focusMap is used to remember which was the Qt focus
+//        widget in the embedded application.  All this would be a lot
+//        simpler if it was implemented inside Qt...
+//
+//        The XPLAIN protocol is much less refined in this respect.
+//        The activation status of the embedded client simply reflect
+//        the focus status of the QXEmbedCopy widget. This is achieved
+//        by sending fake X11 focus message to the client (L1521, L1561).
+//        A passive button grab (L2800) intercepts mouse activity in the
+//        embedded client and sets the Qt focus to the QXEmbedCopy widget
+//        when this happens (L2060).  This can be achieved without
+//        cooperation from the client.
+
+bool QXEmbedCopyAppFilter::eventFilter( QObject *o, QEvent * e)
+{
+    static bool obeyFocus = false;
+    switch ( e->type() ) {
+    case QEvent::MouseButtonPress:
+        // L0612: This will become clear with L0614
+        if ( !((QWidget*)o)->isActiveWindow() )
+            obeyFocus = true;
+        break;
+    case QEvent::FocusIn:
+        // L0613: FocusIn events either occur because the widget already was
+        //        active and has just been given the Qt focus (L0614) or
+        //        because the widget already had the Qt focus and just became
+        //        active (L0615).
+        if ( qApp->focusWidget() == o &&
+             ((QPublicWidget*)qApp->focusWidget()->topLevelWidget())->topData()->embedded ) {
+            QFocusEvent* fe = (QFocusEvent*) e;
+            if ( obeyFocus || fe->reason() == QFocusEvent::Mouse ||
+                 fe->reason() == QFocusEvent::Shortcut ) {
+                // L0614: A widget in the embedded client was just given the Qt focus.
+                //        Variable `obeyFocus' suggests that this is the result of mouse
+                //        activity in the client.  The XEMBED_REQUEST_FOCUS message causes
+                //        the embedding widget to take the Qt focus (L2085).
+                WId window = ((QPublicWidget*)qApp->focusWidget()->topLevelWidget())->topData()->parentWinId;
+                focusMap->remove( qApp->focusWidget()->topLevelWidget() );
+                sendXEmbedMessage( window, XEMBED_REQUEST_FOCUS );
+            } else if ( fe->reason() == QFocusEvent::ActiveWindow ) {
+                // L0615: Both the embedder and the embedded client became active.
+                //        But we do not know whether the QXEmbedCopy widget has the Qt focus.
+                //        So we clear the Qt focus for now.  If indeed the QXEmbedCopy widget
+                //        has the focus, it will receive a FocusIn message (L1530) and
+                //        tell us to restore the focus (L0680, L0683).
+                focusMap->remove( qApp->focusWidget()->topLevelWidget() );
+                focusMap->insert( qApp->focusWidget()->topLevelWidget(),
+                                  new QGuardedPtr<QWidget>(qApp->focusWidget()->topLevelWidget()->focusWidget() ) );
+                // L0616: qApp->focusWidget() might belong to a modal dialog and not be 
+                //        equal to qApp->focusWidget()->topLevelWidget()->focusWidget() !
+                qApp->focusWidget()->clearFocus();
+                // L0617: ??? [why not {obeyFocus=false; return true;} here?]
+            }
+            obeyFocus = false;
+        }
+        break;
+    case QEvent::KeyPress: 
+        if (qApp->focusWidget() == o &&
+            ((QPublicWidget*)qApp->focusWidget()->topLevelWidget())->topData()->embedded ) {
+            // L0620: The following code replaces the Qt code that 
+            //        handles focus focus changes with the tab key. See the
+            //        XEMBED specification for details.  The keypress event
+            //        arrives here after an interesting itinerary. It is first
+            //        saved in the embedding application (L0660). After being
+            //        rejected for tab navigation in the embedding application
+            //        (L1901), it gets forwarded to the embedded client
+            //        (L1400) and arrives here.  Depending on the status of
+            //        the tab chain in the embedded client, focus navigation
+            //        messages are sent back to the embedding application
+            //        (L0653, L0654) which then performs tab navigation
+            //        (L2081).
+            QKeyEvent *k = (QKeyEvent *)e;
+            QWidget *w = qApp->focusWidget();
+            // L0621: The following tests are copied from QWidget::event().
+            bool res = false;
+            bool tabForward = true;
+            if ( !(k->state() & ControlButton || k->state() & AltButton) ) {
+                if ( k->key() == Key_Backtab || (k->key() == Key_Tab && (k->state() & ShiftButton)) ) {
+                    QFocusEvent::setReason( QFocusEvent::Backtab );
+                    res = ((QPublicWidget*)w)->focusNextPrev( tabForward = false );
+                    QFocusEvent::resetReason();
+                } else if ( k->key() == Key_Tab ) {
+                    QFocusEvent::setReason( QFocusEvent::Tab );
+                    res = ((QPublicWidget*)w)->focusNextPrev( tabForward = true );
+                    QFocusEvent::resetReason();
+                }
+            }
+            if (res) {
+                // L0625: We changed the focus because of tab/backtab key
+                //        Now check whether we have been looping around.
+                QFocusData *fd = ((QPublicWidget*)w)->focusData();
+                WId window = ((QPublicWidget*)w->topLevelWidget())->topData()->parentWinId;
+                QWidget *cw = 0;
+                QWidget *fw = fd->home();
+                if (tabForward && window) {
+                    while (cw != w && cw != fw && cw != w->topLevelWidget()) 
+                        cw = fd->prev();
+                    if (cw != w)
+                        sendXEmbedMessage( window, XEMBED_FOCUS_NEXT );
+                } else if (window) {
+                    while (cw != w && cw != fw && cw != w->topLevelWidget()) 
+                        cw = fd->next();
+                    if (cw != w)
+                        sendXEmbedMessage( window, XEMBED_FOCUS_PREV );
+                }
+                // L0628: Qt should no longer process this event.
+                return true;
+            }
+        }
+        break;
+    default:
+        break;
+    }
+    // L0640: Application gets to see the events anyway.
+    return false;
+}
+
+// L0650: This filter receives all XEvents in both the client and the embedder.  
+//        Most of it involves the embedded client (except L0660, L0671).
+static int qxembed_x11_event_filter( XEvent* e)
+{
+    switch ( e->type ) {
+    case XKeyPress:
+    case XKeyRelease: {
+        // L0660: This is for the embedding side (L1450).
+        last_key_event = e->xkey;
+        break;
+    }
+    case ClientMessage:
+        if ( e->xclient.message_type == xembed ) {
+            // L0670: This is where the XEmbed messages are 
+            //        processed on the client side.
+            Time msgtime = (Time) e->xclient.data.l[0];
+            long message = e->xclient.data.l[1];
+            long detail = e->xclient.data.l[2];
+            // L0671: Keep Qt message time up to date
+            if ( msgtime > qt_x_time )
+                qt_x_time = msgtime;
+            QWidget* w = QWidget::find( e->xclient.window );
+            if ( !w )
+                break;
+            switch ( message) {
+            case XEMBED_EMBEDDED_NOTIFY: {
+                // L0675: We just have been embedded into a XEMBED aware widget.
+                QTLWExtra *extra = ((QPublicWidget*)w->topLevelWidget())->topData();
+                extra->embedded = 1;
+                extra->parentWinId = e->xclient.data.l[3];
+                w->topLevelWidget()->show();
+                break;
+            }
+            case XEMBED_WINDOW_ACTIVATE: {
+                // L0676: Embedding window becomes active. Send a fake XFocusIn
+                //        to convince Qt that we are active as well.  Qt will send
+                //        us a focus notification (L0615) that we will intercept to
+                //        ensure that we have no Qt focus widget yet.  The Qt focus
+                //        widget might later be set in L0680.
+                XEvent ev;
+                memset(&ev, 0, sizeof(ev));
+                ev.xfocus.display = qt_xdisplay();
+                ev.xfocus.type = XFocusIn;
+                ev.xfocus.window = w->topLevelWidget()->winId();
+                ev.xfocus.mode = NotifyNormal;
+                ev.xfocus.detail = NotifyAncestor;
+                qApp->x11ProcessEvent( &ev );
+            }
+            break;
+            case XEMBED_WINDOW_DEACTIVATE: {
+                // L0677: Embedding window becomes inactive. Send a fake XFocusOut
+                //        event to convince Qt that we no longer are active.  We will
+                //        receive extra Qt FocusOut events but we do not care.
+                XEvent ev;
+                memset(&ev, 0, sizeof(ev));
+                ev.xfocus.display = qt_xdisplay();
+                ev.xfocus.type = XFocusOut;
+                ev.xfocus.window = w->topLevelWidget()->winId();
+                ev.xfocus.mode = NotifyNormal;
+                ev.xfocus.detail = NotifyAncestor;
+                qApp->x11ProcessEvent( &ev );
+            }
+            break;
+            case XEMBED_FOCUS_IN:
+                // L0680: Embedding application gives us the focus.
+                {
+                    // L0681: Search saved focus widget.
+                    QWidget* focusCurrent = 0;
+                    QGuardedPtr<QWidget>* fw = focusMap->find( w->topLevelWidget() );
+                    if ( fw ) {
+                        focusCurrent = *fw;
+                        // L0682: Remove it from the map
+                        focusMap->remove( w->topLevelWidget() );
+                    }
+                    switch ( detail ) {
+                    case XEMBED_FOCUS_CURRENT:
+                        // L0683: Set focus on saved focus widget
+                        if ( focusCurrent )
+                            focusCurrent->setFocus();
+                        else if ( !w->topLevelWidget()->focusWidget() )
+                            w->topLevelWidget()->setFocus();
+                        break;
+                    case XEMBED_FOCUS_FIRST:
+                        {
+                            // L0684: Search first widget in tab chain
+                            QFocusEvent::setReason( QFocusEvent::Tab );
+                            w->topLevelWidget()->setFocus();
+                            ((QPublicWidget*)w->topLevelWidget())->focusNextPrev(true);
+                            QFocusEvent::resetReason();
+                        }
+                        break;
+                    case XEMBED_FOCUS_LAST:
+                        {
+                            // L0686: Search last widget in tab chain
+                            QFocusEvent::setReason( QFocusEvent::Backtab );
+                            w->topLevelWidget()->setFocus();
+                            ((QPublicWidget*)w->topLevelWidget())->focusNextPrev(false);
+                            QFocusEvent::resetReason();
+                        }
+                        break;
+                    default:
+                        break;
+                    }
+                }
+                break;
+            case XEMBED_FOCUS_OUT:
+                // L0688: Embedding application takes the focus away
+                //        We first record what the focus widget was
+                //        and clear the Qt focus.
+                if ( w->topLevelWidget()->focusWidget() ) {
+                    focusMap->insert( w->topLevelWidget(),
+                        new QGuardedPtr<QWidget>(w->topLevelWidget()->focusWidget() ) );
+                    w->topLevelWidget()->focusWidget()->clearFocus();
+                }
+            break;
+            default:
+                break;
+            }
+        } else if ( e->xclient.format == 32 && e->xclient.message_type ) {
+            if ( e->xclient.message_type == qt_wm_protocols ) {
+                QWidget* w = QWidget::find( e->xclient.window );
+                if ( !w )
+                    break;
+                // L0690: This is for the embedding side!
+                //        See L0902 for more information about the focus proxy.
+                //        Window manager may send WM_TAKE_FOCUS messages to the 
+                //        embedding application to indicate that it becomes active. 
+                //        But this also suggests that the window manager has
+                //        changed the X11 focus. We want to make sure it goes
+                //        to the focus proxy window eventually.
+                Atom a = e->xclient.data.l[0];
+                if ( a == qt_wm_take_focus ) {
+                    // L0695: update Qt message time variable
+                    if ( (ulong) e->xclient.data.l[1] > qt_x_time )
+                        qt_x_time = e->xclient.data.l[1];
+                    // L0696: There is no problem when the window is not active.
+                    //        Qt will generate a WindowActivate event that will
+                    //        do the job (L1310).  This does not happen if the
+                    //        window is already active.  So we simulate it.
+                    if ( w->isActiveWindow() ) {
+                        QEvent e( QEvent::WindowActivate );
+                        QApplication::sendEvent( w, &e );
+                    }
+                }
+            }
+        }
+        break;
+    default:
+        break;
+    }
+    // L0698: The next x11 filter 
+    if ( oldFilter )
+        return oldFilter( e );
+    // L0699: Otherwise process the event as usual.
+    return false;
+}
+
+
+
+// L0700: Install the xembed filters in both client and embedder sides.
+//        This function is called automatically when using
+//        embedClientIntoWindow() or creating an instance of QXEmbedCopy You may
+//        have to call it manually for a client when using embedder-side
+//        embedding, though.
+void QXEmbedCopy::initialize()
+{
+    static bool is_initialized = false;
+    if ( is_initialized )
+        return;
+
+    // L0710: Atom used by the XEMBED protocol.
+    xembed = XInternAtom( qt_xdisplay(), "_XEMBED", false );
+    // L0720: Install low level filter for X11 events (L0650)
+    oldFilter = qt_set_x11_event_filter( qxembed_x11_event_filter );
+    // L0730: See L0610 for an explanation about focusMap.
+    focusMap = new QPtrDict<QGuardedPtr<QWidget> >;
+    focusMap->setAutoDelete( true );
+    // L0740: Create client side application wide event filter (L0610)
+    filter = new QXEmbedCopyAppFilter;
+
+    is_initialized = true;
+}
+
+
+
+
+
+// ------------------------------------------------------------
+// L0800: MOST OF WHAT FOLLOWS CONCERNS THE EMBEDDER SIDE.
+//        Things that happen inside a Qt application that contain
+//        a QXEmbedCopy widget for embedding other applications.
+//        This applies to both the XEMBED and XPLAIN protocols.
+//        Deviations are commented below.
+
+
+
+// L0810: Class QXEmbedCopy.
+//        A QXEmbedCopy widget serves as an embedder that can manage one single
+//        embedded X-window. These so-called client windows can be arbitrary
+//        Qt or non Qt applications.  There are two different ways of using
+//        QXEmbedCopy, from the client side or from the embedder's side.
+
+
+// L0900: Constructs a xembed widget.
+QXEmbedCopy::QXEmbedCopy(QWidget *parent, const char *name, WFlags f)
+  : QWidget(parent, name, f)
+{
+    // L0901: Create private data. See L0100.
+    d = new QXEmbedCopyData;
+    // L0902: Create focus proxy widget. See XEmbed specification.
+    //        Each QXEmbedCopy widget has a focus proxy window. Every single
+    //        QXEmbedCopy widget tries to force its focus proxy window onto the
+    //        whole embedding application. They compete between themselves and
+    //        against Qt (L0690, L0914, L1040, L1310, L1510, L1580). 
+    //        This would be much simpler if implemented within Qt.
+    d->focusProxy = new QWidget( topLevelWidget(), "xembed_focus" );
+    d->focusProxy->setGeometry( -1, -1, 1, 1 );
+    d->focusProxy->show();
+    // make sure it's shown - for XSetInputFocus
+    QApplication::sendPostedEvents( d->focusProxy, 0 );
+    // L0903: Install the client side event filters
+    //        because they also provide services for the embedder side
+    //        See L0660, L0671, L0685.
+    initialize();
+    window = 0;
+    setFocusPolicy(StrongFocus);
+    setKeyCompression( false );
+
+    // L0910: Trick Qt to create extraData();
+    (void) topData();
+
+    // L0912: We are mostly interested in SubstructureNotify
+    //        This is sent when something happens to the children of
+    //        the X11 window associated with the QXEmbedCopy widget.
+    XSelectInput(qt_xdisplay(), winId(),
+                 KeyPressMask | KeyReleaseMask |
+                 ButtonPressMask | ButtonReleaseMask |
+                 KeymapStateMask |
+                 ButtonMotionMask |
+                 PointerMotionMask | // may need this, too
+                 EnterWindowMask | LeaveWindowMask |
+                 FocusChangeMask |
+                 ExposureMask |
+                 StructureNotifyMask |
+                 SubstructureRedirectMask |
+                 SubstructureNotifyMask
+                 );
+    // L0913: all application events pass through eventFilter().
+    //        This is mostly used to force the X11 focus on the 
+    //        proxy focus window. See L1300.
+    topLevelWidget()->installEventFilter( this );
+    qApp->installEventFilter( this );
+
+    // L0914: Start moving the X11 focus on the focus proxy window.
+    //        See L1581 to know why we do not use isActiveWindow().
+    if ( qApp->activeWindow() == topLevelWidget() )
+        if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded )
+            XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(), 
+                            RevertToParent, qt_x_time );
+    // L0915: ??? [drag&drop?]
+    setAcceptDrops( true );
+}
+
+// L1000: Destructor must dispose of the embedded client window.
+QXEmbedCopy::~QXEmbedCopy()
+{
+    // L1010: Make sure no pointer grab is left.
+    if ( d && d->xgrab)
+        XUngrabButton( qt_xdisplay(), AnyButton, AnyModifier, winId() );
+    if ( window && ( autoDelete() || !d->xplain ))
+        {
+            // L1021: Hide the window and safely reparent it into the root,
+            //        otherwise it would be destroyed by X11 together 
+            //        with this QXEmbedCopy's window.
+#if 0
+// TODO: The proper XEmbed way would be to unmap the window, and the embedded
+// app would detect the embedding has ended, and do whatever it finds appropriate.
+// However, QXEmbedCopy currently doesn't provide support for this detection,
+// so for the time being, it's better to leave the window mapped as toplevel window.
+// This will be ever more complicated with the systray windows, as the simple API
+// for them (KWin::setSystemTrayWindowFor()) doesn't make it possible to detect
+// themselves they have been released from systray, but KWin requires them
+// to be visible to allow next Kicker instance to swallow them.
+// See also below the L1022 comment.
+//            XUnmapWindow( qt_xdisplay(), window );
+#else
+            if( autoDelete())
+                XUnmapWindow( qt_xdisplay(), window );
+#endif
+            XReparentWindow(qt_xdisplay(), window, qt_xrootwin(), 0, 0);
+            if( !d->xplain )
+                XRemoveFromSaveSet( qt_xdisplay(), window );
+            if( d->mapAfterRelease )
+                XMapWindow( qt_xdisplay(), window );
+            XSync(qt_xdisplay(), false);
+            // L1022: Send the WM_DELETE_WINDOW message
+            if( autoDelete() /*&& d->xplain*/ ) 
+                // This sendDelete should only apply to XPLAIN.
+                // XEMBED apps are supposed to detect when the embedding ends.
+                // ??? [We do not do this detection yet! 
+                //      So we sendDelete() instead.]
+                sendDelete();
+      }
+    window = 0;
+    // L01040: Our focus proxy window will be destroyed as well.
+    //         Make sure that the X11 focus is not lost in the process.
+    Window focus;
+    int revert;
+    XGetInputFocus( qt_xdisplay(), &focus, &revert );
+    if( focus == d->focusProxy->winId())
+        XSetInputFocus( qt_xdisplay(), topLevelWidget()->winId(), RevertToParent, qt_x_time );
+    // L01045: Delete our private data.
+    delete d;
+}
+
+
+// L1050: Sends a WM_DELETE_WINDOW message to the embedded window.  This is
+//        what typically happens when you click on the close button of a 
+//        window manager decoration.
+void QXEmbedCopy::sendDelete( void )
+{
+  if (window)
+    {
+      sendClientMessage(window, qt_wm_protocols, qt_wm_delete_window);
+      XFlush( qt_xdisplay() );
+    }
+}
+
+// L1100: Sets the protocol used for embedding windows.
+//        This function must be called before embedding a window.
+//        Protocol XEMBED provides maximal functionality (focus, tabs, etc)
+//        but requires explicit cooperation from the embedded window.  
+//        Protocol XPLAIN provides maximal compatibility with 
+//        embedded applications that do not support the XEMBED protocol.
+//        The default is XEMBED.  
+void QXEmbedCopy::setProtocol( Protocol proto )
+{
+    if (!window) {
+        d->xplain = false;
+        if (proto == XPLAIN)
+            d->xplain = true;
+    }
+}
+
+// L1150: Returns the protocol used for embedding the current window.
+QXEmbedCopy::Protocol QXEmbedCopy::protocol()
+{
+  if (d->xplain)
+    return XPLAIN;
+  return XEMBED;
+}
+
+
+// L1200: QXEmbedCopy widget size changes: resize embedded window.
+void QXEmbedCopy::resizeEvent(QResizeEvent*)
+{
+    if (window)
+        XResizeWindow(qt_xdisplay(), window, width(), height());
+}
+
+// L1250: QXEmbedCopy widget is shown: make sure embedded window is visible.
+void QXEmbedCopy::showEvent(QShowEvent*)
+{
+    if (window)
+        XMapRaised(qt_xdisplay(), window);
+}
+
+
+// L1300: This event filter sees all application events (L0913).
+bool QXEmbedCopy::eventFilter( QObject *o, QEvent * e)
+{
+
+    switch ( e->type() ) {
+    case QEvent::WindowActivate:
+        if ( o == topLevelWidget() ) {
+            // L1310: Qt thinks the application window has just been activated.
+            //        Make sure the X11 focus is on the focus proxy window. See L0686.
+            if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded )
+                if (! hasFocus() )
+                    XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(), 
+                                    RevertToParent, qt_x_time );
+            if (d->xplain)
+                // L1311: Activation has changed. Grab state might change. See L2800.
+                checkGrab();
+            else
+                // L1312: Let the client know that we just became active
+                sendXEmbedMessage( window, XEMBED_WINDOW_ACTIVATE );
+        }
+        break;
+    case QEvent::WindowDeactivate:
+        if ( o == topLevelWidget() ) {
+            if (d->xplain)
+                // L1321: Activation has changed. Grab state might change. See L2800.
+                checkGrab();
+            else
+                // L1322: Let the client know that we are no longer active
+                sendXEmbedMessage( window, XEMBED_WINDOW_DEACTIVATE );
+        }
+        break;
+    case QEvent::Move:
+        {
+            QWidget* pos = this;
+            while( pos != o && pos != topLevelWidget())
+                pos = pos->parentWidget();
+            if( pos == o ) {
+                // L1390: Send fake configure notify events whenever the
+                //        global position of the client changes. See L2900.
+                QPoint globalPos = mapToGlobal(QPoint(0,0));
+                if (globalPos != d->lastPos) {
+                    d->lastPos = globalPos;
+                    sendSyntheticConfigureNotifyEvent();
+                }
+            }
+        }                    
+        break;
+    default:
+        break;
+   }
+   return false;
+}
+
+// L1350: ??? [why this?]
+bool  QXEmbedCopy::event( QEvent * e)
+{
+    return QWidget::event( e );
+}
+
+// L1400: Forward keypress event to the client
+//        Receiving a Qt key event indicates that
+//        the QXEmbedCopy object has the Qt focus.
+//        The X11 event that caused the Qt key event
+//        must be forwarded to the client.
+//        See L0660.
+void QXEmbedCopy::keyPressEvent( QKeyEvent *)
+{
+    if (!window)
+        return;
+    last_key_event.window = window;
+    XSendEvent(qt_xdisplay(), window, false, KeyPressMask, (XEvent*)&last_key_event);
+
+}
+
+// L1450: Forward keyrelease event to the client.
+//        See comment L1400.
+void QXEmbedCopy::keyReleaseEvent( QKeyEvent *)
+{
+    if (!window)
+        return;
+    last_key_event.window = window;
+    XSendEvent(qt_xdisplay(), window, false, KeyReleaseMask, (XEvent*)&last_key_event);
+}
+
+// L1500: Handle Qt focus in event.
+void QXEmbedCopy::focusInEvent( QFocusEvent * e ){
+    if (!window)
+        return;
+    // L1510: This is a good time to set the X11 focus on the focus proxy window.
+    //        Except if the the embedding application itself is embedded into another.
+    if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded )
+      if ( qApp->activeWindow() == topLevelWidget() )
+          // L1511: Alter X focus only when window is active. 
+          //        This is dual safety here because FocusIn implies this.
+          //        But see L1581 for an example where this really matters.
+          XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(), 
+                          RevertToParent, qt_x_time );
+    if (d->xplain) {
+        // L1520: Qt focus has changed. Grab state might change. See L2800.
+        checkGrab();
+        // L1521: Window managers activate applications by setting the X11 focus.
+        //        We cannot do this (see L1510) but we can send a fake focus event
+        //        and forward the X11 key events ourselves (see L1400, L1450).
+        sendFocusMessage(window, XFocusIn, NotifyNormal, NotifyPointer );
+    } else {
+        // L1530: No need for fake events with XEMBED.
+        //        Just inform the client. It knows what to do.
+        int detail = XEMBED_FOCUS_CURRENT;
+        // L1531: When the focus change is caused by the tab key,
+        //        the client must select the first (or last) widget of
+        //        its own tab chain.
+        if ( e->reason() == QFocusEvent::Tab )
+            detail = XEMBED_FOCUS_FIRST;
+        else if ( e->reason() == QFocusEvent::Backtab )
+            detail = XEMBED_FOCUS_LAST;
+        sendXEmbedMessage( window, XEMBED_FOCUS_IN, detail);
+    }
+}
+
+// L1550: Handle Qt focus out event.
+void QXEmbedCopy::focusOutEvent( QFocusEvent * ){
+    if (!window)
+        return;
+    if (d->xplain) {
+        // L1560: Qt focus has changed. Grab state might change. See L2800.
+        checkGrab();
+        // L1561: Send fake focus out message. See L1521.
+        sendFocusMessage(window, XFocusOut, NotifyNormal, NotifyPointer );
+    } else {
+        // L1570: Send XEMBED focus out message. See L1531.
+        sendXEmbedMessage( window, XEMBED_FOCUS_OUT );
+    }
+    // L1580: The QXEmbedCopy object might loose the focus because its
+    //        toplevel window looses the X11 focus and is no longer active, 
+    //        or simply because the Qt focus has been moved to another widget.
+    //        In the latter case only, we want to make sure that the X11 focus
+    //        is properly set to the X11 focus widget.  We do this because
+    //        the client application might have moved the X11 focus after
+    //        receiving the fake focus messages.
+    if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded )
+        if ( qApp->activeWindow() == topLevelWidget() )
+            // L1581: Alter X focus only when window is active.
+            //        The test above is not the same as isActiveWindow().
+            //        Function isActiveWindow() also returns true when a modal
+            //        dialog child of this window is active.
+            XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(), 
+                            RevertToParent, qt_x_time );
+}
+
+
+// L1600: Helper for QXEmbedCopy::embed()
+//        Check whether a window is in withdrawn state.
+static bool wstate_withdrawn( WId winid )
+{
+    Atom type;
+    int format;
+    unsigned long length, after;
+    unsigned char *data;
+    int r = XGetWindowProperty( qt_xdisplay(), winid, qt_wm_state, 0, 2,
+                                false, AnyPropertyType, &type, &format,
+                                &length, &after, &data );
+    bool withdrawn = true;
+    // L1610: Non managed windows have no WM_STATE property.
+    //        Returning true ensures that the loop L1711 stops.
+    if ( r == Success && data && format == 32 ) {
+        Q_UINT32 *wstate = (Q_UINT32*)data;
+        withdrawn  = (*wstate == WithdrawnState );
+        XFree( (char *)data );
+    }
+    return withdrawn;
+}
+
+// L1650: Helper for QXEmbedCopy::embed()
+//        Get the X11 id of the parent window.
+static int get_parent(WId winid, Window *out_parent)
+{
+    Window root, *children=0;
+    unsigned int nchildren;
+    int st = XQueryTree(qt_xdisplay(), winid, &root, out_parent, &children, &nchildren);
+    if (st && children) 
+        XFree(children);
+    return st;
+}
+
+// L1700: Embeds the window w into this QXEmbedCopy widget.
+//        See doc in qxembed.h.
+void QXEmbedCopy::embed(WId w)
+{
+    kdDebug() << "*** Embed " << w << " into " << winId() << ". window=" << window << endl;
+    if (!w)
+        return;
+    // L1701: The has_window variable prevents embedding a same window twice.
+    //        ??? [what happens if one embed two windows into the same QXEmbedCopy?]
+    bool has_window =  (w == window);
+    window = w;
+    if ( !has_window ) {
+        KXErrorHandler errhandler; // make X BadWindow errors silent
+        // L1710: Try hard to withdraw the window.
+        //        This makes sure that the window manager will
+        //        no longer try to manage this window.
+        if ( !wstate_withdrawn(window) ) {
+            XWithdrawWindow(qt_xdisplay(), window, qt_xscreen());
+            QApplication::flushX();
+            // L1711: See L1610
+            for (int i=0; i < 10000; ++i) {	// this section changed from original QXEmbed
+                if (wstate_withdrawn(window)) {
+                    Window parent = 0;
+                    get_parent(w, &parent);
+                    if (parent == qt_xrootwin()) break;
+                    else qDebug ("not really withdrawn, yet in loop #%d", i);
+                }
+                USLEEP(1000);
+            }
+        }
+
+        // L1710: It would be sufficient in principle to reparent
+        //        window w into winId(). Everything else happens in L2020.
+        //        The following code might be useful when the X11 server takes 
+        //        time to create the embedded application main window.
+        Window parent = 0;
+        get_parent(w, &parent);
+        if (parent != qt_xrootwin()) {		// this if added to original QXEmbed
+            kdDebug() << QString(" failure to withdraw window") << endl;
+            window = 0;
+            return;
+        }
+        kdDebug() << QString("> before reparent: parent=0x%1").arg(parent,0,16) << endl;
+        for (int i = 0; i < 50; i++) {
+            // this is done once more when finishing embedding, but it's done also here
+            // just in case we crash before reaching that place
+            if( !d->xplain )
+                XAddToSaveSet( qt_xdisplay(), w );
+            XReparentWindow(qt_xdisplay(), w, winId(), 0, 0);
+            if (get_parent(w, &parent) && parent == winId()) {
+               kdDebug() << QString("> Loop %1: ").arg(i)
+                         << QString("> reparent of 0x%1").arg(w,0,16)
+                         << QString(" into 0x%1").arg(winId(),0,16)
+                         << QString(" successful") << endl;
+                break;
+            }
+            kdDebug() << QString("> Loop %1: ").arg(i)
+                      << QString("> reparent of 0x%1").arg(w,0,16)
+                      << QString(" into 0x%1").arg(winId(),0,16)
+                      << QString(" failed") << endl;
+            USLEEP(1000);
+        }
+        if( parent != winId()) // failed
+            window = 0;
+    }
+}
+
+
+// L1800: Returns the window identifier of the embedded window
+WId QXEmbedCopy::embeddedWinId() const
+{
+    return window;
+}
+
+
+// L1900: Control Qt tab focus management.
+//        See Qt documentation.
+bool QXEmbedCopy::focusNextPrevChild( bool next )
+{
+    if ( window )
+        // L1901: Return false when there is an embedded window
+        //        When the user presses TAB, Qt will not change 
+        //        the focus and pass the TAB key events to the QXEmbedCopy widget.
+        //        These key events will be forwarded to the client (L1400, L1450)
+        //        who eventually will manage the tab focus (L0620) and possible
+        //        instruct us to call QWidget::focusNextPrevChild (L2081).
+        return false;
+    else
+        // L1920: Default behavior otherwise.
+        return QWidget::focusNextPrevChild( next );
+}
+
+
+// L2000: Filter for X11 events sent to the QXEmbedCopy window.
+bool QXEmbedCopy::x11Event( XEvent* e)
+{
+    switch ( e->type ) {
+    case DestroyNotify:
+        if ( e->xdestroywindow.window == window ) {
+            // L2005: Client window is being destroyed.
+            window = 0;
+            windowChanged( window );
+            emit embeddedWindowDestroyed();
+        }
+        break;
+    case ReparentNotify:
+        if ( e->xreparent.window == d->focusProxy->winId() )
+            break; // ignore proxy
+        if ( window && e->xreparent.window == window &&
+             e->xreparent.parent != winId() ) {
+            // L2010: We lost the window
+            window = 0;
+            windowChanged( window );
+            emit embeddedWindowDestroyed();
+            // L2011: Remove window from save set
+            //        ??? [not sure it is good to touch this window since
+            //             someone else has taken control of it already.]
+            if( !d->xplain )
+                XRemoveFromSaveSet( qt_xdisplay(), window );
+        } else if ( e->xreparent.parent == winId()){
+            // L2020: We got a window. Complete the embedding process.
+            window = e->xreparent.window;
+            // only XEMBED apps can survive crash,
+            // see http://lists.kde.org/?l=kfm-devel&m=106752026501968&w=2
+            if( !d->xplain )
+                XAddToSaveSet( qt_xdisplay(), window );
+            XResizeWindow(qt_xdisplay(), window, width(), height());
+            XMapRaised(qt_xdisplay(), window);
+            // L2024: see L2900.
+            sendSyntheticConfigureNotifyEvent();
+            // L2025: ??? [any idea about drag&drop?] 
+            extraData()->xDndProxy = window;
+            if ( parent() ) {
+                // L2030: embedded window might have new size requirements.
+                //        see L2500, L2520, L2550.
+                QEvent * layoutHint = new QEvent( QEvent::LayoutHint );
+                QApplication::postEvent( parent(), layoutHint );
+            }
+            windowChanged( window );
+            if (d->xplain) {
+                // L2040: Activation has changed. Grab state might change. See L2800.
+                checkGrab();
+                if ( hasFocus() )
+                    // L2041: Send fake focus message to inform the client. See L1521.
+                    sendFocusMessage(window, XFocusIn, NotifyNormal, NotifyPointer );
+            } else {
+                // L2050: Send XEMBED messages (see L0670, L1312, L1322, L1530)
+                sendXEmbedMessage( window, XEMBED_EMBEDDED_NOTIFY, 0, (long) winId() );
+                if (isActiveWindow())
+                    sendXEmbedMessage( window, XEMBED_WINDOW_ACTIVATE);
+                else
+                    sendXEmbedMessage( window, XEMBED_WINDOW_DEACTIVATE);
+                if ( hasFocus() )
+                    sendXEmbedMessage( window, XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT );
+            }
+        }
+        break;
+    case ButtonPress:
+        if (d->xplain && d->xgrab) {
+            // L2060: The passive grab has intercepted a mouse click
+            //        in the embedded client window. Take the focus.
+            QFocusEvent::setReason( QFocusEvent::Mouse );
+            setFocus();
+            QFocusEvent::resetReason();
+            // L2064: Resume X11 event processing.
+            XAllowEvents(qt_xdisplay(), ReplayPointer, CurrentTime);
+            // L2065: Qt should not know about this.
+            return true;
+        }
+        break;
+    case ButtonRelease:
+        if (d->xplain && d->xgrab) {
+            // L2064: Resume X11 event processing after passive grab (see L2060)
+            XAllowEvents(qt_xdisplay(), SyncPointer, CurrentTime);
+            return true;
+        }
+        break;
+    case MapRequest:
+        // L2070: Behave like a window manager.
+        if ( window && e->xmaprequest.window == window )
+            XMapRaised(qt_xdisplay(), window );
+        break;
+    case ClientMessage:
+        // L2080: This is where the QXEmbedCopy object receives XEMBED 
+        //        messaged from the client application.
+        if ( e->xclient.format == 32 && e->xclient.message_type == xembed ) {
+            long message = e->xclient.data.l[1];
+            switch ( message ) {
+                // L2081: Tab focus management. It is very important to call the 
+                //        focusNextPrevChild() defined by QWidget (not QXEmbedCopy). 
+                //        See L1901.
+            case XEMBED_FOCUS_NEXT:
+                QWidget::focusNextPrevChild( true );
+                break;
+            case XEMBED_FOCUS_PREV:
+                QWidget::focusNextPrevChild( false );
+                break;
+                // L2085: The client asks for the focus.
+            case XEMBED_REQUEST_FOCUS:
+                if( ((QPublicWidget*)topLevelWidget())->topData()->embedded ) {
+                    WId window = ((QPublicWidget*)topLevelWidget())->topData()->parentWinId;
+                    sendXEmbedMessage( window, XEMBED_REQUEST_FOCUS );
+                } else {
+                    QFocusEvent::setReason( QFocusEvent::Mouse );
+                    setFocus();
+                    QFocusEvent::resetReason();
+                }
+                break;
+            default:
+                break;
+            }
+        }
+	break;
+
+    case ConfigureRequest:
+        // L2090: Client wants to change its geometry. 
+        //        Just inform it that nothing has changed.
+        if (e->xconfigurerequest.window == window) 
+        {
+             sendSyntheticConfigureNotifyEvent();
+        }
+        break;
+    case MotionNotify: 
+	// fall through, workaround for Qt 3.0 < 3.0.3
+    case EnterNotify:
+        // L2095: See L2200.
+        if ( QWhatsThis::inWhatsThisMode() )
+            enterWhatsThisMode();
+        break;
+    default:
+        break;
+    }
+    return false;
+}
+
+
+// L2200: Try to handle Qt's "what's this" mode.  Broken.
+//        "temporary, fix in Qt (Matthias, Mon Jul 17 15:20:55 CEST 2000"
+void QXEmbedCopy::enterWhatsThisMode()
+{
+    // L2210: When the what-s-this pointer enters the embedded window (L2095)
+    //        cancel what-s-this mode, and use a non stantard _NET_WM_ message
+    //        to instruct the embedded client to enter the "what's this" mode.
+    //        This works only one way...
+    QWhatsThis::leaveWhatsThisMode();
+    if ( !context_help )
+        context_help = XInternAtom( x11Display(), "_NET_WM_CONTEXT_HELP", false );
+    sendClientMessage(window , qt_wm_protocols, context_help );
+}
+
+
+// L2300: indicates that the embedded window has been changed.
+void QXEmbedCopy::windowChanged( WId )
+{
+}
+
+
+// L2400: Utility function for clients that embed themselves.
+//        This is client side code.
+bool QXEmbedCopy::processClientCmdline( QWidget* client, int& argc, char ** argv )
+{
+    int myargc = argc;
+    WId window = 0;
+    int i, j;
+
+    j = 1;
+    for ( i=1; i<myargc; i++ ) {
+        if ( argv[i] && *argv[i] != '-' ) {
+            argv[j++] = argv[i];
+            continue;
+        }
+        QCString arg = argv[i];
+        if ( !strcmp(arg,"-embed") && i < myargc-1 ) {
+            QCString s = argv[++i];
+            window = s.toInt();
+        } else
+            argv[j++] = argv[i];
+    }
+    argc = j;
+
+    if ( window ) {
+        embedClientIntoWindow( client, window );
+        return true;
+    }
+
+    return false;
+}
+
+
+// L2450: Utility function for clients that embed themselves.
+//        This is client side code.
+void QXEmbedCopy::embedClientIntoWindow(QWidget* client, WId window)
+{
+    initialize();
+    XReparentWindow(qt_xdisplay(), client->winId(), window, 0, 0);
+    // L2451: These two lines are redundant. See L0680.
+    ((QXEmbedCopy*)client)->topData()->embedded = true;
+    ((QXEmbedCopy*)client)->topData()->parentWinId = window;
+    // L2452: This seems redundant because L2020 maps the window.
+    //        But calling show() might also set Qt internal flags.
+    client->show();
+}
+
+
+
+// L2500: Specifies that this widget can use additional space,
+//        and that it can survive on less than sizeHint().
+QSizePolicy QXEmbedCopy::sizePolicy() const
+{
+    return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
+}
+
+
+// L2520: Returns a size sufficient for the embedded window
+QSize QXEmbedCopy::sizeHint() const
+{
+    return minimumSizeHint();
+}
+
+// L2550: Returns the minimum size specified by the embedded window.
+QSize QXEmbedCopy::minimumSizeHint() const
+{
+    int minw = 0;
+    int minh = 0;
+    if ( window ) {
+        XSizeHints size;
+        long msize;
+        if (XGetWMNormalHints(qt_xdisplay(), window, &size, &msize)
+            && ( size.flags & PMinSize) ) {
+            minw = size.min_width;
+            minh = size.min_height;
+        }
+    }
+
+    return QSize( minw, minh );
+}
+
+// L2600: Tells what shoud be done with the embedded window when
+//        the embedding window is destroyed. 
+void QXEmbedCopy::setAutoDelete( bool b)
+{
+    d->autoDelete = b;
+}
+
+// L2650: See L2600.
+bool QXEmbedCopy::autoDelete() const
+{
+    return d->autoDelete;
+}
+
+// L2700: See L2200.
+bool QXEmbedCopy::customWhatsThis() const
+{
+    return true;
+}
+
+// L2800: When using the XPLAIN protocol, this function maintains
+//        a passive button grab when (1) the application is active
+//        and (2) the Qt focus is not on the QXEmbedCopy.  This passive
+//        grab intercepts button clicks in the client window and
+//        give us chance to request the Qt focus (L2060).
+void QXEmbedCopy::checkGrab() 
+{
+    if (d->xplain && isActiveWindow() && !hasFocus()) {
+        if (! d->xgrab)
+            XGrabButton(qt_xdisplay(), AnyButton, AnyModifier, winId(),
+                        false, ButtonPressMask, GrabModeSync, GrabModeAsync,
+                        None, None );
+        d->xgrab = true;
+    } else {
+        if (d->xgrab)
+            XUngrabButton( qt_xdisplay(), AnyButton, AnyModifier, winId() );
+        d->xgrab = false;
+    }
+}
+
+// L2900: This sends fake configure notify events to inform
+//        the client about its window geometry. See L1390, L2024 and L2090.
+void QXEmbedCopy::sendSyntheticConfigureNotifyEvent() 
+{
+    // L2910: It seems that the x and y coordinates are global.
+    //        But this is what ICCCM section 4.1.5 wants.
+    //        See http://lists.kde.org/?l=kfm-devel&m=107090222032378
+    QPoint globalPos = mapToGlobal(QPoint(0,0));
+    if (window) {
+        XConfigureEvent c;
+        memset(&c, 0, sizeof(c));
+        c.type = ConfigureNotify;
+        c.display = qt_xdisplay();
+        c.send_event = True;
+        c.event = window;
+        c.window = window;		// this line changed against the original version of QXEmbed!
+        c.x = globalPos.x();
+        c.y = globalPos.y();
+        c.width = width();
+        c.height = height();
+        c.border_width = 0;
+        c.above = None;
+        c.override_redirect = 0;
+        XSendEvent( qt_xdisplay(), c.event, true, StructureNotifyMask, (XEvent*)&c );
+    }
+}
+
+// L3000: One should not call QWidget::reparent after embedding a window.
+void QXEmbedCopy::reparent( QWidget * parent, WFlags f, const QPoint & p, bool showIt )
+{
+    // QWidget::reparent() destroys the old X Window for the widget, and
+    // creates a new one, thus QXEmbedCopy after reparenting is no longer the
+    // parent of the embedded window.  I think reparenting of QXEmbedCopy can be
+    // done only by a mistake, so just complain.
+    Q_ASSERT( !window );
+    QWidget::reparent( parent, f, p, showIt );
+}
+
+// for KDE
+#include "qxembedcopy.moc"
+#endif // Q_WS_X11

Added: trunk/rkward/rkward/windows/qxembedcopy.h
===================================================================
--- trunk/rkward/rkward/windows/qxembedcopy.h	                        (rev 0)
+++ trunk/rkward/rkward/windows/qxembedcopy.h	2006-11-25 20:09:57 UTC (rev 935)
@@ -0,0 +1,233 @@
+/****************************************************************************
+    Definition of QXEmbedCopy class
+
+   Copyright (C) 1999-2000 Troll Tech AS
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*****************************************************************************/
+
+#ifndef QXEMBED_H
+#define QXEMBED_H
+
+#include <qwidget.h>
+#include <kdelibs_export.h>
+
+#ifdef Q_WS_X11
+
+class QXEmbedCopyData;
+
+/**
+ * A QXEmbedCopy widget serves as an embedder that can manage one single embedded
+ * X-window. These so-called client windows can be arbitrary Qt or non Qt
+ * applications.
+ *
+ * There are two different ways of using QXEmbedCopy,
+ * from the client side or from the embedder's side.
+ * 
+ * Embedding from the client's side requires that the client knows the
+ * window identifier of the respective embedder widget. Use either
+ * embedClientIntoWindow() or the high-level wrapper processClientCmdline().
+ * This is only possible when the client is a Qt application.
+ *
+ * When using it from the embedder's side, you must know the window 
+ * identifier of the window that should be embedded. Simply call embed() 
+ * with this identifier as parameter.  If the client is a Qt application,
+ * make sure it has called QXEmbedCopy::initialize(). Otherwise you should
+ * probably call setProtocol(XPLAIN) before embed().
+ * 
+ * Reimplement the change handler windowChanged() to catch embedding or
+ * the destruction of embedded windows. In the latter case, the
+ * embedder also emits a signal embeddedWindowDestroyed() for
+ * convenience.
+ *
+ * @short The QXEmbedCopy widget is a graphical socket that can embed an external X-Window.
+*/
+class KDEUI_EXPORT QXEmbedCopy : public QWidget
+{
+    Q_OBJECT
+
+public:
+
+    /**
+     *
+     * Constructs a xembed widget.
+     *
+     * The parent, name and f arguments are passed to the QFrame
+     * constructor.
+     */
+    QXEmbedCopy( QWidget *parent=0, const char *name=0, WFlags f = 0 );
+
+    /**
+     * Destructor. Cleans up the focus if necessary.
+     */
+    ~QXEmbedCopy();
+
+    /**
+     * Embedded applications should call this function to make sure
+     * they support the XEMBED protocol. It is called automatically
+     * when you use embedClientIntoWindow() or
+     * processClientCmdline(). Clients might have to call it
+     * manually when you use embed().
+     */
+    static void initialize();
+
+    enum Protocol { XEMBED, XPLAIN };
+
+    /**
+     * Sets the protocol used for embedding windows.
+     * This function must be called before embedding a window.
+     * Protocol XEMBED provides maximal functionality (focus, tabs, etc)
+     * but requires explicit cooperation from the embedded window.
+     * Protocol XPLAIN provides maximal compatibility with
+     * embedded applications that do not support the XEMBED protocol.
+     * The default is XEMBED.
+     *
+     * Non KDE applications should be embedded with protocol XPLAIN. 
+     * This does not happen automatically yet. 
+     * You must call setProtocol() explicitly.
+     */
+
+    void setProtocol( Protocol proto );
+
+    /**
+     * Returns the protocol used for embedding the current window.
+     *
+     * @return the protocol used by QXEmbedCopy.
+     */
+
+    Protocol protocol();
+
+    /**
+     * Embeds the window with the identifier w into this xembed widget.
+     *
+     * This function is useful if the embedder knows about the client window
+     * that should be embedded.  Often it is vice versa: the client knows
+     * about its target embedder. In that case, it is not necessary to call
+     * embed(). Instead, the client will call the static function
+     * embedClientIntoWindow().
+     *
+     * @param w the identifier of the window to embed
+     * @see embeddedWinId()
+     */
+    void embed( WId w );
+
+    /**
+     * Returns the window identifier of the embedded window, or 0 if no
+     * window is embedded yet.
+     *
+     * @return the id of the embedded window (0 if no window is embedded)
+     */
+    WId embeddedWinId() const;
+
+    /**
+     * A function for clients that embed themselves. The widget
+     * client will be embedded in the window window. The application has
+     * to ensure that window is the handle of the window identifier of
+     * an QXEmbedCopy widget.
+     *
+     * @short #processClientCmdline()
+     */
+    static void embedClientIntoWindow( QWidget* client, WId window );
+
+    /**
+     * A utility function for clients that embed theirselves. The widget
+     * client will be embedded in the window that is passed as
+     * -embed command line argument.
+     *
+     * The function returns true on success or false if no such command line
+     * parameter is specified.
+     *
+     * @see embedClientIntoWindow()
+     */
+    static bool processClientCmdline( QWidget* client, int& argc, char ** argv );
+
+    /** 
+     * Sends a WM_DELETE_WINDOW message to the embedded window.  This is what
+     * typically happens when you click on the close button of a window
+     * manager decoration.  This should cause the embedded application to
+     * cleanly close the window.  Signal embeddedWindowDestroyed() can be used
+     * to monitor the status of the embedded window.
+     */
+    void sendDelete( void );
+    
+    /**
+     * Selects what shoud be done with the embedded window when the embedding
+     * window is destroyed.  When the argument is true, the embedded window is
+     * kept alive, is hidden, and receives a WM_DELETE_WINDOW message using
+     * sendDelete().  This is the default.  Otherwise, the destruction of the
+     * QXEmbedCopy object simply destroys the embedded window.
+     *
+     * @see sendDelete()
+     */
+    void setAutoDelete( bool );
+
+    /**
+     * Returns the value of flag indicating what shoud be done with the
+     * embedded window when the embedding window is destroyed.
+     * 
+     * @see setAutoDelete()
+     */
+    bool autoDelete() const;
+
+    /* Reimp */
+    QSize sizeHint() const;
+    QSize minimumSizeHint() const;
+    QSizePolicy sizePolicy() const;
+    bool eventFilter( QObject *, QEvent * );
+    bool customWhatsThis() const;
+    void enterWhatsThisMode(); // temporary, fix in Qt (Matthias, Mon Jul 17 15:20:55 CEST 2000  )
+    virtual void reparent( QWidget * parent, WFlags f, const QPoint & p, bool showIt = false );
+
+signals:
+    /**
+     * This signal is emitted when the embedded window has been lost (destroyed or reparented away)
+     *
+     * @see embeddedWinId()
+     */
+    // KDE4 rename to embeddedWindowLost()
+    void embeddedWindowDestroyed();
+
+protected:
+    bool event( QEvent * );
+    void keyPressEvent( QKeyEvent * );
+    void keyReleaseEvent( QKeyEvent * );
+    void focusInEvent( QFocusEvent * );
+    void focusOutEvent( QFocusEvent * );
+    void resizeEvent(QResizeEvent *);
+    void showEvent( QShowEvent * );
+    bool x11Event( XEvent* );
+
+    /**
+     * A change handler that indicates that the embedded window has been
+     * changed.  The window handle can also be retrieved with
+     * embeddedWinId().
+     *
+     * @param w the handle of the window that changed
+     */
+    virtual void windowChanged( WId w );
+
+    bool focusNextPrevChild( bool next );
+
+private:
+    WId window;
+    QXEmbedCopyData* d;
+    void checkGrab();
+    void sendSyntheticConfigureNotifyEvent();
+};
+
+
+#endif
+#endif


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the rkward-tracker mailing list