]> git.saurik.com Git - wxWidgets.git/blob - src/x11/reparent.cpp
added wxWindow::GetPrev/NextSibling()
[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
31 #ifndef WX_PRECOMP
32 #include "wx/log.h"
33 #include "wx/app.h"
34 #include "wx/timer.h"
35 #endif
36
37 #include "wx/evtloop.h"
38
39 #include "wx/x11/private.h"
40 #include "X11/Xatom.h"
41
42 #include "wx/generic/private/timer.h"
43
44 /*
45 * wxAdoptedWindow
46 */
47
48 wxAdoptedWindow::wxAdoptedWindow()
49 {
50 }
51
52 wxAdoptedWindow::wxAdoptedWindow(WXWindow window)
53 {
54 m_mainWindow = window;
55 }
56
57 wxAdoptedWindow::~wxAdoptedWindow()
58 {
59 }
60
61 /*
62 * wxReparenter
63 */
64
65 static bool Xerror;
66 static Atom WM_STATE = 0;
67 bool wxReparenter::sm_done = false;
68 wxAdoptedWindow* wxReparenter::sm_toReparent = NULL;
69 wxWindow* wxReparenter::sm_newParent = NULL;
70 wxString wxReparenter::sm_name;
71 bool wxReparenter::sm_exactMatch = false;
72
73 static int ErrorHandler(Display* WXUNUSED(dpy), XErrorEvent* WXUNUSED(event))
74 {
75 Xerror = True;
76 return False;
77 }
78
79 // We assume that toReparent has had its X window set
80 // appropriately.
81 bool 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);
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)
100 {
101 XSetErrorHandler(old);
102 return true;
103 }
104
105 if (numchildren > 0)
106 {
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);
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 {
120 XGetWindowAttributes( wxGlobalDisplay(),
121 children[each], &xwa);
122 fprintf(stderr,
123 "Reparenting child at offset %d and position %d, %d.\n",
124 parentOffset, parentOffset+xwa.x, parentOffset+xwa.y);
125 XReparentWindow( wxGlobalDisplay(),
126 children[each], (Window) newParent->GetMainWindow(),
127 xwa.x, xwa.y);
128 }
129 }
130
131 XSetErrorHandler(old);
132 return true;
133 }
134
135 // Wait for an appropriate window to be created.
136 // If exactMatch is false, a substring match is OK.
137 // If windowName is empty, then wait for the next overrideRedirect window.
138 bool 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;
146
147 Display* display = wxGlobalDisplay();
148 XSelectInput(display,
149 RootWindowOfScreen(DefaultScreenOfDisplay(display)),
150 SubstructureNotifyMask);
151
152 if (!WM_STATE)
153 WM_STATE = XInternAtom(display, "WM_STATE", False);
154
155 #ifdef __WXDEBUG__
156 if (!windowName.empty())
157 wxLogDebug(_T("Waiting for window %s"), windowName.c_str());
158 #endif
159
160 sm_done = false;
161
162 wxEventLoop eventLoop;
163 while (!sm_done)
164 {
165 if (eventLoop.Pending())
166 {
167 XEvent xevent;
168 XNextEvent(display, & xevent);
169 if (!wxTheApp->ProcessXEvent((WXEvent*) & xevent))
170 {
171 // Do the local event processing
172 ProcessXEvent((WXEvent*) & xevent);
173 }
174 }
175 else
176 {
177 #if wxUSE_TIMER
178 wxGenericTimerImpl::NotifyTimers();
179 wxTheApp->ProcessIdle();
180 #endif
181 }
182 }
183 return true;
184 }
185
186 bool wxReparenter::ProcessXEvent(WXEvent* event)
187 {
188 XEvent* xevent = (XEvent*) event;
189 Window client;
190
191 if (!sm_done)
192 {
193 if (xevent->type == MapNotify)
194 {
195 wxLogDebug(_T("Window was mapped"));
196 }
197
198 if (xevent->type == MapNotify && !xevent->xmap.override_redirect &&
199 (client = (Window) FindAClientWindow((WXWindow) xevent->xmap.window, sm_name)))
200 {
201 wxLogDebug(_T("Found a client window, about to reparent"));
202 wxASSERT(sm_toReparent->GetParent() == NULL);
203
204 sm_toReparent->SetHandle((WXWindow) client);
205 sm_newParent->AddChild(sm_toReparent);
206 sm_done = Reparent(sm_newParent, sm_toReparent);
207 return sm_done;
208 } else if (xevent->type == MapNotify &&
209 xevent->xmap.override_redirect &&
210 xevent->xmap.window)
211 {
212 wxLogDebug(_T("Found an override redirect window, about to reparent"));
213 sm_toReparent->SetHandle((WXWindow) xevent->xmap.window);
214 sm_newParent->AddChild(sm_toReparent);
215 wxASSERT(sm_toReparent->GetParent() == NULL);
216
217 sm_done = Reparent(sm_newParent, sm_toReparent);
218 return sm_done;
219 }
220 }
221 return false;
222 }
223
224 WXWindow wxReparenter::FindAClientWindow(WXWindow window, const wxString& name)
225 {
226 int rvalue, i;
227 Atom actualtype;
228 int actualformat;
229 unsigned long nitems, bytesafter;
230 unsigned char *propreturn;
231 Window *children;
232 unsigned int numchildren;
233 Window returnroot, returnparent;
234 Window result = 0;
235 XErrorHandler old;
236 char *clientName;
237
238 Xerror = False;
239 old = XSetErrorHandler(ErrorHandler);
240 rvalue = XGetWindowProperty((Display*) wxGetDisplay(),
241 (Window) window, WM_STATE,
242 0, 1, False,
243 AnyPropertyType, &actualtype, &actualformat,
244 &nitems, &bytesafter, &propreturn);
245
246 XSetErrorHandler(old);
247
248 if (!Xerror && rvalue == Success && actualtype != None)
249 {
250 if (rvalue == Success)
251 {
252 XFree((char *) propreturn);
253 }
254 XFetchName((Display*) wxGetDisplay(), (Window) window, &clientName);
255
256 wxString str1(name);
257 wxString str2 = wxString::FromAscii(clientName);
258 str1.Lower();
259 str2.Lower();
260
261 bool matches;
262 if (sm_exactMatch)
263 matches = (name == wxString::FromAscii(clientName));
264 else
265 matches = (str1.Contains(str2) || str2.Contains(str1));
266
267 XFree(clientName);
268
269 if (matches)
270 return (WXWindow) window;
271 else
272 return NULL;
273 }
274
275 old = XSetErrorHandler(ErrorHandler);
276 if (!XQueryTree((Display*) wxGetDisplay(), (Window) window, &returnroot, &returnparent,
277 &children, &numchildren) || Xerror)
278 {
279 XSetErrorHandler(old);
280 return NULL;
281 }
282 XSetErrorHandler(old);
283
284 result = 0;
285 for (i=0; i<(int)numchildren && !result ;i++) {
286 result = (Window) FindAClientWindow((WXWindow) children[i], name);
287 }
288 if (numchildren) {
289 XFree((char *) children);
290 } return (WXWindow) result;
291 }
292
293 #endif // !wxUSE_NANOX