• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdeui
 

tdeui

  • tdeui
qxembed.cpp
1/****************************************************************************
2 Implementation of QXEmbed class
3
4 Copyright (C) 1999-2002 Trolltech AS
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*****************************************************************************/
21
22
23// L-000: About comments marked with Lxxxx.
24//
25// These comments represent an attempt to provide a more adequate
26// documentation to KDE developpers willing to modify QXEmbed. Keep in
27// mind that these comments were written long after most of the code.
28// Please improve them if you spot something wrong or missing
29// (Leon Bottou, 26-10-2003).
30//
31// Relevant documents:
32// - QXEmbed developper documentation
33// (see comments in qxembed.h)
34// - Xlib Reference Manual
35// (sections about focus, reparenting, window management)
36// - ICCCM Manual
37// (window management)
38// - XEMBED specification
39// (http://www.freedesktop.org/Standards/xembed-spec)
40// - XPLAIN and XEMBED.
41// <http://lists.kde.org/?w=2&r=1&s=qxembed+variants&q=t>
42// - Accumulated community knowledge.
43// <http://lists.kde.org/?w=2&r=1&s=qxembed&q=t>
44// <http://lists.kde.org/?l=kde-devel&w=2&r=1&s=qxembed&q=b>
45// <http://lists.kde.org/?l=kfm-devel&w=2&r=1&s=qxembed&q=b>
46//
47
48
49#include <tqapplication.h>
50#include <tqptrlist.h>
51#include <tqptrdict.h>
52#include <tqguardedptr.h>
53#include <tqwhatsthis.h>
54#include <tqfocusdata.h>
55
56// L0001: QXEmbed works only under X windows.
57#ifdef TQ_WS_X11
58
59# include <X11/X.h>
60# include <X11/Xlib.h>
61# include <X11/Xutil.h>
62# include <X11/Xatom.h>
63# define XK_MISCELLANY
64# define XK_LATIN1
65# include <X11/keysymdef.h>
66# include <kdebug.h>
67# include <kxerrorhandler.h>
68
69// L0002: Is file config.h KDE specific?
70# include <config.h>
71# ifdef HAVE_UNISTD_H
72# include <unistd.h>
73# ifdef HAVE_USLEEP
74# define USLEEP(x) usleep(x)
75# else
76# define USLEEP(x) sleep(0)
77# endif
78# else
79# define USLEEP(x) sleep(0)
80# endif
81
82# include "qxembed.h"
83
84// L0003: This keysym is used for focus navigation.
85# ifndef XK_ISO_Left_Tab
86# define XK_ISO_Left_Tab 0xFE20
87# endif
88
89// L0004: Conflicts between X11 and Qt definitions.
90const int XFocusOut = FocusOut;
91const int XFocusIn = FocusIn;
92const int XKeyPress = KeyPress;
93const int XKeyRelease = KeyRelease;
94# undef KeyRelease
95# undef KeyPress
96# undef FocusOut
97# undef FocusIn
98
99// L0005: Variables defined in qapplication_x11.cpp
100extern Atom tqt_wm_protocols;
101extern Atom tqt_wm_delete_window;
102extern Atom tqt_wm_take_focus;
103extern Atom tqt_wm_state;
104
105// L0006: X11 atoms private to QXEmbed
106static Atom xembed = 0;
107static Atom context_help = 0;
108
109// L0007: Xembed message codes (see XEmbed spec)
110#define XEMBED_EMBEDDED_NOTIFY 0
111#define XEMBED_WINDOW_ACTIVATE 1
112#define XEMBED_WINDOW_DEACTIVATE 2
113#define XEMBED_REQUEST_FOCUS 3
114#define XEMBED_FOCUS_IN 4
115#define XEMBED_FOCUS_OUT 5
116#define XEMBED_FOCUS_NEXT 6
117#define XEMBED_FOCUS_PREV 7
118
119// L0008: Xembed message details (see XEmbed spec)
120// -- XEMBED_FOCUS_IN:
121#define XEMBED_FOCUS_CURRENT 0
122#define XEMBED_FOCUS_FIRST 1
123#define XEMBED_FOCUS_LAST 2
124
125
126// L0100: Private data held by the QXEmbed object.
127// This belongs to the embedder side.
128class QXEmbedData
129{
130public:
131 QXEmbedData(){
132 autoDelete = true;
133 xplain = false;
134 xgrab = false;
135 mapAfterRelease = false;
136 lastPos = TQPoint(0,0);
137 }
138 ~QXEmbedData(){}
139
140 bool autoDelete; // L0101: See L2600
141 bool xplain; // L0102: See L1100
142 bool xgrab; // L0103: See L2800
143 bool mapAfterRelease;
144 TQWidget* focusProxy; // L0104: See XEmbed spec
145 TQPoint lastPos; // L0105: See L1390
146};
147
148namespace
149{
150 // L0200: This application wide event filter handles focus
151 // issues in the embedded client.
152 class QXEmbedAppFilter : public TQObject
153 {
154 public:
155 QXEmbedAppFilter() { tqApp->installEventFilter( this ); }
156 ~QXEmbedAppFilter() { }
157 bool eventFilter( TQObject *, TQEvent * );
158 };
159}
160
161// L0201: See L0200, L0740
162static QXEmbedAppFilter* filter = 0;
163// L0202: See L0610, L0730
164static TQPtrDict<TQGuardedPtr<TQWidget> > *focusMap = 0;
165// L0203: See L0660, L1400, L1450
166static XKeyEvent last_key_event;
167
168// L0300: This class gives access protected members of class TQWidget.
169// Function focusData() is useful to reimplement tab focus management
170// (L0620) Function topData() returns a structure QTLWExtra containing
171// information unique to toplevel windows. This structure contains two
172// members for the sole use of QXEmbed. Flag `embedded' indicates whether
173// the toplevel window is embedded using the XEMBED protocol (L0680).
174// Handle `parentWinId' then records the id of the embedding window.
175
176class QPublicWidget : public TQWidget
177{
178public:
179 TQTLWExtra* topData() { return TQWidget::topData(); }
180 TQFocusData *focusData(){ return TQWidget::focusData(); }
181 bool focusNextPrev(bool b) { return focusNextPrevChild(b); }
182};
183
184// L0400: This sets a very low level filter for X11 messages.
185// See qapplication_x11.cpp
186typedef int (*QX11EventFilter) (XEvent*);
187extern QX11EventFilter tqt_set_x11_event_filter (QX11EventFilter filter);
188static QX11EventFilter oldFilter = 0;
189
190
191// L0500: Helper to send XEmbed messages.
192static void sendXEmbedMessage( WId window, long message, long detail = 0,
193 long data1 = 0, long data2 = 0)
194{
195 if (!window) return;
196 XEvent ev;
197 memset(&ev, 0, sizeof(ev));
198 ev.xclient.type = ClientMessage;
199 ev.xclient.window = window;
200 ev.xclient.message_type = xembed;
201 ev.xclient.format = 32;
202 ev.xclient.data.l[0] = get_tqt_x_time();
203 ev.xclient.data.l[1] = message;
204 ev.xclient.data.l[2] = detail;
205 ev.xclient.data.l[3] = data1;
206 ev.xclient.data.l[4] = data2;
207 XSendEvent(tqt_xdisplay(), window, false, NoEventMask, &ev);
208}
209
210// L0501: Helper to send ICCCM Client messages.
211// See X11 ICCCM Specification.
212static void sendClientMessage(Window window, Atom a, long x)
213{
214 if (!window) return;
215 XEvent ev;
216 memset(&ev, 0, sizeof(ev));
217 ev.xclient.type = ClientMessage;
218 ev.xclient.window = window;
219 ev.xclient.message_type = a;
220 ev.xclient.format = 32;
221 ev.xclient.data.l[0] = x;
222 ev.xclient.data.l[1] = get_tqt_x_time();
223 XSendEvent(tqt_xdisplay(), window, false, NoEventMask, &ev);
224}
225
226// L0502: Helper to send fake X11 focus messages.
227// See X11 Reference Manual and Window Management stuff.
228static void sendFocusMessage(Window window, int type, int mode, int detail)
229{
230 if (!window) return;
231 XEvent ev;
232 memset(&ev, 0, sizeof(ev));
233 ev.xfocus.type = type;
234 ev.xfocus.window = window;
235 ev.xfocus.mode = mode;
236 ev.xfocus.detail = detail;
237 XSendEvent(tqt_xdisplay(), window, false, FocusChangeMask, &ev);
238}
239
240
241// ------------------------------------------------------------
242// L0600: MOST OF WHAT FOLLOWS CONCERNS THE CLIENT SIDE.
243// The following code mostly executes inside a Qt application swallowed
244// by QXEmbed widget. It mostly consists of event filters that fight
245// the normal Qt mechanisms in order to implement the XEMBED protocol.
246// All this would be a lot simpler if it was implemented by Qt itself.
247
248
249
250// L0610: This event filter receives all Qt events. Its main purpose is to
251// capture the Qt focus events in the embedded client in order to
252// implement the XEMBED protocol.
253//
254// Let's start with a few reminders:
255//
256// - X11 only has the concept of the "X11 focus window". This window
257// basically receives all key events. The ICCCM conventions define
258// how the window manager and the applications must cooperate to
259// choose the X11 focus window.
260//
261// - Most toolkits, including Qt, maintain the concepts of 'active
262// widget' and 'Qt focus widget'. A toplevel widget is active when
263// the X11 focus is set to one of its children. By extension a
264// widget is active when its toplevel widget is active. There is one
265// Qt focus widget for each toplevel widget. When the toplevel
266// widget is active, all key events are sent to the Qt focus widget,
267// regardless of which descendant of the toplevel window has the X11
268// focus. Widgets can adjust their appearance according to both
269// their activation and focus states. The Qt FocusIn and FocusOut
270// events indicate when a widget simultaneously is active and has
271// the Qt focus.
272//
273// The XEMBED protocol defines ways to communicate abouth both
274// activation and focus. The embedded client is active as soon as the
275// embedding window is active (L0676, L0677). A widget in the embedded
276// client receives key events when (1) it has the Qt focus in the
277// embedded application, and (2) the QXEmbed widget in the embedding
278// application is active and has the Qt focus. The Qt library in the
279// embedded application is unaware of the focus status of the QXEmbed
280// widget. We must make sure it does the right thing regarding the
281// sending of focus events and the visual appearance of the focussed
282// widgets. When the QXEmbed widget looses the Qt focus, we clear the
283// focus in the embedded client (L1570, L0688). Conversely, when
284// the QXEmbed widget gains the Qt focus, we restore the Qt focus
285// window in the embedded client (L1530, L0680, L0683).
286// Variable focusMap is used to remember which was the Qt focus
287// widget in the embedded application. All this would be a lot
288// simpler if it was implemented inside Qt...
289//
290// The XPLAIN protocol is much less refined in this respect.
291// The activation status of the embedded client simply reflect
292// the focus status of the QXEmbed widget. This is achieved
293// by sending fake X11 focus message to the client (L1521, L1561).
294// A passive button grab (L2800) intercepts mouse activity in the
295// embedded client and sets the Qt focus to the QXEmbed widget
296// when this happens (L2060). This can be achieved without
297// cooperation from the client.
298
299bool QXEmbedAppFilter::eventFilter( TQObject *o, TQEvent * e)
300{
301 static bool obeyFocus = false;
302 switch ( e->type() ) {
303 case TQEvent::MouseButtonPress:
304 // L0612: This will become clear with L0614
305 if ( !((TQWidget*)o)->isActiveWindow() )
306 obeyFocus = true;
307 break;
308 case TQEvent::FocusIn:
309 // L0613: FocusIn events either occur because the widget already was
310 // active and has just been given the Qt focus (L0614) or
311 // because the widget already had the Qt focus and just became
312 // active (L0615).
313 if ( tqApp->focusWidget() == o &&
314 ((QPublicWidget*)tqApp->focusWidget()->topLevelWidget())->topData()->embedded ) {
315 TQFocusEvent* fe = (TQFocusEvent*) e;
316 if ( obeyFocus || fe->reason() != TQFocusEvent::ActiveWindow /*|| fe->reason() == TQFocusEvent::Mouse ||
317 fe->reason() == TQFocusEvent::Shortcut*/ ) {
318 // L0614: A widget in the embedded client was just given the Qt focus.
319 // Variable `obeyFocus' suggests that this is the result of mouse
320 // activity in the client. The XEMBED_REQUEST_FOCUS message causes
321 // the embedding widget to take the Qt focus (L2085).
322 WId window = ((QPublicWidget*)tqApp->focusWidget()->topLevelWidget())->topData()->parentWinId;
323 focusMap->remove( tqApp->focusWidget()->topLevelWidget() );
324 sendXEmbedMessage( window, XEMBED_REQUEST_FOCUS );
325 } else if ( fe->reason() == TQFocusEvent::ActiveWindow ) {
326 // L0615: Both the embedder and the embedded client became active.
327 // But we do not know whether the QXEmbed widget has the Qt focus.
328 // So we clear the Qt focus for now. If indeed the QXEmbed widget
329 // has the focus, it will receive a FocusIn message (L1530) and
330 // tell us to restore the focus (L0680, L0683).
331 focusMap->remove( tqApp->focusWidget()->topLevelWidget() );
332 focusMap->insert( tqApp->focusWidget()->topLevelWidget(),
333 new TQGuardedPtr<TQWidget>(tqApp->focusWidget()->topLevelWidget()->focusWidget() ) );
334 // L0616: tqApp->focusWidget() might belong to a modal dialog and not be
335 // equal to tqApp->focusWidget()->topLevelWidget()->focusWidget() !
336 tqApp->focusWidget()->clearFocus();
337 // L0617: ??? [why not {obeyFocus=false; return true;} here?]
338 }
339 obeyFocus = false;
340 }
341 break;
342 case TQEvent::KeyPress:
343 if (tqApp->focusWidget() == o &&
344 ((QPublicWidget*)tqApp->focusWidget()->topLevelWidget())->topData()->embedded ) {
345 // L0620: The following code replaces the Qt code that
346 // handles focus focus changes with the tab key. See the
347 // XEMBED specification for details. The keypress event
348 // arrives here after an interesting itinerary. It is first
349 // saved in the embedding application (L0660). After being
350 // rejected for tab navigation in the embedding application
351 // (L1901), it gets forwarded to the embedded client
352 // (L1400) and arrives here. Depending on the status of
353 // the tab chain in the embedded client, focus navigation
354 // messages are sent back to the embedding application
355 // (L0653, L0654) which then performs tab navigation
356 // (L2081).
357 TQKeyEvent *k = (TQKeyEvent *)e;
358 TQWidget *w = tqApp->focusWidget();
359 // L0621: The following tests are copied from TQWidget::event().
360 bool res = false;
361 bool tabForward = true;
362 if ( !(k->state() & ControlButton || k->state() & AltButton) ) {
363 if ( k->key() == Key_Backtab || (k->key() == Key_Tab && (k->state() & ShiftButton)) ) {
364 TQFocusEvent::setReason( TQFocusEvent::Backtab );
365 res = ((QPublicWidget*)w)->focusNextPrev( tabForward = false );
366 TQFocusEvent::resetReason();
367 } else if ( k->key() == Key_Tab ) {
368 TQFocusEvent::setReason( TQFocusEvent::Tab );
369 res = ((QPublicWidget*)w)->focusNextPrev( tabForward = true );
370 TQFocusEvent::resetReason();
371 }
372 }
373 if (res) {
374 // L0625: We changed the focus because of tab/backtab key
375 // Now check whether we have been looping around.
376 TQFocusData *fd = ((QPublicWidget*)w)->focusData();
377 WId window = ((QPublicWidget*)w->topLevelWidget())->topData()->parentWinId;
378 TQWidget *cw = 0;
379 TQWidget *fw = fd->home();
380 if (tabForward && window) {
381 while (cw != w && cw != fw && cw != w->topLevelWidget())
382 cw = fd->prev();
383 if (cw != w)
384 sendXEmbedMessage( window, XEMBED_FOCUS_NEXT );
385 } else if (window) {
386 while (cw != w && cw != fw && cw != w->topLevelWidget())
387 cw = fd->next();
388 if (cw != w)
389 sendXEmbedMessage( window, XEMBED_FOCUS_PREV );
390 }
391 // L0628: Qt should no longer process this event.
392 return true;
393 }
394 }
395 break;
396 default:
397 break;
398 }
399 // L0640: Application gets to see the events anyway.
400 return false;
401}
402
403// L0650: This filter receives all XEvents in both the client and the embedder.
404// Most of it involves the embedded client (except L0660, L0671).
405static int qxembed_x11_event_filter( XEvent* e)
406{
407 switch ( e->type ) {
408 case XKeyPress:
409 case XKeyRelease: {
410 // L0660: This is for the embedding side (L1450).
411 last_key_event = e->xkey;
412 break;
413 }
414 case ClientMessage:
415 if ( e->xclient.message_type == xembed ) {
416 // L0670: This is where the XEmbed messages are
417 // processed on the client side.
418 Time msgtime = (Time) e->xclient.data.l[0];
419 long message = e->xclient.data.l[1];
420 long detail = e->xclient.data.l[2];
421 // L0671: Keep Qt message time up to date
422 if ( msgtime > get_tqt_x_time() )
423 set_tqt_x_time(msgtime);
424 TQWidget* w = TQWidget::find( e->xclient.window );
425 if ( !w )
426 break;
427 switch ( message) {
428 case XEMBED_EMBEDDED_NOTIFY: {
429 // L0675: We just have been embedded into a XEMBED aware widget.
430 TQTLWExtra *extra = ((QPublicWidget*)w->topLevelWidget())->topData();
431 extra->embedded = 1;
432 extra->parentWinId = e->xclient.data.l[3];
433 w->topLevelWidget()->show();
434 break;
435 }
436 case XEMBED_WINDOW_ACTIVATE: {
437 // L0676: Embedding window becomes active. Send a fake XFocusIn
438 // to convince Qt that we are active as well. Qt will send
439 // us a focus notification (L0615) that we will intercept to
440 // ensure that we have no Qt focus widget yet. The Qt focus
441 // widget might later be set in L0680.
442 XEvent ev;
443 memset(&ev, 0, sizeof(ev));
444 ev.xfocus.display = tqt_xdisplay();
445 ev.xfocus.type = XFocusIn;
446 ev.xfocus.window = w->topLevelWidget()->winId();
447 ev.xfocus.mode = NotifyNormal;
448 ev.xfocus.detail = NotifyAncestor;
449 tqApp->x11ProcessEvent( &ev );
450 }
451 break;
452 case XEMBED_WINDOW_DEACTIVATE: {
453 // L0677: Embedding window becomes inactive. Send a fake XFocusOut
454 // event to convince Qt that we no longer are active. We will
455 // receive extra Qt FocusOut events but we do not care.
456 XEvent ev;
457 memset(&ev, 0, sizeof(ev));
458 ev.xfocus.display = tqt_xdisplay();
459 ev.xfocus.type = XFocusOut;
460 ev.xfocus.window = w->topLevelWidget()->winId();
461 ev.xfocus.mode = NotifyNormal;
462 ev.xfocus.detail = NotifyAncestor;
463 tqApp->x11ProcessEvent( &ev );
464 }
465 break;
466 case XEMBED_FOCUS_IN:
467 // L0680: Embedding application gives us the focus.
468 {
469 // L0681: Search saved focus widget.
470 TQWidget* focusCurrent = 0;
471 TQGuardedPtr<TQWidget>* fw = focusMap->find( w->topLevelWidget() );
472 if ( fw ) {
473 focusCurrent = *fw;
474 // L0682: Remove it from the map
475 focusMap->remove( w->topLevelWidget() );
476 }
477 switch ( detail ) {
478 case XEMBED_FOCUS_CURRENT:
479 // L0683: Set focus on saved focus widget
480 if ( focusCurrent ) {
481 focusCurrent->setFocus();
482 if( QXEmbed* emb = dynamic_cast< QXEmbed* >( focusCurrent ))
483 emb->updateEmbeddedFocus( true );
484 }
485 else if ( !w->topLevelWidget()->focusWidget() )
486 w->topLevelWidget()->setFocus();
487 break;
488 case XEMBED_FOCUS_FIRST:
489 {
490 // L0684: Search first widget in tab chain
491 TQFocusEvent::setReason( TQFocusEvent::Tab );
492 w->topLevelWidget()->setFocus();
493 ((QPublicWidget*)w->topLevelWidget())->focusNextPrev(true);
494 TQFocusEvent::resetReason();
495 }
496 break;
497 case XEMBED_FOCUS_LAST:
498 {
499 // L0686: Search last widget in tab chain
500 TQFocusEvent::setReason( TQFocusEvent::Backtab );
501 w->topLevelWidget()->setFocus();
502 ((QPublicWidget*)w->topLevelWidget())->focusNextPrev(false);
503 TQFocusEvent::resetReason();
504 }
505 break;
506 default:
507 break;
508 }
509 }
510 break;
511 case XEMBED_FOCUS_OUT:
512 // L0688: Embedding application takes the focus away
513 // We first record what the focus widget was
514 // and clear the Qt focus.
515 if ( w->topLevelWidget()->focusWidget() ) {
516 if( QXEmbed* emb = dynamic_cast< QXEmbed* >( w->topLevelWidget()->focusWidget()))
517 emb->updateEmbeddedFocus( false );
518 focusMap->insert( w->topLevelWidget(),
519 new TQGuardedPtr<TQWidget>(w->topLevelWidget()->focusWidget() ) );
520 w->topLevelWidget()->focusWidget()->clearFocus();
521 }
522 break;
523 default:
524 break;
525 }
526 } else if ( e->xclient.format == 32 && e->xclient.message_type ) {
527 if ( e->xclient.message_type == tqt_wm_protocols ) {
528 TQWidget* w = TQWidget::find( e->xclient.window );
529 if ( !w )
530 break;
531 // L0690: This is for the embedding side!
532 // See L0902 for more information about the focus proxy.
533 // Window manager may send WM_TAKE_FOCUS messages to the
534 // embedding application to indicate that it becomes active.
535 // But this also suggests that the window manager has
536 // changed the X11 focus. We want to make sure it goes
537 // to the focus proxy window eventually.
538 Atom a = e->xclient.data.l[0];
539 if ( a == tqt_wm_take_focus ) {
540 // L0695: update Qt message time variable
541 if ( (ulong) e->xclient.data.l[1] > get_tqt_x_time() )
542 set_tqt_x_time(e->xclient.data.l[1]);
543 // L0696: There is no problem when the window is not active.
544 // Qt will generate a WindowActivate event that will
545 // do the job (L1310). This does not happen if the
546 // window is already active. So we simulate it.
547 if ( w->isActiveWindow() ) {
548 TQEvent e( TQEvent::WindowActivate );
549 TQApplication::sendEvent( w, &e );
550 }
551 }
552 }
553 }
554 break;
555 default:
556 break;
557 }
558 // L0698: The next x11 filter
559 if ( oldFilter )
560 return oldFilter( e );
561 // L0699: Otherwise process the event as usual.
562 return false;
563}
564
565
566
567// L0700: Install the xembed filters in both client and embedder sides.
568// This function is called automatically when using
569// embedClientIntoWindow() or creating an instance of QXEmbed You may
570// have to call it manually for a client when using embedder-side
571// embedding, though.
572void QXEmbed::initialize()
573{
574 static bool is_initialized = false;
575 if ( is_initialized )
576 return;
577
578 // L0710: Atom used by the XEMBED protocol.
579 xembed = XInternAtom( tqt_xdisplay(), "_XEMBED", false );
580 // L0720: Install low level filter for X11 events (L0650)
581 oldFilter = tqt_set_x11_event_filter( qxembed_x11_event_filter );
582 // L0730: See L0610 for an explanation about focusMap.
583 focusMap = new TQPtrDict<TQGuardedPtr<TQWidget> >;
584 focusMap->setAutoDelete( true );
585 // L0740: Create client side application wide event filter (L0610)
586 filter = new QXEmbedAppFilter;
587
588 is_initialized = true;
589}
590
591
592
593
594
595// ------------------------------------------------------------
596// L0800: MOST OF WHAT FOLLOWS CONCERNS THE EMBEDDER SIDE.
597// Things that happen inside a Qt application that contain
598// a QXEmbed widget for embedding other applications.
599// This applies to both the XEMBED and XPLAIN protocols.
600// Deviations are commented below.
601
602
603
604// L0810: Class QXEmbed.
605// A QXEmbed widget serves as an embedder that can manage one single
606// embedded X-window. These so-called client windows can be arbitrary
607// Qt or non Qt applications. There are two different ways of using
608// QXEmbed, from the client side or from the embedder's side.
609
610
611// L0900: Constructs a xembed widget.
612QXEmbed::QXEmbed(TQWidget *parent, const char *name, WFlags f)
613 : TQWidget(parent, name, f)
614{
615 // L0901: Create private data. See L0100.
616 d = new QXEmbedData;
617 // L0902: Create focus proxy widget. See XEmbed specification.
618 // Each QXEmbed widget has a focus proxy window. Every single
619 // QXEmbed widget tries to force its focus proxy window onto the
620 // whole embedding application. They compete between themselves and
621 // against Qt (L0690, L0914, L1040, L1310, L1510, L1580).
622 // This would be much simpler if implemented within Qt.
623 d->focusProxy = new TQWidget( topLevelWidget(), "xembed_focus" );
624 d->focusProxy->setGeometry( -1, -1, 1, 1 );
625 d->focusProxy->show();
626 // make sure it's shown - for XSetInputFocus
627 TQApplication::sendPostedEvents( d->focusProxy, 0 );
628 // L0903: Install the client side event filters
629 // because they also provide services for the embedder side
630 // See L0660, L0671, L0685.
631 initialize();
632 window = 0;
633 setFocusPolicy(TQWidget::StrongFocus);
634 setKeyCompression( false );
635
636 // L0910: Trick Qt to create extraData();
637 (void) topData();
638
639 // L0912: We are mostly interested in SubstructureNotify
640 // This is sent when something happens to the children of
641 // the X11 window associated with the QXEmbed widget.
642 XSelectInput(tqt_xdisplay(), winId(),
643 KeyPressMask | KeyReleaseMask |
644 ButtonPressMask | ButtonReleaseMask |
645 KeymapStateMask |
646 ButtonMotionMask |
647 PointerMotionMask | // may need this, too
648 EnterWindowMask | LeaveWindowMask |
649 FocusChangeMask |
650 ExposureMask |
651 StructureNotifyMask |
652 SubstructureRedirectMask |
653 SubstructureNotifyMask
654 );
655 // L0913: all application events pass through eventFilter().
656 // This is mostly used to force the X11 focus on the
657 // proxy focus window. See L1300.
658 topLevelWidget()->installEventFilter( this );
659 tqApp->installEventFilter( this );
660
661 // L0914: Start moving the X11 focus on the focus proxy window.
662 // See L1581 to know why we do not use isActiveWindow().
663 if ( tqApp->activeWindow() == topLevelWidget() )
664 if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded )
665 XSetInputFocus( tqt_xdisplay(), d->focusProxy->winId(),
666 RevertToParent, get_tqt_x_time() );
667 // L0915: ??? [drag&drop?]
668 setAcceptDrops( true );
669}
670
671// L1000: Destructor must dispose of the embedded client window.
672QXEmbed::~QXEmbed()
673{
674 // L1010: Make sure no pointer grab is left.
675 if ( d && d->xgrab)
676 XUngrabButton( tqt_xdisplay(), AnyButton, AnyModifier, winId() );
677 if ( window && ( autoDelete() || !d->xplain ))
678 {
679 // L1021: Hide the window and safely reparent it into the root,
680 // otherwise it would be destroyed by X11 together
681 // with this QXEmbed's window.
682#if 0
683// TODO: The proper XEmbed way would be to unmap the window, and the embedded
684// app would detect the embedding has ended, and do whatever it finds appropriate.
685// However, QXEmbed currently doesn't provide support for this detection,
686// so for the time being, it's better to leave the window mapped as toplevel window.
687// This will be ever more complicated with the systray windows, as the simple API
688// for them (KWin::setSystemTrayWindowFor()) doesn't make it possible to detect
689// themselves they have been released from systray, but KWin requires them
690// to be visible to allow next Kicker instance to swallow them.
691// See also below the L1022 comment.
692// XUnmapWindow( tqt_xdisplay(), window );
693#else
694 if( autoDelete())
695 XUnmapWindow( tqt_xdisplay(), window );
696#endif
697 XReparentWindow(tqt_xdisplay(), window, tqt_xrootwin(), 0, 0);
698 if( !d->xplain )
699 XRemoveFromSaveSet( tqt_xdisplay(), window );
700 if( d->mapAfterRelease )
701 XMapWindow( tqt_xdisplay(), window );
702 XSync(tqt_xdisplay(), false);
703 // L1022: Send the WM_DELETE_WINDOW message
704 if( autoDelete() /*&& d->xplain*/ )
705 // This sendDelete should only apply to XPLAIN.
706 // XEMBED apps are supposed to detect when the embedding ends.
707 // ??? [We do not do this detection yet!
708 // So we sendDelete() instead.]
709 sendDelete();
710 }
711 window = 0;
712 // L01040: Our focus proxy window will be destroyed as well.
713 // Make sure that the X11 focus is not lost in the process.
714 Window focus;
715 int revert;
716 XGetInputFocus( tqt_xdisplay(), &focus, &revert );
717 if( focus == d->focusProxy->winId())
718 XSetInputFocus( tqt_xdisplay(), topLevelWidget()->winId(), RevertToParent, get_tqt_x_time() );
719 // L01045: Delete our private data.
720 delete d;
721}
722
723
724// L1050: Sends a WM_DELETE_WINDOW message to the embedded window. This is
725// what typically happens when you click on the close button of a
726// window manager decoration.
727void QXEmbed::sendDelete( void )
728{
729 if (window)
730 {
731 sendClientMessage(window, tqt_wm_protocols, tqt_wm_delete_window);
732 XFlush( tqt_xdisplay() );
733 }
734}
735
736// L1100: Sets the protocol used for embedding windows.
737// This function must be called before embedding a window.
738// Protocol XEMBED provides maximal functionality (focus, tabs, etc)
739// but requires explicit cooperation from the embedded window.
740// Protocol XPLAIN provides maximal compatibility with
741// embedded applications that do not support the XEMBED protocol.
742// The default is XEMBED.
743void QXEmbed::setProtocol( Protocol proto )
744{
745 if (!window) {
746 d->xplain = false;
747 if (proto == XPLAIN)
748 d->xplain = true;
749 }
750}
751
752// L1150: Returns the protocol used for embedding the current window.
753QXEmbed::Protocol QXEmbed::protocol()
754{
755 if (d->xplain)
756 return XPLAIN;
757 return XEMBED;
758}
759
760
761// L1200: QXEmbed widget size changes: resize embedded window.
762void QXEmbed::resizeEvent(TQResizeEvent*)
763{
764 if (window)
765 XResizeWindow(tqt_xdisplay(), window, width(), height());
766}
767
768// L1250: QXEmbed widget is shown: make sure embedded window is visible.
769void QXEmbed::showEvent(TQShowEvent*)
770{
771 if (window)
772 XMapRaised(tqt_xdisplay(), window);
773}
774
775
776// L1300: This event filter sees all application events (L0913).
777bool QXEmbed::eventFilter( TQObject *o, TQEvent * e)
778{
779
780 switch ( e->type() ) {
781 case TQEvent::WindowActivate:
782 if ( o == topLevelWidget() ) {
783 // L1310: Qt thinks the application window has just been activated.
784 // Make sure the X11 focus is on the focus proxy window. See L0686.
785 if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded )
786 if (! hasFocus() )
787 XSetInputFocus( tqt_xdisplay(), d->focusProxy->winId(),
788 RevertToParent, get_tqt_x_time() );
789 if (d->xplain)
790 // L1311: Activation has changed. Grab state might change. See L2800.
791 checkGrab();
792 else
793 // L1312: Let the client know that we just became active
794 sendXEmbedMessage( window, XEMBED_WINDOW_ACTIVATE );
795 }
796 break;
797 case TQEvent::WindowDeactivate:
798 if ( o == topLevelWidget() ) {
799 if (d->xplain)
800 // L1321: Activation has changed. Grab state might change. See L2800.
801 checkGrab();
802 else
803 // L1322: Let the client know that we are no longer active
804 sendXEmbedMessage( window, XEMBED_WINDOW_DEACTIVATE );
805 }
806 break;
807 case TQEvent::Move:
808 {
809 TQWidget* pos = this;
810 while( pos != o && pos != topLevelWidget())
811 pos = pos->parentWidget();
812 if( pos == o ) {
813 // L1390: Send fake configure notify events whenever the
814 // global position of the client changes. See L2900.
815 TQPoint globalPos = mapToGlobal(TQPoint(0,0));
816 if (globalPos != d->lastPos) {
817 d->lastPos = globalPos;
818 sendSyntheticConfigureNotifyEvent();
819 }
820 }
821 }
822 break;
823 default:
824 break;
825 }
826 return false;
827}
828
829// L1350: ??? [why this?]
830bool QXEmbed::event( TQEvent * e)
831{
832 return TQWidget::event( e );
833}
834
835// L1400: Forward keypress event to the client
836// Receiving a Qt key event indicates that
837// the QXEmbed object has the Qt focus.
838// The X11 event that caused the Qt key event
839// must be forwarded to the client.
840// See L0660.
841void QXEmbed::keyPressEvent( TQKeyEvent *)
842{
843 if (!window)
844 return;
845 last_key_event.window = window;
846 XSendEvent(tqt_xdisplay(), window, false, KeyPressMask, (XEvent*)&last_key_event);
847
848}
849
850// L1450: Forward keyrelease event to the client.
851// See comment L1400.
852void QXEmbed::keyReleaseEvent( TQKeyEvent *)
853{
854 if (!window)
855 return;
856 last_key_event.window = window;
857 XSendEvent(tqt_xdisplay(), window, false, KeyReleaseMask, (XEvent*)&last_key_event);
858}
859
860// L1500: Handle Qt focus in event.
861void QXEmbed::focusInEvent( TQFocusEvent * e ){
862 if (!window)
863 return;
864 // L1510: This is a good time to set the X11 focus on the focus proxy window.
865 // Except if the the embedding application itself is embedded into another.
866 if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded )
867 if ( tqApp->activeWindow() == topLevelWidget() )
868 // L1511: Alter X focus only when window is active.
869 // This is dual safety here because FocusIn implies this.
870 // But see L1581 for an example where this really matters.
871 XSetInputFocus( tqt_xdisplay(), d->focusProxy->winId(),
872 RevertToParent, get_tqt_x_time() );
873 if (d->xplain) {
874 // L1520: Qt focus has changed. Grab state might change. See L2800.
875 checkGrab();
876 // L1521: Window managers activate applications by setting the X11 focus.
877 // We cannot do this (see L1510) but we can send a fake focus event
878 // and forward the X11 key events ourselves (see L1400, L1450).
879 sendFocusMessage(window, XFocusIn, NotifyNormal, NotifyPointer );
880 } else {
881 // L1530: No need for fake events with XEMBED.
882 // Just inform the client. It knows what to do.
883 int detail = XEMBED_FOCUS_CURRENT;
884 // L1531: When the focus change is caused by the tab key,
885 // the client must select the first (or last) widget of
886 // its own tab chain.
887 if ( e->reason() == TQFocusEvent::Tab )
888 detail = XEMBED_FOCUS_FIRST;
889 else if ( e->reason() == TQFocusEvent::Backtab )
890 detail = XEMBED_FOCUS_LAST;
891 sendXEmbedMessage( window, XEMBED_FOCUS_IN, detail);
892 }
893}
894
895// L1550: Handle Qt focus out event.
896void QXEmbed::focusOutEvent( TQFocusEvent * ){
897 if (!window)
898 return;
899 if (d->xplain) {
900 // L1560: Qt focus has changed. Grab state might change. See L2800.
901 checkGrab();
902 // L1561: Send fake focus out message. See L1521.
903 sendFocusMessage(window, XFocusOut, NotifyNormal, NotifyPointer );
904 } else {
905 // L1570: Send XEMBED focus out message. See L1531.
906 sendXEmbedMessage( window, XEMBED_FOCUS_OUT );
907 }
908 // L1580: The QXEmbed object might loose the focus because its
909 // toplevel window looses the X11 focus and is no longer active,
910 // or simply because the Qt focus has been moved to another widget.
911 // In the latter case only, we want to make sure that the X11 focus
912 // is properly set to the X11 focus widget. We do this because
913 // the client application might have moved the X11 focus after
914 // receiving the fake focus messages.
915 if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded )
916 if ( tqApp->activeWindow() == topLevelWidget() )
917 // L1581: Alter X focus only when window is active.
918 // The test above is not the same as isActiveWindow().
919 // Function isActiveWindow() also returns true when a modal
920 // dialog child of this window is active.
921 XSetInputFocus( tqt_xdisplay(), d->focusProxy->winId(),
922 RevertToParent, get_tqt_x_time() );
923}
924
925
926// When QXEmbed has TQt focus and gets/loses X focus, make sure the client knows
927// about the state of the focus.
928void QXEmbed::updateEmbeddedFocus( bool hasfocus ){
929 if (!window || d->xplain)
930 return;
931 if( hasfocus )
932 sendXEmbedMessage( window, XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT);
933 else
934 sendXEmbedMessage( window, XEMBED_FOCUS_OUT);
935}
936
937// L1600: Helper for QXEmbed::embed()
938// Check whether a window is in withdrawn state.
939static bool wstate_withdrawn( WId winid )
940{
941 Atom type;
942 int format;
943 unsigned long length, after;
944 unsigned char *data;
945 int r = XGetWindowProperty( tqt_xdisplay(), winid, tqt_wm_state, 0, 2,
946 false, AnyPropertyType, &type, &format,
947 &length, &after, &data );
948 bool withdrawn = true;
949 // L1610: Non managed windows have no WM_STATE property.
950 // Returning true ensures that the loop L1711 stops.
951 if ( r == Success && data && format == 32 ) {
952 TQ_UINT32 *wstate = (TQ_UINT32*)data;
953 withdrawn = (*wstate == WithdrawnState );
954 XFree( (char *)data );
955 }
956 return withdrawn;
957}
958
959// L1650: Helper for QXEmbed::embed()
960// Get the X11 id of the parent window.
961static int get_parent(WId winid, Window *out_parent)
962{
963 Window root, *children=0;
964 unsigned int nchildren;
965 int st = XQueryTree(tqt_xdisplay(), winid, &root, out_parent, &children, &nchildren);
966 if (st && children)
967 XFree(children);
968 return st;
969}
970
971// L1700: Embeds the window w into this QXEmbed widget.
972// See doc in qxembed.h.
973void QXEmbed::embed(WId w)
974{
975 kdDebug() << "*** Embed " << w << " into " << winId() << ". window=" << window << endl;
976 if (!w)
977 return;
978 // L1701: The has_window variable prevents embedding a same window twice.
979 // ??? [what happens if one embed two windows into the same QXEmbed?]
980 bool has_window = (w == window);
981 window = w;
982 if ( !has_window ) {
983 KXErrorHandler errhandler; // make X BadWindow errors silent
984 // L1710: Try hard to withdraw the window.
985 // This makes sure that the window manager will
986 // no longer try to manage this window.
987 if ( !wstate_withdrawn(window) ) {
988 XWithdrawWindow(tqt_xdisplay(), window, tqt_xscreen());
989 TQApplication::flushX();
990 // L1711: See L1610
991 for (int i=0; i < 10000; ++i) {
992 if (wstate_withdrawn(window)) {
993 Window parent = 0;
994 get_parent(w, &parent);
995 if (parent == tqt_xrootwin()) break;
996 }
997 USLEEP(1000);
998 }
999 }
1000 // L1710: It would be sufficient in principle to reparent
1001 // window w into winId(). Everything else happens in L2020.
1002 // The following code might be useful when the X11 server takes
1003 // time to create the embedded application main window.
1004 Window parent = 0;
1005 get_parent(w, &parent);
1006 kdDebug() << TQString(TQString("> before reparent: parent=0x%1").arg(parent,0,16)) << endl;
1007 for (int i = 0; i < 50; i++) {
1008 // this is done once more when finishing embedding, but it's done also here
1009 // just in case we crash before reaching that place
1010 if( !d->xplain )
1011 XAddToSaveSet( tqt_xdisplay(), w );
1012 XReparentWindow(tqt_xdisplay(), w, winId(), 0, 0);
1013 if (get_parent(w, &parent) && parent == winId()) {
1014 kdDebug() << TQString(TQString("> Loop %1: ").arg(i))
1015 << TQString(TQString("> reparent of 0x%1").arg(w,0,16))
1016 << TQString(TQString(" into 0x%1").arg(winId(),0,16))
1017 << TQString(" successful") << endl;
1018 break;
1019 }
1020 kdDebug() << TQString(TQString("> Loop %1: ").arg(i))
1021 << TQString(TQString("> reparent of 0x%1").arg(w,0,16))
1022 << TQString(TQString(" into 0x%1").arg(winId(),0,16))
1023 << TQString(" failed") << endl;
1024 USLEEP(1000);
1025 }
1026 if( parent != winId()) // failed
1027 window = 0;
1028 }
1029}
1030
1031// When a window is reparented into QXEmbed (or created inside of it), this function
1032// sets up the actual embedding.
1033void QXEmbed::handleEmbed()
1034{
1035 // only XEMBED apps can survive crash,
1036 // see http://lists.kde.org/?l=kfm-devel&m=106752026501968&w=2
1037 if( !d->xplain )
1038 XAddToSaveSet( tqt_xdisplay(), window );
1039 XResizeWindow(tqt_xdisplay(), window, width(), height());
1040 XMapRaised(tqt_xdisplay(), window);
1041 // L2024: see L2900.
1042 sendSyntheticConfigureNotifyEvent();
1043 // L2025: ??? [any idea about drag&drop?]
1044 extraData()->xDndProxy = window;
1045 if ( parent() ) {
1046 // L2030: embedded window might have new size requirements.
1047 // see L2500, L2520, L2550.
1048 TQEvent * layoutHint = new TQEvent( TQEvent::LayoutHint );
1049 TQApplication::postEvent( parent(), layoutHint );
1050 }
1051 windowChanged( window );
1052 if (d->xplain) {
1053 // L2040: Activation has changed. Grab state might change. See L2800.
1054 checkGrab();
1055 if ( hasFocus() )
1056 // L2041: Send fake focus message to inform the client. See L1521.
1057 sendFocusMessage(window, XFocusIn, NotifyNormal, NotifyPointer );
1058 } else {
1059 // L2050: Send XEMBED messages (see L0670, L1312, L1322, L1530)
1060 sendXEmbedMessage( window, XEMBED_EMBEDDED_NOTIFY, 0, (long) winId() );
1061 if (isActiveWindow())
1062 sendXEmbedMessage( window, XEMBED_WINDOW_ACTIVATE);
1063 else
1064 sendXEmbedMessage( window, XEMBED_WINDOW_DEACTIVATE);
1065 if ( hasFocus() )
1066 sendXEmbedMessage( window, XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT );
1067 }
1068}
1069
1070// L1800: Returns the window identifier of the embedded window
1071WId QXEmbed::embeddedWinId() const
1072{
1073 return window;
1074}
1075
1076
1077// L1900: Control Qt tab focus management.
1078// See Qt documentation.
1079bool QXEmbed::focusNextPrevChild( bool next )
1080{
1081 if ( window )
1082 // L1901: Return false when there is an embedded window
1083 // When the user presses TAB, Qt will not change
1084 // the focus and pass the TAB key events to the QXEmbed widget.
1085 // These key events will be forwarded to the client (L1400, L1450)
1086 // who eventually will manage the tab focus (L0620) and possible
1087 // instruct us to call TQWidget::focusNextPrevChild (L2081).
1088 return false;
1089 else
1090 // L1920: Default behavior otherwise.
1091 return TQWidget::focusNextPrevChild( next );
1092}
1093
1094
1095// L2000: Filter for X11 events sent to the QXEmbed window.
1096bool QXEmbed::x11Event( XEvent* e)
1097{
1098 switch ( e->type ) {
1099 case DestroyNotify:
1100 if ( e->xdestroywindow.window == window ) {
1101 // L2005: Client window is being destroyed.
1102 window = 0;
1103 windowChanged( window );
1104 emit embeddedWindowDestroyed();
1105 }
1106 break;
1107 case CreateNotify:
1108 // A window was created inside of QXEmbed, handle it as embedded
1109 if( window == 0 ) { // only one window
1110 window = e->xcreatewindow.window;
1111 handleEmbed();
1112 }
1113 break;
1114 case ReparentNotify:
1115 if ( e->xreparent.window == d->focusProxy->winId() )
1116 break; // ignore proxy
1117 if ( window && e->xreparent.window == window &&
1118 e->xreparent.parent != winId() ) {
1119 // L2010: We lost the window
1120 window = 0;
1121 windowChanged( window );
1122 emit embeddedWindowDestroyed();
1123 // L2011: Remove window from save set
1124 // ??? [not sure it is good to touch this window since
1125 // someone else has taken control of it already.]
1126 if( !d->xplain )
1127 XRemoveFromSaveSet( tqt_xdisplay(), window );
1128 } else if ( e->xreparent.parent == winId()){
1129 if( window == 0 ) // something started embedding from the outside
1130 window = e->xreparent.window;
1131 // L2020: We got a window. Complete the embedding process.
1132 if( e->xreparent.window == window )
1133 handleEmbed();
1134 }
1135 break;
1136 case ButtonPress:
1137 if (d->xplain && d->xgrab) {
1138 // L2060: The passive grab has intercepted a mouse click
1139 // in the embedded client window. Take the focus.
1140 TQFocusEvent::setReason( TQFocusEvent::Mouse );
1141 setFocus();
1142 TQFocusEvent::resetReason();
1143 // L2064: Resume X11 event processing.
1144 XAllowEvents(tqt_xdisplay(), ReplayPointer, CurrentTime);
1145 // L2065: Qt should not know about this.
1146 return true;
1147 }
1148 break;
1149 case ButtonRelease:
1150 if (d->xplain && d->xgrab) {
1151 // L2064: Resume X11 event processing after passive grab (see L2060)
1152 XAllowEvents(tqt_xdisplay(), SyncPointer, CurrentTime);
1153 return true;
1154 }
1155 break;
1156 case MapRequest:
1157 // L2070: Behave like a window manager.
1158 if ( window && e->xmaprequest.window == window )
1159 XMapRaised(tqt_xdisplay(), window );
1160 break;
1161 case ClientMessage:
1162 // L2080: This is where the QXEmbed object receives XEMBED
1163 // messaged from the client application.
1164 if ( e->xclient.format == 32 && e->xclient.message_type == xembed ) {
1165 long message = e->xclient.data.l[1];
1166 switch ( message ) {
1167 // L2081: Tab focus management. It is very important to call the
1168 // focusNextPrevChild() defined by TQWidget (not QXEmbed).
1169 // See L1901.
1170 case XEMBED_FOCUS_NEXT:
1171 TQWidget::focusNextPrevChild( true );
1172 break;
1173 case XEMBED_FOCUS_PREV:
1174 TQWidget::focusNextPrevChild( false );
1175 break;
1176 // L2085: The client asks for the focus.
1177 case XEMBED_REQUEST_FOCUS:
1178 if( ((QPublicWidget*)topLevelWidget())->topData()->embedded ) {
1179 focusMap->remove( topLevelWidget() );
1180 focusMap->insert( topLevelWidget(), new TQGuardedPtr<TQWidget>( this ));
1181 WId window = ((QPublicWidget*)topLevelWidget())->topData()->parentWinId;
1182 sendXEmbedMessage( window, XEMBED_REQUEST_FOCUS );
1183 } else {
1184 TQFocusEvent::setReason( TQFocusEvent::Mouse );
1185 setFocus();
1186 TQFocusEvent::resetReason();
1187 }
1188 break;
1189 default:
1190 break;
1191 }
1192 }
1193 break;
1194
1195 case ConfigureRequest:
1196 // L2090: Client wants to change its geometry.
1197 // Just inform it that nothing has changed.
1198 if (e->xconfigurerequest.window == window)
1199 {
1200 sendSyntheticConfigureNotifyEvent();
1201 }
1202 break;
1203 case MotionNotify:
1204 // fall through, workaround for Qt 3.0 < 3.0.3
1205 case EnterNotify:
1206 // L2095: See L2200.
1207 if ( TQWhatsThis::inWhatsThisMode() )
1208 enterWhatsThisMode();
1209 break;
1210 default:
1211 break;
1212 }
1213 return false;
1214}
1215
1216
1217// L2200: Try to handle Qt's "what's this" mode. Broken.
1218// "temporary, fix in Qt (Matthias, Mon Jul 17 15:20:55 CEST 2000"
1219void QXEmbed::enterWhatsThisMode()
1220{
1221 // L2210: When the what-s-this pointer enters the embedded window (L2095)
1222 // cancel what-s-this mode, and use a non stantard _NET_WM_ message
1223 // to instruct the embedded client to enter the "what's this" mode.
1224 // This works only one way...
1225 TQWhatsThis::leaveWhatsThisMode();
1226 if ( !context_help )
1227 context_help = XInternAtom( x11Display(), "_NET_WM_CONTEXT_HELP", false );
1228 sendClientMessage(window , tqt_wm_protocols, context_help );
1229}
1230
1231
1232// L2300: indicates that the embedded window has been changed.
1233void QXEmbed::windowChanged( WId )
1234{
1235}
1236
1237
1238// L2400: Utility function for clients that embed themselves.
1239// This is client side code.
1240bool QXEmbed::processClientCmdline( TQWidget* client, int& argc, char ** argv )
1241{
1242 int myargc = argc;
1243 WId window = 0;
1244 int i, j;
1245
1246 j = 1;
1247 for ( i=1; i<myargc; i++ ) {
1248 if ( argv[i] && *argv[i] != '-' ) {
1249 argv[j++] = argv[i];
1250 continue;
1251 }
1252 TQCString arg = argv[i];
1253 if ( !strcmp(arg,"-embed") && i < myargc-1 ) {
1254 TQCString s = argv[++i];
1255 window = s.toInt();
1256 } else
1257 argv[j++] = argv[i];
1258 }
1259 argc = j;
1260
1261 if ( window ) {
1262 embedClientIntoWindow( client, window );
1263 return true;
1264 }
1265
1266 return false;
1267}
1268
1269
1270// L2450: Utility function for clients that embed themselves.
1271// This is client side code.
1272void QXEmbed::embedClientIntoWindow(TQWidget* client, WId window)
1273{
1274 initialize();
1275 XReparentWindow(tqt_xdisplay(), client->winId(), window, 0, 0);
1276 // L2451: These two lines are redundant. See L0680.
1277 ((QXEmbed*)client)->topData()->embedded = true;
1278 ((QXEmbed*)client)->topData()->parentWinId = window;
1279 // L2452: This seems redundant because L2020 maps the window.
1280 // But calling show() might also set Qt internal flags.
1281 client->show();
1282}
1283
1284
1285
1286// L2500: Specifies that this widget can use additional space,
1287// and that it can survive on less than sizeHint().
1288TQSizePolicy QXEmbed::sizePolicy() const
1289{
1290 return TQSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Expanding );
1291}
1292
1293
1294// L2520: Returns a size sufficient for the embedded window
1295TQSize QXEmbed::sizeHint() const
1296{
1297 return minimumSizeHint();
1298}
1299
1300// L2550: Returns the minimum size specified by the embedded window.
1301TQSize QXEmbed::minimumSizeHint() const
1302{
1303 int minw = 0;
1304 int minh = 0;
1305 if ( window ) {
1306 XSizeHints size;
1307 long msize;
1308 if (XGetWMNormalHints(tqt_xdisplay(), window, &size, &msize)
1309 && ( size.flags & PMinSize) ) {
1310 minw = size.min_width;
1311 minh = size.min_height;
1312 }
1313 }
1314
1315 return TQSize( minw, minh );
1316}
1317
1318// L2600: Tells what shoud be done with the embedded window when
1319// the embedding window is destroyed.
1320void QXEmbed::setAutoDelete( bool b)
1321{
1322 d->autoDelete = b;
1323}
1324
1325// L2650: See L2600.
1326bool QXEmbed::autoDelete() const
1327{
1328 return d->autoDelete;
1329}
1330
1331// L2700: See L2200.
1332bool QXEmbed::customWhatsThis() const
1333{
1334 return true;
1335}
1336
1337// L2800: When using the XPLAIN protocol, this function maintains
1338// a passive button grab when (1) the application is active
1339// and (2) the Qt focus is not on the QXEmbed. This passive
1340// grab intercepts button clicks in the client window and
1341// give us chance to request the Qt focus (L2060).
1342void QXEmbed::checkGrab()
1343{
1344 if (d->xplain && isActiveWindow() && !hasFocus()) {
1345 if (! d->xgrab)
1346 XGrabButton(tqt_xdisplay(), AnyButton, AnyModifier, winId(),
1347 false, ButtonPressMask, GrabModeSync, GrabModeAsync,
1348 None, None );
1349 d->xgrab = true;
1350 } else {
1351 if (d->xgrab)
1352 XUngrabButton( tqt_xdisplay(), AnyButton, AnyModifier, winId() );
1353 d->xgrab = false;
1354 }
1355}
1356
1357// L2900: This sends fake configure notify events to inform
1358// the client about its window geometry. See L1390, L2024 and L2090.
1359void QXEmbed::sendSyntheticConfigureNotifyEvent()
1360{
1361 // L2910: It seems that the x and y coordinates are global.
1362 // But this is what ICCCM section 4.1.5 wants.
1363 // See http://lists.kde.org/?l=kfm-devel&m=107090222032378
1364 TQPoint globalPos = mapToGlobal(TQPoint(0,0));
1365 if (window) {
1366#if 0
1367 XConfigureEvent c;
1368 memset(&c, 0, sizeof(c));
1369 c.type = ConfigureNotify;
1370 c.display = tqt_xdisplay();
1371 c.send_event = True;
1372 c.event = window;
1373 c.window = window;
1374 c.x = globalPos.x();
1375 c.y = globalPos.y();
1376 c.width = width();
1377 c.height = height();
1378 c.border_width = 0;
1379 c.above = None;
1380 c.override_redirect = 0;
1381 XSendEvent( tqt_xdisplay(), c.event, true, StructureNotifyMask, (XEvent*)&c );
1382#endif
1383 // Yes, this doesn't make sense at all. See the commit message.
1384 XSetWindowBorderWidth( tqt_xdisplay(), window, 1 );
1385 XSetWindowBorderWidth( tqt_xdisplay(), window, 0 );
1386 }
1387}
1388
1389// L3000: One should not call TQWidget::reparent after embedding a window.
1390void QXEmbed::reparent( TQWidget * parent, WFlags f, const TQPoint & p, bool showIt )
1391{
1392 // TQWidget::reparent() destroys the old X Window for the widget, and
1393 // creates a new one, thus QXEmbed after reparenting is no longer the
1394 // parent of the embedded window. I think reparenting of QXEmbed can be
1395 // done only by a mistake, so just complain.
1396 Q_ASSERT( !window );
1397 TQWidget::reparent( parent, f, p, showIt );
1398}
1399
1400// for KDE
1401#include "qxembed.moc"
1402#endif // TQ_WS_X11
KXErrorHandler
endl
kndbgstream & endl(kndbgstream &s)
kdDebug
kdbgstream kdDebug(int area=0)
KStdAction::revert
TDEAction * revert(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name)
Revert the current document to the last saved version (essentially will undo all changes).
Definition: kstdaction.cpp:152
TDEStdAccel::name
TQString name(StdAccel id)

tdeui

Skip menu "tdeui"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdeui

Skip menu "tdeui"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeui by doxygen 1.9.4
This website is maintained by Timothy Pearson.