[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: KDE/kdegraphics/ksnapshot
From: Pau Garcia i Quiles <pgquiles () elpauer ! org>
Date: 2011-01-13 2:43:51
Message-ID: 20110113024351.09F03AC8B3 () svn ! kde ! org
[Download RAW message or body]
SVN commit 1214116 by pgquiles:
* Implement 'child window' capture on Windows (tested on Windows XP SP3)
* Unbreak compilation on X11
* Sanitize indenting
* Rectangular region and freehand region grabbing have a weird behavior (screen does \
not go grey and you cannot select the capture area) which can be "fixed" by pressing \
ctrl + alt + del. I think this is something I broke lately because I'd say it worked \
fine.
M +24 -1 ksnapshot.cpp
M +99 -51 windowgrabber.cpp
--- trunk/KDE/kdegraphics/ksnapshot/ksnapshot.cpp #1214115:1214116
@@ -107,7 +107,30 @@
setButtonGuiItem(User2, KGuiItem(i18n("Send To..."), "document-open"));
setDefaultButton(Apply);
grabber = new QWidget( 0, Qt::X11BypassWindowManagerHint );
- grabber->move( -1000, -1000 );
+
+ // TODO X11 (Xinerama and Twinview, actually) and Windows use different \
coordinates for the two monitors case + //
+ // On Windows, there are two displays. The origin (0, 0) ('o') is the top left \
of display 1. If display 2 is to the left, then coordinates in display 2 are \
negative: + // .-------.
+ // | |o-----.
+ // | 2 | |
+ // | | 1 |
+ // ._______.._____.
+ //
+ // On Xinerama and Twinview, there is only one display and two screens. The \
origin (0, 0) ('o') is the top left of the display: + // o-------.
+ // | |.-----.
+ // | 2 | |
+ // | | 1 |
+ // ._______.._____.
+ //
+ // Instead of moving to (-10000, -10000), we should compute how many displays \
are and make sure we move to somewhere out of the total coordinates. + // - \
Windows: use GetSystemMetrics ( \
http://msdn.microsoft.com/en-us/library/ms724385(v=vs.85).aspx ) +
+ // If moving to a negative position, we need to count the size of the dialog; \
moving to a positive position avoids having to compute the size of the dialog +
+ grabber->move( -10000, -10000 ); // FIXME Read above
+
grabber->installEventFilter( this );
KStartupInfo::appStarted();
--- trunk/KDE/kdegraphics/ksnapshot/windowgrabber.cpp #1214115:1214116
@@ -20,6 +20,7 @@
#include "windowgrabber.h"
+#include <iostream>
#include <algorithm>
#include <kwindowinfo.h>
@@ -43,6 +44,8 @@
#ifdef Q_WS_WIN
#include <windows.h>
+
+static UINT cxWindowBorder, cyWindowBorder;
#endif // Q_WS_WIN
static
@@ -64,6 +67,7 @@
{
XWindowAttributes atts;
XGetWindowAttributes( QX11Info::display(), w, &atts );
+
if ( atts.map_state == IsViewable &&
atts.width >= minSize && atts.height >= minSize ) {
int x = 0, y = 0;
@@ -91,29 +95,41 @@
}
}
}
+
if ( depth == 0 ) {
std::sort( windows->begin(), windows->end() );
}
}
#elif defined(Q_WS_WIN)
-
static
bool maybeAddWindow(HWND hwnd, std::vector<QRect> *windows) {
WINDOWINFO wi;
GetWindowInfo(hwnd, &wi);
+ RECT rect = wi.rcClient;
- int width = wi.rcWindow.right - wi.rcWindow.left;
- int height = wi.rcWindow.top - wi.rcWindow.bottom;
+#if 0
+ RECT rect;
+ GetWindowRect( hwnd, &rect );
+#endif
- if ( ( ( wi.dwStyle & WS_VISIBLE ) != 0 )
- && (width >= minSize ) && (height >= minSize ) )
+ int width = rect.right - rect.left;
+ int height = rect.bottom - rect.top;
+
+ // For some reason, rect.left and rect.top are shifted by cxWindowBorders and \
cyWindowBorders pixels respectively + // in *every* case (for every window), but \
cxWindowBorders and cyWindowBorders are non-zero only in the + // biggest-window \
case, therefore we need to save the biggest cxWindowBorders and cyWindowBorders to \
adjust the rect later + cxWindowBorder = qMax(cxWindowBorder, wi.cxWindowBorders);
+ cyWindowBorder = qMax(cyWindowBorder, wi.cyWindowBorders);
+
+ if ( ( ( wi.dwStyle & WS_VISIBLE ) != 0 ) && (width >= minSize ) && (height >= \
minSize ) ) {
- QRect r( wi.rcWindow.left, wi.rcWindow.top, width, height );
-// if ( std::find( windows->begin(), windows->end(), r ) == windows->end() ) {
+ //QRect r( rect.left + 4, rect.top + 4, width, height); // 4 = \
max(wi.cxWindowBorders) = max(wi.cyWindowBorders) + QRect r(rect.left + \
cxWindowBorder, rect.top + cyWindowBorder, width, height); + if ( std::find( \
windows->begin(), windows->end(), r ) == windows->end() ) { windows->push_back( r );
return true;
-// }
}
+ }
return false;
}
@@ -132,43 +148,52 @@
EnumChildWindows( hwnd, getWindowsRecursiveHelper, (LPARAM) windows );
-// if( depth == 0 ) {
std::sort( windows->begin(), windows->end() );
-// }
}
-
#endif // Q_WS_X11
#ifdef Q_WS_X11
static
Window findRealWindow( Window w, int depth = 0 )
{
- if( depth > 5 )
+ if( depth > 5 ) {
return None;
+ }
+
static Atom wm_state = XInternAtom( QX11Info::display(), "WM_STATE", False );
Atom type;
int format;
unsigned long nitems, after;
unsigned char* prop;
+
if( XGetWindowProperty( QX11Info::display(), w, wm_state, 0, 0, False, \
AnyPropertyType, &type, &format, &nitems, &after, &prop ) == Success ) {
- if( prop != NULL )
+ if( prop != NULL ) {
XFree( prop );
- if( type != None )
+ }
+
+ if( type != None ) {
return w;
}
+ }
+
Window root, parent;
Window* children;
unsigned int nchildren;
Window ret = None;
+
if( XQueryTree( QX11Info::display(), w, &root, &parent, &children, &nchildren ) \
!= 0 ) { for( unsigned int i = 0;
i < nchildren && ret == None;
- ++i )
+ ++i ) {
ret = findRealWindow( children[ i ], depth + 1 );
- if( children != NULL )
+ }
+
+ if( children != NULL ) {
XFree( children );
}
+ }
+
return ret;
}
#elif defined(Q_WS_WIN)
@@ -188,23 +213,29 @@
Window child;
uint mask;
int rootX, rootY, winX, winY;
+
XGrabServer( QX11Info::display() );
XQueryPointer( QX11Info::display(), QX11Info::appRootWindow(), &root, &child,
&rootX, &rootY, &winX, &winY, &mask );
- if( child == None )
+
+ if( child == None ) {
child = QX11Info::appRootWindow();
+ }
+
if( !includeDecorations ) {
Window real_child = findRealWindow( child );
- if( real_child != None ) // test just in case
+
+ if( real_child != None ) { // test just in case
child = real_child;
}
+ }
+
return child;
}
#elif defined(Q_WS_WIN)
static
HWND windowUnderCursor(bool includeDecorations = true)
{
- // TODO include decorations if includeDecorations = true
POINT pointCursor;
QPoint qpointCursor = QCursor::pos();
pointCursor.x = qpointCursor.x();
@@ -217,7 +248,6 @@
windowUnderCursor = GetAncestor( windowUnderCursor, GA_ROOT );
}
}
-
return windowUnderCursor;
}
#endif
@@ -230,10 +260,14 @@
QPixmap pm( QPixmap::grabWindow( QX11Info::appRootWindow(), x, y, w, h ) );
KWindowInfo winInfo( findRealWindow(child), NET::WMVisibleName, \
NET::WM2WindowClass );
- if ( title )
+
+ if ( title ) {
(*title) = winInfo.visibleName();
- if ( windowClass )
+ }
+
+ if ( windowClass ) {
(*windowClass) = winInfo.windowClassName();
+ }
#ifdef HAVE_X11_EXTENSIONS_SHAPE_H
int tmp1, tmp2;
@@ -293,7 +327,6 @@
GetWindowRect(hWnd, &windowRect);
int w = windowRect.right - windowRect.left;
int h = windowRect.bottom - windowRect.top;
-
HDC targetDC = GetWindowDC(hWnd);
HDC hDC = CreateCompatibleDC(targetDC);
HBITMAP tempPict = CreateCompatibleBitmap(targetDC, w, h);
@@ -303,7 +336,7 @@
QPixmap pm = QPixmap::fromWinHBITMAP(tempPict);
DeleteDC(hDC);
- ReleaseDC(GetDesktopWindow(), targetDC);
+ ReleaseDC(hWnd, targetDC);
KWindowInfo winInfo( findRealWindow(hWnd), NET::WMVisibleName, \
NET::WM2WindowClass ); if ( title ) {
@@ -313,7 +346,6 @@
if ( windowClass ) {
(*windowClass) = winInfo.windowClassName();
}
-
return pm;
}
#endif // Q_WS_X11
@@ -328,33 +360,45 @@
{
setWindowModality( Qt::WindowModal );
int y,x;
- uint w, h, border, depth;
+ uint w, h;
#ifdef Q_WS_X11
+ uint border, depth;
Window root;
XGrabServer( QX11Info::display() );
Window child = windowUnderCursor();
XGetGeometry( QX11Info::display(), child, &root, &x, &y, &w, &h, &border, &depth \
); + XUngrabServer( QX11Info::display() );
+
+ QPixmap pm( grabWindow( child, x, y, w, h, border, &title, &windowClass ) );
#elif defined(Q_WS_WIN)
- HWND root;
HWND child = windowUnderCursor();
- // TODO XGetGeometry
-#endif
+ WINDOWINFO wi;
+ GetWindowInfo( child, &wi);
+
+ RECT r;
+ GetWindowRect( child, &r);
+ x = r.left;
+ y = r.top;
+ w = r.right - r.left;
+ h = r.bottom - r.top;
+ cxWindowBorder = wi.cxWindowBorders;
+ cyWindowBorder = wi.cyWindowBorders;
+
+ HDC childDC = GetDC(child);
+
QPixmap pm( grabWindow( child, &title, &windowClass ) );
+#endif // Q_WS_X11
+
getWindowsRecursive( &windows, child );
-#ifdef Q_WS_X11
- XUngrabServer( QX11Info::display() );
-#endif // Q_WS_X11
-
QPalette p = palette();
p.setBrush( backgroundRole(), QBrush( pm ) );
setPalette( p );
setFixedSize( pm.size() );
setMouseTracking( true );
setGeometry( x, y, w, h );
-
current = windowIndex( mapFromGlobal(QCursor::pos()) );
}
@@ -364,37 +408,41 @@
QPixmap WindowGrabber::grabCurrent( bool includeDecorations )
{
+ int x, y;
#ifdef Q_WS_X11
Window root;
- int x, y;
uint w, h, border, depth;
+
XGrabServer( QX11Info::display() );
Window child = windowUnderCursor( includeDecorations );
XGetGeometry( QX11Info::display(), child, &root, &x, &y, &w, &h, &border, &depth \
); +
Window parent;
Window* children;
unsigned int nchildren;
+
if( XQueryTree( QX11Info::display(), child, &root, &parent,
&children, &nchildren ) != 0 ) {
- if( children != NULL )
+ if( children != NULL ) {
XFree( children );
+ }
+
int newx, newy;
Window dummy;
+
if( XTranslateCoordinates( QX11Info::display(), parent, \
QX11Info::appRootWindow(), x, y, &newx, &newy, &dummy )) {
x = newx;
y = newy;
}
}
+
windowPosition = QPoint(x,y);
QPixmap pm( grabWindow( child, x, y, w, h, border, &title, &windowClass ) );
XUngrabServer( QX11Info::display() );
return pm;
#elif defined(Q_WS_WIN)
HWND hWindow;
- int x, y;
- uint w, h;
-
hWindow = windowUnderCursor(includeDecorations);
Q_ASSERT(hWindow);
@@ -413,7 +461,6 @@
y = r.top;
windowPosition = QPoint(x,y);
-
QPixmap pm( grabWindow( hParent, &title, &windowClass) );
return pm;
#endif // Q_WS_X11
@@ -423,9 +470,9 @@
void WindowGrabber::mousePressEvent( QMouseEvent *e )
{
- if ( e->button() == Qt::RightButton )
+ if ( e->button() == Qt::RightButton ) {
yPos = e->globalY();
- else {
+ } else {
if ( current ) {
windowPosition = e->globalPos() - e->pos() + windows[current].topLeft();
emit windowGrabbed( palette().brush( backgroundRole() ).texture().copy( \
windows[ current ] ) ); @@ -439,9 +486,10 @@
void WindowGrabber::mouseReleaseEvent( QMouseEvent *e )
{
- if ( e->button() == Qt::RightButton )
+ if ( e->button() == Qt::RightButton ) {
yPos = -1;
}
+}
static
const int minDistance = 10;
@@ -454,14 +502,12 @@
current = w;
repaint();
}
- }
- else {
+ } else {
int y = e->globalY();
if ( y > yPos + minDistance ) {
decreaseScope( e->pos() );
yPos = y;
- }
- else if ( y < yPos - minDistance ) {
+ } else if ( y < yPos - minDistance ) {
increaseScope( e->pos() );
yPos = y;
}
@@ -470,13 +516,14 @@
void WindowGrabber::wheelEvent( QWheelEvent *e )
{
- if ( e->delta() > 0 )
+ if ( e->delta() > 0 ) {
increaseScope( e->pos() );
- else if ( e->delta() < 0 )
+ } else if ( e->delta() < 0 ) {
decreaseScope( e->pos() );
- else
+ } else {
e->ignore();
}
+}
// Increases the scope to the next-bigger window containing the mouse pointer.
// This method is activated by either rotating the mouse wheel forwards or by
@@ -511,9 +558,10 @@
int WindowGrabber::windowIndex( const QPoint &pos ) const
{
for ( uint i = 0; i < windows.size(); i++ ) {
- if ( windows[ i ].contains( pos ) )
+ if ( windows[ i ].contains( pos ) ) {
return i;
}
+ }
return -1;
}
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic