]> git.saurik.com Git - wxWidgets.git/blame - src/x11/reparent.cpp
Fixed bug [ 754596 ] wxUSE_CONSTRAINTS 0 breaks AutoLayout() with sizers
[wxWidgets.git] / src / x11 / reparent.cpp
CommitLineData
c978d361
JS
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
14f355c2 20#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
c978d361
JS
21 #pragma implementation "reparent.h"
22#endif
23
2b5f62a0 24#include "wx/setup.h"
15d5a947
JS
25
26#if !wxUSE_NANOX
27
2b5f62a0 28#include "wx/x11/reparent.h"
c978d361
JS
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
c978d361
JS
37/*
38 * wxAdoptedWindow
39 */
40
41wxAdoptedWindow::wxAdoptedWindow()
42{
43}
44
45wxAdoptedWindow::wxAdoptedWindow(WXWindow window)
46{
ab6b6b15 47 m_mainWindow = window;
c978d361
JS
48}
49
50wxAdoptedWindow::~wxAdoptedWindow()
51{
52}
174046a3 53
c978d361
JS
54/*
55 * wxReparenter
56 */
57
58static bool Xerror;
59static Atom WM_STATE = 0;
60bool wxReparenter::sm_done = FALSE;
61wxAdoptedWindow* wxReparenter::sm_toReparent = NULL;
62wxWindow* wxReparenter::sm_newParent = NULL;
63wxString wxReparenter::sm_name;
64bool wxReparenter::sm_exactMatch = FALSE;
65
174046a3 66static int ErrorHandler(Display* dpy, XErrorEvent* event)
c978d361 67{
174046a3
JS
68 Xerror = True;
69 return False;
c978d361
JS
70}
71
72// We assume that toReparent has had its X window set
73// appropriately.
74bool wxReparenter::Reparent(wxWindow* newParent, wxAdoptedWindow* toReparent)
75{
76 XWindowAttributes xwa;
77 Window *children;
78 unsigned int numchildren, each;
79 Window returnroot, returnparent;
80 XErrorHandler old;
81 int parentOffset = 0;
82
83 old = XSetErrorHandler(ErrorHandler);
ab6b6b15
RR
84 XReparentWindow( wxGlobalDisplay(),
85 (Window) toReparent->GetMainWindow(),
86 (Window) newParent->GetMainWindow(),
87 0, 0);
88
89 if (!XQueryTree( wxGlobalDisplay(),
90 (Window) toReparent->GetMainWindow(),
91 &returnroot, &returnparent,
92 &children, &numchildren) || Xerror)
c978d361
JS
93 {
94 XSetErrorHandler(old);
95 return TRUE;
96 }
97
98 if (numchildren > 0)
99 {
046ba576
JS
100 // TEST: see if we can get away with reparenting just
101 // first one
102 if (numchildren > 1)
103 {
104 wxLogDebug(wxT("Found %d, but only reparenting 1 child."), numchildren);
105 numchildren = 1;
106 }
107 wxLogDebug(wxT("Reparenting %d children."), numchildren);
c978d361
JS
108 /* Stacking order is preserved since XQueryTree returns its children in
109 bottommost to topmost order
110 */
111 for (each=0; each<numchildren; each++)
112 {
ab6b6b15
RR
113 XGetWindowAttributes( wxGlobalDisplay(),
114 children[each], &xwa);
c978d361
JS
115 fprintf(stderr,
116 "Reparenting child at offset %d and position %d, %d.\n",
117 parentOffset, parentOffset+xwa.x, parentOffset+xwa.y);
ab6b6b15
RR
118 XReparentWindow( wxGlobalDisplay(),
119 children[each], (Window) newParent->GetMainWindow(),
120 xwa.x, xwa.y);
c978d361
JS
121 }
122 }
123
124 XSetErrorHandler(old);
125 return TRUE;
126}
127
128// Wait for an appropriate window to be created.
129// If exactMatch is FALSE, a substring match is OK.
130// If windowName is empty, then wait for the next overrideRedirect window.
131bool wxReparenter::WaitAndReparent(wxWindow* newParent, wxAdoptedWindow* toReparent,
132 const wxString& windowName,
133 bool exactMatch)
134{
135 sm_newParent = newParent;
136 sm_toReparent = toReparent;
137 sm_exactMatch = exactMatch;
138 sm_name = windowName;
139
ab6b6b15 140 Display* display = wxGlobalDisplay();
c978d361
JS
141 XSelectInput(display,
142 RootWindowOfScreen(DefaultScreenOfDisplay(display)),
143 SubstructureNotifyMask);
144
145 if (!WM_STATE)
146 WM_STATE = XInternAtom(display, "WM_STATE", False);
147
148#ifdef __WXDEBUG__
149 if (!windowName.IsEmpty())
150 wxLogDebug(_T("Waiting for window %s"), windowName.c_str());
151#endif
152
153 sm_done = FALSE;
154
155 wxEventLoop eventLoop;
156 while (!sm_done)
157 {
158 if (eventLoop.Pending())
159 {
160 XEvent xevent;
161 XNextEvent(display, & xevent);
162 if (!wxTheApp->ProcessXEvent((WXEvent*) & xevent))
163 {
164 // Do the local event processing
165 ProcessXEvent((WXEvent*) & xevent);
166 }
167 }
168 else
169 {
170#if wxUSE_TIMER
171 wxTimer::NotifyTimers();
a0749355 172 wxTheApp->ProcessIdle();
c978d361
JS
173#endif
174 }
175 }
176 return TRUE;
177}
178
179bool wxReparenter::ProcessXEvent(WXEvent* event)
180{
181 XEvent* xevent = (XEvent*) event;
182 Window client;
183
184 if (!sm_done)
185 {
186 if (xevent->type == MapNotify)
187 {
188 wxLogDebug(_T("Window was mapped"));
189 }
190
191 if (xevent->type == MapNotify && !xevent->xmap.override_redirect &&
192 (client = (Window) FindAClientWindow((WXWindow) xevent->xmap.window, sm_name)))
193 {
194 wxLogDebug(_T("Found a client window, about to reparent"));
195 wxASSERT(sm_toReparent->GetParent() == NULL);
196
197 sm_toReparent->SetHandle((WXWindow) client);
198 sm_newParent->AddChild(sm_toReparent);
199 sm_done = Reparent(sm_newParent, sm_toReparent);
200 return sm_done;
201 } else if (xevent->type == MapNotify &&
202 xevent->xmap.override_redirect &&
203 xevent->xmap.window)
204 {
205 wxLogDebug(_T("Found an override redirect window, about to reparent"));
206 sm_toReparent->SetHandle((WXWindow) xevent->xmap.window);
207 sm_newParent->AddChild(sm_toReparent);
208 wxASSERT(sm_toReparent->GetParent() == NULL);
209
210 sm_done = Reparent(sm_newParent, sm_toReparent);
211 return sm_done;
212 }
213 }
214 return FALSE;
215}
216
217WXWindow wxReparenter::FindAClientWindow(WXWindow window, const wxString& name)
218{
174046a3
JS
219 int rvalue, i;
220 Atom actualtype;
221 int actualformat;
222 unsigned long nitems, bytesafter;
223 unsigned char *propreturn;
224 Window *children;
225 unsigned int numchildren;
226 Window returnroot, returnparent;
227 Window result = 0;
228 XErrorHandler old;
229 char *clientName;
230
231 Xerror = False;
232 old = XSetErrorHandler(ErrorHandler);
233 rvalue = XGetWindowProperty((Display*) wxGetDisplay(),
234 (Window) window, WM_STATE,
235 0, 1, False,
236 AnyPropertyType, &actualtype, &actualformat,
237 &nitems, &bytesafter, &propreturn);
c978d361 238
c978d361 239 XSetErrorHandler(old);
c978d361 240
174046a3
JS
241 if (!Xerror && rvalue == Success && actualtype != None)
242 {
243 if (rvalue == Success)
244 {
245 XFree((char *) propreturn);
246 }
247 XFetchName((Display*) wxGetDisplay(), (Window) window, &clientName);
248
249 wxString str1(name);
250 wxString str2 = wxString::FromAscii(clientName);
251 str1.Lower();
252 str2.Lower();
253
254 bool matches;
255 if (sm_exactMatch)
256 matches = (name == wxString::FromAscii(clientName));
257 else
258 matches = (str1.Contains(str2) || str2.Contains(str1));
259
260 XFree(clientName);
261
262 if (matches)
263 return (WXWindow) window;
264 else
265 return NULL;
266 }
267
268 old = XSetErrorHandler(ErrorHandler);
269 if (!XQueryTree((Display*) wxGetDisplay(), (Window) window, &returnroot, &returnparent,
270 &children, &numchildren) || Xerror)
271 {
272 XSetErrorHandler(old);
273 return NULL;
274 }
275 XSetErrorHandler(old);
276
277 result = 0;
278 for (i=0; i<(int)numchildren && !result ;i++) {
279 result = (Window) FindAClientWindow((WXWindow) children[i], name);
280 }
281 if (numchildren) {
282 XFree((char *) children);
283 } return (WXWindow) result;
c978d361
JS
284}
285
15d5a947 286#endif