~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to kwin/kcmkwin/kwinrules/detectwidget.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2004 Lubos Lunak <l.lunak@kde.org>
 
3
 *
 
4
 *  This program is free software; you can redistribute it and/or modify
 
5
 *  it under the terms of the GNU General Public License as published by
 
6
 *  the Free Software Foundation; either version 2 of the License, or
 
7
 *  (at your option) any later version.
 
8
 *
 
9
 *  This program is distributed in the hope that it will be useful,
 
10
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 *  GNU General Public License for more details.
 
13
 *
 
14
 *  You should have received a copy of the GNU General Public License
 
15
 *  along with this program; if not, write to the Free Software
 
16
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
17
 */
 
18
 
 
19
#include <KDialog>
 
20
#include "detectwidget.h"
 
21
 
 
22
#include <kapplication.h>
 
23
#include <klocale.h>
 
24
#include <kdebug.h>
 
25
#include <kwindowsystem.h>
 
26
#include <QLabel>
 
27
#include <QRadioButton>
 
28
#include <QCheckBox>
 
29
//Added by qt3to4:
 
30
#include <QMouseEvent>
 
31
#include <QEvent>
 
32
#include <QByteArray>
 
33
#include <QTimer>
 
34
 
 
35
#include <X11/Xlib.h>
 
36
#include <X11/Xatom.h>
 
37
#include <X11/Xutil.h>
 
38
#include <fixx11h.h>
 
39
#include <QX11Info>
 
40
 
 
41
namespace KWin
 
