The detect button is still not what it should be, but now it at least

does something.

svn path=/trunk/kdebase/kwin/; revision=322845
This commit is contained in:
Luboš Luňák 2004-06-22 16:31:57 +00:00
parent e095c52a40
commit 389771f957
7 changed files with 469 additions and 3 deletions

View file

@ -3,8 +3,8 @@ AM_CPPFLAGS = $(all_includes) -DKCMRULES
kde_module_LTLIBRARIES = kcm_kwinrules.la
kcm_kwinrules_la_SOURCES = main.cpp ruleswidget.cpp ruleslist.cpp kwinsrc.cpp \
ruleswidgetbase.ui ruleslistbase.ui
kcm_kwinrules_la_SOURCES = main.cpp ruleswidget.cpp ruleslist.cpp kwinsrc.cpp detectwidget.cpp \
ruleswidgetbase.ui ruleslistbase.ui detectwidgetbase.ui
kcm_kwinrules_la_LDFLAGS = -module -avoid-version $(all_libraries) -no-undefined
kcm_kwinrules_la_LIBADD = $(LIB_KDEUI)

View file

@ -0,0 +1,202 @@
/*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "detectwidget.h"
#include <kapplication.h>
#include <klocale.h>
#include <kdebug.h>
#include <kxerrorhandler.h>
#include <kwin.h>
#include <qlabel.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
namespace KWinInternal
{
DetectWidget::DetectWidget( QWidget* parent, const char* name )
: DetectWidgetBase( parent, name )
{
}
DetectDialog::DetectDialog( QWidget* parent, const char* name )
: KDialogBase( parent, name, true, "", Ok /*| Cancel*/ )
, grabber( NULL )
{
widget = new DetectWidget( this );
setMainWidget( widget );
}
void DetectDialog::detect( WId window )
{
if( window == 0 )
selectWindow();
else
readWindow( window );
}
static QCString getStringProperty(WId w, Atom prop, char separator=0)
{
Atom type;
int format, status;
unsigned long nitems = 0;
unsigned long extra = 0;
unsigned char *data = 0;
QCString result = "";
status = XGetWindowProperty( qt_xdisplay(), w, prop, 0, 10000,
FALSE, XA_STRING, &type, &format,
&nitems, &extra, &data );
if ( status == Success)
{
if (data && separator)
{
for (int i=0; i<(int)nitems; i++)
if (!data[i] && i+1<(int)nitems)
data[i] = separator;
}
if (data)
result = (const char*) data;
XFree(data);
}
return result;
}
void DetectDialog::readWindow( WId w )
{
if( w == 0 )
{
emit detectionDone( false );
return;
}
KXErrorHandler err;
XClassHint hint;
XGetClassHint( qt_xdisplay(), w, &hint );
Atom wm_role = XInternAtom( qt_xdisplay(), "WM_WINDOW_ROLE", False );
KWin::WindowInfo info = KWin::windowInfo( w );
if( !info.valid())
{
emit detectionDone( false );
return;
}
wmclass_class = hint.res_class;
wmclass_name = hint.res_name;
role = getStringProperty( w, wm_role );
type = info.windowType( NET::NormalMask | NET::DesktopMask | NET::DockMask
| NET::ToolbarMask | NET::MenuMask | NET::DialogMask | NET::OverrideMask | NET::TopMenuMask
| NET::UtilityMask | NET::SplashMask );
title = info.name();
extrarole = ""; // TODO
machine = getStringProperty( w, XA_WM_CLIENT_MACHINE );
if( err.error( true ))
{
emit detectionDone( false );
return;
}
executeDialog();
}
void DetectDialog::executeDialog()
{
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( "Splashscreen" )
};
widget->class_label->setText( wmclass_class + " (" + wmclass_name + ' ' + wmclass_class + ")" );
widget->role_label->setText( role );
if( type == NET::Unknown )
widget->type_label->setText( i18n( "Unknown - will be treated as Normal Window" ));
else
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() == QDialog::Accepted );
}
void DetectDialog::selectWindow()
{
// 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
grabber = new QDialog( NULL, NULL, true, WX11BypassWM );
grabber->move( -1000, -1000 );
grabber->show();
grabber->grabMouse( crossCursor );
grabber->installEventFilter( this );
}
bool DetectDialog::eventFilter( QObject* o, QEvent* e )
{
if( o != grabber )
return false;
if( e->type() != QEvent::MouseButtonRelease )
return false;
delete grabber;
grabber = NULL;
readWindow( findWindow());
return true;
}
WId DetectDialog::findWindow()
{
Window root;
Window child;
uint mask;
int rootX, rootY, x, y;
Window parent = qt_xrootwin();
Atom wm_state = XInternAtom( qt_xdisplay(), "WM_STATE", False );
for( int i = 0;
i < 10;
++i )
{
XQueryPointer( qt_xdisplay(), parent, &root, &child,
&rootX, &rootY, &x, &y, &mask );
if( child == None )
return 0;
Atom type;
int format;
unsigned long nitems, after;
unsigned char* prop;
if( XGetWindowProperty( qt_xdisplay(), child, wm_state, 0, 0, False, AnyPropertyType,
&type, &format, &nitems, &after, &prop ) == Success )
{
if( prop != NULL )
XFree( prop );
if( type != None )
return child;
}
parent = child;
}
return 0;
}
} // namespace
#include "detectwidget.moc"

