From kde-core-devel Tue Nov 23 01:27:56 2004 From: =?ISO-8859-1?Q?S=E9bastien_Lao=FBt?= "\[temporar\]" Date: Tue, 23 Nov 2004 01:27:56 +0000 To: kde-core-devel Subject: Re: KDElibs: KSystemTray: On window close dialog Message-Id: <1101173275.2747.31.camel () localhost ! localdomain> X-MARC-Message: https://marc.info/?l=kde-core-devel&m=110117333122934 MIME-Version: 1 Content-Type: multipart/mixed; boundary="--=-95BkJPirIL7FMgfTVy47" --=-95BkJPirIL7FMgfTVy47 Content-Type: text/plain; charset=iso-8859-15 Content-Transfer-Encoding: quoted-printable Hello, Yes I'm back :-) As usualy, I'm always waiting the last minute to do things. Since freeze is soon, it's time to hurry up me :-/ So, I've worked to: - Get the dialog don't show if there isn't any systray area or it is hidden. - But before try to show/raise this area. Sources are joined. I'm facing one problem: if the kicker is under other windows I'm trying to raise it, wait 1 second for a refresh, take the screenshot and then show the message box. But the raising is done JUST AFTER the message box is shown! Even if I insert kapp->processEvents(), wait, use all the available KWin methods... It does nothing. Is anyone has an idea of what is the problem? It's on point 4. in the code. Also, kapp->widgetAt() seems to don't work on systray. I will also look at how to add a "warning" color to KDE colorsheme. Best regards, S=E9bastien Lao=FBt. --=-95BkJPirIL7FMgfTVy47 Content-Disposition: attachment; filename=ksystray_onclose.txt Content-Type: text/plain; name=ksystray_onclose.txt; charset=iso-8859-15 Content-Transfer-Encoding: quoted-printable /** * Call this method when the user clicked the close button of the window * (the [x]) to inform him that the application sit in the system tray * and willn't be closed (as he is used to). * * You usualy call it from reimplemented KMainWindow::queryClose() * * @author S=E9bastien Lao=FBt * @since 3.4 */ void displayCloseMessage(QString fileMenu =3D ""); void KSystemTray::displayCloseMessage(QString fileMenu) { /* IDEAS OF IMPROVEMENTS: * - Use queuedMessageBox() but it need a dontAskAgainName parameter * and image in QMimeSourceFactory shouldn't be removed. * - Sometimes the systray icon is coever (a passive popup...) * Use XComposite extension, if available, to get the kicker pixmap. * - Perhapse desaturate the area around the proper SysTray icon, * helping bring it into sharper focus. Or draw the cicle with XOR * brush. * - Perhapse add the icon in the text (eg. "... in the * system tray ([icon])."). Add some clutter to the dialog. */ #if KDE_IS_VERSION( 3, 1, 90 ) // Don't do all the computations if they are unneeded: if ( ! KMessageBox::shouldBeShownContinue("hideOnCloseInfo") ) return; #endif // "Default parameter". Here, to avoid a i18n() call and dependancy in the= .h if (fileMenu.isEmpty()) fileMenu =3D i18n("File"); // Some values we need: QPoint g =3D mapToGlobal(pos()); int desktopWidth =3D kapp->desktop()->width(); int desktopHeight =3D kapp->desktop()->height(); int tw =3D width(); int th =3D height(); // We are triying to make a live screenshot of the systray icon to circle = it // and show it to the user. If no systray is used or if the icon is not v= isible, // we should not show that screenshot but only a text! // 1. Determine if the user use a system tray area or not: QCString screenstr; screenstr.setNum(qt_xscreen()); QCString trayatom =3D "_NET_SYSTEM_TRAY_S" + screenstr; bool useSystray =3D (KSelectionWatcher(trayatom).owner() !=3D None); // 2. And then if the icon is visible too (eg. this->show() has been calle= d): useSystray =3D useSystray && isVisible(); // 3. Kicker (or another systray manager) can be visible but masked out of // the screen (ie. on right or on left of it). We check if the icon isn= 't // out of screen. if (useSystray) { QRect deskRect(0, 0, desktopWidth, desktopHeight); if ( !deskRect.contains(g.x(), g.y()) || !deskRect.contains(g.x() + tw, g.y() + th) ) useSystray =3D false; } // 4. We raise the window containing the systray icon (typically the kicke= r) to // have the most chances it is visible during the capture: if (useSystray) { // We are testing if one of the corners is hidden, and if yes, we would e= nter // a time consuming process (raise kicker and wait some time): // if (kapp->widgetAt(g) !=3D this || // kapp->widgetAt(g + QPoint(tw-1, 0)) !=3D this || // kapp->widgetAt(g + QPoint(0, th-1)) !=3D this || // kapp->widgetAt(g + QPoint(tw-1, th-1)) !=3D this) { int systrayManagerWinId =3D topLevelWidget()->winId(); KWin::forceActiveWindow(systrayManagerWinId); kapp->processEvents(); // Because without it the systrayManager is raise= d only after the messageBox is displayed // KWin::activateWindow(systrayManagerWinId); // kapp->processEvents(); // Because without it the systrayManager is rai= sed only after the messageBox is displayed // KWin::raiseWindow(systrayManagerWinId); // kapp->processEvents(); // Because without it the systrayManager is rai= sed only after the messageBox is displayed sleep(1); // TODO: Re-verify that at elast one corner is now visible // } } // KMessageBox::information(this, QString::number(g.x()) + ":" + QString::n= umber(g.y()) + ":" + // QString::number((int)(kapp->widgetAt(g+QPoint(1= ,1))))); QString message =3D i18n( "

