--------------Boundary-00=_8CROJ9ZBIP2KMYEUDEW6 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 8bit Slightly updated versions of my patches to qxembed. - L. --------------Boundary-00=_8CROJ9ZBIP2KMYEUDEW6 Content-Type: text/x-diff; charset="us-ascii"; name="qxembed.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="qxembed.diff" --- kdelibs/kdeui/qxembed.h 2002-08-16 21:58:50.000000000 -0400 +++ qxembed.h 2003-02-21 08:48:13.000000000 -0500 @@ -78,8 +78,41 @@ */ ~QXEmbed(); + /** + * Embedded applications should call this function to make sure + * they support the XEMBED protocol. It is called automatically + * when you use @ref #embedClientIntoWindow() or + * @ref #processClientCmdline(). Clients might have to call it + * manually when you use @ref #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. + * + * Future work: + * Create a protocol AUTO that selects the best option. + * This will be possible with the XEMBED v2 specification. + */ + + void setProtocol( Protocol proto ); + + /** + * Returns the protocol used for embedding the current window. + * + * @return the protocol used by QXEmbed. + */ + + Protocol protocol(); + /** * Embeds the window with the identifier w into this xembed widget. * @@ -88,8 +121,9 @@ * about its target embedder. In that case, it is not necessary to call * embed(). Instead, the client will call the static function * @ref #embedClientIntoWindow(). - * + * * @param w the identifier of the window to embed + * @param proto is the embedding protocol to use * @see #embeddedWinId() */ void embed( WId w ); @@ -181,6 +215,7 @@ private: WId window; QXEmbedData* d; + void checkGrab(); void sendSyntheticConfigureNotifyEvent(); }; --- kdelibs/kdeui/qxembed.cpp 2002-11-21 16:59:25.000000000 -0500 +++ qxembed.cpp 2003-02-21 19:43:05.000000000 -0500 @@ -97,15 +97,18 @@ public: QXEmbedData(){ autoDelete = TRUE; + xplain = FALSE; + xgrab = FALSE; lastPos = QPoint(0,0); } ~QXEmbedData(){}; bool autoDelete; + bool xplain; + bool xgrab; QWidget* focusProxy; QPoint lastPos; - }; class QXEmbedAppFilter : public QObject @@ -139,6 +142,7 @@ static void send_xembed_message( 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; @@ -153,7 +157,9 @@ XSendEvent(qt_xdisplay(), window, FALSE, NoEventMask, &ev); } -static void sendClientMessage(Window window, Atom a, long x){ +static void sendClientMessage(Window window, Atom a, long x) +{ + if (!window) return; XEvent ev; memset(&ev, 0, sizeof(ev)); ev.xclient.type = ClientMessage; @@ -165,6 +171,18 @@ XSendEvent(qt_xdisplay(), window, FALSE, NoEventMask, &ev); } +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); +} + bool QXEmbedAppFilter::eventFilter( QObject *o, QEvent * e) { @@ -456,6 +474,10 @@ topLevelWidget()->installEventFilter( this ); qApp->installEventFilter( this ); + if (isActiveWindow()) + if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded ) + XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(), RevertToParent, qt_x_time ); + setAcceptDrops( TRUE ); } @@ -464,11 +486,13 @@ */ QXEmbed::~QXEmbed() { - - if ( window != 0 ) { + if ( d && d->xgrab) + XUngrabButton( qt_xdisplay(), AnyButton, AnyModifier, winId() ); + + if ( window != 0 ) { if ( autoDelete() ) XUnmapWindow( qt_xdisplay(), window ); - + XReparentWindow(qt_xdisplay(), window, qt_xrootwin(), 0, 0); XSync(qt_xdisplay(), FALSE); @@ -484,9 +508,43 @@ } XFlush( qt_xdisplay() ); } - window = 0; + window = 0; - delete d; + delete d; +} + + +/*! + 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. + + Future work: + Create a protocol AUTO that selects the best option. + This will be possible with the XEMBED v2 specification. +*/ +void QXEmbed::setProtocol( Protocol proto ) +{ + if (window == 0) { + d->xplain = FALSE; + if (proto == XPLAIN) + d->xplain = TRUE; + } +} + +/*! + Returns the protocol used for embedding the current window. +*/ + +QXEmbed::Protocol QXEmbed::protocol() +{ + if (d->xplain) + return XPLAIN; + return XEMBED; } @@ -504,7 +562,6 @@ { if (window != 0) XMapRaised(qt_xdisplay(), window); - } @@ -518,12 +575,19 @@ if ( o == topLevelWidget() ) { if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded ) XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(), RevertToParent, qt_x_time ); - send_xembed_message( window, XEMBED_WINDOW_ACTIVATE ); + if (d->xplain) + checkGrab(); + else + send_xembed_message( window, XEMBED_WINDOW_ACTIVATE ); } break; case QEvent::WindowDeactivate: - if ( o == topLevelWidget() ) - send_xembed_message( window, XEMBED_WINDOW_DEACTIVATE ); + if ( o == topLevelWidget() ) { + if (d->xplain) + checkGrab(); + else + send_xembed_message( window, XEMBED_WINDOW_DEACTIVATE ); + } break; case QEvent::Move: { @@ -553,7 +617,7 @@ if (!window) return; last_key_event.window = window; - XSendEvent(qt_xdisplay(), window, FALSE, NoEventMask, (XEvent*)&last_key_event); + XSendEvent(qt_xdisplay(), window, FALSE, KeyPressMask, (XEvent*)&last_key_event); } @@ -564,7 +628,7 @@ if (!window) return; last_key_event.window = window; - XSendEvent(qt_xdisplay(), window, FALSE, NoEventMask, (XEvent*)&last_key_event); + XSendEvent(qt_xdisplay(), window, FALSE, KeyReleaseMask, (XEvent*)&last_key_event); } /*!\reimp @@ -572,10 +636,15 @@ void QXEmbed::focusInEvent( QFocusEvent * e ){ if (!window) return; - int detail = XEMBED_FOCUS_CURRENT; - if ( e->reason() == QFocusEvent::Tab ) - detail = tabForward?XEMBED_FOCUS_FIRST:XEMBED_FOCUS_LAST; - send_xembed_message( window, XEMBED_FOCUS_IN, detail); + if (d->xplain) { + checkGrab(); + sendFocusMessage(window, XFocusIn, NotifyNormal, NotifyPointer ); + } else { + int detail = XEMBED_FOCUS_CURRENT; + if ( e->reason() == QFocusEvent::Tab ) + detail = tabForward?XEMBED_FOCUS_FIRST:XEMBED_FOCUS_LAST; + send_xembed_message( window, XEMBED_FOCUS_IN, detail); + } } /*!\reimp @@ -583,7 +652,12 @@ void QXEmbed::focusOutEvent( QFocusEvent * ){ if (!window) return; - send_xembed_message( window, XEMBED_FOCUS_OUT ); + if (d->xplain) { + checkGrab(); + sendFocusMessage(window, XFocusOut, NotifyNormal, NotifyPointer ); + } else { + send_xembed_message( window, XEMBED_FOCUS_OUT ); + } } @@ -675,10 +749,16 @@ QApplication::postEvent( parent(), layoutHint ); } windowChanged( window ); - send_xembed_message( window, XEMBED_EMBEDDED_NOTIFY, 0, (long) winId() ); - send_xembed_message( window, isActiveWindow() ? XEMBED_WINDOW_ACTIVATE : XEMBED_WINDOW_DEACTIVATE ); - if ( hasFocus() ) - send_xembed_message( window, XEMBED_FOCUS_IN ); + if (d->xplain) { + checkGrab(); + if ( hasFocus() ) + sendFocusMessage(window, XFocusIn, NotifyNormal, NotifyPointer ); + } else { + send_xembed_message( window, XEMBED_EMBEDDED_NOTIFY, 0, (long) winId() ); + send_xembed_message( window, isActiveWindow() ? XEMBED_WINDOW_ACTIVATE : XEMBED_WINDOW_DEACTIVATE ); + if ( hasFocus() ) + send_xembed_message( window, XEMBED_FOCUS_IN ); + } } @@ -730,6 +810,19 @@ embed( window ); } break; + case ButtonPress: + if (d->xplain) { + QFocusEvent::setReason( QFocusEvent::Mouse ); + setFocus(); + QFocusEvent::resetReason(); + XAllowEvents(qt_xdisplay(), ReplayPointer, CurrentTime); + return TRUE; + } + break; + case ButtonRelease: + if (d->xplain) + XAllowEvents(qt_xdisplay(), SyncPointer, CurrentTime); + break; case MapRequest: if ( window && e->xmaprequest.window == window ) XMapRaised(qt_xdisplay(), window ); @@ -918,7 +1011,25 @@ return TRUE; } -void QXEmbed::sendSyntheticConfigureNotifyEvent() { + +void QXEmbed::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; + } +} + + +void QXEmbed::sendSyntheticConfigureNotifyEvent() +{ QPoint globalPos = mapToGlobal(QPoint(0,0)); if (window) { // kdDebug(6100) << "*************** sendSyntheticConfigureNotify ******************" << endl; --------------Boundary-00=_8CROJ9ZBIP2KMYEUDEW6 Content-Type: text/x-diff; charset="us-ascii"; name="nsplugin.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="nsplugin.diff" Index: nspluginloader.cpp =================================================================== RCS file: /home/kde/kdebase/nsplugins/nspluginloader.cpp,v retrieving revision 1.30 diff -u -3 -p -r1.30 nspluginloader.cpp --- nspluginloader.cpp 27 Oct 2002 18:31:00 -0000 1.30 +++ nspluginloader.cpp 21 Feb 2003 14:16:44 -0000 @@ -56,6 +56,7 @@ NSPluginInstance::NSPluginInstance(QWidg shown = false; _loader = NSPluginLoader::instance(); setBackgroundMode(QWidget::NoBackground); + setProtocol(QXEmbed::XPLAIN); embed( NSPluginInstanceIface_stub::winId() ); displayPlugin(); shown = true; Index: viewer/nsplugin.cpp =================================================================== RCS file: /home/kde/kdebase/nsplugins/viewer/nsplugin.cpp,v retrieving revision 1.77 diff -u -3 -p -r1.77 nsplugin.cpp --- viewer/nsplugin.cpp 22 Aug 2002 16:39:59 -0000 1.77 +++ viewer/nsplugin.cpp 21 Feb 2003 14:16:45 -0000 @@ -322,6 +322,20 @@ NPError g_NPN_SetValue(NPP /*instance*/, /******************************************************************/ +void +NSPluginInstance::forwarder(Widget w, XtPointer cl_data, XEvent * event, Boolean * cont) +{ + NSPluginInstance *inst = (NSPluginInstance*)cl_data; + *cont = True; + if (inst->_area == 0 || event->xkey.window == XtWindow(inst->_area)) + return; + *cont = False; + event->xkey.window = XtWindow(inst->_area); + event->xkey.subwindow = None; + XtDispatchEvent(event); +} + + NSPluginInstance::NSPluginInstance(NPP privateData, NPPluginFuncs *pluginFuncs, KLibrary *handle, int width, int height, QString src, QString /*mime*/, @@ -381,6 +395,12 @@ NSPluginInstance::NSPluginInstance(NPP p _area = XmCreateDrawingArea( _form, (char*)("drawingArea"), args, nargs); XtRealizeWidget(_area); XtMapWidget(_area); + + // Register forwarder + XtAddEventHandler(_toplevel, (KeyPressMask|KeyReleaseMask), + False, forwarder, (XtPointer)this ); + XtAddEventHandler(_form, (KeyPressMask|KeyReleaseMask), + False, forwarder, (XtPointer)this ); } NSPluginInstance::~NSPluginInstance() @@ -429,6 +449,10 @@ void NSPluginInstance::destroy() if (saved) g_NPN_MemFree(saved); + XtRemoveEventHandler(_form, (KeyPressMask|KeyReleaseMask), + False, forwarder, (XtPointer)this); + XtRemoveEventHandler(_toplevel, (KeyPressMask|KeyReleaseMask), + False, forwarder, (XtPointer)this); XtDestroyWidget(_area); XtDestroyWidget(_form); XtDestroyWidget(_toplevel); Index: viewer/nsplugin.h =================================================================== RCS file: /home/kde/kdebase/nsplugins/viewer/nsplugin.h,v retrieving revision 1.32 diff -u -3 -p -r1.32 nsplugin.h --- viewer/nsplugin.h 9 Jul 2002 04:18:52 -0000 1.32 +++ viewer/nsplugin.h 21 Feb 2003 14:16:45 -0000 @@ -201,6 +201,8 @@ private slots: private: friend class NSPluginStreamBase; + static void forwarder(Widget, XtPointer, XEvent *, Boolean*); + void destroy(); bool _destroyed; --------------Boundary-00=_8CROJ9ZBIP2KMYEUDEW6-- >> Visit http://mail.kde.org/mailman/listinfo/kde-devel#unsub to unsubscribe <<