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