[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kwin
Subject:    Re: [Panel-devel] [PATCH] tooltips + taskbar thumbnails
From:       Lubos Lunak <l.lunak () suse ! cz>
Date:       2008-01-02 15:53:06
Message-ID: 200801021653.06692.l.lunak () suse ! cz
[Download RAW message or body]

On Friday 28 of December 2007, Sebastian Kuegler wrote:
> On Friday 28 December 2007 02:57:18 Aaron J. Seigo wrote:
> > On Thursday 27 December 2007, Sebastian Kuegler wrote:
> > > On Thursday 27 December 2007 05:38:04 Jason Stubbs wrote:
> > > > On Thursday 27 December 2007 13:06:41 Sebastian Kuegler wrote:
> > > > > Here's a patch that adds a configuration dialogue and switches
> > > > > tooltips on and off. What do you think about this?
> > > >
> > > > Looks good. :)
> > >
> > > Thanks for having a look. I've committed it as r753455.
> >
> > don't know if this is there yet (haven't looked, sorry =/ ) but the
> > tooltips really ought to show the window thumbnail when composite is
> > available.
>
> I agree, and was thinking of that as well. Let's say for now it exceeds
> what I can code up, but pointers how to get the preview out of kwin (and
> have it updated all the time as it is now) are definitely welcome. Not sure
> if it's worth pursuing before 4.0 (as in: I don't think so). :-)

 Attached patches for KWin (SVN as of now) and workspace/libs implement a 
different taskbar thumbnail effect (it turned out to be simpler than to fix 
issues in the temporary one). This one makes Plasma reserve an area in the 
tooltip, set a hint and KWin renders the thumbnail directly in that area. The 
hint is just an ad hoc format for now, and the way to detect the necessary 
KWin support is just a quick hack, but otherwise this should work fine (those 
can be done properly later).

 Is that patch ok for Plasma?


 PS: Telling relevant people occassionally helps.

 PPS: Seeing the subject, could the 90's [Panel-devel] thingy from it go away 
please? Thanks.

-- 
Lubos Lunak
KDE developer
--------------------------------------------------------------
SUSE LINUX, s.r.o.   e-mail: l.lunak@suse.cz , l.lunak@kde.org
Lihovarska 1060/12   tel: +420 284 028 972
190 00 Prague 9      fax: +420 284 028 951
Czech Republic       http//www.suse.cz

["kwin.patch" (text/x-diff)]

