2007-04-29 17:35:43 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2004 Lubos Lunak <l.lunak@kde.org>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
2007-07-28 15:55:22 +00:00
|
|
|
#include <KDialog>
|
2007-04-29 17:35:43 +00:00
|
|
|
#include "detectwidget.h"
|
|
|
|
|
|
|
|
#include <kapplication.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kdebug.h>
|
2007-04-30 15:48:34 +00:00
|
|
|
#include <kwindowsystem.h>
|
2007-04-29 17:35:43 +00:00
|
|
|
#include <QLabel>
|
|
|
|
#include <QRadioButton>
|
|
|
|
#include <QCheckBox>
|
|
|
|
//Added by qt3to4:
|
|
|
|
#include <QMouseEvent>
|
|
|
|
#include <QEvent>
|
|
|
|
#include <QByteArray>
|
|
|
|
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include <X11/Xatom.h>
|
|
|
|
#include <X11/Xutil.h>
|
|
|
|
#include <fixx11h.h>
|
|
|
|
#include <QX11Info>
|
|
|
|
|
|
|
|
namespace KWin
|
|
|
|
{
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
DetectWidget::DetectWidget(QWidget* parent)
|
|
|
|
: QWidget(parent)
|
|
|
|
{
|
|
|
|
setupUi(this);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
DetectDialog::DetectDialog(QWidget* parent, const char* name)
|
|
|
|
: KDialog(parent),
|
|
|
|
grabber(NULL)
|
|
|
|
{
|
|
|
|
setObjectName(name);
|
|
|
|
setModal(true);
|
|
|
|
setButtons(Ok | Cancel);
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
widget = new DetectWidget(this);
|
|
|
|
setMainWidget(widget);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void DetectDialog::detect(WId window)
|
|
|
|
{
|
|
|
|
if (window == 0)
|
2007-04-29 17:35:43 +00:00
|
|
|
selectWindow();
|
|
|
|
else
|
2011-01-30 14:34:42 +00:00
|
|
|
readWindow(window);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void DetectDialog::readWindow(WId w)
|
|
|
|
{
|
|
|
|
if (w == 0) {
|
|
|
|
emit detectionDone(false);
|
2007-04-29 17:35:43 +00:00
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
info = KWindowSystem::windowInfo(w, -1U, -1U); // read everything
|
|
|
|
if (!info.valid()) {
|
|
|
|
emit detectionDone(false);
|
2007-04-29 17:35:43 +00:00
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
wmclass_class = info.windowClassClass();
|
|
|
|
wmclass_name = info.windowClassName();
|
|
|
|
role = info.windowRole();
|
2011-01-30 14:34:42 +00:00
|
|
|
type = info.windowType(NET::NormalMask | NET::DesktopMask | NET::DockMask
|
|
|
|
| NET::ToolbarMask | NET::MenuMask | NET::DialogMask | NET::OverrideMask | NET::TopMenuMask
|
|
|
|
| NET::UtilityMask | NET::SplashMask);
|
2007-04-29 17:35:43 +00:00
|
|
|
title = info.name();
|
|
|
|
extrarole = ""; // TODO
|
|
|
|
machine = info.clientMachine();
|
|
|
|
executeDialog();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
void DetectDialog::executeDialog()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
static const char* const types[] = {
|
|
|
|
I18N_NOOP("Normal Window"),
|
|
|
|
I18N_NOOP("Desktop"),
|
|
|
|
I18N_NOOP("Dock (panel)"),
|
|
|
|
I18N_NOOP("Toolbar"),
|
|
|
|
I18N_NOOP("Torn-Off Menu"),
|
|
|
|
I18N_NOOP("Dialog Window"),
|
|
|
|
I18N_NOOP("Override Type"),
|
|
|
|
I18N_NOOP("Standalone Menubar"),
|
|
|
|
I18N_NOOP("Utility Window"),
|
|
|
|
I18N_NOOP("Splash Screen")
|
|
|
|
};
|
|
|
|
widget->class_label->setText(wmclass_class + " (" + wmclass_name + ' ' + wmclass_class + ')');
|
|
|
|
widget->role_label->setText(role);
|
|
|
|
widget->use_role->setEnabled(!role.isEmpty());
|
|
|
|
if (widget->use_role->isEnabled())
|
|
|
|
widget->use_role->setChecked(true);
|
2007-04-29 17:35:43 +00:00
|
|
|
else
|
2011-01-30 14:34:42 +00:00
|
|
|
widget->use_whole_class->setChecked(true);
|
|
|
|
if (type == NET::Unknown)
|
|
|
|
widget->type_label->setText(i18n("Unknown - will be treated as Normal Window"));
|
2007-04-29 17:35:43 +00:00
|
|
|
else
|
2011-01-30 14:34:42 +00:00
|
|
|
widget->type_label->setText(i18n(types[ type ]));
|
|
|
|
widget->title_label->setText(title);
|
|
|
|
widget->extrarole_label->setText(extrarole);
|
|
|
|
widget->machine_label->setText(machine);
|
|
|
|
emit detectionDone(exec() == KDialog::Accepted);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
QByteArray DetectDialog::selectedClass() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
if (widget->use_class->isChecked() || widget->use_role->isChecked())
|
2007-04-29 17:35:43 +00:00
|
|
|
return wmclass_class;
|
|
|
|
return wmclass_name + ' ' + wmclass_class;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
bool DetectDialog::selectedWholeClass() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
return widget->use_whole_class->isChecked();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
QByteArray DetectDialog::selectedRole() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
if (widget->use_role->isChecked())
|
2007-04-29 17:35:43 +00:00
|
|
|
return role;
|
|
|
|
return "";
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
QString DetectDialog::selectedTitle() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
return title;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
Rules::StringMatch DetectDialog::titleMatch() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
return widget->match_title->isChecked() ? Rules::ExactMatch : Rules::UnimportantMatch;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
bool DetectDialog::selectedWholeApp() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
return widget->use_class->isChecked();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
NET::WindowType DetectDialog::selectedType() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
return type;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
QByteArray DetectDialog::selectedMachine() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
return machine;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
void DetectDialog::selectWindow()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
// use a dialog, so that all user input is blocked
|
|
|
|
// use WX11BypassWM and moving away so that it's not actually visible
|
|
|
|
// grab only mouse, so that keyboard can be used e.g. for switching windows
|
2011-01-30 14:34:42 +00:00
|
|
|
grabber = new KDialog(0, Qt::X11BypassWindowManagerHint);
|
|
|
|
grabber->move(-1000, -1000);
|
|
|
|
grabber->setModal(true);
|
2007-04-29 17:35:43 +00:00
|
|
|
grabber->show();
|
2011-01-30 14:34:42 +00:00
|
|
|
grabber->grabMouse(Qt::CrossCursor);
|
|
|
|
grabber->installEventFilter(this);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
bool DetectDialog::eventFilter(QObject* o, QEvent* e)
|
|
|
|
{
|
|
|
|
if (o != grabber)
|
2007-04-29 17:35:43 +00:00
|
|
|
return false;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (e->type() != QEvent::MouseButtonRelease)
|
2007-04-29 17:35:43 +00:00
|
|
|
return false;
|
|
|
|
delete grabber;
|
|
|
|
grabber = NULL;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (static_cast< QMouseEvent* >(e)->button() != Qt::LeftButton) {
|
|
|
|
emit detectionDone(false);
|
2007-04-29 17:35:43 +00:00
|
|
|
return true;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
readWindow(findWindow());
|
|
|
|
return true;
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
WId DetectDialog::findWindow()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
Window root;
|
|
|
|
Window child;
|
|
|
|
uint mask;
|
|
|
|
int rootX, rootY, x, y;
|
|
|
|
Window parent = QX11Info::appRootWindow();
|
2011-01-30 14:34:42 +00:00
|
|
|
Atom wm_state = XInternAtom(QX11Info::display(), "WM_STATE", False);
|
|
|
|
for (int i = 0;
|
|
|
|
i < 10;
|
|
|
|
++i) {
|
|
|
|
XQueryPointer(QX11Info::display(), parent, &root, &child,
|
|
|
|
&rootX, &rootY, &x, &y, &mask);
|
|
|
|
if (child == None)
|
2007-04-29 17:35:43 +00:00
|
|
|
return 0;
|
|
|
|
Atom type;
|
|
|
|
int format;
|
|
|
|
unsigned long nitems, after;
|
|
|
|
unsigned char* prop;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (XGetWindowProperty(QX11Info::display(), child, wm_state, 0, 0, False, AnyPropertyType,
|
|
|
|
&type, &format, &nitems, &after, &prop) == Success) {
|
|
|
|
if (prop != NULL)
|
|
|
|
XFree(prop);
|
|
|
|
if (type != None)
|
|
|
|
return child;
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
parent = child;
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
#include "detectwidget.moc"
|