42
{
 
43
 
 
44
DetectWidget::DetectWidget(QWidget* parent)
 
45
    : QWidget(parent)
 
46
{
 
47
    setupUi(this);
 
48
}
 
49
 
 
50
DetectDialog::DetectDialog(QWidget* parent, const char* name)
 
51
    : KDialog(parent),
 
52
      grabber(NULL)
 
53
{
 
54
    setObjectName(name);
 
55
    setModal(true);
 
56
    setButtons(Ok | Cancel);
 
57
 
 
58
    widget = new DetectWidget(this);
 
59
    setMainWidget(widget);
 
60
}
 
61
 
 
62
void DetectDialog::detect(WId window, int secs)
 
63
{
 
64
    if (window == 0)
 
65
        QTimer::singleShot(secs*1000, this, SLOT(selectWindow()));
 
66
    else
 
67
        readWindow(window);
 
68
}
 
69
 
 
70
void DetectDialog::readWindow(WId w)
 
71
{
 
72
    if (w == 0) {
 
73
        emit detectionDone(false);
 
74
        return;
 
75
    }
 
76
    info = KWindowSystem::windowInfo(w, -1U, -1U);   // read everything
 
77
    if (!info.valid()) {
 
78
        emit detectionDone(false);
 
79
        return;
 
80
    }
 
81
    wmclass_class = info.windowClassClass();
 
82
    wmclass_name = info.windowClassName();
 
83
    role = info.windowRole();
 
84
    type = info.windowType(NET::NormalMask | NET::DesktopMask | NET::DockMask
 
85
                           | NET::ToolbarMask | NET::MenuMask | NET::DialogMask | NET::OverrideMask | NET::TopMenuMask
 
86
                           | NET::UtilityMask | NET::SplashMask);
 
87
    title = info.name();
 
88
    extrarole = ""; // TODO
 
89
    machine = info.clientMachine();
 
90
    executeDialog();
 
91
}
 
92
 
 
93
void DetectDialog::executeDialog()
 
94
{
 
95
    static const char* const types[] = {
 
96
        I18N_NOOP("Normal Window"),
 
97
        I18N_NOOP("Desktop"),
 
98
        I18N_NOOP("Dock (panel)"),
 
99
        I18N_NOOP("Toolbar"),
 
100
        I18N_NOOP("Torn-Off Menu"),
 
101
        I18N_NOOP("Dialog Window"),
 
102
        I18N_NOOP("Override Type"),
 
103
        I18N_NOOP("Standalone Menubar"),
 
104
        I18N_NOOP("Utility Window"),
 
105
        I18N_NOOP("Splash Screen")
 
106
    };
 
107
    widget->class_label->setText(wmclass_class + " (" + wmclass_name + ' ' + wmclass_class + ')');
 
108
    widget->role_label->setText(role);
 
109
    widget->use_role->setEnabled(!role.isEmpty());
 
110
    if (widget->use_role->isEnabled())
 
111
        widget->use_role->setChecked(true);
 
112
    else
 
113
        widget->use_whole_class->setChecked(true);
 
114
    if (type == NET::Unknown)
 
115
        widget->type_label->setText(i18n("Unknown - will be treated as Normal Window"));
 
116
    else
 
117
        widget->type_label->setText(i18n(types[ type ]));
 
118
    widget->title_label->setText(title);
 
119
    widget->extrarole_label->setText(extrarole);
 
120
    widget->machine_label->setText(machine);
 
121
    widget->adjustSize();
 
122
    adjustSize();
 
123
    if (width() < 4*height()/3)
 
124
        resize(4*height()/3, height());
 
125
    emit detectionDone(exec() == KDialog::Accepted);
 
126
}
 
127
 
 
128
QByteArray DetectDialog::selectedClass() const
 
129
{
 
130
    if (widget->use_class->isChecked() || widget->use_role->isChecked())
 
131
        return wmclass_class;
 
132
    return wmclass_name + ' ' + wmclass_class;
 
133
}
 
134
 
 
135
bool DetectDialog::selectedWholeClass() const
 
136
{
 
137
    return widget->use_whole_class->isChecked();
 
138
}
 
139
 
 
140
QByteArray DetectDialog::selectedRole() const
 
141
{
 
142
    if (widget->use_role->isChecked())
 
143
        return role;
 
144
    return "";
 
145
}
 
146
 
 
147
QString DetectDialog::selectedTitle() const
 
148
{
 
149
    return title;
 
150
}
 
151
 
 
152
Rules::StringMatch DetectDialog::titleMatch() const
 
153
{
 
154
    return widget->match_title->isChecked() ? Rules::ExactMatch : Rules::UnimportantMatch;
 
155
}
 
156
 
 
157
bool DetectDialog::selectedWholeApp() const
 
158
{
 
159
    return widget->use_class->isChecked();
 
160
}
 
161
 
 
162
NET::WindowType DetectDialog::selectedType() const
 
163
{
 
164
    return type;
 
165
}
 
166
 
 
167
QByteArray DetectDialog::selectedMachine() const
 
168
{
 
169
    return machine;
 
170
}
 
171
 
 
172
void DetectDialog::selectWindow()
 
173
{
 
174
    // use a dialog, so that all user input is blocked
 
175
    // use WX11BypassWM and moving away so that it's not actually visible
 
176
    // grab only mouse, so that keyboard can be used e.g. for switching windows
 
177
    grabber = new KDialog(0, Qt::X11BypassWindowManagerHint);
 
178
    grabber->move(-1000, -1000);
 
179
    grabber->setModal(true);
 
180
    grabber->show();
 
181
    grabber->grabMouse(Qt::CrossCursor);
 
182
    grabber->installEventFilter(this);
 
183
}
 
184
 
 
185
bool DetectDialog::eventFilter(QObject* o, QEvent* e)
 
186
{
 
187
    if (o != grabber)
 
188
        return false;
 
189
    if (e->type() != QEvent::MouseButtonRelease)
 
190
        return false;
 
191
    delete grabber;
 
192
    grabber = NULL;
 
193
    if (static_cast< QMouseEvent* >(e)->button() != Qt::LeftButton) {
 
194
        emit detectionDone(false);
 
195
        return true;
 
196
    }
 
197
    readWindow(findWindow());
 
198
    return true;
 
199
}
 
200
 
 
201
WId DetectDialog::findWindow()
 
202
{
 
203
    Window root;
 
204
    Window child;
 
205
    uint mask;
 
206
    int rootX, rootY, x, y;
 
207
    Window parent = QX11Info::appRootWindow();
 
208
    Atom wm_state = XInternAtom(QX11Info::display(), "WM_STATE", False);
 
209
    for (int i = 0;
 
210
            i < 10;
 
211
            ++i) {
 
212
        XQueryPointer(QX11Info::display(), parent, &root, &child,
 
213
                      &rootX, &rootY, &x, &y, &mask);
 
214
        if (child == None)
 
215
            return 0;
 
216
        Atom type;
 
217
        int format;
 
218
        unsigned long nitems, after;
 
219
        unsigned char* prop;
 
220
        if (XGetWindowProperty(QX11Info::display(), child, wm_state, 0, 0, False, AnyPropertyType,
 
221
                              &type, &format, &nitems, &after, &prop) == Success) {
 
222
            if (prop != NULL)
 
223
                XFree(prop);
 
224
            if (type != None)
 
225
                return child;
 
226
        }
 
227
        parent = child;
 
228
    }
 
229
    return 0;
 
230
}
 
231
 
 
232
} // namespace
 
233
 
 
234
#include "detectwidget.moc"