--- kwin/effects/CMakeLists.txt.sav	2007-12-31 23:46:01.000000000 +0100
+++ kwin/effects/CMakeLists.txt	2008-01-01 01:12:55.000000000 +0100
@@ -35,7 +35,6 @@ install( FILES kwineffect.desktop DESTIN
 # sources
 SET(kwin4_effect_builtins_sources
     boxswitch.cpp
-    demo_taskbarthumbnail.cpp
     desktopgrid.cpp
     dialogparent.cpp
     diminactive.cpp
@@ -47,13 +46,13 @@ SET(kwin4_effect_builtins_sources
     minimizeanimation.cpp
     presentwindows.cpp
     scalein.cpp
+    taskbarthumbnail.cpp
     thumbnailaside.cpp
     zoom.cpp
     )
 # their .desktop files
 install( FILES
     boxswitch.desktop
-    demo_taskbarthumbnail.desktop
     desktopgrid.desktop
     dialogparent.desktop
     diminactive.desktop
@@ -65,6 +64,7 @@ install( FILES
     minimizeanimation.desktop
     presentwindows.desktop
     scalein.desktop
+    taskbarthumbnail.desktop
     thumbnailaside.desktop
     zoom.desktop
     DESTINATION ${SERVICES_INSTALL_DIR}/kwin )
--- kwin/effects/taskbarthumbnail.desktop.sav	2007-12-31 23:46:01.000000000 +0100
+++ kwin/effects/taskbarthumbnail.desktop	2008-01-01 01:12:55.000000000 +0100
@@ -0,0 +1,85 @@
+[Desktop Entry]
+Name=Taskbar Thumbnails
+Name[ca]=Miniatures a la barra de tasques
+Name[csb]=Miniaturczi listwë dzejaniów
+Name[de]=Vorschaubild in der Fensterleiste
+Name[el]=Εικόνες επισκόπησης της Γραμμής \
εργασιών +Name[eo]=Taskobretaj miniaturoj
+Name[es]=Miniaturas de la barra de tareas
+Name[et]=Tegumiriba pisipildid
+Name[eu]=Ataza-barraren koadro txikiak
+Name[fy]=Taakbalke miniatueren
+Name[hu]=Feladatsáv-ablaktartalom
+Name[ja]=タスクバーのサ ネイル
+Name[km]=រូបភាព​តូចៗ​របារ​ភារកិច្ច
+Name[lv]=Uzdevumjoslas sīktēli
+Name[nb]=Oppgavelinje-minibilder
+Name[nds]=Programmbalken-Vöransichten
+Name[nl]=Taakbalkminiaturen
+Name[nn]=Oppgåvelinjeminiatyrbilete
+Name[pa]=ਟਾਸਕਬਾਰ ਥੰਮਨੇਲ
+Name[pl]=Miniaturki w pasku zadań
+Name[pt]=Miniaturas da Barra de Tarefas
+Name[pt_BR]=Miniaturas da Barra de Tarefas
+Name[sr]=Сличице у траци задатака
+Name[sr@latin]=Sličice u traci zadataka
+Name[sv]=Miniatyrbilder i aktivitetsfält
+Name[x-test]=xxTaskbar Thumbnailsxx
+Name[zh_CN]=任务 缩略图
+Name[zh_TW]=工作列縮圖
+Icon=preferences-system-windows-effect-taskbarthumbnail
+Comment=Shows window thumbnails when cursor is on their taskbar entry
+Comment[ca]=Mostra una miniatura de la finestra quan el cursor est  sobre la seva \
entrada de la barra de tasques +Comment[de]=Zeigt Fenster-Vorschaubilder an, wenn \
sich der Mauszeiger über dem Fensterleisten-Eintrag befindet. \
+Comment[el]=Εμφάνιση εικόνας επισκόπησης \
παραθύρου όταν το ποντίκι περνάει πάνω από την \
καταχώρησή του στη γραμμή εργασιών +Comment[eo]=Kiam la \
muso ŝvebas super taskobreta ero, miniaturo de tiu fenestro aperas \
+Comment[es]=Muestra miniaturas de la ventana cuando el cursor está en la entrada de \
su barra de tareas +Comment[et]=Akende pisipiltide näitamine, kui kursor on nende \
tegumiriba kirje kohal +Comment[fi]=Näyttää ikkunan esikatselukuvan, kun kohdistin \
osoittaa ohjelmaa tehtävärivillä. +Comment[fy]=Finsterrminiateuren sjen litte as \
it rinnerke op syn taakbalke setten wurdt +Comment[hu]=Megmutatja a feladatokhoz \
tartozó ablakok kicsinyített képét \
+Comment[ja]=タスクバーエントリの上にマウスが来たときに、そのウィンドウのサ \
ネイルを表示します +Comment[km]=បង្ \
ាញ​រូបភាព​តូចៗ​របស់​បង្អួច \
នៅ​ពេល​ទស្សន៍​នៅ​លើ​ធាតុ​របារ​ភារកិច្ច​របស់​ពួកវា
 +Comment[lv]=Parāda loga sīktēlu, kad kursors atrodas uz uzdevumjoslas ieraksta
+Comment[nb]=Viser minibilder av vinduene når pekeren er over oppgavelinja
+Comment[nds]=Wiest Vöransichten vun de Finstern, wenn Du mit de Muus op ehr \
Programmbalken-Indrääg wiest. +Comment[nl]=Vensterminiaturen tonen als cursor op \
bijhorende taakbalkknop wordt geplaatst +Comment[nn]=Vis miniatyrbilete av vindauge \
når peikaren er over ikona deira på oppgåvelinja +Comment[pl]=Pokazuje miniaturki \
okien, kiedy kursor znajduje się na ich pozycji w pasku zadań +Comment[pt]=Mostra \
as miniaturas das janelas quando o cursor está no seu item da barra de tarefas \
+Comment[pt_BR]=Mostra miniaturas das janelas quando o cursor está nas suas entradas \
na barra de tarefas +Comment[se]=Čájeha govaža láses go seaván lea dan ikona \
bajábealde +Comment[sr]=Сличице прозора како показивач \
преко ставки у траци задатака +Comment[sr@latin]=Sličice \
prozora kako pokazivač preko stavki u traci zadataka +Comment[sv]=Visar \
miniatyrbilder av fönster när markören är över deras post i aktivitetsfältet \
+Comment[x-test]=xxShows window thumbnails when cursor is on their taskbar entryxx \
+Comment[zh_CN]=当  指针指向任务 时显示窗口缩略图 \
+Comment[zh_TW]=當游標停在工作列的按鈕上面時,顯示視窗的縮圖 +
+Type=Service
+X-KDE-ServiceTypes=KWin/Effect
+X-KDE-PluginInfo-Author=Lubos Lunak
+X-KDE-PluginInfo-Email=l.lunak@kde.org
+X-KDE-PluginInfo-Name=kwin4_effect_taskbarthumbnail
+X-KDE-PluginInfo-Version=0.1.0
+X-KDE-PluginInfo-Category=Window Management
+X-KDE-PluginInfo-Category[ca]=Gestió de les finestres
+X-KDE-PluginInfo-Category[de]=Fensterverwaltung
+X-KDE-PluginInfo-Category[el]=Διαχείριση παραθύρων
+X-KDE-PluginInfo-Category[ga]=Bainisteoireacht Fuinneog
+X-KDE-PluginInfo-Category[hu]=Ablakkezelés
+X-KDE-PluginInfo-Category[ja]=ウィンドウマネージメント
+X-KDE-PluginInfo-Category[km]=ការ​គ្រប់គ្រង​បង្អួច
 +X-KDE-PluginInfo-Category[lv]=Logu pārvaldība
+X-KDE-PluginInfo-Category[nds]=Finsterpleeg
+X-KDE-PluginInfo-Category[pt]=Gestão de Janelas
+X-KDE-PluginInfo-Category[pt_BR]=Gerenciamento de Janelas
+X-KDE-PluginInfo-Category[sr]=Управљање прозорима
+X-KDE-PluginInfo-Category[sr@latin]=Upravljanje prozorima
+X-KDE-PluginInfo-Category[sv]=Fönsterhantering
+X-KDE-PluginInfo-Category[zh_CN]=窗口管理
+X-KDE-PluginInfo-Category[zh_TW]=視窗管理
+X-KDE-PluginInfo-Depends=
+X-KDE-PluginInfo-License=GPL
+X-KDE-PluginInfo-EnabledByDefault=true
+X-KDE-Library=kwin4_effect_builtins
--- kwin/effects/taskbarthumbnail.h.sav	2007-12-31 23:46:01.000000000 +0100
+++ kwin/effects/taskbarthumbnail.h	2008-01-01 02:07:10.000000000 +0100
@@ -0,0 +1,55 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2007 Rivo Laks <rivolaks@hot.ee>
+Copyright (C) 2007 Lubos Lunak <l.lunak@kde.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*********************************************************************/
+
+#ifndef KWIN_TASKBARTHUMBNAIL_H
+#define KWIN_TASKBARTHUMBNAIL_H
+
+#include <kwineffects.h>
+
+namespace KWin
+{
+
+class TaskbarThumbnailEffect
+    : public Effect
+    {
+    public:
+        TaskbarThumbnailEffect();
+        virtual ~TaskbarThumbnailEffect();
+        virtual void prePaintScreen( ScreenPrePaintData& data, int time );
+        virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int \
time ); +        virtual void paintWindow( EffectWindow* w, int mask, QRegion region, \
WindowPaintData& data ); +        virtual void windowAdded( EffectWindow* w );
+        virtual void windowRemoved( EffectWindow* w );
+        virtual void propertyNotify( EffectWindow* w, long atom );
+    protected:
+    private:
+        struct Data
+            {
+            Window window; // thumbnail of this window
+            QRect rect;
+            };
+        long atom;
+        QMultiHash< EffectWindow*, Data > thumbnails;
+    };
+
+} // namespace
+
+#endif
--- kwin/effects/taskbarthumbnail.cpp.sav	2007-12-31 23:46:01.000000000 +0100
+++ kwin/effects/taskbarthumbnail.cpp	2008-01-01 12:32:06.000000000 +0100
@@ -0,0 +1,118 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2007 Rivo Laks <rivolaks@hot.ee>
+Copyright (C) 2007 Lubos Lunak <l.lunak@kde.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*********************************************************************/
+
+#include "taskbarthumbnail.h"
+
+#include <kdebug.h>
+
+namespace KWin
+{
+
+KWIN_EFFECT( taskbarthumbnail, TaskbarThumbnailEffect )
+
+TaskbarThumbnailEffect::TaskbarThumbnailEffect()
+    {
+    atom = XInternAtom( display(), "_KDE_WINDOW_PREVIEW", False );
+    effects->registerPropertyType( atom, true );
+    // TODO hackish way to announce support, make better after 4.0
+    unsigned char dummy = 0;
+    XChangeProperty( display(), rootWindow(), atom, atom, 8, PropModeReplace, \
&dummy, 1 ); +    }
+
+TaskbarThumbnailEffect::~TaskbarThumbnailEffect()
+    {
+    XDeleteProperty( display(), rootWindow(), atom );
+    effects->registerPropertyType( atom, false );
+    }
+
+void TaskbarThumbnailEffect::prePaintScreen( ScreenPrePaintData& data, int time )
+    {
+//    if( thumbnails.count() > 0 )
+//        // TODO this should not be needed (it causes whole screen repaint)
+//        data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
+    effects->prePaintScreen(data, time);
+    }
+
+void TaskbarThumbnailEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& \
data, int time ) +    {
+    // TODO what if of the windows is translucent and one not? change data.mask?
+    effects->prePaintWindow( w, data, time );
+    }
+
+void TaskbarThumbnailEffect::paintWindow( EffectWindow* w, int mask, QRegion region, \
WindowPaintData& data ) +    {
+    effects->paintWindow( w, mask, region, data ); // paint window first
+    if( thumbnails.contains( w ))
+        { // paint thumbnails on it
+        foreach( const Data thumb, thumbnails.values( w ))
+            {
+            EffectWindow* thumbw = effects->findWindow( thumb.window );
+            WindowPaintData data( thumbw );
+            QRect r;
+            setPositionTransformations( data, r,
+                thumbw, thumb.rect.translated( w->pos()), Qt::KeepAspectRatio );
+            effects->drawWindow( thumbw,
+                PAINT_WINDOW_OPAQUE | PAINT_WINDOW_TRANSFORMED,
+                r, data );
+            }
+        }
+    }
+
+void TaskbarThumbnailEffect::windowAdded( EffectWindow* w )
+    {
+    propertyNotify( w, atom ); // read initial value
+    }
+
+void TaskbarThumbnailEffect::windowRemoved( EffectWindow* w )
+    {
+    thumbnails.remove( w );
+    }
+
+void TaskbarThumbnailEffect::propertyNotify( EffectWindow* w, long a )
+    {
+    if( a != atom )
+        return;
+    thumbnails.remove( w );
+    QByteArray data = w->readProperty( atom, atom, 32 );
+    if( data.length() < 1 )
+        return;
+    long* d = reinterpret_cast< long* >( data.data());
+    int len = data.length() / 4;
+    int pos = 0;
+    int cnt = d[ 0 ];
+    ++pos;
+    for( int i = 0;
+         i < cnt;
+         ++i )
+        {
+        int size = d[ pos ];
+        if( len - pos < size )
+            return; // format error
+        ++pos;
+        Data data;
+        data.window = d[ pos ];
+        data.rect = QRect( d[ pos + 1 ], d[ pos + 2 ], d[ pos + 3 ], d[ pos + 4 ] );
+        thumbnails.insert( w, data );
+        pos += size;
+        }
+    }
+
+} // namespace


["plasma.patch" (text/x-diff)]

--- plasma/widgets/widget.h.sav	2008-01-02 11:35:11.000000000 +0100
+++ plasma/widgets/widget.h	2008-01-02 16:46:04.000000000 +0100
@@ -40,9 +40,11 @@ namespace Plasma
 
 struct PLASMA_EXPORT ToolTipData
 {
+    ToolTipData() : windowToPreview( 0 ) {}
     QString mainText; //Important information
     QString subText; //Elaborates on the Main Text
     QPixmap image; // Icon to show;
+    WId windowToPreview; // Id of window to show preview
 };
 
 class Layout;
--- plasma/widgets/tooltip.cpp.sav	2008-01-02 11:35:11.000000000 +0100
+++ plasma/widgets/tooltip.cpp	2008-01-02 16:51:01.000000000 +0100
@@ -24,8 +24,13 @@
 #include <QPixmap>
 #include <QTimer>
 #include <QGraphicsView>
+#include <QX11Info>
 
 #include <kglobal.h>
+#include <kwindowsystem.h>
+
+#include <X11/Xlib.h>
+#include <fixx11h.h>
 
 namespace Plasma {
 
@@ -35,6 +40,8 @@ class ToolTip::Private
         Private()
         : label(0)
         , imageLabel(0)
+        , preview(0)
+        , windowToPreview(0)
         , currentWidget(0)
         , isShown(false)
         , showTimer(0)
@@ -43,6 +50,8 @@ class ToolTip::Private
 
     QLabel *label;
     QLabel *imageLabel;
+    WindowPreview *preview;
+    WId windowToPreview;
     Plasma::Widget *currentWidget;
     bool isShown;
     QTimer *showTimer;
@@ -112,18 +121,30 @@ void ToolTip::slotResetTimer()
     }
 }
 
