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