]>
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 // ----------------------------------------------------------------------------
24 #include "wx/x11/reparent.h"
25 #include "wx/evtloop.h"
30 #include "wx/x11/private.h"
31 #include "X11/Xatom.h"
37 wxAdoptedWindow::wxAdoptedWindow()
41 wxAdoptedWindow::wxAdoptedWindow(WXWindow window
)
43 m_mainWindow
= window
;
46 wxAdoptedWindow::~wxAdoptedWindow()
55 static Atom WM_STATE
= 0;
56 bool wxReparenter::sm_done
= FALSE
;
57 wxAdoptedWindow
* wxReparenter::sm_toReparent
= NULL
;
58 wxWindow
* wxReparenter::sm_newParent
= NULL
;
59 wxString
wxReparenter::sm_name
;
60 bool wxReparenter::sm_exactMatch
= FALSE
;
62 static int ErrorHandler(Display
* dpy
, XErrorEvent
* event
)
68 // We assume that toReparent has had its X window set
70 bool wxReparenter::Reparent(wxWindow
* newParent
, wxAdoptedWindow
* toReparent
)
72 XWindowAttributes xwa
;
74 unsigned int numchildren
, each
;
75 Window returnroot
, returnparent
;
79 old
= XSetErrorHandler(ErrorHandler
);
80 XReparentWindow( wxGlobalDisplay(),
81 (Window
) toReparent
->GetMainWindow(),
82 (Window
) newParent
->GetMainWindow(),
85 if (!XQueryTree( wxGlobalDisplay(),
86 (Window
) toReparent
->GetMainWindow(),
87 &returnroot
, &returnparent
,
88 &children
, &numchildren
) || Xerror
)
90 XSetErrorHandler(old
);
96 // TEST: see if we can get away with reparenting just
100 wxLogDebug(wxT("Found %d, but only reparenting 1 child."), numchildren
);
103 wxLogDebug(wxT("Reparenting %d children."), numchildren
);
104 /* Stacking order is preserved since XQueryTree returns its children in
105 bottommost to topmost order
107 for (each
=0; each
<numchildren
; each
++)
109 XGetWindowAttributes( wxGlobalDisplay(),
110 children
[each
], &xwa
);
112 "Reparenting child at offset %d and position %d, %d.\n",
113 parentOffset
, parentOffset
+xwa
.x
, parentOffset
+xwa
.y
);
114 XReparentWindow( wxGlobalDisplay(),
115 children
[each
], (Window
) newParent
->GetMainWindow(),
120 XSetErrorHandler(old
);
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.
127 bool wxReparenter::WaitAndReparent(wxWindow
* newParent
, wxAdoptedWindow
* toReparent
,
128 const wxString
& windowName
,
131 sm_newParent
= newParent
;
132 sm_toReparent
= toReparent
;
133 sm_exactMatch
= exactMatch
;
134 sm_name
= windowName
;
136 Display
* display
= wxGlobalDisplay();
137 XSelectInput(display
,
138 RootWindowOfScreen(DefaultScreenOfDisplay(display
)),
139 SubstructureNotifyMask
);
142 WM_STATE
= XInternAtom(display
, "WM_STATE", False
);
145 if (!windowName
.IsEmpty())
146 wxLogDebug(_T("Waiting for window %s"), windowName
.c_str());
151 wxEventLoop eventLoop
;
154 if (eventLoop
.Pending())
157 XNextEvent(display
, & xevent
);
158 if (!wxTheApp
->ProcessXEvent((WXEvent
*) & xevent
))
160 // Do the local event processing
161 ProcessXEvent((WXEvent
*) & xevent
);
167 wxTimer::NotifyTimers();
168 wxTheApp
->ProcessIdle();
175 bool wxReparenter::ProcessXEvent(WXEvent
* event
)
177 XEvent
* xevent
= (XEvent
*) event
;
182 if (xevent
->type
== MapNotify
)
184 wxLogDebug(_T("Window was mapped"));
187 if (xevent
->type
== MapNotify
&& !xevent
->xmap
.override_redirect
&&
188 (client
= (Window
) FindAClientWindow((WXWindow
) xevent
->xmap
.window
, sm_name
)))
190 wxLogDebug(_T("Found a client window, about to reparent"));
191 wxASSERT(sm_toReparent
->GetParent() == NULL
);
193 sm_toReparent
->SetHandle((WXWindow
) client
);
194 sm_newParent
->AddChild(sm_toReparent
);
195 sm_done
= Reparent(sm_newParent
, sm_toReparent
);
197 } else if (xevent
->type
== MapNotify
&&
198 xevent
->xmap
.override_redirect
&&
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
);
206 sm_done
= Reparent(sm_newParent
, sm_toReparent
);
213 WXWindow
wxReparenter::FindAClientWindow(WXWindow window
, const wxString
& name
)
218 unsigned long nitems
, bytesafter
;
219 unsigned char *propreturn
;
221 unsigned int numchildren
;
222 Window returnroot
, returnparent
;
228 old
= XSetErrorHandler(ErrorHandler
);
229 rvalue
= XGetWindowProperty((Display
*) wxGetDisplay(),
230 (Window
) window
, WM_STATE
,
232 AnyPropertyType
, &actualtype
, &actualformat
,
233 &nitems
, &bytesafter
, &propreturn
);
235 XSetErrorHandler(old
);
237 if (!Xerror
&& rvalue
== Success
&& actualtype
!= None
)
239 if (rvalue
== Success
)
241 XFree((char *) propreturn
);
243 XFetchName((Display
*) wxGetDisplay(), (Window
) window
, &clientName
);
246 wxString str2
= wxString::FromAscii(clientName
);
252 matches
= (name
== wxString::FromAscii(clientName
));
254 matches
= (str1
.Contains(str2
) || str2
.Contains(str1
));
259 return (WXWindow
) window
;
264 old
= XSetErrorHandler(ErrorHandler
);
265 if (!XQueryTree((Display
*) wxGetDisplay(), (Window
) window
, &returnroot
, &returnparent
,
266 &children
, &numchildren
) || Xerror
)
268 XSetErrorHandler(old
);
271 XSetErrorHandler(old
);
274 for (i
=0; i
<(int)numchildren
&& !result
;i
++) {
275 result
= (Window
) FindAClientWindow((WXWindow
) children
[i
], name
);
278 XFree((char *) children
);
279 } return (WXWindow
) result
;