00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 #include "config.h"
00026 #include <qpainter.h>
00027 #include <qvaluelist.h>
00028 
00029 #if defined Q_WS_X11 && ! defined K_WS_QTONLY // only used in kicker and kdesktop
00030 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00031 #include <kwin.h> 
00032 #include <kwinmodule.h> 
00033 #endif
00034 
00035 #include <klocale.h>
00036 #include <kstringhandler.h>
00037 
00038 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00039 
00040 #include <netwm.h> 
00041 #endif
00042 #include <kapplication.h>
00043 #include <kstyle.h>
00044 #include <dcopclient.h>
00045 #include <qtimer.h>
00046 
00047 #undef Bool
00048 #include "kwindowlistmenu.h"
00049 #include "kwindowlistmenu.moc"
00050 
00051 
00052 namespace
00053 {
00054 class NameSortedInfoList : public QPtrList<KWin::WindowInfo>
00055 {
00056 public:
00057     NameSortedInfoList() { setAutoDelete(true); };
00058     ~NameSortedInfoList() {};
00059 
00060 private:
00061     int compareItems( QPtrCollection::Item s1, QPtrCollection::Item s2 );
00062 };
00063 
00064 int NameSortedInfoList::compareItems( QPtrCollection::Item s1, QPtrCollection::Item s2 )
00065 {
00066 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00067 
00068     KWin::WindowInfo *i1 = static_cast<KWin::WindowInfo *>(s1);
00069     KWin::WindowInfo *i2 = static_cast<KWin::WindowInfo *>(s2);
00070     QString title1, title2;
00071     if (i1)
00072         title1 = i1->visibleNameWithState().lower();
00073     if (i2)
00074         title2 = i2->visibleNameWithState().lower();
00075     return title1.compare(title2);
00076 #endif
00077 }
00078 
00079 } 
00080 
00081 KWindowListMenu::KWindowListMenu(QWidget *parent, const char *name)
00082   : KPopupMenu(parent, name)
00083 {
00084 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00085 
00086     kwin_module = new KWinModule(this);
00087 #endif
00088 
00089     connect(this, SIGNAL(activated(int)), SLOT(slotExec(int)));
00090     connect(this, SIGNAL(aboutToShow()), SLOT(startActivateCurrentWindow()));
00091 }
00092 
00093 KWindowListMenu::~KWindowListMenu()
00094 {
00095 
00096 }
00097 
00098 static bool standaloneDialog( const KWin::WindowInfo* info, const NameSortedInfoList& list )
00099 {
00100     WId group = info->groupLeader();
00101     if( group == 0 )
00102     {
00103         return info->transientFor() == qt_xrootwin();
00104     }
00105     for( QPtrListIterator< KWin::WindowInfo > it( list );
00106          it.current() != NULL;
00107          ++it )
00108         if( (*it)->groupLeader() == group )
00109             return false;
00110     return true;
00111 }
00112 
00113 void KWindowListMenu::init()
00114 {
00115     int i, d;
00116     i = 0;
00117 
00118 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00119 
00120     int nd = kwin_module->numberOfDesktops();
00121     int cd = kwin_module->currentDesktop();
00122     WId active_window = kwin_module->activeWindow();
00123 
00124     clear();
00125     map.clear();
00126 
00127     int unclutter = insertItem( i18n("Unclutter Windows"),
00128                                 this, SLOT( slotUnclutterWindows() ) );
00129     int cascade = insertItem( i18n("Cascade Windows"),
00130                               this, SLOT( slotCascadeWindows() ) );
00131 
00132     
00133     if (nd == 1)
00134     {
00135         insertSeparator();
00136     }
00137 
00138 
00139     QValueList<KWin::WindowInfo> windows;
00140     for (QValueList<WId>::ConstIterator it = kwin_module->windows().begin();
00141          it != kwin_module->windows().end(); ++it) {
00142          windows.append( KWin::windowInfo( *it, NET::WMDesktop ));
00143     }
00144     bool show_all_desktops_group = ( nd > 1 );
00145     for (d = 1; d <= nd + (show_all_desktops_group ? 1 : 0); d++) {
00146         bool on_all_desktops = ( d > nd );
00147     int items = 0;
00148 
00149     if (!active_window && d == cd)
00150         setItemChecked(1000 + d, true);
00151 
00152         NameSortedInfoList list;
00153         list.setAutoDelete(true);
00154 
00155     for (QValueList<KWin::WindowInfo>::ConstIterator it = windows.begin();
00156              it != windows.end(); ++it) {
00157         if (((*it).desktop() == d) || (on_all_desktops && (*it).onAllDesktops())
00158                 || (!show_all_desktops_group && (*it).onAllDesktops())) {
00159             list.inSort(new KWin::WindowInfo( (*it).win(),
00160                     NET::WMVisibleName | NET::WMState | NET::XAWMState | NET::WMWindowType,
00161                     NET::WM2GroupLeader | NET::WM2TransientFor ));
00162             }
00163         }
00164 
00165         for (KWin::WindowInfo* info = list.first(); info!=0; info = list.next(), i++)
00166         {
00167             QString itemText = KStringHandler::cEmSqueeze(info->visibleNameWithState(), fontMetrics(), 40);
00168             NET::WindowType windowType = info->windowType( NET::NormalMask | NET::DesktopMask
00169                 | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask
00170                 | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask );
00171             if ( (windowType == NET::Normal || windowType == NET::Unknown
00172                     || (windowType == NET::Dialog && standaloneDialog( info, list )))
00173                 && !(info->state() & NET::SkipTaskbar) ) {
00174                 QPixmap pm = KWin::icon(info->win(), 16, 16, true );
00175                 items++;
00176 
00177                 
00178                 if ( items == 1 && nd > 1 )
00179                 {
00180                     if( !on_all_desktops )
00181                         insertTitle(kwin_module->desktopName( d ), 1000 + d);
00182                     else
00183                         insertTitle(i18n("On All Desktops"), 2000 );
00184                 }
00185 
00186                 
00187                 itemText.replace("&", "&&");
00188                 insertItem( pm, itemText, i);
00189                 map.insert(i, info->win());
00190                 if (info->win() == active_window)
00191                     setItemChecked(i, true);
00192             }
00193         }
00194 
00195         if (d == cd)
00196         {
00197             setItemEnabled(unclutter, items > 0);
00198             setItemEnabled(cascade, items > 0);
00199         }
00200     }
00201 
00202     
00203     if (i == 0)
00204     {
00205         if (nd > 1)
00206         {
00207             
00208             insertSeparator();
00209         }
00210 
00211         setItemEnabled(insertItem(i18n("No windows")), false);
00212     }
00213 #endif
00214 
00215     adjustSize();
00216 }
00217 
00218 void KWindowListMenu::slotExec(int id)
00219 {
00220 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00221 
00222     if (id == 2000)
00223         ; 
00224     else if (id > 1000)
00225         KWin::setCurrentDesktop(id - 1000);
00226     else if ( id >= 0 )
00227     KWin::forceActiveWindow(map[id]);
00228 #endif
00229 }
00230 
00231 
00232 
00233 
00234 
00235 
00236 void KWindowListMenu::startActivateCurrentWindow()
00237 {
00238     QTimer::singleShot( 0, this, SLOT( activateCurrentWindow()));
00239 }
00240 
00241 void KWindowListMenu::activateCurrentWindow()
00242 {
00243     for( unsigned int i = 0;
00244          i < count();
00245          ++i )
00246         if( isItemChecked( idAt( i )))
00247             {
00248             setActiveItem( i );
00249             break;
00250             }
00251 }
00252 
00253 void KWindowListMenu::slotUnclutterWindows()
00254 {
00255     kapp->dcopClient()->send("kwin", "KWinInterface", "unclutterDesktop()", "");
00256 }
00257 
00258 void KWindowListMenu::slotCascadeWindows()
00259 {
00260     kapp->dcopClient()->send("kwin", "KWinInterface", "cascadeDesktop()", "");
00261 }
00262 
00263 void KWindowListMenu::virtual_hook( int id, void* data )
00264 { KPopupMenu::virtual_hook( id, data ); }
00265 
00266 #endif
00267