~compiz-team/compiz/0.9.12

« back to all changes in this revision

Viewing changes to plugins/regex/src/regex.cpp

  • Committer: Dennis kasprzyk
  • Author(s): Dennis Kasprzyk
  • Date: 2009-03-15 05:09:18 UTC
  • Revision ID: git-v1:163f6b6f3c3b7764987cbdf8e03cc355edeaa499
New generalized build system.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2007 Novell, Inc.
 
3
 *
 
4
 * Permission to use, copy, modify, distribute, and sell this software
 
5
 * and its documentation for any purpose is hereby granted without
 
6
 * fee, provided that the above copyright notice appear in all copies
 
7
 * and that both that copyright notice and this permission notice
 
8
 * appear in supporting documentation, and that the name of
 
9
 * Novell, Inc. not be used in advertising or publicity pertaining to
 
10
 * distribution of the software without specific, written prior permission.
 
11
 * Novell, Inc. makes no representations about the suitability of this
 
12
 * software for any purpose. It is provided "as is" without express or
 
13
 * implied warranty.
 
14
 *
 
15
 * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
16
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
 
17
 * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
18
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
 
19
 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 
20
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 
21
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
22
 *
 
23
 * Author: David Reveman <davidr@novell.com>
 
24
 */
 
25
 
 
26
#include "regexplugin.h"
 
27
#include <limits.h>
 
28
 
 
29
COMPIZ_PLUGIN_20081216 (regex, RegexPluginVTable);
 
30
 
 
31
class RegexExp : public CompMatch::Expression
 
32
{
 
33
    public:
 
34
        typedef enum {
 
35
            TypeTitle,
 
36
            TypeRole,
 
37
            TypeClass,
 
38
            TypeName,
 
39
        } Type;
 
40
 
 
41
        RegexExp (const CompString& str, int item);
 
42
        virtual ~RegexExp ();
 
43
 
 
44
        bool evaluate (CompWindow *w);
 
45
        static int matches (const CompString& str);
 
46
 
 
47
    private:
 
48
        typedef struct {
 
49
            const char   *name;
 
50
            size_t       length;
 
51
            Type         type;
 
52
            unsigned int flags;
 
53
        } Prefix;
 
54
        
 
55
        static const Prefix prefix[];
 
56
 
 
57
        Type    mType;
 
58
        regex_t *mRegex;
 
59
};
 
60
 
 
61
const RegexExp::Prefix RegexExp::prefix[] = {
 
62
    { "title=", 6, TypeTitle, 0 },
 
63
    { "role=",  5, TypeRole, 0  },
 
64
    { "class=", 6, TypeClass, 0 },
 
65
    { "name=",  5, TypeName, 0  },
 
66
    { "ititle=", 7, TypeTitle, REG_ICASE },
 
67
    { "irole=",  6, TypeRole, REG_ICASE  },
 
68
    { "iclass=", 7, TypeClass, REG_ICASE },
 
69
    { "iname=",  6, TypeName, REG_ICASE  }
 
70
};
 
71
 
 
72
RegexExp::RegexExp (const CompString& str, int item) :
 
73
    mRegex (NULL)
 
74
{
 
75
    if (item < sizeof (prefix) / sizeof (prefix[0]))
 
76
    {
 
77
        int        status;
 
78
        CompString value;
 
79
 
 
80
        value  = str.substr (prefix[item].length);
 
81
        mRegex = new regex_t;
 
82
        status = regcomp (mRegex, value.c_str (),
 
83
                          REG_NOSUB | prefix[item].flags);
 
84
 
 
85
        if (status)
 
86
        {
 
87
            char errMsg[1024];
 
88
 
 
89
            regerror (status, mRegex, errMsg, sizeof (errMsg));
 
90
 
 
91
            compLogMessage ("regex", CompLogLevelWarn,
 
92
                            "%s = %s", errMsg, value.c_str ());
 
93
 
 
94
            regfree (mRegex);
 
95
            delete mRegex;
 
96
            mRegex = NULL;
 
97
        }
 
98
 
 
99
        mType = prefix[item].type;
 
100
    }
 
101
}
 
102
 
 
103
RegexExp::~RegexExp ()
 
104
{
 
105
    if (mRegex)
 
106
    {
 
107
        regfree (mRegex);
 
108
        delete mRegex;
 
109
    }
 
110
}
 
111
 
 
112
bool
 
113
RegexExp::evaluate (CompWindow *w)
 
114
{
 
115
    CompString  *string = NULL;
 
116
    RegexWindow *rw = RegexWindow::get (w);
 
117
 
 
118
    switch (mType)
 
119
    {
 
120
        case TypeRole:
 
121
            string = &rw->role;
 
122
            break;
 
123
        case TypeTitle:
 
124
            string = &rw->title;
 
125
            break;
 
126
        case TypeClass:
 
127
            string = &rw->resClass;
 
128
            break;
 
129
        case TypeName:
 
130
            string = &rw->resName;
 
131
            break;
 
132
    }
 
133
 
 
134
    if (!mRegex || !string)
 
135
        return false;
 
136
 
 
137
    if (regexec (mRegex, string->c_str (), 0, NULL, 0))
 
138
        return false;
 
139
 
 
140
    return true;
 
141
}
 
142
 
 
143
int
 
144
RegexExp::matches (const CompString& str)
 
145
{
 
146
    int i;
 
147
 
 
148
    for (i = 0; i < sizeof (prefix) / sizeof (prefix[0]); i++)
 
149
        if (str.compare (0, prefix[i].length, prefix[i].name) == 0)
 
150
            return i;
 
151
 
 
152
    return -1;
 
153
}
 
