~ubuntu-branches/ubuntu/gutsy/kdebase-workspace/gutsy-backports

« back to all changes in this revision

Viewing changes to libs/workspace/kwindowlistmenu.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2007-09-05 20:45:14 UTC
  • Revision ID: james.westby@ubuntu.com-20070905204514-632hhspl0nvrc84i
Tags: upstream-3.93.0
ImportĀ upstreamĀ versionĀ 3.93.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************
 
2
 
 
3
Copyright (c) 2000 Matthias Elter <elter@kde.org>
 
4
                   Matthias Ettrich <ettrich@kde.org>
 
5
 
 
6
Permission is hereby granted, free of charge, to any person obtaining a copy
 
7
of this software and associated documentation files (the "Software"), to deal
 
8
in the Software without restriction, including without limitation the rights
 
9
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
10
copies of the Software, and to permit persons to whom the Software is
 
11
furnished to do so, subject to the following conditions:
 
12
 
 
13
The above copyright notice and this permission notice shall be included in
 
14
all copies or substantial portions of the Software.
 
15
 
 
16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
17
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
18
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 
19
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 
20
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
21
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
22
 
 
23
******************************************************************/
 
24
 
 
25
#include "kwindowlistmenu.h"
 
26
 
 
27
#include <QtCore/QBool>
 
28
 
 
29
#include <QtGui/QApplication>
 
30
#include <QtGui/QDesktopWidget>
 
31
#include <QtGui/QPainter>
 
32
#include <QtGui/QX11Info>
 
33
 
 
34
#include <QtDBus/QtDBus>
 
35
#include <klocale.h>
 
36
#include <kstringhandler.h>
 
37
#include <kstyle.h>
 
38
#include <kwindowsystem.h>
 
39
#include <netwm.h>
 
40
 
 
41
#undef Bool
 
42
#include "kwindowlistmenu.moc"
 
43
#include "kwin_interface.h"
 
44
 
 
45
static bool compareKWinWindowInfo( KWindowInfo* firstInfo, KWindowInfo* secondInfo )
 
46
{
 
47
  QString firstTitle, secondTitle;
 
48
 
 
49
  if ( firstInfo )
 
50
    firstTitle = firstInfo->visibleNameWithState().toLower();
 
51
 
 
52
  if ( secondInfo )
 
53
    secondTitle = secondInfo->visibleNameWithState().toLower();
 
54
 
 
55
  return firstTitle.compare( secondTitle ) >= 0;
 
56
}
 
57
 
 
58
class KWindowListMenu::Private
 
59
{
 
60
};
 
61
 
 
62
KWindowListMenu::KWindowListMenu( QWidget *parent )
 
63
  : KMenu( parent ), d( new Private )
 
64
{
 
65
}
 
66
 
 
67
KWindowListMenu::~KWindowListMenu()
 
68
{
 
69
  delete d;
 
70
}
 
71
 
 
72
static bool standaloneDialog( const KWindowInfo* info, const QList<KWindowInfo*>& list )
 
73
{
 
74
  WId group = info->groupLeader();
 
75
 
 
76
  if ( group == 0 )
 
77
    return info->transientFor() == QX11Info::appRootWindow();
 
78
 
 
79
  foreach ( KWindowInfo* info, list )
 
80
    if ( info->groupLeader() == group )
 
81
      return false;
 
82
 
 
83
  return true;
 
84
}
 
85
 
 
86
void KWindowListMenu::init()
 
