Added reparenting helper classes to help apps to grab the windows
of other applications. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@14524 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -631,6 +631,7 @@ palette.cpp X11
|
||||
pen.cpp X11
|
||||
popupwin.cpp X11
|
||||
region.cpp X11
|
||||
reparent.cpp X11
|
||||
settings.cpp X11
|
||||
toplevel.cpp X11
|
||||
utils.cpp X11
|
||||
@@ -1206,6 +1207,7 @@ pen.h X11H
|
||||
print.h X11H
|
||||
private.h X11H
|
||||
region.h X11H
|
||||
reparent.h X11H
|
||||
settings.h X11H
|
||||
toolbar.h X11H
|
||||
toplevel.h X11H
|
||||
|
71
include/wx/x11/reparent.h
Normal file
71
include/wx/x11/reparent.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: reparent.h
|
||||
// Purpose: Reparenting classes
|
||||
// Author: Julian Smart
|
||||
// Modified by:
|
||||
// Created: 2002-03-09
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Julian Smart
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _WX_REPARENT_H_
|
||||
#define _WX_REPARENT_H_
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "reparent.h"
|
||||
#endif
|
||||
|
||||
#include "wx/window.h"
|
||||
|
||||
/*
|
||||
* This class helps to reparent a specific window
|
||||
*/
|
||||
|
||||
class wxAdoptedWindow;
|
||||
class wxReparenter: public wxObject
|
||||
{
|
||||
public:
|
||||
wxReparenter() {}
|
||||
|
||||
// We assume that toReparent has had its X window set
|
||||
// appropriately. toReparent is typically a wxAdoptedWindow.
|
||||
bool Reparent(wxWindow* newParent, wxAdoptedWindow* toReparent);
|
||||
|
||||
// Wait for an appropriate window to be created.
|
||||
// If exactMatch is FALSE, a substring match is OK.
|
||||
// If windowName is empty, then wait for the next overrideRedirect window.
|
||||
bool WaitAndReparent(wxWindow* newParent, wxAdoptedWindow* toReparent,
|
||||
const wxString& windowName = wxEmptyString,
|
||||
bool exactMatch = TRUE);
|
||||
|
||||
protected:
|
||||
|
||||
bool ProcessXEvent(WXEvent* event);
|
||||
WXWindow FindAClientWindow(WXWindow window, const wxString& name);
|
||||
|
||||
static bool sm_done;
|
||||
static wxAdoptedWindow* sm_toReparent;
|
||||
static wxWindow* sm_newParent;
|
||||
static wxString sm_name;
|
||||
static bool sm_exactMatch;
|
||||
};
|
||||
|
||||
/*
|
||||
* A window that adopts its handle from the native
|
||||
* toolkit. It has no parent until reparented.
|
||||
*/
|
||||
|
||||
class wxAdoptedWindow: public wxWindow
|
||||
{
|
||||
public:
|
||||
wxAdoptedWindow();
|
||||
wxAdoptedWindow(WXWindow window);
|
||||
~wxAdoptedWindow();
|
||||
|
||||
void SetHandle(WXWindow window) { m_mainWidget = window; }
|
||||
WXWindow GetHandle() const { return GetXWindow(); }
|
||||
};
|
||||
|
||||
#endif
|
||||
// _WX_REPARENT_H_
|
@@ -403,7 +403,7 @@ bool wxApp::Initialized()
|
||||
|
||||
int wxApp::MainLoop()
|
||||
{
|
||||
int rt;
|
||||
int rt;
|
||||
m_mainLoop = new wxEventLoop;
|
||||
|
||||
rt = m_mainLoop->Run();
|
||||
|
@@ -1410,6 +1410,7 @@ int GrGetPixelColor(GR_SCREEN_INFO* sinfo, GR_PALETTE* palette, GR_PIXELVAL pixe
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
// wxUSE_NANOX
|
||||
|
||||
|
@@ -840,6 +840,126 @@ void wxWindowDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y)
|
||||
{
|
||||
}
|
||||
|
||||
#if wxUSE_NANOX
|
||||
void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
|
||||
wxCoord x, wxCoord y,
|
||||
bool useMask )
|
||||
{
|
||||
wxCHECK_RET( Ok(), wxT("invalid window dc") );
|
||||
|
||||
wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
|
||||
|
||||
bool is_mono = (bitmap.GetBitmap() != NULL);
|
||||
|
||||
/* scale/translate size and position */
|
||||
int xx = XLOG2DEV(x);
|
||||
int yy = YLOG2DEV(y);
|
||||
|
||||
int w = bitmap.GetWidth();
|
||||
int h = bitmap.GetHeight();
|
||||
|
||||
CalcBoundingBox( x, y );
|
||||
CalcBoundingBox( x + w, y + h );
|
||||
|
||||
if (!m_window) return;
|
||||
|
||||
int ww = XLOG2DEVREL(w);
|
||||
int hh = YLOG2DEVREL(h);
|
||||
|
||||
/* compare to current clipping region */
|
||||
if (!m_currentClippingRegion.IsNull())
|
||||
{
|
||||
wxRegion tmp( xx,yy,ww,hh );
|
||||
tmp.Intersect( m_currentClippingRegion );
|
||||
if (tmp.IsEmpty())
|
||||
return;
|
||||
}
|
||||
|
||||
/* scale bitmap if required */
|
||||
wxBitmap use_bitmap;
|
||||
if ((w != ww) || (h != hh))
|
||||
{
|
||||
wxImage image( bitmap );
|
||||
image.Rescale( ww, hh );
|
||||
#if 0
|
||||
if (is_mono)
|
||||
use_bitmap = image.ConvertToMonoBitmap(255,255,255);
|
||||
else
|
||||
#endif
|
||||
use_bitmap = image.ConvertToBitmap();
|
||||
}
|
||||
else
|
||||
{
|
||||
use_bitmap = bitmap;
|
||||
}
|
||||
|
||||
/* apply mask if any */
|
||||
WXPixmap mask = NULL;
|
||||
if (use_bitmap.GetMask())
|
||||
mask = use_bitmap.GetMask()->GetBitmap();
|
||||
|
||||
if (useMask && mask)
|
||||
{
|
||||
Pixmap pixmap = (Pixmap) use_bitmap.GetPixmap() ;
|
||||
Pixmap maskPixmap = (Pixmap) use_bitmap.GetMask()->GetBitmap() ;
|
||||
Pixmap bufPixmap = GrNewPixmap(w, h, 0);
|
||||
GC gc = GrNewGC();
|
||||
GrSetGCUseBackground(gc, FALSE);
|
||||
GrSetGCMode(gc, GR_MODE_COPY);
|
||||
|
||||
// This code assumes that background and foreground
|
||||
// colours are used in ROPs, like in MSW.
|
||||
// Not sure if this is true.
|
||||
|
||||
// Copy destination to buffer.
|
||||
// In DoBlit, we need this step because Blit has
|
||||
// a ROP argument. Here, we don't need it.
|
||||
// In DoBlit, we may be able to eliminate this step
|
||||
// if we check if the rop = copy
|
||||
#if 0
|
||||
GrCopyArea(bufPixmap, gc, 0, 0, w, h, (Window) m_window,
|
||||
0, 0, GR_MODE_COPY);
|
||||
#endif
|
||||
|
||||
// Copy src to buffer using selected raster op (none selected
|
||||
// in DrawBitmap, so just use Gxcopy)
|
||||
GrCopyArea(bufPixmap, gc, 0, 0, w, h, pixmap,
|
||||
0, 0, GR_MODE_COPY);
|
||||
|
||||
// Set masked area in buffer to BLACK (pixel value 0)
|
||||
GrSetGCBackground(gc, WHITE);
|
||||
GrSetGCForeground(gc, BLACK);
|
||||
GrCopyArea(bufPixmap, gc, 0, 0, w, h, maskPixmap,
|
||||
0, 0, GR_MODE_AND);
|
||||
|
||||
// set unmasked area in dest to BLACK
|
||||
GrSetGCBackground(gc, BLACK);
|
||||
GrSetGCForeground(gc, WHITE);
|
||||
GrCopyArea((Window) m_window, gc, xx, yy, w, h, maskPixmap,
|
||||
0, 0, GR_MODE_AND);
|
||||
|
||||
// OR buffer to dest
|
||||
GrCopyArea((Window) m_window, gc, xx, yy, w, h, bufPixmap,
|
||||
0, 0, GR_MODE_OR);
|
||||
|
||||
GrDestroyGC(gc);
|
||||
GrDestroyWindow(bufPixmap);
|
||||
}
|
||||
else
|
||||
XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window,
|
||||
(GC) m_penGC, 0, 0, w, h, xx, yy );
|
||||
|
||||
/* remove mask again if any */
|
||||
if (useMask && mask)
|
||||
{
|
||||
if (!m_currentClippingRegion.IsNull())
|
||||
XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// Normal X11
|
||||
void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
|
||||
wxCoord x, wxCoord y,
|
||||
bool useMask )
|
||||
@@ -970,6 +1090,8 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// wxUSE_NANOX/!wxUSE_NANOX
|
||||
|
||||
bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
|
||||
wxDC *source, wxCoord xsrc, wxCoord ysrc, int rop, bool useMask,
|
||||
|
@@ -27,6 +27,7 @@ ALL_SOURCES = \
|
||||
x11/pen.cpp \
|
||||
x11/popupwin.cpp \
|
||||
x11/region.cpp \
|
||||
x11/reparent.cpp \
|
||||
x11/settings.cpp \
|
||||
x11/toplevel.cpp \
|
||||
x11/utils.cpp \
|
||||
@@ -492,6 +493,7 @@ ALL_HEADERS = \
|
||||
x11/print.h \
|
||||
x11/private.h \
|
||||
x11/region.h \
|
||||
x11/reparent.h \
|
||||
x11/settings.h \
|
||||
x11/toolbar.h \
|
||||
x11/toplevel.h \
|
||||
@@ -622,6 +624,7 @@ GUI_LOWLEVEL_OBJS = \
|
||||
pen.o \
|
||||
popupwin.o \
|
||||
region.o \
|
||||
reparent.o \
|
||||
settings.o \
|
||||
toplevel.o \
|
||||
utils.o \
|
||||
|
322
src/x11/reparent.cpp
Normal file
322
src/x11/reparent.cpp
Normal file
@@ -0,0 +1,322 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: reparent.cpp
|
||||
// Purpose: wxWindow
|
||||
// Author: Julian Smart
|
||||
// Modified by:
|
||||
// Created: 2002-03-09
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Julian Smart
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ============================================================================
|
||||
// declarations
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "reparent.h"
|
||||
#endif
|
||||
|
||||
#include "wx/x11/reparent.h"
|
||||
#include "wx/evtloop.h"
|
||||
#include "wx/log.h"
|
||||
#include "wx/app.h"
|
||||
#include "wx/timer.h"
|
||||
|
||||
#include "wx/x11/private.h"
|
||||
#include "X11/Xatom.h"
|
||||
|
||||
/*
|
||||
|
||||
Adapted from code by Mike Yang, as follows.
|
||||
|
||||
From: Mike Yang (mikey@eukanuba.wpd.sgi.com)
|
||||
Subject: Re: Wrapping new widget around existing windows
|
||||
Newsgroups: comp.windows.x
|
||||
View: Complete Thread (17 articles) | Original Format
|
||||
Date: 1991-08-09 09:45:48 PST
|
||||
|
||||
|
||||
Enough people asked, so here's my test program which reparents another
|
||||
window. It's a single file (reparent.c), and will work with Motif or
|
||||
Xaw. Xaw users should comment out the "#define MOTIF" line.
|
||||
|
||||
The reparent program first prompts for the application name of the
|
||||
client that it will reparent. If you're going to start the
|
||||
application override_redirect (e.g. -xrm "*overrideRedirect: true"),
|
||||
then this name is ignored and the first override_redirect window is
|
||||
assumed to be the one.
|
||||
|
||||
Input focus is supposed to be correctly handled, as is resizing with
|
||||
window manager hints. If you have input focus problems, try launching
|
||||
your application override_redirect instead. This method is preferred
|
||||
anyway, since you can map it off-screen and then avoid the "window
|
||||
flash" effect as the application's top-level window is reparented.
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
Mike Yang Silicon Graphics, Inc.
|
||||
mikey@sgi.com 415/335-1786
|
||||
|
||||
|
||||
------------------------------- cut here ------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Copyright 1991 by Mike Yang, mikey@sgi.com, Silicon Graphics, Inc.
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this software and its
|
||||
documentation for any purpose is hereby granted without fee, provided that
|
||||
the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation, and that the name of SGI not be used in advertising or
|
||||
publicity pertaining to distribution of the software without specific,
|
||||
written prior permission. SGI makes no representations about the
|
||||
suitability of this software for any purpose. It is provided "as is"
|
||||
without express or implied warranty.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
* wxAdoptedWindow
|
||||
*/
|
||||
|
||||
wxAdoptedWindow::wxAdoptedWindow()
|
||||
{
|
||||
}
|
||||
|
||||
wxAdoptedWindow::wxAdoptedWindow(WXWindow window)
|
||||
{
|
||||
m_mainWidget = window;
|
||||
}
|
||||
|
||||
wxAdoptedWindow::~wxAdoptedWindow()
|
||||
{
|
||||
}
|
||||
/*
|
||||
* wxReparenter
|
||||
*/
|
||||
|
||||
static bool Xerror;
|
||||
static Atom WM_STATE = 0;
|
||||
bool wxReparenter::sm_done = FALSE;
|
||||
wxAdoptedWindow* wxReparenter::sm_toReparent = NULL;
|
||||
wxWindow* wxReparenter::sm_newParent = NULL;
|
||||
wxString wxReparenter::sm_name;
|
||||
bool wxReparenter::sm_exactMatch = FALSE;
|
||||
|
||||
static int
|
||||
ErrorHandler(Display* dpy, XErrorEvent* event)
|
||||
{
|
||||
Xerror = True;
|
||||
return False;
|
||||
}
|
||||
|
||||
// We assume that toReparent has had its X window set
|
||||
// appropriately.
|
||||
bool wxReparenter::Reparent(wxWindow* newParent, wxAdoptedWindow* toReparent)
|
||||
{
|
||||
XWindowAttributes xwa;
|
||||
Window *children;
|
||||
unsigned int numchildren, each;
|
||||
Window returnroot, returnparent;
|
||||
XErrorHandler old;
|
||||
int parentOffset = 0;
|
||||
|
||||
old = XSetErrorHandler(ErrorHandler);
|
||||
XReparentWindow((Display*) newParent->GetXDisplay(),
|
||||
(Window) toReparent->GetXWindow(),
|
||||
(Window) newParent->GetXWindow(),
|
||||
0, 0);
|
||||
|
||||
if (!XQueryTree((Display*) newParent->GetXDisplay(),
|
||||
(Window) toReparent->GetXWindow(),
|
||||
&returnroot, &returnparent,
|
||||
&children, &numchildren) || Xerror)
|
||||
{
|
||||
XSetErrorHandler(old);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (numchildren > 0)
|
||||
{
|
||||
fprintf(stderr, "Reparenting %d children.\n", numchildren);
|
||||
/* Stacking order is preserved since XQueryTree returns its children in
|
||||
bottommost to topmost order
|
||||
*/
|
||||
for (each=0; each<numchildren; each++)
|
||||
{
|
||||
XGetWindowAttributes((Display*) newParent->GetXDisplay(),
|
||||
children[each], &xwa);
|
||||
fprintf(stderr,
|
||||
"Reparenting child at offset %d and position %d, %d.\n",
|
||||
parentOffset, parentOffset+xwa.x, parentOffset+xwa.y);
|
||||
XReparentWindow((Display*) newParent->GetXDisplay(),
|
||||
children[each], (Window) newParent->GetXWindow(),
|
||||
xwa.x, xwa.y);
|
||||
}
|
||||
}
|
||||
|
||||
XSetErrorHandler(old);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Wait for an appropriate window to be created.
|
||||
// If exactMatch is FALSE, a substring match is OK.
|
||||
// If windowName is empty, then wait for the next overrideRedirect window.
|
||||
bool wxReparenter::WaitAndReparent(wxWindow* newParent, wxAdoptedWindow* toReparent,
|
||||
const wxString& windowName,
|
||||
bool exactMatch)
|
||||
{
|
||||
sm_newParent = newParent;
|
||||
sm_toReparent = toReparent;
|
||||
sm_exactMatch = exactMatch;
|
||||
sm_name = windowName;
|
||||
|
||||
Display* display = (Display*) newParent->GetXDisplay() ;
|
||||
XSelectInput(display,
|
||||
RootWindowOfScreen(DefaultScreenOfDisplay(display)),
|
||||
SubstructureNotifyMask);
|
||||
|
||||
if (!WM_STATE)
|
||||
WM_STATE = XInternAtom(display, "WM_STATE", False);
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
if (!windowName.IsEmpty())
|
||||
wxLogDebug(_T("Waiting for window %s"), windowName.c_str());
|
||||
#endif
|
||||
|
||||
sm_done = FALSE;
|
||||
|
||||
wxEventLoop eventLoop;
|
||||
while (!sm_done)
|
||||
{
|
||||
if (eventLoop.Pending())
|
||||
{
|
||||
XEvent xevent;
|
||||
XNextEvent(display, & xevent);
|
||||
if (!wxTheApp->ProcessXEvent((WXEvent*) & xevent))
|
||||
{
|
||||
// Do the local event processing
|
||||
ProcessXEvent((WXEvent*) & xevent);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if wxUSE_TIMER
|
||||
wxTimer::NotifyTimers();
|
||||
wxTheApp->SendIdleEvents();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxReparenter::ProcessXEvent(WXEvent* event)
|
||||
{
|
||||
XEvent* xevent = (XEvent*) event;
|
||||
Window client;
|
||||
|
||||
if (!sm_done)
|
||||
{
|
||||
if (xevent->type == MapNotify)
|
||||
{
|
||||
wxLogDebug(_T("Window was mapped"));
|
||||
}
|
||||
|
||||
if (xevent->type == MapNotify && !xevent->xmap.override_redirect &&
|
||||
(client = (Window) FindAClientWindow((WXWindow) xevent->xmap.window, sm_name)))
|
||||
{
|
||||
wxLogDebug(_T("Found a client window, about to reparent"));
|
||||
wxASSERT(sm_toReparent->GetParent() == NULL);
|
||||
|
||||
sm_toReparent->SetHandle((WXWindow) client);
|
||||
sm_newParent->AddChild(sm_toReparent);
|
||||
sm_done = Reparent(sm_newParent, sm_toReparent);
|
||||
return sm_done;
|
||||
} else if (xevent->type == MapNotify &&
|
||||
xevent->xmap.override_redirect &&
|
||||
xevent->xmap.window)
|
||||
{
|
||||
wxLogDebug(_T("Found an override redirect window, about to reparent"));
|
||||
sm_toReparent->SetHandle((WXWindow) xevent->xmap.window);
|
||||
sm_newParent->AddChild(sm_toReparent);
|
||||
wxASSERT(sm_toReparent->GetParent() == NULL);
|
||||
|
||||
sm_done = Reparent(sm_newParent, sm_toReparent);
|
||||
return sm_done;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WXWindow wxReparenter::FindAClientWindow(WXWindow window, const wxString& name)
|
||||
{
|
||||
int rvalue, i;
|
||||
Atom actualtype;
|
||||
int actualformat;
|
||||
unsigned long nitems, bytesafter;
|
||||
unsigned char *propreturn;
|
||||
Window *children;
|
||||
unsigned int numchildren;
|
||||
Window returnroot, returnparent;
|
||||
Window result = 0;
|
||||
XErrorHandler old;
|
||||
char *clientName;
|
||||
|
||||
Xerror = False;
|
||||
old = XSetErrorHandler(ErrorHandler);
|
||||
rvalue = XGetWindowProperty((Display*) wxGetDisplay(),
|
||||
(Window) window, WM_STATE,
|
||||
0, 1, False,
|
||||
AnyPropertyType, &actualtype, &actualformat,
|
||||
&nitems, &bytesafter, &propreturn);
|
||||
XSetErrorHandler(old);
|
||||
if (!Xerror && rvalue == Success && actualtype != None)
|
||||
{
|
||||
if (rvalue == Success)
|
||||
{
|
||||
XFree((char *) propreturn);
|
||||
}
|
||||
XFetchName((Display*) wxGetDisplay(), (Window) window, &clientName);
|
||||
|
||||
wxString str1(name);
|
||||
wxString str2(clientName);
|
||||
str1.Lower();
|
||||
str2.Lower();
|
||||
|
||||
bool matches;
|
||||
if (sm_exactMatch)
|
||||
matches = (name == clientName);
|
||||
else
|
||||
matches = (str1.Contains(str2) || str2.Contains(str1));
|
||||
|
||||
XFree(clientName);
|
||||
|
||||
if (matches)
|
||||
return (WXWindow) window;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
old = XSetErrorHandler(ErrorHandler);
|
||||
if (!XQueryTree((Display*) wxGetDisplay(), (Window) window, &returnroot, &returnparent,
|
||||
&children, &numchildren) || Xerror) {
|
||||
XSetErrorHandler(old);
|
||||
return NULL;
|
||||
}
|
||||
XSetErrorHandler(old);
|
||||
|
||||
result = 0;
|
||||
for (i=0; i<(int)numchildren && !result ;i++) {
|
||||
result = (Window) FindAClientWindow((WXWindow) children[i], name);
|
||||
}
|
||||
if (numchildren) {
|
||||
XFree((char *) children);
|
||||
} return (WXWindow) result;
|
||||
}
|
||||
|
Reference in New Issue
Block a user