]>
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"
28 #include "wx/x11/reparent.h"
29 #include "wx/evtloop.h"
34 #include "wx/x11/private.h"
35 #include "X11/Xatom.h"
41 wxAdoptedWindow::wxAdoptedWindow()
45 wxAdoptedWindow::wxAdoptedWindow(WXWindow window
)
47 m_mainWindow
= window
;
50 wxAdoptedWindow::~wxAdoptedWindow()
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
;
66 static int ErrorHandler(Display
* dpy
, XErrorEvent
* event
)
72 // We assume that toReparent has had its X window set
74 bool wxReparenter::Reparent(wxWindow
* newParent
, wxAdoptedWindow
* toReparent
)
76 XWindowAttributes xwa
;
78 unsigned int numchildren
, each
;
79 Window returnroot
, returnparent
;
83 old
= XSetErrorHandler(ErrorHandler
);
84 XReparentWindow( wxGlobalDisplay(),
85 (Window
) toReparent
->GetMainWindow(),
86 (Window
) newParent
->GetMainWindow(),
89 if (!XQueryTree( wxGlobalDisplay(),
90 (Window
) toReparent
->GetMainWindow(),
91 &returnroot
, &returnparent
,
92 &children
, &numchildren
) || Xerror
)
94 XSetErrorHandler(old
);
100 // TEST: see if we can get away with reparenting just
104 wxLogDebug(wxT("Found %d, but only reparenting 1 child."), numchildren
);
107 wxLogDebug(wxT("Reparenting %d children."), numchildren
);
108 /* Stacking order is preserved since XQueryTree returns its children in
109 bottommost to topmost order
111 for (each
=0; each
<numchildren
; each
++)
113 XGetWindowAttributes( wxGlobalDisplay(),
114 children
[each
], &xwa
);
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(),
124 XSetErrorHandler(old
);
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
,
135 sm_newParent
= newParent
;
136 sm_toReparent
= toReparent
;
137 sm_exactMatch
= exactMatch
;
138 sm_name
= windowName
;
140 Display
* display
= wxGlobalDisplay();
141 XSelectInput(display
,
142 RootWindowOfScreen(DefaultScreenOfDisplay(display
)),
143 SubstructureNotifyMask
);
146 WM_STATE
= XInternAtom(display
, "WM_STATE", False
);
149 if (!windowName
.IsEmpty())
150 wxLogDebug(_T("Waiting for window %s"), windowName
.c_str());
155 wxEventLoop eventLoop
;
158 if (eventLoop
.Pending())
161 XNextEvent(display
, & xevent
);
162 if (!wxTheApp
->ProcessXEvent((WXEvent
*) & xevent
))
164 // Do the local event processing
165 ProcessXEvent((WXEvent
*) & xevent
);
171 wxTimer::NotifyTimers();
172 wxTheApp
->ProcessIdle();
179 bool wxReparenter::ProcessXEvent(WXEvent
* event
)
181 XEvent
* xevent
= (XEvent
*) event
;
186 if (xevent
->type
== MapNotify
)
188 wxLogDebug(_T("Window was mapped"));
191 if (xevent
->type
== MapNotify
&& !xevent
->xmap
.override_redirect
&&
192 (client
= (Window
) FindAClientWindow((WXWindow
) xevent
->xmap
.window
, sm_name
)))
194 wxLogDebug(_T("Found a client window, about to reparent"));
195 wxASSERT(sm_toReparent
->GetParent() == NULL
);
197 sm_toReparent
->SetHandle((WXWindow
) client
);
198 sm_newParent
->AddChild(sm_toReparent
);
199 sm_done
= Reparent(sm_newParent
, sm_toReparent
);
201 } else if (xevent
->type
== MapNotify
&&
202 xevent
->xmap
.override_redirect
&&
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
);
210 sm_done
= Reparent(sm_newParent
, sm_toReparent
);
217 WXWindow
wxReparenter::FindAClientWindow(WXWindow window
, const wxString
& name
)
222 unsigned long nitems
, bytesafter
;
223 unsigned char *propreturn
;
225 unsigned int numchildren
;
226 Window returnroot
, returnparent
;
232 old
= XSetErrorHandler(ErrorHandler
);
233 rvalue
= XGetWindowProperty((Display
*) wxGetDisplay(),
234 (Window
) window
, WM_STATE
,
236 AnyPropertyType
, &actualtype
, &actualformat
,
237 &nitems
, &bytesafter
, &propreturn
);
239 XSetErrorHandler(old
);
241 if (!Xerror
&& rvalue
== Success
&& actualtype
!= None
)
243 if (rvalue
== Success
)
245 XFree((char *) propreturn
);
247 XFetchName((Display
*) wxGetDisplay(), (Window
) window
, &clientName
);
250 wxString str2
= wxString::FromAscii(clientName
);
256 matches
= (name
== wxString::FromAscii(clientName
));
258 matches
= (str1
.Contains(str2
) || str2
.Contains(str1
));
263 return (WXWindow
) window
;
268 old
= XSetErrorHandler(ErrorHandler
);
269 if (!XQueryTree((Display
*) wxGetDisplay(), (Window
) window
, &returnroot
, &returnparent
,
270 &children
, &numchildren
) || Xerror
)
272 XSetErrorHandler(old
);
275 XSetErrorHandler(old
);
278 for (i
=0; i
<(int)numchildren
&& !result
;i
++) {
279 result
= (Window
) FindAClientWindow((WXWindow
) children
[i
], name
);
282 XFree((char *) children
);
283 } return (WXWindow
) result
;