]> git.saurik.com Git - wxWidgets.git/blame - src/x11/reparent.cpp
Applied #15375 to stop event-sending in generic wxSpinCtrl ctor (eco)
[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
c978d361 7// Copyright: (c) Julian Smart
65571936 8// Licence: wxWindows licence
c978d361
JS
9/////////////////////////////////////////////////////////////////////////////
10
521bf4ff
WS
11// for compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
14#if defined(__BORLANDC__)
15#pragma hdrstop
16#endif
17
c978d361
JS
18// ============================================================================
19// declarations
20// ============================================================================
21
22// ----------------------------------------------------------------------------
23// headers
24// ----------------------------------------------------------------------------
25
15d5a947
JS
26#if !wxUSE_NANOX
27
2b5f62a0 28#include "wx/x11/reparent.h"
e4db172a
WS
29
30#ifndef WX_PRECOMP
31 #include "wx/log.h"
670f9935 32 #include "wx/app.h"
c0badb70 33 #include "wx/timer.h"
e4db172a
WS
34#endif
35
c978d361 36#include "wx/evtloop.h"
c978d361
JS
37
38#include "wx/x11/private.h"
39#include "X11/Xatom.h"
40
c2ca375c
VZ
41#include "wx/generic/private/timer.h"
42
c978d361
JS
43/*
44 * wxAdoptedWindow
45 */
46
47wxAdoptedWindow::wxAdoptedWindow()
48{
49}
50
51wxAdoptedWindow::wxAdoptedWindow(WXWindow window)
52{
ab6b6b15 53 m_mainWindow = window;
c978d361
JS
54}
55
56wxAdoptedWindow::~wxAdoptedWindow()
57{
58}
174046a3 59
c978d361
JS
60/*
61 * wxReparenter
62 */
63
64static bool Xerror;
65static Atom WM_STATE = 0;
670f9935 66bool wxReparenter::sm_done = false;
c978d361
JS
67wxAdoptedWindow* wxReparenter::sm_toReparent = NULL;
68wxWindow* wxReparenter::sm_newParent = NULL;
69wxString wxReparenter::sm_name;
670f9935 70bool wxReparenter::sm_exactMatch = false;
c978d361 71
89954433 72static int ErrorHandler(Display* WXUNUSED(dpy), XErrorEvent* WXUNUSED(event))
c978d361 73{
174046a3
JS
74 Xerror = True;
75 return False;
c978d361
JS
76}
77
78// We assume that toReparent has had its X window set
79// appropriately.
80bool wxReparenter::Reparent(wxWindow* newParent, wxAdoptedWindow* toReparent)
81{
82 XWindowAttributes xwa;
83 Window *children;
84 unsigned int numchildren, each;
85 Window returnroot, returnparent;
86 XErrorHandler old;
87 int parentOffset = 0;
88
89 old = XSetErrorHandler(ErrorHandler);
ab6b6b15 90 XReparentWindow( wxGlobalDisplay(),
679918f9
VZ
91 (Window) toReparent->X11GetMainWindow(),
92 (Window) newParent->X11GetMainWindow(),
ab6b6b15
RR
93 0, 0);
94
95 if (!XQueryTree( wxGlobalDisplay(),
679918f9 96 (Window) toReparent->X11GetMainWindow(),
ab6b6b15
RR
97 &returnroot, &returnparent,
98 &children, &numchildren) || Xerror)
c978d361
JS
99 {
100 XSetErrorHandler(old);
521bf4ff 101 return true;
c978d361
JS
102 }
103
104 if (numchildren > 0)
105 {
046ba576
JS
106 // TEST: see if we can get away with reparenting just
107 // first one
108 if (numchildren > 1)
109 {
110 wxLogDebug(wxT("Found %d, but only reparenting 1 child."), numchildren);
111 numchildren = 1;
112 }
113 wxLogDebug(wxT("Reparenting %d children."), numchildren);
c978d361
JS
114 /* Stacking order is preserved since XQueryTree returns its children in
115 bottommost to topmost order
116 */
117 for (each=0; each<numchildren; each++)
118 {
ab6b6b15
RR
119 XGetWindowAttributes( wxGlobalDisplay(),
120 children[each], &xwa);
c978d361
JS
121 fprintf(stderr,
122 "Reparenting child at offset %d and position %d, %d.\n",
123 parentOffset, parentOffset+xwa.x, parentOffset+xwa.y);
ab6b6b15 124 XReparentWindow( wxGlobalDisplay(),
679918f9 125 children[each], (Window) newParent->X11GetMainWindow(),
ab6b6b15 126 xwa.x, xwa.y);
c978d361
JS
127 }
128 }
129
130 XSetErrorHandler(old);
521bf4ff 131 return true;
c978d361
JS
132}
133
134// Wait for an appropriate window to be created.
670f9935 135// If exactMatch is false, a substring match is OK.
c978d361
JS
136// If windowName is empty, then wait for the next overrideRedirect window.
137bool wxReparenter::WaitAndReparent(wxWindow* newParent, wxAdoptedWindow* toReparent,
138 const wxString& windowName,
139 bool exactMatch)
140{
141 sm_newParent = newParent;
142 sm_toReparent = toReparent;
143 sm_exactMatch = exactMatch;
144 sm_name = windowName;
521bf4ff 145
ab6b6b15 146 Display* display = wxGlobalDisplay();
c978d361
JS
147 XSelectInput(display,
148 RootWindowOfScreen(DefaultScreenOfDisplay(display)),
149 SubstructureNotifyMask);
150
151 if (!WM_STATE)
152 WM_STATE = XInternAtom(display, "WM_STATE", False);
153
670f9935 154 sm_done = false;
c978d361
JS
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
c2ca375c 172 wxGenericTimerImpl::NotifyTimers();
a0749355 173 wxTheApp->ProcessIdle();
c978d361
JS
174#endif
175 }
176 }
521bf4ff 177 return true;
c978d361
JS
178}
179
180bool 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 {
9a83f860 189 wxLogDebug(wxT("Window was mapped"));
c978d361 190 }
521bf4ff 191
c978d361
JS
192 if (xevent->type == MapNotify && !xevent->xmap.override_redirect &&
193 (client = (Window) FindAClientWindow((WXWindow) xevent->xmap.window, sm_name)))
194 {
9a83f860 195 wxLogDebug(wxT("Found a client window, about to reparent"));
c978d361 196 wxASSERT(sm_toReparent->GetParent() == NULL);
521bf4ff 197
c978d361
JS
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 {
9a83f860 206 wxLogDebug(wxT("Found an override redirect window, about to reparent"));
c978d361
JS
207 sm_toReparent->SetHandle((WXWindow) xevent->xmap.window);
208 sm_newParent->AddChild(sm_toReparent);
209 wxASSERT(sm_toReparent->GetParent() == NULL);
521bf4ff 210
c978d361
JS
211 sm_done = Reparent(sm_newParent, sm_toReparent);
212 return sm_done;
213 }
214 }
670f9935 215 return false;
c978d361
JS
216}
217
218WXWindow wxReparenter::FindAClientWindow(WXWindow window, const wxString& name)
219{
174046a3
JS
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;
521bf4ff 231
174046a3
JS
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);
c978d361 239
c978d361 240 XSetErrorHandler(old);
c978d361 241
174046a3
JS
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);
521bf4ff 249
174046a3
JS
250 wxString str1(name);
251 wxString str2 = wxString::FromAscii(clientName);
252 str1.Lower();
253 str2.Lower();
521bf4ff 254
174046a3
JS
255 bool matches;
256 if (sm_exactMatch)
257 matches = (name == wxString::FromAscii(clientName));
258 else
259 matches = (str1.Contains(str2) || str2.Contains(str1));
521bf4ff 260
174046a3 261 XFree(clientName);
521bf4ff 262
174046a3
JS
263 if (matches)
264 return (WXWindow) window;
265 else
266 return NULL;
267 }
521bf4ff 268
174046a3
JS
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);
521bf4ff 277
174046a3
JS
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;
c978d361
JS
285}
286
e4db172a 287#endif // !wxUSE_NANOX