Closing the main window will keep %1 running in the system tray. " "Use Quit from the %2 menu to quit the application.

" ).arg(KGlobal::instance()->aboutData()->programName(), "Basket"); // We are sure the systray icon is visible: ouf! if (useSystray) { // Compute size and position of the pixmap to be grabbed: int w =3D desktopWidth / 4; int h =3D desktopHeight / 9; int x =3D g.x() + tw/2 - w/2; // Center the rectange in the systray icon int y =3D g.y() + th/2 - h/2; if (x < 0) x =3D 0; // Move the rectangle to stay in the = desktop limits if (y < 0) y =3D 0; if (x + w > desktopWidth) x =3D desktopWidth - w; if (y + h > desktopHeight) y =3D desktopHeight - h; // Grab the desktop and draw a circle arround the icon: QPixmap shot =3D QPixmap::grabWindow(qt_xrootwin(), x, y, w, h); QPainter painter(&shot); const int CIRCLE_MARGINS =3D 6; const int CIRCLE_WIDTH =3D 3; const int SHADOW_OFFSET =3D 1; const int IMAGE_BORDER =3D 1; int ax =3D g.x() - x - CIRCLE_MARGINS - 1; int ay =3D g.y() - y - CIRCLE_MARGINS - 1; painter.setPen( QPen(KApplication::palette().active().dark(), CIRCLE_WIDT= H) ); painter.drawArc(ax + SHADOW_OFFSET, ay + SHADOW_OFFSET, tw + 2*CIRCLE_MARGINS, th + 2*CIRCLE_MARGINS, 0, 16*360); painter.setPen( QPen(Qt::red/*KApplication::palette().active().highlight(= )*/, CIRCLE_WIDTH) ); painter.drawArc(ax, ay, tw + 2*CIRCLE_MARGINS, th + 2*CIRCLE_MARGINS, 0, = 16*360); painter.end(); // Then, we add a border arround the image to make it more visible: QPixmap finalShot(w + 2*IMAGE_BORDER, h + 2*IMAGE_BORDER); finalShot.fill(KApplication::palette().active().foreground()); painter.begin(&finalShot); painter.drawPixmap(IMAGE_BORDER, IMAGE_BORDER, shot); painter.end(); // Associate source to image and show the dialog: QMimeSourceFactory::defaultFactory()->setPixmap("systray_shot", finalShot= ); KMessageBox::information(this, message + "

", i18n("Docking in System Tray"), "hideOnCloseInfo"); QMimeSourceFactory::defaultFactory()->setData("systray_shot", 0L); } else { KMessageBox::information(this, message, i18n("Docking in System Tray"), "hideOnCloseInfo"); } } --=-95BkJPirIL7FMgfTVy47--