]>
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 fprintf(stderr
, "Reparenting %d children.\n", numchildren
);
148 /* Stacking order is preserved since XQueryTree returns its children in
149 bottommost to topmost order
151 for (each
=0; each
<numchildren
; each
++)
153 XGetWindowAttributes((Display
*) newParent
->GetXDisplay(),
154 children
[each
], &xwa
);
156 "Reparenting child at offset %d and position %d, %d.\n",
157 parentOffset
, parentOffset
+xwa
.x
, parentOffset
+xwa
.y
);
158 XReparentWindow((Display
*) newParent
->GetXDisplay(),
159 children
[each
], (Window
) newParent
->GetXWindow(),
164 XSetErrorHandler(old
);
168 // Wait for an appropriate window to be created.
169 // If exactMatch is FALSE, a substring match is OK.
170 // If windowName is empty, then wait for the next overrideRedirect window.
171 bool wxReparenter::WaitAndReparent(wxWindow
* newParent
, wxAdoptedWindow
* toReparent
,
172 const wxString
& windowName
,
175 sm_newParent
= newParent
;
176 sm_toReparent
= toReparent
;
177 sm_exactMatch
= exactMatch
;
178 sm_name
= windowName
;
180 Display
* display
= (Display
*) newParent
->GetXDisplay() ;
181 XSelectInput(display
,
182 RootWindowOfScreen(DefaultScreenOfDisplay(display
)),
183 SubstructureNotifyMask
);
186 WM_STATE
= XInternAtom(display
, "WM_STATE", False
);
189 if (!windowName
.IsEmpty())
190 wxLogDebug(_T("Waiting for window %s"), windowName
.c_str());
195 wxEventLoop eventLoop
;
198 if (eventLoop
.Pending())
201 XNextEvent(display
, & xevent
);
202 if (!wxTheApp
->ProcessXEvent((WXEvent
*) & xevent
))
204 // Do the local event processing
205 ProcessXEvent((WXEvent
*) & xevent
);
211 wxTimer::NotifyTimers();
212 wxTheApp
->SendIdleEvents();
219 bool wxReparenter::ProcessXEvent(WXEvent
* event
)
221 XEvent
* xevent
= (XEvent
*) event
;
226 if (xevent
->type
== MapNotify
)
228 wxLogDebug(_T("Window was mapped"));
231 if (xevent
->type
== MapNotify
&& !xevent
->xmap
.override_redirect
&&
232 (client
= (Window
) FindAClientWindow((WXWindow
) xevent
->xmap
.window
, sm_name
)))
234 wxLogDebug(_T("Found a client window, about to reparent"));
235 wxASSERT(sm_toReparent
->GetParent() == NULL
);
237 sm_toReparent
->SetHandle((WXWindow
) client
);
238 sm_newParent
->AddChild(sm_toReparent
);
239 sm_done
= Reparent(sm_newParent
, sm_toReparent
);
241 } else if (xevent
->type
== MapNotify
&&
242 xevent
->xmap
.override_redirect
&&
245 wxLogDebug(_T("Found an override redirect window, about to reparent"));
246 sm_toReparent
->SetHandle((WXWindow
) xevent
->xmap
.window
);
247 sm_newParent
->AddChild(sm_toReparent
);
248 wxASSERT(sm_toReparent
->GetParent() == NULL
);
250 sm_done
= Reparent(sm_newParent
, sm_toReparent
);
257 WXWindow
wxReparenter::FindAClientWindow(WXWindow window
, const wxString
& name
)
262 unsigned long nitems
, bytesafter
;
263 unsigned char *propreturn
;
265 unsigned int numchildren
;
266 Window returnroot
, returnparent
;
272 old
= XSetErrorHandler(ErrorHandler
);
273 rvalue
= XGetWindowProperty((Display
*) wxGetDisplay(),
274 (Window
) window
, WM_STATE
,
276 AnyPropertyType
, &actualtype
, &actualformat
,
277 &nitems
, &bytesafter
, &propreturn
);
278 XSetErrorHandler(old
);
279 if (!Xerror
&& rvalue
== Success
&& actualtype
!= None
)
281 if (rvalue
== Success
)
283 XFree((char *) propreturn
);
285 XFetchName((Display
*) wxGetDisplay(), (Window
) window
, &clientName
);
288 wxString
str2(clientName
);
294 matches
= (name
== clientName
);
296 matches
= (str1
.Contains(str2
) || str2
.Contains(str1
));
301 return (WXWindow
) window
;
306 old
= XSetErrorHandler(ErrorHandler
);
307 if (!XQueryTree((Display
*) wxGetDisplay(), (Window
) window
, &returnroot
, &returnparent
,
308 &children
, &numchildren
) || Xerror
) {
309 XSetErrorHandler(old
);
312 XSetErrorHandler(old
);
315 for (i
=0; i
<(int)numchildren
&& !result
;i
++) {
316 result
= (Window
) FindAClientWindow((WXWindow
) children
[i
], name
);
319 XFree((char *) children
);
320 } return (WXWindow
) result
;