87
{
 
88
  int numberOfDesktops = KWindowSystem::numberOfDesktops();
 
89
  int currentDesktop = KWindowSystem::currentDesktop();
 
90
  WId activeWindow = KWindowSystem::activeWindow();
 
91
 
 
92
  // Make sure the popup is not too wide, otherwise clicking in the middle of kdesktop
 
93
  // wouldn't leave any place for the popup, and release would activate some menu entry.
 
94
  int maxwidth = qApp->desktop()->screenGeometry( this ).width() / 2 - 100;
 
95
 
 
96
  clear();
 
97
 
 
98
  QAction* unclutter = addAction( i18n("Unclutter Windows"),
 
99
                              this, SLOT( slotUnclutterWindows() ) );
 
100
  QAction* cascade = addAction( i18n("Cascade Windows"),
 
101
                            this, SLOT( slotCascadeWindows() ) );
 
102
 
 
103
  // if we only have one desktop we won't be showing titles, so put a separator in
 
104
  if ( numberOfDesktops == 1 )
 
105
    addSeparator();
 
106
 
 
107
  QList<KWindowInfo> windows;
 
108
  foreach ( WId id, KWindowSystem::windows() )
 
109
    windows.append( KWindowSystem::windowInfo( id, NET::WMDesktop ) );
 
110
 
 
111
  bool showAllDesktopsGroup = ( numberOfDesktops > 1 );
 
112
 
 
113
  int i = 0;
 
114
  for ( int j = 1; j <= numberOfDesktops + (showAllDesktopsGroup ? 1 : 0); j++ ) {
 
115
    bool onAllDesktops = ( j > numberOfDesktops );
 
116
    int items = 0;
 
117
 
 
118
    // KDE4 porting - huh? didn't know you could set an item checked before it's created?
 
119
    //if (!activeWindow && d == cd)
 
120
        //setItemChecked(1000 + d, true);
 
121
 
 
122
    QList<KWindowInfo*> list;
 
123
 
 
124
    foreach (KWindowInfo wi, windows) {
 
125
      if ( (wi.desktop() == j) || (onAllDesktops && wi.onAllDesktops())
 
126
           || (!showAllDesktopsGroup && wi.onAllDesktops()) ) {
 
127
        list.append( new KWindowInfo( wi.win(),
 
128
                         NET::WMVisibleName | NET::WMState | NET::XAWMState | NET::WMWindowType,
 
129
                         NET::WM2GroupLeader | NET::WM2TransientFor ) );
 
130
      }
 
131
    }
 
132
 
 
133
    qStableSort( list.begin(), list.end(), compareKWinWindowInfo );
 
134
 
 
135
    foreach ( KWindowInfo* info, list ) {
 
136
      ++i;
 
137
      QString itemText = fontMetrics().elidedText(info->visibleNameWithState(), Qt::ElideMiddle, maxwidth);
 
138
 
 
139
      NET::WindowType windowType = info->windowType( NET::NormalMask | NET::DesktopMask
 
140
          | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask
 
141
          | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask );
 
142
 
 
143
      if ( (windowType == NET::Normal || windowType == NET::Unknown
 
144
              || (windowType == NET::Dialog && standaloneDialog( info, list )))
 
145
              && !(info->state() & NET::SkipTaskbar) ) {
 
146
 
 
147
        QPixmap pm = KWindowSystem::icon( info->win(), 16, 16, true );
 
148
        items++;
 
149
 
 
150
        // ok, we have items on this desktop, let's show the title
 
151
        if ( items == 1 && numberOfDesktops > 1 ) {
 
152
          if( !onAllDesktops )
 
153
              addTitle( KWindowSystem::desktopName( j ) );
 
154
          else
 
155
              addTitle( i18n( "On All Desktops" ) );
 
156
        }
 
157
 
 
158
        // Avoid creating unwanted accelerators.
 
159
        itemText.replace( '&', QLatin1String( "&&" ));
 
160
 
 
161
        QAction* action = addAction( pm, itemText, this, SLOT( slotForceActiveWindow() ) );
 
162
        action->setData( (int)info->win() );
 
163
 
 
164
        if ( info->win() == activeWindow )
 
165
          action->setChecked( true );
 
166
      }
 
167
    }
 
168
 
 
169
    if ( j == currentDesktop ) {
 
170
      unclutter->setEnabled( items > 0 );
 
171
      cascade->setEnabled( items > 0 );
 
172
    }
 
173
 
 
174
    qDeleteAll( list );
 
175
  }
 
176
 
 
177
  // no windows?
 
178
  if ( i == 0 ) {
 
179
    if ( numberOfDesktops > 1 )
 
180
      addSeparator(); // because we don't have any titles, nor a separator
 
181
 
 
182
    addAction( i18n( "No Windows" ) )->setEnabled( false );
 
183
  }
 
184
}
 
185
 
 
186
void KWindowListMenu::slotForceActiveWindow()
 
187
{
 
188
    QAction* window = qobject_cast<QAction*>(sender());
 
189
    if (!window || !window->data().canConvert(QVariant::Int))
 
190
        return;
 
191
 
 
192
    KWindowSystem::forceActiveWindow(window->data().toInt());
 
193
}
 
194
 
 
195
void KWindowListMenu::slotSetCurrentDesktop()
 
196
{
 
197
    QAction* window = qobject_cast<QAction*>(sender());
 
198
    if (!window || !window->data().canConvert(QVariant::Int))
 
199
        return;
 
200
 
 
201
    KWindowSystem::setCurrentDesktop(window->data().toInt());
 
202
}
 
203
 
 
204
// This popup is much more useful from keyboard if it has the active
 
205
// window active by default - however, QPopupMenu tries hard to resist.
 
206
// QPopupMenu::popup() resets the active item, so this needs to be
 
207
// called after popup().
 
208
void KWindowListMenu::selectActiveWindow()
 
209
{
 
210
    foreach (QAction* action, actions())
 
211
        if (action->isChecked()) {
 
212
            setActiveAction(action);
 
213
            break;
 
214
        }
 
215
}
 
216
 
 
217
void KWindowListMenu::slotUnclutterWindows()
 
218
{
 
219
    org::kde::KWin kwin("org.kde.kwin", "/KWin", QDBusConnection::sessionBus());
 
220
    kwin.unclutterDesktop();
 
221
}
 
222
 
 
223
void KWindowListMenu::slotCascadeWindows()
 
224
{
 
225
    org::kde::KWin kwin("org.kde.kwin", "/KWin", QDBusConnection::sessionBus());
 
226
    kwin.cascadeDesktop();
 
227
}
 
228