]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/x11/reparent.cpp
Typo.
[wxWidgets.git] / src / x11 / reparent.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: reparent.cpp
3// Purpose: wxWindow
4// Author: Julian Smart
5// Modified by:
6// Created: 2002-03-09
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#ifdef __GNUG__
21 #pragma implementation "reparent.h"
22#endif
23
24#include "wx/setup.h"
25
26#if !wxUSE_NANOX
27
28#include "wx/x11/reparent.h"
29#include "wx/evtloop.h"
30#include "wx/log.h"
31#include "wx/app.h"
32#include "wx/timer.h"
33
34#include "wx/x11/private.h"
35#include "X11/Xatom.h"
36
37/*
38
39 Adapted from code by Mike Yang, as follows.
40
41From: Mike Yang (mikey@eukanuba.wpd.sgi.com)
42Subject: Re: Wrapping new widget around existing windows
43Newsgroups: comp.windows.x
44View: Complete Thread (17 articles) | Original Format
45Date: 1991-08-09 09:45:48 PST
46
47
48Enough people asked, so here's my test program which reparents another
49window. It's a single file (reparent.c), and will work with Motif or
50Xaw. Xaw users should comment out the "#define MOTIF" line.
51
52The reparent program first prompts for the application name of the
53client that it will reparent. If you're going to start the
54application override_redirect (e.g. -xrm "*overrideRedirect: true"),
55then this name is ignored and the first override_redirect window is
56assumed to be the one.
57
58Input focus is supposed to be correctly handled, as is resizing with
59window manager hints. If you have input focus problems, try launching
60your application override_redirect instead. This method is preferred
61anyway, since you can map it off-screen and then avoid the "window
62flash" effect as the application's top-level window is reparented.
63
64-----------------------------------------------------------------------
65 Mike Yang Silicon Graphics, Inc.
66 mikey@sgi.com 415/335-1786
67
68
69------------------------------- cut here ------------------------------
70*/
71
72/*
73
74Copyright 1991 by Mike Yang, mikey@sgi.com, Silicon Graphics, Inc.
75
76Permission to use, copy, modify, distribute, and sell this software and its
77documentation for any purpose is hereby granted without fee, provided that
78the above copyright notice appear in all copies and that both that
79copyright notice and this permission notice appear in supporting
80documentation, and that the name of SGI not be used in advertising or
81publicity pertaining to distribution of the software without specific,
82written prior permission. SGI makes no representations about the
83suitability of this software for any purpose. It is provided "as is"
84without express or implied warranty.
85
86*/
87
88/*
89 * wxAdoptedWindow
90 */
91
92wxAdoptedWindow::wxAdoptedWindow()
93{
94}
95
96wxAdoptedWindow::wxAdoptedWindow(WXWindow window)
97{
98 m_mainWindow = window;
99}
100
101wxAdoptedWindow::~wxAdoptedWindow()
102{
103}
104/*
105 * wxReparenter
106 */
107
108static bool Xerror;
109static Atom WM_STATE = 0;
110bool wxReparenter::sm_done = FALSE;
111wxAdoptedWindow* wxReparenter::sm_toReparent = NULL;
112wxWindow* wxReparenter::sm_newParent = NULL;
113wxString wxReparenter::sm_name;
114bool wxReparenter::sm_exactMatch = FALSE;
115
116static int
117ErrorHandler(Display* dpy, XErrorEvent* event)
118{
119 Xerror = True;
120 return False;
121}
122
123// We assume that toReparent has had its X window set
124// appropriately.
125bool wxReparenter::Reparent(wxWindow* newParent, wxAdoptedWindow* toReparent)
126{
127 XWindowAttributes xwa;
128 Window *children;
129 unsigned int numchildren, each;
130 Window returnroot, returnparent;
131 XErrorHandler old;
132 int parentOffset = 0;
133
134 old = XSetErrorHandler(ErrorHandler);
135 XReparentWindow( wxGlobalDisplay(),
136 (Window) toReparent->GetMainWindow(),
137 (Window) newParent->GetMainWindow(),
138 0, 0);
139
140 if (!XQueryTree( wxGlobalDisplay(),
141 (Window) toReparent->GetMainWindow(),
142 &returnroot, &returnparent,
143 &children, &numchildren) || Xerror)
144 {
145 XSetErrorHandler(old);
146 return TRUE;
147 }
148
149 if (numchildren > 0)
150 {
151 // TEST: see if we can get away with reparenting just
152 // first one
153 if (numchildren > 1)
154 {
155 wxLogDebug(wxT("Found %d, but only reparenting 1 child."), numchildren);
156 numchildren = 1;
157 }
158 wxLogDebug(wxT("Reparenting %d children."), numchildren);
159 /* Stacking order is preserved since XQueryTree returns its children in
160 bottommost to topmost order
161 */
162 for (each=0; each<numchildren; each++)
163 {
164 XGetWindowAttributes( wxGlobalDisplay(),
165 children[each], &xwa);
166 fprintf(stderr,
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(),
171 xwa.x, xwa.y);
172 }
173 }
174
175 XSetErrorHandler(old);
176 return TRUE;
177}
178
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.
182bool wxReparenter::WaitAndReparent(wxWindow* newParent, wxAdoptedWindow* toReparent,
183 const wxString& windowName,
184 bool exactMatch)
185{
186 sm_newParent = newParent;
187 sm_toReparent = toReparent;
188 sm_exactMatch = exactMatch;
189 sm_name = windowName;
190
191 Display* display = wxGlobalDisplay();
192 XSelectInput(display,
193 RootWindowOfScreen(DefaultScreenOfDisplay(display)),
194 SubstructureNotifyMask);
195
196 if (!WM_STATE)
197 WM_STATE = XInternAtom(display, "WM_STATE", False);
198
199#ifdef __WXDEBUG__
200 if (!windowName.IsEmpty())
201 wxLogDebug(_T("Waiting for window %s"), windowName.c_str());
202#endif
203
204 sm_done = FALSE;
205
206 wxEventLoop eventLoop;
207 while (!sm_done)
208 {
209 if (eventLoop.Pending())
210 {
211 XEvent xevent;
212 XNextEvent(display, & xevent);
213 if (!wxTheApp->ProcessXEvent((WXEvent*) & xevent))
214 {
215 // Do the local event processing
216 ProcessXEvent((WXEvent*) & xevent);
217 }
218 }
219 else
220 {
221#if wxUSE_TIMER
222 wxTimer::NotifyTimers();
223 wxTheApp->SendIdleEvents();
224#endif
225 }
226 }
227 return TRUE;
228}
229
230bool wxReparenter::ProcessXEvent(WXEvent* event)
231{
232 XEvent* xevent = (XEvent*) event;
233 Window client;
234
235 if (!sm_done)
236 {
237 if (xevent->type == MapNotify)
238 {
239 wxLogDebug(_T("Window was mapped"));
240 }
241
242 if (xevent->type == MapNotify && !xevent->xmap.override_redirect &&
243 (client = (Window) FindAClientWindow((WXWindow) xevent->xmap.window, sm_name)))
244 {
245 wxLogDebug(_T("Found a client window, about to reparent"));
246 wxASSERT(sm_toReparent->GetParent() == NULL);
247
248 sm_toReparent->SetHandle((WXWindow) client);
249 sm_newParent->AddChild(sm_toReparent);
250 sm_done = Reparent(sm_newParent, sm_toReparent);
251 return sm_done;
252 } else if (xevent->type == MapNotify &&
253 xevent->xmap.override_redirect &&
254 xevent->xmap.window)
255 {
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);
260
261 sm_done = Reparent(sm_newParent, sm_toReparent);
262 return sm_done;
263 }
264 }
265 return FALSE;
266}
267
268WXWindow wxReparenter::FindAClientWindow(WXWindow window, const wxString& name)
269{
270 int rvalue, i;
271 Atom actualtype;
272 int actualformat;
273 unsigned long nitems, bytesafter;
274 unsigned char *propreturn;
275 Window *children;
276 unsigned int numchildren;
277 Window returnroot, returnparent;
278 Window result = 0;
279 XErrorHandler old;
280 char *clientName;
281
282 Xerror = False;
283 old = XSetErrorHandler(ErrorHandler);
284 rvalue = XGetWindowProperty((Display*) wxGetDisplay(),
285 (Window) window, WM_STATE,
286 0, 1, False,
287 AnyPropertyType, &actualtype, &actualformat,
288 &nitems, &bytesafter, &propreturn);
289 XSetErrorHandler(old);
290 if (!Xerror && rvalue == Success && actualtype != None)
291 {
292 if (rvalue == Success)
293 {
294 XFree((char *) propreturn);
295 }
296 XFetchName((Display*) wxGetDisplay(), (Window) window, &clientName);
297
298 wxString str1(name);
299 wxString str2 = wxString::FromAscii(clientName);
300 str1.Lower();
301 str2.Lower();
302
303 bool matches;
304 if (sm_exactMatch)
305 matches = (name == wxString::FromAscii(clientName));
306 else
307 matches = (str1.Contains(str2) || str2.Contains(str1));
308
309 XFree(clientName);
310
311 if (matches)
312 return (WXWindow) window;
313 else
314 return NULL;
315 }
316
317 old = XSetErrorHandler(ErrorHandler);
318 if (!XQueryTree((Display*) wxGetDisplay(), (Window) window, &returnroot, &returnparent,
319 &children, &numchildren) || Xerror)
320 {
321 XSetErrorHandler(old);
322 return NULL;
323 }
324 XSetErrorHandler(old);
325
326 result = 0;
327 for (i=0; i<(int)numchildren && !result ;i++) {
328 result = (Window) FindAClientWindow((WXWindow) children[i], name);
329 }
330 if (numchildren) {
331 XFree((char *) children);
332 } return (WXWindow) result;
333}
334
335#endif