]>
git.saurik.com Git - wxWidgets.git/blob - src/x11/reparent.cpp
1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation "reparent.h"
28 #include "wx/x11/reparent.h"
29 #include "wx/evtloop.h"
34 #include "wx/x11/private.h"
35 #include "X11/Xatom.h"
39 Adapted from code by Mike Yang, as follows.
41 From: Mike Yang (mikey@eukanuba.wpd.sgi.com)
42 Subject: Re: Wrapping new widget around existing windows
43 Newsgroups: comp.windows.x
44 View: Complete Thread (17 articles) | Original Format
45 Date: 1991-08-09 09:45:48 PST
48 Enough people asked, so here's my test program which reparents another
49 window. It's a single file (reparent.c), and will work with Motif or
50 Xaw. Xaw users should comment out the "#define MOTIF" line.
52 The reparent program first prompts for the application name of the
53 client that it will reparent. If you're going to start the
54 application override_redirect (e.g. -xrm "*overrideRedirect: true"),
55 then this name is ignored and the first override_redirect window is
56 assumed to be the one.
58 Input focus is supposed to be correctly handled, as is resizing with
59 window manager hints. If you have input focus problems, try launching
60 your application override_redirect instead. This method is preferred
61 anyway, since you can map it off-screen and then avoid the "window
62 flash" effect as the application's top-level window is reparented.
64 -----------------------------------------------------------------------
65 Mike Yang Silicon Graphics, Inc.
66 mikey@sgi.com 415/335-1786
69 ------------------------------- cut here ------------------------------
74 Copyright 1991 by Mike Yang, mikey@sgi.com, Silicon Graphics, Inc.
76 Permission to use, copy, modify, distribute, and sell this software and its
77 documentation for any purpose is hereby granted without fee, provided that
78 the above copyright notice appear in all copies and that both that
79 copyright notice and this permission notice appear in supporting
80 documentation, and that the name of SGI not be used in advertising or
81 publicity pertaining to distribution of the software without specific,
82 written prior permission. SGI makes no representations about the
83 suitability of this software for any purpose. It is provided "as is"
84 without express or implied warranty.
92 wxAdoptedWindow::wxAdoptedWindow()
96 wxAdoptedWindow::wxAdoptedWindow(WXWindow window
)
98 m_mainWindow
= window
;
101 wxAdoptedWindow::~wxAdoptedWindow()
109 static Atom WM_STATE
= 0;
110 bool wxReparenter::sm_done
= FALSE
;
111 wxAdoptedWindow
* wxReparenter::sm_toReparent
= NULL
;
112 wxWindow
* wxReparenter::sm_newParent
= NULL
;
113 wxString
wxReparenter::sm_name
;
114 bool wxReparenter::sm_exactMatch
= FALSE
;
117 ErrorHandler(Display
* dpy
, XErrorEvent
* event
)
123 // We assume that toReparent has had its X window set
125 bool wxReparenter::Reparent(wxWindow
* newParent
, wxAdoptedWindow
* toReparent
)
127 XWindowAttributes xwa
;
129 unsigned int numchildren
, each
;
130 Window returnroot
, returnparent
;
132 int parentOffset
= 0;
134 old
= XSetErrorHandler(ErrorHandler
);
135 XReparentWindow( wxGlobalDisplay(),
136 (Window
) toReparent
->GetMainWindow(),
137 (Window
) newParent
->GetMainWindow(),
140 if (!XQueryTree( wxGlobalDisplay(),
141 (Window
) toReparent
->GetMainWindow(),
142 &returnroot
, &returnparent
,
143 &children
, &numchildren
) || Xerror
)
145 XSetErrorHandler(old
);
151 // TEST: see if we can get away with reparenting just
155 wxLogDebug(wxT("Found %d, but only reparenting 1 child."), numchildren
);
158 wxLogDebug(wxT("Reparenting %d children."), numchildren
);
159 /* Stacking order is preserved since XQueryTree returns its children in
160 bottommost to topmost order
162 for (each
=0; each
<numchildren
; each
++)
164 XGetWindowAttributes( wxGlobalDisplay(),
165 children
[each
], &xwa
);
167 "Reparenting child at offset %d and position %d, %d.\n",
168 parentOffset
, parentOffset
+xwa
.x
, parentOffset
+xwa
.y
);
169 XReparentWindow( wxGlobalDisplay(),
170 children
[each
], (Window
) newParent
->GetMainWindow(),
175 XSetErrorHandler(old
);
179 // Wait for an appropriate window to be created.
180 // If exactMatch is FALSE, a substring match is OK.
181 // If windowName is empty, then wait for the next overrideRedirect window.
182 bool wxReparenter::WaitAndReparent(wxWindow
* newParent
, wxAdoptedWindow
* toReparent
,
183 const wxString
& windowName
,
186 sm_newParent
= newParent
;
187 sm_toReparent
= toReparent
;
188 sm_exactMatch
= exactMatch
;
189 sm_name
= windowName
;
191 Display
* display
= wxGlobalDisplay();
192 XSelectInput(display
,
193 RootWindowOfScreen(DefaultScreenOfDisplay(display
)),
194 SubstructureNotifyMask
);
197 WM_STATE
= XInternAtom(display
, "WM_STATE", False
);
200 if (!windowName
.IsEmpty())
201 wxLogDebug(_T("Waiting for window %s"), windowName
.c_str());
206 wxEventLoop eventLoop
;
209 if (eventLoop
.Pending())
212 XNextEvent(display
, & xevent
);
213 if (!wxTheApp
->ProcessXEvent((WXEvent
*) & xevent
))
215 // Do the local event processing
216 ProcessXEvent((WXEvent
*) & xevent
);
222 wxTimer::NotifyTimers();
223 wxTheApp
->SendIdleEvents();
230 bool wxReparenter::ProcessXEvent(WXEvent
* event
)
232 XEvent
* xevent
= (XEvent
*) event
;
237 if (xevent
->type
== MapNotify
)
239 wxLogDebug(_T("Window was mapped"));
242 if (xevent
->type
== MapNotify
&& !xevent
->xmap
.override_redirect
&&
243 (client
= (Window
) FindAClientWindow((WXWindow
) xevent
->xmap
.window
, sm_name
)))
245 wxLogDebug(_T("Found a client window, about to reparent"));
246 wxASSERT(sm_toReparent
->GetParent() == NULL
);
248 sm_toReparent
->SetHandle((WXWindow
) client
);
249 sm_newParent
->AddChild(sm_toReparent
);
250 sm_done
= Reparent(sm_newParent
, sm_toReparent
);
252 } else if (xevent
->type
== MapNotify
&&
253 xevent
->xmap
.override_redirect
&&
256 wxLogDebug(_T("Found an override redirect window, about to reparent"));
257 sm_toReparent
->SetHandle((WXWindow
) xevent
->xmap
.window
);
258 sm_newParent
->AddChild(sm_toReparent
);
259 wxASSERT(sm_toReparent
->GetParent() == NULL
);
261 sm_done
= Reparent(sm_newParent
, sm_toReparent
);
268 WXWindow
wxReparenter::FindAClientWindow(WXWindow window
, const wxString
& name
)
273 unsigned long nitems
, bytesafter
;
274 unsigned char *propreturn
;
276 unsigned int numchildren
;
277 Window returnroot
, returnparent
;
283 old
= XSetErrorHandler(ErrorHandler
);
284 rvalue
= XGetWindowProperty((Display
*) wxGetDisplay(),
285 (Window
) window
, WM_STATE
,
287 AnyPropertyType
, &actualtype
, &actualformat
,
288 &nitems
, &bytesafter
, &propreturn
);
289 XSetErrorHandler(old
);
290 if (!Xerror
&& rvalue
== Success
&& actualtype
!= None
)
292 if (rvalue
== Success
)
294 XFree((char *) propreturn
);
296 XFetchName((Display
*) wxGetDisplay(), (Window
) window
, &clientName
);
299 wxString str2
= wxString::FromAscii(clientName
);
305 matches
= (name
== wxString::FromAscii(clientName
));
307 matches
= (str1
.Contains(str2
) || str2
.Contains(str1
));
312 return (WXWindow
) window
;
317 old
= XSetErrorHandler(ErrorHandler
);
318 if (!XQueryTree((Display
*) wxGetDisplay(), (Window
) window
, &returnroot
, &returnparent
,
319 &children
, &numchildren
) || Xerror
)
321 XSetErrorHandler(old
);
324 XSetErrorHandler(old
);
327 for (i
=0; i
<(int)numchildren
&& !result
;i
++) {
328 result
= (Window
) FindAClientWindow((WXWindow
) children
[i
], name
);
331 XFree((char *) children
);
332 } return (WXWindow
) result
;