]>
git.saurik.com Git - wxWidgets.git/blob - src/x11/reparent.cpp
1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation "reparent.h"
24 #include "wx/x11/reparent.h"
25 #include "wx/evtloop.h"
30 #include "wx/x11/private.h"
31 #include "X11/Xatom.h"
35 Adapted from code by Mike Yang, as follows.
37 From: Mike Yang (mikey@eukanuba.wpd.sgi.com)
38 Subject: Re: Wrapping new widget around existing windows
39 Newsgroups: comp.windows.x
40 View: Complete Thread (17 articles) | Original Format
41 Date: 1991-08-09 09:45:48 PST
44 Enough people asked, so here's my test program which reparents another
45 window. It's a single file (reparent.c), and will work with Motif or
46 Xaw. Xaw users should comment out the "#define MOTIF" line.
48 The reparent program first prompts for the application name of the
49 client that it will reparent. If you're going to start the
50 application override_redirect (e.g. -xrm "*overrideRedirect: true"),
51 then this name is ignored and the first override_redirect window is
52 assumed to be the one.
54 Input focus is supposed to be correctly handled, as is resizing with
55 window manager hints. If you have input focus problems, try launching
56 your application override_redirect instead. This method is preferred
57 anyway, since you can map it off-screen and then avoid the "window
58 flash" effect as the application's top-level window is reparented.
60 -----------------------------------------------------------------------
61 Mike Yang Silicon Graphics, Inc.
62 mikey@sgi.com 415/335-1786
65 ------------------------------- cut here ------------------------------
70 Copyright 1991 by Mike Yang, mikey@sgi.com, Silicon Graphics, Inc.
72 Permission to use, copy, modify, distribute, and sell this software and its
73 documentation for any purpose is hereby granted without fee, provided that
74 the above copyright notice appear in all copies and that both that
75 copyright notice and this permission notice appear in supporting
76 documentation, and that the name of SGI not be used in advertising or
77 publicity pertaining to distribution of the software without specific,
78 written prior permission. SGI makes no representations about the
79 suitability of this software for any purpose. It is provided "as is"
80 without express or implied warranty.
88 wxAdoptedWindow::wxAdoptedWindow()
92 wxAdoptedWindow::wxAdoptedWindow(WXWindow window
)
94 m_mainWidget
= window
;
97 wxAdoptedWindow::~wxAdoptedWindow()
105 static Atom WM_STATE
= 0;
106 bool wxReparenter::sm_done
= FALSE
;
107 wxAdoptedWindow
* wxReparenter::sm_toReparent
= NULL
;
108 wxWindow
* wxReparenter::sm_newParent
= NULL
;
109 wxString
wxReparenter::sm_name
;
110 bool wxReparenter::sm_exactMatch
= FALSE
;
113 ErrorHandler(Display
* dpy
, XErrorEvent
* event
)
119 // We assume that toReparent has had its X window set
121 bool wxReparenter::Reparent(wxWindow
* newParent
, wxAdoptedWindow
* toReparent
)
123 XWindowAttributes xwa
;
125 unsigned int numchildren
, each
;
126 Window returnroot
, returnparent
;
128 int parentOffset
= 0;
130 old
= XSetErrorHandler(ErrorHandler
);
131 XReparentWindow((Display
*) newParent
->GetXDisplay(),
132 (Window
) toReparent
->GetXWindow(),
133 (Window
) newParent
->GetXWindow(),
136 if (!XQueryTree((Display
*) newParent
->GetXDisplay(),
137 (Window
) toReparent
->GetXWindow(),
138 &returnroot
, &returnparent
,
139 &children
, &numchildren
) || Xerror
)
141 XSetErrorHandler(old
);
147 // TEST: see if we can get away with reparenting just
151 wxLogDebug(wxT("Found %d, but only reparenting 1 child."), numchildren
);
154 wxLogDebug(wxT("Reparenting %d children."), numchildren
);
155 /* Stacking order is preserved since XQueryTree returns its children in
156 bottommost to topmost order
158 for (each
=0; each
<numchildren
; each
++)
160 XGetWindowAttributes((Display
*) newParent
->GetXDisplay(),
161 children
[each
], &xwa
);
163 "Reparenting child at offset %d and position %d, %d.\n",
164 parentOffset
, parentOffset
+xwa
.x
, parentOffset
+xwa
.y
);
165 XReparentWindow((Display
*) newParent
->GetXDisplay(),
166 children
[each
], (Window
) newParent
->GetXWindow(),
171 XSetErrorHandler(old
);
175 // Wait for an appropriate window to be created.
176 // If exactMatch is FALSE, a substring match is OK.
177 // If windowName is empty, then wait for the next overrideRedirect window.
178 bool wxReparenter::WaitAndReparent(wxWindow
* newParent
, wxAdoptedWindow
* toReparent
,
179 const wxString
& windowName
,
182 sm_newParent
= newParent
;
183 sm_toReparent
= toReparent
;
184 sm_exactMatch
= exactMatch
;
185 sm_name
= windowName
;
187 Display
* display
= (Display
*) newParent
->GetXDisplay() ;
188 XSelectInput(display
,
189 RootWindowOfScreen(DefaultScreenOfDisplay(display
)),
190 SubstructureNotifyMask
);
193 WM_STATE
= XInternAtom(display
, "WM_STATE", False
);
196 if (!windowName
.IsEmpty())
197 wxLogDebug(_T("Waiting for window %s"), windowName
.c_str());
202 wxEventLoop eventLoop
;
205 if (eventLoop
.Pending())
208 XNextEvent(display
, & xevent
);
209 if (!wxTheApp
->ProcessXEvent((WXEvent
*) & xevent
))
211 // Do the local event processing
212 ProcessXEvent((WXEvent
*) & xevent
);
218 wxTimer::NotifyTimers();
219 wxTheApp
->SendIdleEvents();
226 bool wxReparenter::ProcessXEvent(WXEvent
* event
)
228 XEvent
* xevent
= (XEvent
*) event
;
233 if (xevent
->type
== MapNotify
)
235 wxLogDebug(_T("Window was mapped"));
238 if (xevent
->type
== MapNotify
&& !xevent
->xmap
.override_redirect
&&
239 (client
= (Window
) FindAClientWindow((WXWindow
) xevent
->xmap
.window
, sm_name
)))
241 wxLogDebug(_T("Found a client window, about to reparent"));
242 wxASSERT(sm_toReparent
->GetParent() == NULL
);
244 sm_toReparent
->SetHandle((WXWindow
) client
);
245 sm_newParent
->AddChild(sm_toReparent
);
246 sm_done
= Reparent(sm_newParent
, sm_toReparent
);
248 } else if (xevent
->type
== MapNotify
&&
249 xevent
->xmap
.override_redirect
&&
252 wxLogDebug(_T("Found an override redirect window, about to reparent"));
253 sm_toReparent
->SetHandle((WXWindow
) xevent
->xmap
.window
);
254 sm_newParent
->AddChild(sm_toReparent
);
255 wxASSERT(sm_toReparent
->GetParent() == NULL
);
257 sm_done
= Reparent(sm_newParent
, sm_toReparent
);
264 WXWindow
wxReparenter::FindAClientWindow(WXWindow window
, const wxString
& name
)
269 unsigned long nitems
, bytesafter
;
270 unsigned char *propreturn
;
272 unsigned int numchildren
;
273 Window returnroot
, returnparent
;
279 old
= XSetErrorHandler(ErrorHandler
);
280 rvalue
= XGetWindowProperty((Display
*) wxGetDisplay(),
281 (Window
) window
, WM_STATE
,
283 AnyPropertyType
, &actualtype
, &actualformat
,
284 &nitems
, &bytesafter
, &propreturn
);
285 XSetErrorHandler(old
);
286 if (!Xerror
&& rvalue
== Success
&& actualtype
!= None
)
288 if (rvalue
== Success
)
290 XFree((char *) propreturn
);
292 XFetchName((Display
*) wxGetDisplay(), (Window
) window
, &clientName
);
295 wxString
str2(clientName
);
301 matches
= (name
== clientName
);
303 matches
= (str1
.Contains(str2
) || str2
.Contains(str1
));
308 return (WXWindow
) window
;
313 old
= XSetErrorHandler(ErrorHandler
);
314 if (!XQueryTree((Display
*) wxGetDisplay(), (Window
) window
, &returnroot
, &returnparent
,
315 &children
, &numchildren
) || Xerror
) {
316 XSetErrorHandler(old
);
319 XSetErrorHandler(old
);
322 for (i
=0; i
<(int)numchildren
&& !result
;i
++) {
323 result
= (Window
) FindAClientWindow((WXWindow
) children
[i
], name
);
326 XFree((char *) children
);
327 } return (WXWindow
) result
;