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