twindowlistmenu.cpp
00001 /***************************************************************** 00002 00003 Copyright (c) 2000 Matthias Elter <elter@kde.org> 00004 Matthias Ettrich <ettrich@kde.org> 00005 00006 Permission is hereby granted, free of charge, to any person obtaining a copy 00007 of this software and associated documentation files (the "Software"), to deal 00008 in the Software without restriction, including without limitation the rights 00009 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00010 copies of the Software, and to permit persons to whom the Software is 00011 furnished to do so, subject to the following conditions: 00012 00013 The above copyright notice and this permission notice shall be included in 00014 all copies or substantial portions of the Software. 00015 00016 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00017 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00018 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00019 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00020 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00021 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00022 00023 ******************************************************************/ 00024 00025 #include <tqglobal.h> 00026 00027 #ifdef Q_WS_X11 00028 00029 #include "config.h" 00030 #include <tqpainter.h> 00031 #include <tqvaluelist.h> 00032 00033 #include <twin.h> 00034 #include <twinmodule.h> 00035 00036 #include <tdelocale.h> 00037 #include <kstringhandler.h> 00038 00039 #include <netwm.h> 00040 #include <tdeapplication.h> 00041 #include <tdestyle.h> 00042 #include <dcopclient.h> 00043 00044 #undef Bool 00045 #include "twindowlistmenu.h" 00046 #include "twindowlistmenu.moc" 00047 00048 static TQCString twinName() { 00049 TQCString appname; 00050 int screen_number = DefaultScreen(tqt_xdisplay()); 00051 if (screen_number == 0) 00052 appname = "twin"; 00053 else 00054 appname.sprintf("twin-screen-%d", screen_number); 00055 return appname; 00056 } 00057 00058 // helper class 00059 namespace 00060 { 00061 class NameSortedInfoList : public TQPtrList<KWin::WindowInfo> 00062 { 00063 public: 00064 NameSortedInfoList() { setAutoDelete(true); } 00065 ~NameSortedInfoList() {} 00066 00067 private: 00068 int compareItems( TQPtrCollection::Item s1, TQPtrCollection::Item s2 ); 00069 }; 00070 00071 int NameSortedInfoList::compareItems( TQPtrCollection::Item s1, TQPtrCollection::Item s2 ) 00072 { 00073 KWin::WindowInfo *i1 = static_cast<KWin::WindowInfo *>(s1); 00074 KWin::WindowInfo *i2 = static_cast<KWin::WindowInfo *>(s2); 00075 TQString 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 } // namespace 00084 00085 KWindowListMenu::KWindowListMenu(TQWidget *parent, const char *name) 00086 : TDEPopupMenu(parent, name) 00087 { 00088 twin_module = new KWinModule(TQT_TQOBJECT(this)); 00089 00090 connect(this, TQT_SIGNAL(activated(int)), TQT_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() == tqt_xrootwin(); 00104 } 00105 for( TQPtrListIterator< 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 = twin_module->numberOfDesktops(); 00119 int cd = twin_module->currentDesktop(); 00120 WId active_window = twin_module->activeWindow(); 00121 00122 // Make sure the popup is not too wide, otherwise clicking in the middle of kdesktop 00123 // wouldn't leave any place for the popup, and release would activate some menu entry. 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, TQT_SLOT( slotUnclutterWindows() ) ); 00131 int cascade = insertItem( i18n("Cascade Windows"), 00132 this, TQT_SLOT( slotCascadeWindows() ) ); 00133 00134 // if we only have one desktop we won't be showing titles, so put a separator in 00135 if (nd == 1) 00136 { 00137 insertSeparator(); 00138 } 00139 00140 00141 TQValueList<KWin::WindowInfo> windows; 00142 for (TQValueList<WId>::ConstIterator it = twin_module->windows().begin(); 00143 it != twin_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 (TQValueList<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 TQString 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 TQPixmap pm = KWin::icon(info->win(), 16, 16, true ); 00177 items++; 00178 00179 // ok, we have items on this desktop, let's show the title 00180 if ( items == 1 && nd > 1 ) 00181 { 00182 if( !on_all_desktops ) 00183 insertTitle(twin_module->desktopName( d ), 1000 + d); 00184 else 00185 insertTitle(i18n("On All Desktops"), 2000 ); 00186 } 00187 00188 // Avoid creating unwanted accelerators. 00189 itemText.replace('&', TQString::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 // no windows? 00205 if (i == 0) 00206 { 00207 if (nd > 1) 00208 { 00209 // because we don't have any titles, nor a separator 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 ; // do nothing 00221 else if (id > 1000) 00222 KWin::setCurrentDesktop(id - 1000); 00223 else if ( id >= 0 ) 00224 KWin::forceActiveWindow(map[id]); 00225 } 00226 00227 // This popup is much more useful from keyboard if it has the active 00228 // window active by default - however, TQPopupMenu tries hard to resist. 00229 // TQPopupMenu::popup() resets the active item, so this needs to be 00230 // called after popup(). 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(twinName(), "KWinInterface", "unclutterDesktop()", TQString("")); 00246 } 00247 00248 void KWindowListMenu::slotCascadeWindows() 00249 { 00250 kapp->dcopClient()->send(twinName(), "KWinInterface", "cascadeDesktop()", TQString("")); 00251 } 00252 00253 void KWindowListMenu::virtual_hook( int id, void* data ) 00254 { TDEPopupMenu::virtual_hook( id, data ); } 00255 00256 #endif // Q_WS_X11 00257