+void ToolTip::showEvent( QShowEvent* e )
+{
+    QWidget::showEvent( e );
+    if( d->windowToPreview != 0 ) {
+        d->preview->show();
+        d->preview->setInfo();
+    } else
+        d->preview->hide();
+}
+
 ToolTip::ToolTip()
     : QWidget(0)
     , d( new Private )
 {
     setWindowFlags(Qt::ToolTip);
-    QHBoxLayout *l = new QHBoxLayout;
+    QGridLayout *l = new QGridLayout;
+    d->preview = new WindowPreview;
     d->label = new QLabel;
     d->label->setWordWrap(true);
     d->imageLabel = new QLabel;
     d->imageLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
-    l->addWidget(d->imageLabel);
-    l->addWidget(d->label);
+    l->addWidget(d->preview, 0, 0, 1, 2);
+    l->addWidget(d->imageLabel, 1, 0);
+    l->addWidget(d->label, 1, 1);
     setLayout(l);
 
     d->showTimer = new QTimer(this);
@@ -140,6 +161,7 @@ void ToolTip::setData(const Plasma::Tool
     d->label->setText("<qt><h3>" + data.mainText + "</h3><p>" +
                         data.subText + "</p></qt>");
     d->imageLabel->setPixmap(data.image);
+    d->preview->setWindowId( data.windowToPreview );
 }
 
 ToolTip::~ToolTip()
@@ -147,5 +169,76 @@ ToolTip::~ToolTip()
     delete d;
 }
 