154
 
 
155
CompMatch::Expression *
 
156
RegexScreen::matchInitExp (const CompString& str)
 
157
{
 
158
    int item = RegexExp::matches (str);
 
159
 
 
160
    if (item >= 0)
 
161
        return new RegexExp (str, item);
 
162
 
 
163
    return screen->matchInitExp (str);
 
164
}
 
165
 
 
166
bool
 
167
RegexWindow::getStringProperty (Atom        nameAtom,
 
168
                                Atom        typeAtom,
 
169
                                CompString& string)
 
170
{
 
171
    Atom          type;
 
172
    unsigned long nItems;
 
173
    unsigned long bytesAfter;
 
174
    unsigned char *str = NULL;
 
175
    int           format, result;
 
176
    char          *retval;
 
177
 
 
178
    result = XGetWindowProperty (screen->dpy (), window->id (), nameAtom, 0,
 
179
                                 LONG_MAX, FALSE, typeAtom, &type, &format,
 
180
                                 &nItems, &bytesAfter, (unsigned char **) &str);
 
181
 
 
182
    if (result != Success)
 
183
        return false;
 
184
 
 
185
    if (type != typeAtom)
 
186
    {
 
187
        XFree (str);
 
188
        return false;
 
189
    }
 
190
 
 
191
    string = (char *) str;
 
192
 
 
193
    XFree (str);
 
194
 
 
195
    return true;
 
196
}
 
197
 
 
198
void
 
199
RegexWindow::updateRole ()
 
200
{
 
201
    RegexScreen *rs = RegexScreen::get (screen);
 
202
 
 
203
    role = "";
 
204
    getStringProperty (rs->roleAtom, XA_STRING, role);
 
205
}
 
206
 
 
207
void
 
208
RegexWindow::updateTitle ()
 
209
{
 
210
    RegexScreen *rs = RegexScreen::get (screen);
 
211
 
 
212
    title = "";
 
213
 
 
214
    if (getStringProperty (rs->visibleNameAtom, Atoms::utf8String, title))
 
215
        return;
 
216
 
 
217
    if (getStringProperty (Atoms::wmName, Atoms::utf8String, title))
 
218
        return;
 
219
 
 
220
    getStringProperty (XA_WM_NAME, XA_STRING, title);
 
221
}
 
222
 
 
223
void RegexWindow::updateClass ()
 
224
{
 
225
    XClassHint classHint;
 
226
 
 
227
    resClass = "";
 
228
    resName  = "";
 
229
 
 
230
    if (!XGetClassHint (screen->dpy (), window->id (), &classHint) != Success)
 
231
        return;
 
232
 
 
233
    if (classHint.res_name)
 
234
    {
 
235
        resName = classHint.res_name;
 
236
        XFree (classHint.res_name);
 
237
    }
 
238
 
 
239
    if (classHint.res_class)
 
240
    {
 
241
        resClass = classHint.res_class;
 
242
        XFree (classHint.res_class);
 
243
    }
 
244
}
 
245
 
 
246
void
 
247
RegexScreen::handleEvent (XEvent *event)
 
248
{
 
249
    CompWindow *w;
 
250
 
 
251
    screen->handleEvent (event);
 
252
 
 
253
    if (event->type != PropertyNotify)
 
254
        return;
 
255
 
 
256
    w = screen->findWindow (event->xproperty.window);
 
257
    if (!w)
 
258
        return;
 
259
 
 
260
    if (event->xproperty.atom == XA_WM_NAME)
 
261
    {
 
262
        RegexWindow::get (w)->updateTitle ();
 
263
        screen->matchPropertyChanged (w);
 
264
    }
 
265
    else if (event->xproperty.atom == roleAtom)
 
266
    {
 
267
        RegexWindow::get (w)->updateRole ();
 
268
        screen->matchPropertyChanged (w);
 
269
    }
 
270
    else if (event->xproperty.atom == XA_WM_CLASS)
 
271
    {
 
272
        RegexWindow::get (w)->updateClass ();
 
273
        screen->matchPropertyChanged (w);
 
274
    }
 
275
}
 
276
 
 
277
RegexScreen::RegexScreen (CompScreen *s) :
 
278
    PrivateHandler<RegexScreen, CompScreen> (s)
 
279
{
 
280
    ScreenInterface::setHandler (s);
 
281
 
 
282
    roleAtom        = XInternAtom (s->dpy (), "WM_WINDOW_ROLE", 0);
 
283
    visibleNameAtom = XInternAtom (s->dpy (), "_NET_WM_VISIBLE_NAME", 0);
 
284
 
 
285
    s->matchExpHandlerChanged ();
 
286
}
 
287
 
 
288
RegexScreen::~RegexScreen ()
 
289
{
 
290
    screen->matchInitExpSetEnabled (this, false);
 
291
    screen->matchExpHandlerChanged ();
 
292
}
 
293
 
 
294
RegexWindow::RegexWindow (CompWindow *w) :
 
295
    PrivateHandler<RegexWindow, CompWindow> (w),
 
296
    window (w)
 
297
{
 
298
    updateRole ();
 
299
    updateTitle ();
 
300
    updateClass ();
 
301
}
 
302
 
 
303
bool
 
304
RegexPluginVTable::init ()
 
305
{
 
306
    if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
 
307
        return false;
 
308
 
 
309
    getMetadata ()->addFromFile (name ());
 
310
 
 
311
    return true;
 
312
}