windows_handler.cpp 5.42 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/****************************************************************************

 KHotKeys

 Copyright (C) 1999-2001 Lubos Lunak <l.lunak@kde.org>

 Distributed under the terms of the GNU General Public License version 2.

****************************************************************************/

#define _WINDOWS_CPP_

#include "windows_handler.h"

#include "windows_helper/window_selection_rules.h"
#include "windows_helper/window_selection_list.h"

#include <QRegExp>

#include <kconfig.h>
#include <kconfiggroup.h>
David Edmundson's avatar
David Edmundson committed
22
#include <QDebug>
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <kwindowsystem.h>
#include <klocale.h>

#include "khotkeysglobal.h"

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <QX11Info>

namespace KHotKeys
{

// WindowsHandler

WindowsHandler::WindowsHandler( bool enable_signal_P, QObject* parent_P )
    : QObject( parent_P ), signals_enabled( enable_signal_P ),
Martin Flöser's avatar
Martin Flöser committed
39
40
        _action_window( 0 ),
        m_isX11(QX11Info::isPlatformX11())
41
42
43
    {
    if( signals_enabled )
        {
Laurent Montel's avatar
Laurent Montel committed
44
45
46
47
        connect( KWindowSystem::self(), SIGNAL(windowAdded(WId)), SLOT(window_added_slot(WId)));
        connect( KWindowSystem::self(), SIGNAL(windowRemoved(WId)), SLOT(window_removed_slot(WId)));
        connect( KWindowSystem::self(), SIGNAL(activeWindowChanged(WId)),
            SLOT(active_window_changed_slot(WId)));
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
        }
    }

WindowsHandler::~WindowsHandler()
    {
    }

void WindowsHandler::window_added_slot( WId window_P )
    {
    if( signals_enabled )
        emit window_added( window_P );
    // CHECKME tyhle i dalsi by asi mely jit nastavit, jestli aktivuji vsechny, nebo jen jeden
    // pripojeny slot ( stejne jako u Kdb, kde by to take melo jit nastavit )
    }

void WindowsHandler::window_removed_slot( WId window_P )
    {
    if( signals_enabled )
        emit window_removed( window_P );
    if( window_P == _action_window )
        _action_window = 0;
    }

void WindowsHandler::active_window_changed_slot( WId window_P )
    {
    if( signals_enabled )
        emit active_window_changed( window_P );
    }

void WindowsHandler::window_changed_slot( WId window_P )
    {
    if( signals_enabled )
        emit window_changed( window_P );
    }

void WindowsHandler::window_changed_slot( WId window_P, unsigned int flags_P )
    {
    if( signals_enabled )
        emit window_changed( window_P, flags_P );
    }

QString WindowsHandler::get_window_role( WId id_P )
    {
    // TODO this is probably just a hack
Laurent Montel's avatar
Laurent Montel committed
92
    return KWindowInfo( id_P, {}, NET::WM2WindowRole ).windowRole();
93
94
95
96
    }

QString WindowsHandler::get_window_class( WId id_P )
    {
Martin Flöser's avatar
Martin Flöser committed
97
98
99
    if (!m_isX11) {
        return QString();
    }
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
    XClassHint hints_ret;
    if( XGetClassHint( QX11Info::display(), id_P, &hints_ret ) == 0 ) // 0 means error
	return "";
    QString ret( hints_ret.res_name );
    ret += ' ';
    ret += hints_ret.res_class;
    XFree( hints_ret.res_name );
    XFree( hints_ret.res_class );
    return ret;
    }

WId WindowsHandler::active_window()
    {
    return KWindowSystem::activeWindow();
    }

WId WindowsHandler::action_window()
    {
    return _action_window;
    }

void WindowsHandler::set_action_window( WId window_P )
    {
    _action_window = window_P;
    }

WId WindowsHandler::find_window( const Windowdef_list* window_P )
    {
128
129
130
    const QList<WId> windows = KWindowSystem::windows();
    for( auto it = windows.begin();
         it != windows.end();
131
132
133
134
135
136
137
138
139
140
141
         ++it )
        {
        Window_data tmp( *it );
        if( window_P->match( tmp ))
            return *it;
        }
    return None;
    }

WId WindowsHandler::window_at_position( int x, int y )
    {
Martin Flöser's avatar
Martin Flöser committed
142
143
144
    if (!QX11Info::isPlatformX11()) {
        return 0;
    }
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
    Window child, dummy;
    Window parent = QX11Info::appRootWindow();
    Atom wm_state = XInternAtom( QX11Info::display(), "WM_STATE", False );
    for( int i = 0;
         i < 10;
         ++i )
        {
        int destx, desty;
        // find child at that position
        if( !XTranslateCoordinates( QX11Info::display(), parent, parent, x, y, &destx, &desty, &child )
            || child == None )
            return 0;
        // and now transform coordinates to the child
        if( !XTranslateCoordinates( QX11Info::display(), parent, child, x, y, &destx, &desty, &dummy ))
            return 0;
        x = destx;
        y = desty;
        Atom type;
        int format;
        unsigned long nitems, after;
        unsigned char* prop;
        if( XGetWindowProperty( QX11Info::display(), child, wm_state, 0, 0, False, AnyPropertyType,
	    &type, &format, &nitems, &after, &prop ) == Success )
            {
Laurent Montel's avatar
Laurent Montel committed
169
	    if( prop != nullptr )
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
	        XFree( prop );
	    if( type != None )
	        return child;
            }
        parent = child;
        }
    return 0;

    }

void WindowsHandler::activate_window( WId id_P )
    {
    KWindowSystem::forceActiveWindow( id_P );
    }

// Window_data

Window_data::Window_data( WId id_P )
    : type( NET::Unknown )
    {
190
    KWindowInfo kwin_info( id_P, NET::WMName | NET::WMWindowType ); // TODO optimize
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
    if( kwin_info.valid())
        {
        title = kwin_info.name();
        role = windows_handler->get_window_role( id_P );
        wclass = windows_handler->get_window_class( id_P );
        type = kwin_info.windowType( SUPPORTED_WINDOW_TYPES_MASK );
        if( type == NET::Override ) // HACK consider non-NETWM fullscreens to be normal too
            type = NET::Normal;
        if( type == NET::Unknown )
            type = NET::Normal;
        }
    }

} // namespace KHotKeys

#include "moc_windows_handler.cpp"