summaryrefslogtreecommitdiffstats
path: root/chalk/plugins/viewplugins/screenshot/ksnapshot.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chalk/plugins/viewplugins/screenshot/ksnapshot.cpp')
-rw-r--r--chalk/plugins/viewplugins/screenshot/ksnapshot.cpp499
1 files changed, 499 insertions, 0 deletions
diff --git a/chalk/plugins/viewplugins/screenshot/ksnapshot.cpp b/chalk/plugins/viewplugins/screenshot/ksnapshot.cpp
new file mode 100644
index 00000000..f9887821
--- /dev/null
+++ b/chalk/plugins/viewplugins/screenshot/ksnapshot.cpp
@@ -0,0 +1,499 @@
+/*
+ * KSnapshot
+ *
+ * (c) Richard J. Moore 1997-2002
+ * (c) Matthias Ettrich 2000
+ * (c) Aaron J. Seigo 2002
+ * (c) Nadeem Hasan 2003
+ * This adaptation: (c) Boudewijn Rempt 2005
+ *
+ * Released under the GPL see file LICENSE for details.
+ */
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <kimageio.h>
+#include <kfiledialog.h>
+#include <kimagefilepreview.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+#include <kprinter.h>
+#include <kio/netaccess.h>
+#include <ksavefile.h>
+#include <ktempfile.h>
+
+#include <tqbitmap.h>
+#include <tqdragobject.h>
+#include <tqimage.h>
+#include <tqclipboard.h>
+#include <tqvbox.h>
+
+#include <kaccel.h>
+#include <knotifyclient.h>
+#include <khelpmenu.h>
+#include <kpopupmenu.h>
+#include <kpushbutton.h>
+#include <kstartupinfo.h>
+
+#include <tqcursor.h>
+#include <tqregexp.h>
+#include <tqpainter.h>
+#include <tqpaintdevicemetrics.h>
+#include <tqwhatsthis.h>
+
+#include <stdlib.h>
+
+#include "ksnapshot.h"
+#include "regiongrabber.h"
+#include "ksnapshotwidget.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#include <config.h>
+
+#ifdef HAVE_X11_EXTENSIONS_SHAPE_H
+#include <X11/extensions/shape.h>
+#endif
+
+#include <kglobal.h>
+
+KSnapshot::KSnapshot(TQWidget *tqparent, const char *name)
+ : super(tqparent, name, false, TQString(), Ok|Cancel)
+{
+ grabber = new TQWidget( 0, 0, WStyle_Customize | WX11BypassWM );
+ Q_CHECK_PTR(grabber);
+ grabber->move( -1000, -1000 );
+ grabber->installEventFilter( this );
+
+#ifdef HAVE_X11_EXTENSIONS_SHAPE_H
+ int tmp1, tmp2;
+ //Check whether the extension is available
+ haveXShape = XShapeQueryExtension( qt_xdisplay(), &tmp1, &tmp2 );
+#endif
+
+ TQVBox *vbox = makeVBoxMainWidget();
+ mainWidget = new KSnapshotWidget( vbox, "mainWidget" );
+ Q_CHECK_PTR(mainWidget);
+
+ mainWidget->btnSave->hide();
+ mainWidget->btnPrint->hide();
+ connect(mainWidget, TQT_SIGNAL(startImageDrag()), TQT_SLOT(slotDragSnapshot()));
+
+ connect( mainWidget, TQT_SIGNAL( newClicked() ), TQT_SLOT( slotGrab() ) );
+ connect( mainWidget, TQT_SIGNAL( printClicked() ), TQT_SLOT( slotPrint() ) );
+
+ grabber->show();
+ grabber->grabMouse( waitCursor );
+
+ snapshot = TQPixmap::grabWindow( qt_xrootwin() );
+ updatePreview();
+ grabber->releaseMouse();
+ grabber->hide();
+
+ KConfig *conf=KGlobal::config();
+ conf->setGroup("GENERAL");
+ mainWidget->setDelay(conf->readNumEntry("delay",0));
+ mainWidget->setMode( conf->readNumEntry( "mode", 0 ) );
+ mainWidget->setIncludeDecorations(conf->readBoolEntry("includeDecorations",true));
+
+ connect( &grabTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( grabTimerDone() ) );
+
+ KAccel* accel = new KAccel(this);
+ Q_CHECK_PTR(accel);
+ accel->insert(KStdAccel::Print, TQT_TQOBJECT(this), TQT_SLOT(slotPrint()));
+ accel->insert(KStdAccel::New, TQT_TQOBJECT(this), TQT_SLOT(slotGrab()));
+
+ accel->insert( "Print2", TQt::Key_P, TQT_TQOBJECT(this), TQT_SLOT(slotPrint()));
+ accel->insert( "New2", TQt::Key_N, TQT_TQOBJECT(this), TQT_SLOT(slotGrab()));
+ accel->insert( "New3", TQt::Key_Space, TQT_TQOBJECT(this), TQT_SLOT(slotGrab()));
+
+ mainWidget->btnNew->setFocus();
+
+}
+
+KSnapshot::~KSnapshot()
+{
+}
+
+bool KSnapshot::save( const TQString &filename )
+{
+ return save( KURL::fromPathOrURL( filename ));
+}
+
+bool KSnapshot::save( const KURL& url )
+{
+ TQString type( KImageIO::type(url.path()) );
+ if ( type.isNull() )
+ type = "PNG";
+
+ bool ok = false;
+
+ if ( url.isLocalFile() ) {
+ KSaveFile saveFile( url.path() );
+ if ( saveFile.status() == 0 ) {
+ if ( snapshot.save( saveFile.file(), type.latin1() ) )
+ ok = saveFile.close();
+ }
+ }
+ else {
+ KTempFile tmpFile;
+ tmpFile.setAutoDelete( true );
+ if ( tmpFile.status() == 0 ) {
+ if ( snapshot.save( tmpFile.file(), type.latin1() ) ) {
+ if ( tmpFile.close() )
+ ok = KIO::NetAccess::upload( tmpFile.name(), url, this );
+ }
+ }
+ }
+
+ TQApplication::restoreOverrideCursor();
+ if ( !ok ) {
+ kdWarning() << "KSnapshot was unable to save the snapshot" << endl;
+
+ TQString caption = i18n("Unable to Save Image");
+ TQString text = i18n("KSnapshot was unable to save the image to\n%1.")
+ .tqarg(url.prettyURL());
+ KMessageBox::error(this, text, caption);
+ }
+
+ return ok;
+}
+
+void KSnapshot::slotCopy()
+{
+ TQClipboard *cb = TQApplication::tqclipboard();
+ cb->setPixmap( snapshot );
+}
+
+void KSnapshot::slotDragSnapshot()
+{
+ TQDragObject *drobj = new TQImageDrag(snapshot.convertToImage(), this);
+ Q_CHECK_PTR(drobj);
+ drobj->setPixmap(mainWidget->preview());
+ drobj->dragCopy();
+}
+
+void KSnapshot::slotGrab()
+{
+ hide();
+ if ( mainWidget->mode() == Region )
+ {
+ rgnGrab = new RegionGrabber();
+ Q_CHECK_PTR(rgnGrab);
+ connect( rgnGrab, TQT_SIGNAL( regionGrabbed( const TQPixmap & ) ),
+ TQT_SLOT( slotRegionGrabbed( const TQPixmap & ) ) );
+ }
+ else
+ {
+ if ( mainWidget->delay() )
+ grabTimer.start( mainWidget->delay() * 1000, true );
+ else {
+ grabber->show();
+ grabber->grabMouse( crossCursor );
+ }
+ }
+}
+
+void KSnapshot::slotPrint()
+{
+ KPrinter printer;
+ if (snapshot.width() > snapshot.height())
+ printer.setOrientation(KPrinter::Landscape);
+ else
+ printer.setOrientation(KPrinter::Portrait);
+
+ tqApp->processEvents();
+
+ if (printer.setup(this, i18n("Print Screenshot")))
+ {
+ tqApp->processEvents();
+
+ TQPainter painter(&printer);
+ TQPaintDeviceMetrics metrics(painter.device());
+
+ float w = snapshot.width();
+ float dw = w - metrics.width();
+ float h = snapshot.height();
+ float dh = h - metrics.height();
+ bool scale = false;
+
+ if ( (dw > 0.0) || (dh > 0.0) )
+ scale = true;
+
+ if ( scale ) {
+
+ TQImage img = snapshot.convertToImage();
+ tqApp->processEvents();
+
+ float newh, neww;
+ if ( dw > dh ) {
+ neww = w-dw;
+ newh = neww/w*h;
+ }
+ else {
+ newh = h-dh;
+ neww = newh/h*w;
+ }
+
+ img = img.smoothScale( int(neww), int(newh), TQ_ScaleMin );
+ tqApp->processEvents();
+
+ int x = (metrics.width()-img.width())/2;
+ int y = (metrics.height()-img.height())/2;
+
+ painter.drawImage( x, y, img);
+ }
+ else {
+ int x = (metrics.width()-snapshot.width())/2;
+ int y = (metrics.height()-snapshot.height())/2;
+ painter.drawPixmap( x, y, snapshot );
+ }
+ }
+
+ tqApp->processEvents();
+}
+
+void KSnapshot::slotRegionGrabbed( const TQPixmap &pix )
+{
+ if ( !pix.isNull() )
+ {
+ snapshot = pix;
+ updatePreview();
+ modified = true;
+ }
+
+ delete rgnGrab;
+ TQApplication::restoreOverrideCursor();
+ show();
+}
+
+bool KSnapshot::eventFilter( TQObject* o, TQEvent* e)
+{
+ if ( TQT_BASE_OBJECT(o) == TQT_BASE_OBJECT(grabber) && e->type() == TQEvent::MouseButtonPress ) {
+ TQMouseEvent* me = (TQMouseEvent*) e;
+ if ( TQWidget::mouseGrabber() != grabber )
+ return false;
+ if ( me->button() == Qt::LeftButton )
+ performGrab();
+ }
+ return false;
+}
+
+void KSnapshot::updatePreview()
+{
+ TQImage img = snapshot.convertToImage();
+ double r1 = ((double) snapshot.height() ) / snapshot.width();
+ if ( r1 * mainWidget->previewWidth() < mainWidget->previewHeight() )
+ img = img.smoothScale( mainWidget->previewWidth(),
+ int( mainWidget->previewWidth() * r1 ));
+ else
+ img = img.smoothScale( (int) (((double)mainWidget->previewHeight()) / r1),
+ (mainWidget->previewHeight() ) );
+
+ TQPixmap pm;
+ pm.convertFromImage( img );
+ mainWidget->setPreview( pm );
+}
+
+void KSnapshot::grabTimerDone()
+{
+ performGrab();
+ KNotifyClient::beep(i18n("The screen has been successfully grabbed."));
+}
+
+static
+Window findRealWindow( Window w, int depth = 0 )
+{
+ if( depth > 5 )
+ return None;
+ static Atom wm_state = XInternAtom( qt_xdisplay(), "WM_STATE", False );
+ Atom type;
+ int format;
+ unsigned long nitems, after;
+ unsigned char* prop;
+ if( XGetWindowProperty( qt_xdisplay(), w, wm_state, 0, 0, False, AnyPropertyType,
+ &type, &format, &nitems, &after, &prop ) == Success ) {
+ if( prop != NULL )
+ XFree( prop );
+ if( type != None )
+ return w;
+ }
+ Window root, tqparent;
+ Window* tqchildren;
+ unsigned int ntqchildren;
+ Window ret = None;
+ if( XQueryTree( qt_xdisplay(), w, &root, &tqparent, &tqchildren, &ntqchildren ) != 0 ) {
+ for( unsigned int i = 0;
+ i < ntqchildren && ret == None;
+ ++i )
+ ret = findRealWindow( tqchildren[ i ], depth + 1 );
+ if( tqchildren != NULL )
+ XFree( tqchildren );
+ }
+ return ret;
+}
+
+void KSnapshot::performGrab()
+{
+ grabber->releaseMouse();
+ grabber->hide();
+ grabTimer.stop();
+ XGrabServer( qt_xdisplay());
+ if ( mainWidget->mode() == WindowUnderCursor ) {
+ Window root;
+ Window child;
+ uint tqmask;
+ int rootX, rootY, winX, winY;
+ XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child,
+ &rootX, &rootY, &winX, &winY,
+ &tqmask);
+ if( child == None )
+ child = qt_xrootwin();
+ if( !mainWidget->includeDecorations()) {
+ Window real_child = findRealWindow( child );
+ if( real_child != None ) // test just in case
+ child = real_child;
+ }
+ int x, y;
+ unsigned int w, h;
+ unsigned int border;
+ unsigned int depth;
+ XGetGeometry( qt_xdisplay(), child, &root, &x, &y,
+ &w, &h, &border, &depth );
+ w += 2 * border;
+ h += 2 * border;
+
+ Window tqparent;
+ Window* tqchildren;
+ unsigned int ntqchildren;
+ if( XQueryTree( qt_xdisplay(), child, &root, &tqparent,
+ &tqchildren, &ntqchildren ) != 0 ) {
+ if( tqchildren != NULL )
+ XFree( tqchildren );
+ int newx, newy;
+ Window dummy;
+ if( XTranslateCoordinates( qt_xdisplay(), tqparent, qt_xrootwin(),
+ x, y, &newx, &newy, &dummy )) {
+ x = newx;
+ y = newy;
+ }
+ }
+
+ snapshot = TQPixmap::grabWindow( qt_xrootwin(), x, y, w, h );
+
+#ifdef HAVE_X11_EXTENSIONS_SHAPE_H
+ //No XShape - no work.
+ if (haveXShape) {
+ TQBitmap tqmask(w, h);
+ //As the first step, get the tqmask from XShape.
+ int count, order;
+ XRectangle* rects = XShapeGetRectangles( qt_xdisplay(), child,
+ ShapeBounding, &count, &order);
+ //The ShapeBounding region is the outermost tqshape of the window;
+ //ShapeBounding - ShapeClipping is defined to be the border.
+ //Since the border area is part of the window, we use bounding
+ // to limit our work region
+ if (rects) {
+ //Create a TQRegion from the rectangles describing the bounding tqmask.
+ TQRegion contents;
+ for (int pos = 0; pos < count; pos++)
+ contents += TQRegion(rects[pos].x, rects[pos].y,
+ rects[pos].width, rects[pos].height);
+ XFree(rects);
+
+ //Create the bounding box.
+ TQRegion bbox(0, 0, snapshot.width(), snapshot.height());
+
+ if( border > 0 ) {
+ contents.translate( border, border );
+ contents += TQRegion( 0, 0, border, h );
+ contents += TQRegion( 0, 0, w, border );
+ contents += TQRegion( 0, h - border, w, border );
+ contents += TQRegion( w - border, 0, border, h );
+ }
+
+ //Get the tqmasked away area.
+ TQRegion tqmaskedAway = bbox - contents;
+ TQMemArray<TQRect> tqmaskedAwayRects = tqmaskedAway.rects();
+
+ //Construct a bitmap tqmask from the rectangles
+ TQPainter p(&tqmask);
+ p.fillRect(0, 0, w, h, TQt::color1);
+ for (uint pos = 0; pos < tqmaskedAwayRects.count(); pos++)
+ p.fillRect(tqmaskedAwayRects[pos], TQt::color0);
+ p.end();
+
+ snapshot.setMask(tqmask);
+ }
+ }
+#endif
+ }
+ else {
+ snapshot = TQPixmap::grabWindow( qt_xrootwin() );
+ }
+ XUngrabServer( qt_xdisplay());
+ updatePreview();
+ TQApplication::restoreOverrideCursor();
+ modified = true;
+// show();
+ slotOk();
+}
+
+void KSnapshot::setTime(int newTime)
+{
+ mainWidget->setDelay(newTime);
+}
+
+void KSnapshot::setURL( const TQString &url )
+{
+ KURL newURL = KURL::fromPathOrURL( url );
+ if ( newURL == filename )
+ return;
+
+ filename = newURL;
+}
+
+void KSnapshot::setGrabMode( int m )
+{
+ mainWidget->setMode( m );
+}
+
+void KSnapshot::slotMovePointer(int x, int y)
+{
+ TQCursor::setPos( x, y );
+}
+
+void KSnapshot::exit()
+{
+
+ KConfig *conf=KGlobal::config();
+ conf->setGroup("GENERAL");
+ conf->writeEntry("delay",mainWidget->delay());
+ conf->writeEntry("mode",mainWidget->mode());
+ conf->writeEntry("includeDecorations",mainWidget->includeDecorations());
+ KURL url = filename;
+ url.setPass( TQString() );
+ conf->writePathEntry("filename",url.url());
+
+ reject();
+}
+
+void KSnapshot::slotOk()
+{
+
+ KConfig *conf=KGlobal::config();
+ conf->setGroup("GENERAL");
+ conf->writeEntry("delay",mainWidget->delay());
+ conf->writeEntry("mode",mainWidget->mode());
+ conf->writeEntry("includeDecorations",mainWidget->includeDecorations());
+ KURL url = filename;
+ url.setPass( TQString() );
+ conf->writePathEntry("filename",url.url());
+
+ emit screenGrabbed();
+
+ accept();
+}
+
+#include "ksnapshot.moc"