+
+void WindowPreview::setWindowId( WId w )
+{
+    if( !previewsAvailable()) {
+        id = 0;
+        return;
+    }
+    id = w;
+    windowSize = QSize();
+}
+
+bool WindowPreview::previewsAvailable() const
+{
+    if( !KWindowSystem::compositingActive())
+        return false;
+    // hackish way to find out if KWin has the effect enabled,
+    // TODO provide proper support
+    Display* dpy = QX11Info::display();
+    Atom atom = XInternAtom( dpy, "_KDE_WINDOW_PREVIEW", False );
+    int cnt;
+    Atom* list = XListProperties( dpy, DefaultRootWindow( dpy ), &cnt );
+    if( list != NULL ) {
+        bool ret = ( qFind( list, list + cnt, atom ) != list + cnt );
+        XFree( list );
+        return ret;
+    }
+    return false;
+}
+
+QSize WindowPreview::sizeHint() const
+{
+    if( id == 0 )
+        return QSize();
+    if( !windowSize.isValid())
+        readWindowSize();
+    QSize s = windowSize;
+    s.scale( 200, 150, Qt::KeepAspectRatio );
+    return s;
+}
+
+void WindowPreview::readWindowSize() const
+{
+    Window r;
+    int x, y;
+    unsigned int w, h, b, d;
+    if( XGetGeometry( QX11Info::display(), id, &r, &x, &y, &w, &h, &b, &d ))
+        windowSize = QSize( w, h );
+    else
+        windowSize = QSize();
+}
+
+void WindowPreview::setInfo()
+{
+    Display* dpy = QX11Info::display();
+    Atom atom = XInternAtom( dpy, "_KDE_WINDOW_PREVIEW", False );
+    if( id == 0 ) {
+        XDeleteProperty( dpy, winId(), atom );
+        return;
+    }
+    if( !windowSize.isValid())
+        readWindowSize();
+    if( !windowSize.isValid()) {
+        XDeleteProperty( dpy, winId(), atom );
+        return;
+    }
+    Q_ASSERT( parentWidget()->isWindow()); // parent must be toplevel
+    long data[] = { 1, 5, id, x(), y(), width(), height() };
+    XChangeProperty( dpy, parentWidget()->winId(), atom, atom, 32, PropModeReplace,
+        reinterpret_cast< unsigned char* >( data ), sizeof( data ) / sizeof( data[ 0 ] ));
+}
+
 }
 #include "tooltip_p.moc"
--- plasma/widgets/tooltip_p.h.sav	2008-01-02 11:35:11.000000000 +0100
+++ plasma/widgets/tooltip_p.h	2008-01-02 16:46:04.000000000 +0100
@@ -49,6 +49,9 @@ public:
 
     Plasma::Widget *currentWidget() const;
 
+protected:
+    virtual void showEvent( QShowEvent* );
+
 private Q_SLOTS:
     void slotResetTimer();
     void slotShowToolTip();
@@ -60,6 +63,20 @@ private:
     Private *const d;
 };
 
+class WindowPreview : public QWidget
+{
+    Q_OBJECT
+public:
+    void setWindowId( WId w );
+    void setInfo();
+    virtual QSize sizeHint() const;
+    bool previewsAvailable() const;
+private:
+    void readWindowSize() const;
+    WId id;
+    mutable QSize windowSize;
+};
+
 }
 
 #endif


_______________________________________________
Kwin mailing list
Kwin@kde.org
https://mail.kde.org/mailman/listinfo/kwin


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic