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 <qglobal.h>
00026
00027 #ifdef Q_WS_X11
00028
00029 #include "config.h"
00030 #include <qpainter.h>
00031 #include <qvaluelist.h>
00032
00033 #include <kwin.h>
00034 #include <kwinmodule.h>
00035
00036 #include <klocale.h>
00037 #include <kstringhandler.h>
00038
00039 #include <netwm.h>
00040 #include <kapplication.h>
00041 #include <kstyle.h>
00042 #include <dcopclient.h>
00043
00044 #undef Bool
00045 #include "kwindowlistmenu.h"
00046 #include "kwindowlistmenu.moc"
00047
00048 static QCString kwinName() {
00049 QCString appname;
00050 int screen_number = DefaultScreen(qt_xdisplay());
00051 if (screen_number == 0)
00052 appname = "kwin";
00053 else
00054 appname.sprintf("kwin-screen-%d", screen_number);
00055 return appname;
00056 }
00057
00058
00059 namespace
00060 {
00061 class NameSortedInfoList : public QPtrList<KWin::WindowInfo>
00062 {
00063 public:
00064 NameSortedInfoList() { setAutoDelete(true); }
00065 ~NameSortedInfoList() {}
00066
00067 private:
00068 int compareItems( QPtrCollection::Item s1, QPtrCollection::Item s2 );
00069 };
00070
00071 int NameSortedInfoList::compareItems( QPtrCollection::Item s1, QPtrCollection::Item s2 )
00072 {
00073 KWin::WindowInfo *i1 = static_cast<KWin::WindowInfo *>(s1);
00074 KWin::WindowInfo *i2 = static_cast<KWin::WindowInfo *>(s2);
00075 QString title1, title2;
00076 if (i1)
00077 title1 = i1->visibleNameWithState().lower();
00078 if (i2)
00079 title2 = i2->visibleNameWithState().lower();
00080 return title1.compare(title2);
00081 }
00082
00083 }
00084
00085 KWindowListMenu::KWindowListMenu(QWidget *parent, const char *name)
00086 : KPopupMenu(parent, name)
00087 {
00088 kwin_module = new KWinModule(this);
00089
00090 connect(this, SIGNAL(activated(int)), SLOT(slotExec(int)));
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 int nd = kwin_module->numberOfDesktops();
00119 int cd = kwin_module->currentDesktop();
00120 WId active_window = kwin_module->activeWindow();
00121
00122
00123
00124 int maxwidth = kapp->desktop()->screenGeometry( this ).width() / 2 - 100;
00125
00126 clear();
00127 map.clear();
00128
00129 int unclutter = insertItem( i18n("Unclutter Windows"),
00130 this, SLOT( slotUnclutterWindows() ) );
00131 int cascade = insertItem( i18n("Cascade Windows"),
00132 this, SLOT( slotCascadeWindows() ) );
00133
00134
00135 if (nd == 1)
00136 {
00137 insertSeparator();
00138 }
00139
00140
00141 QValueList<KWin::WindowInfo> windows;
00142 for (QValueList<WId>::ConstIterator it = kwin_module->windows().begin();
00143 it != kwin_module->windows().end(); ++it) {
00144 windows.append( KWin::windowInfo( *it, NET::WMDesktop ));
00145 }
00146 bool show_all_desktops_group = ( nd > 1 );
00147 for (d = 1; d <= nd + (show_all_desktops_group ? 1 : 0); d++) {
00148 bool on_all_desktops = ( d > nd );
00149 int items = 0;
00150
00151 if (!active_window && d == cd)
00152 setItemChecked(1000 + d, true);
00153
00154 NameSortedInfoList list;
00155 list.setAutoDelete(true);
00156
00157 for (QValueList<KWin::WindowInfo>::ConstIterator it = windows.begin();
00158 it != windows.end(); ++it) {
00159 if (((*it).desktop() == d) || (on_all_desktops && (*it).onAllDesktops())
00160 || (!show_all_desktops_group && (*it).onAllDesktops())) {
00161 list.inSort(new KWin::WindowInfo( (*it).win(),
00162 NET::WMVisibleName | NET::WMState | NET::XAWMState | NET::WMWindowType,
00163 NET::WM2GroupLeader | NET::WM2TransientFor ));
00164 }
00165 }
00166
00167 for (KWin::WindowInfo* info = list.first(); info; info = list.next(), ++i)
00168 {
00169 QString itemText = KStringHandler::cPixelSqueeze(info->visibleNameWithState(), fontMetrics(), maxwidth);
00170 NET::WindowType windowType = info->windowType( NET::NormalMask | NET::DesktopMask
00171 | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask
00172 | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask );
00173 if ( (windowType == NET::Normal || windowType == NET::Unknown
00174 || (windowType == NET::Dialog && standaloneDialog( info, list )))
00175 && !(info->state() & NET::SkipTaskbar) ) {
00176 QPixmap pm = KWin::icon(info->win(), 16, 16, true );
00177 items++;
00178
00179
00180 if ( items == 1 && nd > 1 )
00181 {
00182 if( !on_all_desktops )
00183 insertTitle(kwin_module->desktopName( d ), 1000 + d);
00184 else
00185 insertTitle(i18n("On All Desktops"), 2000 );
00186 }
00187
00188
00189 itemText.replace('&', QString::fromLatin1("&&"));
00190 insertItem( pm, itemText, i);
00191 map.insert(i, info->win());
00192 if (info->win() == active_window)
00193 setItemChecked(i, true);
00194 }
00195 }
00196
00197 if (d == cd)
00198 {
00199 setItemEnabled(unclutter, items > 0);
00200 setItemEnabled(cascade, items > 0);
00201 }
00202 }
00203
00204
00205 if (i == 0)
00206 {
00207 if (nd > 1)
00208 {
00209
00210 insertSeparator();
00211 }
00212
00213 setItemEnabled(insertItem(i18n("No Windows")), false);
00214 }
00215 }
00216
00217 void KWindowListMenu::slotExec(int id)
00218 {
00219 if (id == 2000)
00220 ;
00221 else if (id > 1000)
00222 KWin::setCurrentDesktop(id - 1000);
00223 else if ( id >= 0 )
00224 KWin::forceActiveWindow(map[id]);
00225 }
00226
00227
00228
00229
00230
00231 void KWindowListMenu::selectActiveWindow()
00232 {
00233 for( unsigned int i = 0;
00234 i < count();
00235 ++i )
00236 if( isItemChecked( idAt( i )))
00237 {
00238 setActiveItem( i );
00239 break;
00240 }
00241 }
00242
00243 void KWindowListMenu::slotUnclutterWindows()
00244 {
00245 kapp->dcopClient()->send(kwinName(), "KWinInterface", "unclutterDesktop()", "");
00246 }
00247
00248 void KWindowListMenu::slotCascadeWindows()
00249 {
00250 kapp->dcopClient()->send(kwinName(), "KWinInterface", "cascadeDesktop()", "");
00251 }
00252
00253 void KWindowListMenu::virtual_hook( int id, void* data )
00254 { KPopupMenu::virtual_hook( id, data ); }
00255
00256 #endif // Q_WS_X11
00257