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