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