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