View file

@ -0,0 +1,68 @@
/*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __DETECTWIDGET_H__
#define __DETECTWIDGET_H__
#include "detectwidgetbase.h"
#include <kdialogbase.h>
#include <netwm_def.h>
namespace KWinInternal
{
class DetectWidget
: public DetectWidgetBase
{
Q_OBJECT
public:
DetectWidget( QWidget* parent = NULL, const char* name = NULL );
};
class DetectDialog
: public KDialogBase
{
Q_OBJECT
public:
DetectDialog( QWidget* parent = NULL, const char* name = NULL );
void detect( WId window );
signals:
void detectionDone( bool );
protected:
virtual bool eventFilter( QObject* o, QEvent* e );
private:
void selectWindow();
void readWindow( WId window );
void executeDialog();
WId findWindow();
QCString wmclass_class;
QCString wmclass_name;
QCString role;
NET::WindowType type;
QString title;
QCString extrarole;
QCString machine;
DetectWidget* widget;
QDialog* grabber;
};
} // namespace
#endif

View file

@ -0,0 +1,156 @@
<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
<class>KWinInternal::DetectWidgetBase</class>
<widget class="QWidget">
<property name="name">
<cstring>Form3</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>480</height>
</rect>
</property>
<property name="caption">
<string>Form1</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLabel">
<property name="name">
<cstring>textLabel9</cstring>
</property>
<property name="text">
<string>Information about the selected window:</string>
</property>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout1</cstring>
</property>
<grid>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLabel" row="0" column="0">
<property name="name">
<cstring>textLabel1</cstring>
</property>
<property name="text">
<string>Class:</string>
</property>
</widget>
<widget class="QLabel" row="5" column="0">
<property name="name">
<cstring>textLabel13</cstring>
</property>
<property name="text">
<string>Machine:</string>
</property>
</widget>
<widget class="QLabel" row="2" column="0">
<property name="name">
<cstring>textLabel4</cstring>
</property>
<property name="text">
<string>Type:</string>
</property>
</widget>
<widget class="QLabel" row="4" column="0">
<property name="name">
<cstring>textLabel11</cstring>
</property>
<property name="text">
<string>Extra role:</string>
</property>
</widget>
<widget class="QLabel" row="3" column="1">
<property name="name">
<cstring>title_label</cstring>
</property>
<property name="text">
<string></string>
</property>
</widget>
<widget class="QLabel" row="0" column="1">
<property name="name">
<cstring>class_label</cstring>
</property>
<property name="text">
<string></string>
</property>
</widget>
<widget class="QLabel" row="4" column="1">
<property name="name">
<cstring>extrarole_label</cstring>
</property>
<property name="text">
<string></string>
</property>
</widget>
<widget class="QLabel" row="3" column="0">
<property name="name">
<cstring>textLabel8</cstring>
</property>
<property name="text">
<string>Title:</string>
</property>
</widget>
<widget class="QLabel" row="5" column="1">
<property name="name">
<cstring>machine_label</cstring>
</property>
<property name="text">
<string></string>
</property>
</widget>
<widget class="QLabel" row="2" column="1">
<property name="name">
<cstring>type_label</cstring>
</property>
<property name="text">
<string></string>
</property>
</widget>
<widget class="QLabel" row="1" column="0">
<property name="name">
<cstring>textLabel3</cstring>
</property>
<property name="text">
<string>Role:</string>
</property>
</widget>
<widget class="QLabel" row="1" column="1">
<property name="name">
<cstring>role_label</cstring>
</property>
<property name="text">
<string></string>
</property>
</widget>
</grid>
</widget>
<spacer>
<property name="name">
<cstring>spacer1</cstring>
</property>
<property name="orientation">
<enum>Vertical</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</vbox>
</widget>
<layoutdefaults spacing="6" margin="11"/>
</UI>

View file

@ -28,9 +28,12 @@
#include <klocale.h>
#include <qregexp.h>
#include <qwhatsthis.h>
#include <assert.h>
#include "../../rules.h"
#include "detectwidget.h"
namespace KWinInternal
{
@ -43,6 +46,7 @@ namespace KWinInternal
RulesWidget::RulesWidget( QWidget* parent, const char* name )
: RulesWidgetBase( parent, name )
, detect_dlg( NULL )
{
QString enableDesc =
i18n( "Enable this checkbox to alter this window property for the specified window(s)." );
@ -459,6 +463,20 @@ Rules* RulesWidget::rules() const
#undef LINEEDIT_FORCE_RULE
#undef COMBOBOX_FORCE_RULE
void RulesWidget::detectClicked()
{
assert( detect_dlg == NULL );
detect_dlg = new DetectDialog;
connect( detect_dlg, SIGNAL( detectionDone( bool )), this, SLOT( detected( bool )));
detect_dlg->detect( 0 );
}
void RulesWidget::detected( bool ok )
{
delete detect_dlg;
detect_dlg = NULL;
}
RulesDialog::RulesDialog( QWidget* parent, const char* name )
: KDialogBase( parent, name, true, "", Ok | Cancel )
{

View file

@ -28,6 +28,7 @@ namespace KWinInternal
{
class Rules;
class DetectDialog;
class RulesWidget
: public RulesWidgetBase
@ -39,6 +40,8 @@ class RulesWidget
Rules* rules() const;
signals:
void changed( bool state );
protected slots:
virtual void detectClicked();
private slots:
// geometry tab
void updateEnableposition();
@ -65,6 +68,10 @@ class RulesWidget
void updateEnableignoreposition();
void updateEnableminsize();
void updateEnablemaxsize();
// internal
void detected( bool );
private:
DetectDialog* detect_dlg;
};
class RulesDialog

View file

@ -12,6 +12,9 @@
<height>477</height>
</rect>
</property>
<property name="caption">
<string>Form1</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
@ -275,7 +278,10 @@
<cstring>detect1</cstring>
</property>
<property name="text">
<string>Detect (bad luck, this one doesn't work yet)</string>
<string>&amp;Detect</string>
</property>
<property name="accel">
<string>Alt+D</string>
</property>
</widget>
<spacer>
@ -2125,6 +2131,12 @@
<receiver>edit_reg_wmclass</receiver>
<slot>setEnabled(bool)</slot>
</connection>
<connection>
<sender>detect1</sender>
<signal>clicked()</signal>
<receiver>Form2</receiver>
<slot>detectClicked()</slot>
</connection>
</connections>
<tabstops>
<tabstop>tabWidget2</tabstop>
@ -2213,6 +2225,9 @@
<tabstop>rule_maxsize</tabstop>
<tabstop>maxsize</tabstop>
</tabstops>
<slots>
<slot access="protected">detectClicked()</slot>
</slots>
<layoutdefaults spacing="6" margin="11"/>
<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
<includehints>