[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