#include "screengrab.h" #include "dialogs.h" #include "ifapp.h" #include "imageutils.h" #include "attributedialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include QPixmap getWindow(Window window, bool nobdrs) { XWindowAttributes win_info; int absx, absy, x, y; int width, height; int dwidth, dheight; int bw; Window dummywin; Display *dpy = QApplication::desktop()->x11Display(); QPixmap pix; XImage *image; qWarning("Getting target window information"); if(!XGetWindowAttributes(dpy, window, &win_info)){ qWarning("Can't get target window attributes."); return(pix); } if(!XTranslateCoordinates (dpy, window, RootWindow(dpy, DefaultScreen(dpy)), 0, 0, &absx, &absy, &dummywin)){ qWarning("Unable to translate window coordinates (%d,%d)", absx, absy); return(pix); } win_info.x = absx; win_info.y = absy; width = win_info.width; height = win_info.height; bw = 0; if(!nobdrs){ absx -= win_info.border_width; absy -= win_info.border_width; bw = win_info.border_width; width += (2 * bw); height += (2 * bw); } dwidth = QApplication::desktop()->width(); dheight = QApplication::desktop()->height(); /* clip to window */ if (absx < 0) width += absx, absx = 0; if (absy < 0) height += absy, absy = 0; if (absx + width > dwidth) width = dwidth - absx; if (absy + height > dheight) height = dheight - absy; x = absx - win_info.x; y = absy - win_info.y; image = XGetImage(dpy, window, x, y, width, height, AllPlanes, ZPixmap); if(!image){ qWarning("Unable to get image at %dx%d+%d+%d", width, height, x, y); return(pix); } GC gc = qt_xget_temp_gc(qt_xscreen(), false); pix.resize(width, height); XPutImage(dpy, pix.handle(), gc, image, 0, 0, 0, 0, width, height); XFree(image); return(pix); } KIFScreenGrab::KIFScreenGrab(QWidget *parent, const char *name) : QSemiModal(parent, name, false) { QVBoxLayout *layout = new QVBoxLayout(this, 4); QLabel *lbl = new QLabel(i18n("This dialog will grab either your desktop or\n\ a single application window. If you grab a\n\ single window your mouse cursor will change\n\ into crosshairs and simply select the window\n\ with your mouse."), this); layout->addWidget(lbl); desktopCB = new QCheckBox(i18n("Grab the entire desktop."), this); desktopCB->setChecked(true); layout->addWidget(desktopCB); hideCB = new QCheckBox(i18n("Hide all pixie windows."), this); hideCB->setChecked(true); layout->addWidget(hideCB); lbl = new QLabel(i18n("Delay (in secs):"), this); layout->addWidget(lbl); delay = new KIntNumInput(this); delay->setRange(0, 60); layout->addWidget(delay); layout->addStretch(1); KButtonBox *bbox = new KButtonBox(this); bbox->addStretch(1); connect(bbox->addButton(i18n("Cancel")), SIGNAL(clicked()), this, SLOT(slotCancel())); connect(bbox->addButton(i18n("OK")), SIGNAL(clicked()), this, SLOT(slotCheckIfDelay())); layout->addWidget(bbox); setCaption(i18n("Screenshot")); inSelect = false; show(); inLoop = true; while(inLoop) kapp->processEvents(); delete this; }; void KIFScreenGrab::slotCheckIfDelay() { // do hiding first move(-4000, -4000); if(hideCB->isChecked()){ if(desktopCB->isChecked()){ //hide(); kifapp()->hideWindows(); kifapp()->processEvents(); QApplication::syncX(); } else{ //hide(); kifapp()->hideWindows(); kifapp()->processEvents(); QApplication::syncX(); } } if(delay->value()){ QTimer::singleShot(delay->value()*1000, this, SLOT(slotStartGrab())); kifapp()->processEvents(); } else slotStartGrab(); } void KIFScreenGrab::slotStartGrab() { QPixmap pixmap; if(desktopCB->isChecked()){ QApplication::syncX(); sleep(1); pixmap = QPixmap::grabWindow(QApplication::desktop()->winId()); } else{ Display *disp = QApplication::desktop()->x11Display(); Window rootWin, childWin; int rootX, rootY, winX, winY; unsigned int mask; winSelected = false; inSelect = true; grabMouse(crossCursor); QApplication::syncX(); while(!winSelected) kifapp()->processEvents(); releaseMouse(); inSelect = false; XQueryPointer(disp, DefaultRootWindow(disp), &rootWin, &childWin, &rootX, &rootY, &winX, &winY, &mask); QApplication::flushX(); if(!childWin){ kdDebug() << "Pixie: no child window selected, using root" << endl; pixmap = QPixmap::grabWindow(QApplication::desktop()->winId()); } else{ pixmap = getWindow(childWin, false); } } KNotifyClient::beep(); if(hideCB->isChecked()){ kifapp()->showWindows(); QApplication::syncX(); } if(pixmap.isNull()){ KMessageBox::sorry(NULL, i18n("Unable to take snapshot!"), i18n("Screenshot Error")); inLoop = false; return; } QImage image = pixmap.convertToImage(); KFileDialog dlg(QDir::currentDirPath(), QString::null, NULL, "screenshotfiledialog", true); dlg.setOperationMode(KFileDialog::Saving); dlg.setCaption(i18n("Save Screenshot as")); KIFScreenGrabPreview *preview = new KIFScreenGrabPreview(&image); dlg.setPreviewWidget(preview); int result = dlg.exec(); QString filename = dlg.selectedFile(); if(result == QDialog::Rejected || filename.isEmpty()){ inLoop = false; return; } const char *format = formatForFilename(filename); QString formatStr; bool saved = false; while(!format){ QString extStr = QFileInfo(filename).extension(false); FormatDialog formatDlg(!extStr.isEmpty() ? extStr : filename); if(formatDlg.exec() != QDialog::Rejected){ formatStr = formatDlg.format(); format = formatStr.latin1(); } else{ inLoop = false; return; } } while(!saved){ int quality; QString commentStr; if(formatUsesComment(format)){ KIFAttributeDialog attrDlg(true, this); if(attrDlg.exec() != QDialog::Rejected){ quality = attrDlg.quality(); commentStr = attrDlg.comment(); saved = saveImage(image, filename, format, quality, commentStr); } else{ inLoop = false; return; } } else saved = saveImage(image, filename, format); if(!saved){ if(KMessageBox::warningContinueCancel(NULL, i18n("Cannot save screenshot."), i18n("Pixie Screenshot Error!"), i18n("Continue"), QString::null, true) == KMessageBox::Cancel){ qWarning("Screenshot save canceled"); inLoop = false; return; } } } KRecentDocument::add(filename); inLoop = false; } void KIFScreenGrab::slotCancel() { inLoop = false; } void KIFScreenGrab::mousePressEvent(QMouseEvent *ev) { kdDebug() << "In mousePressEvent" << endl; if(inSelect) winSelected = true; else QSemiModal::mousePressEvent(ev); } KIFScreenGrabPreview::KIFScreenGrabPreview(const QImage *image, QWidget *parent, const char *name) : KPreviewWidgetBase(parent, name) { setMinimumSize(200, 200); setMaximumWidth(200); img = image; pix = new QPixmap; if(image->width() > 200 || image->height() > 200){ QImage scaledImg; if(image->width() > image->height()){ float percent = (((float)200)/image->width()); int h = (int)(image->height()*percent); scaledImg = image->smoothScale(200, h); } else{ float percent = (((float)200)/image->height()); int w = (int)(image->width()*percent); scaledImg = image->smoothScale(w, 200); } pix->convertFromImage(scaledImg); } else pix->convertFromImage(*image); } void KIFScreenGrabPreview::paintEvent(QPaintEvent *) { bitBlt(this, 0, 0, pix, 0, 0, pix->width(), pix->height()); } // do nothing on next two calls - always show the screenshot void KIFScreenGrabPreview::showPreview(const KURL &) { ; } void KIFScreenGrabPreview::clearPreview() { ; }