~compiz-team/compiz-libcompizconfig/0.9.5

« back to all changes in this revision

Viewing changes to plugin/ccp/src/ccp.cpp~

  • Committer: Sam Spilsbury
  • Date: 2011-07-29 15:10:33 UTC
  • mfrom: (412.1.3)
  • Revision ID: git-v1:21d23fe4074b65ff356bf24c51925ab48a70535c
Merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Compiz configuration system library plugin
3
 
 *
4
 
 * Copyright (C) 2007  Dennis Kasprzyk <onestone@opencompositing.org>
5
 
 *
6
 
 * This library is free software; you can redistribute it and/or
7
 
 * modify it under the terms of the GNU Lesser General Public
8
 
 * License as published by the Free Software Foundation; either
9
 
 * version 2.1 of the License, or (at your option) any later version.
10
 
 
11
 
 * This library is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 
 * Lesser General Public License for more details.
15
 
 
16
 
 * You should have received a copy of the GNU Lesser General Public
17
 
 * License along with this library; if not, write to the Free Software
18
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
 
 */
20
 
 
21
 
#include "ccp.h"
22
 
 
23
 
COMPIZ_PLUGIN_20090315 (ccp, CcpPluginVTable)
24
 
 
25
 
#define CCP_UPDATE_MIN_TIMEOUT 250
26
 
#define CCP_UPDATE_MAX_TIMEOUT 4000
27
 
#define CORE_VTABLE_NAME  "core"
28
 
 
29
 
 
30
 
        
31
 
static void
32
 
ccpSetValueToValue (CCSSettingValue *sv,
33
 
                    CompOption::Value *v,
34
 
                    CCSSettingType  type)
35
 
{
36
 
    switch (type)
37
 
    {
38
 
        case TypeInt:
39
 
            v->set ((int) sv->value.asInt);
40
 
            break;
41
 
        case TypeFloat:
42
 
            v->set ((float) sv->value.asFloat);
43
 
            break;
44
 
        case TypeBool:
45
 
            v->set ((bool) sv->value.asBool);
46
 
            break;
47
 
        case TypeColor:
48
 
            v->set ((unsigned short *) sv->value.asColor.array.array);
49
 
            break;
50
 
        case TypeString:
51
 
            v->set (CompString (sv->value.asString));
52
 
            break;
53
 
        case TypeMatch:
54
 
            v->set (CompMatch (sv->value.asMatch));
55
 
            break;
56
 
        case TypeKey:
57
 
            {
58
 
                CompAction action;
59
 
 
60
 
                int keycode =
61
 
                    (sv->value.asKey.keysym == NoSymbol) ? 0 :
62
 
                    XKeysymToKeycode (screen->dpy (), sv->value.asKey.keysym);
63
 
                
64
 
                action.setKey (CompAction::KeyBinding (keycode,
65
 
                               sv->value.asKey.keyModMask));
66
 
                v->set (action);
67
 
            }
68
 
            break;
69
 
        case TypeButton:
70
 
            {
71
 
                CompAction action;
72
 
 
73
 
                action.setEdgeMask (sv->value.asButton.edgeMask);
74
 
 
75
 
                action.setButton (CompAction::ButtonBinding (
76
 
                                  sv->value.asButton.button,
77
 
                                  sv->value.asButton.buttonModMask));
78
 
                v->set (action);
79
 
            }
80
 
            break;
81
 
        case TypeEdge:
82
 
            {
83
 
                CompAction action;
84
 
                
85
 
                action.setEdgeMask (sv->value.asEdge);
86
 
                v->set (action);
87
 
            }
88
 
            break;
89
 
        case TypeBell:
90
 
            {
91
 
                CompAction action;
92
 
                
93
 
                action.setBell (sv->value.asBell);
94
 
 
95
 
                v->set (action);
96
 
            }
97
 
            break;
98
 
        default:
99
 
            break;
100
 
    }
101
 
}
102
 
 
103
 
static bool
104
 
ccpCCSTypeToCompizType (CCSSettingType st, CompOption::Type *ct)
105
 
{
106
 
    switch (st) {
107
 
        case TypeBool:
108
 
            *ct = CompOption::TypeBool;
109
 
            break;
110
 
        case TypeInt:
111
 
            *ct = CompOption::TypeInt;
112
 
            break;
113
 
        case TypeFloat:
114
 
            *ct = CompOption::TypeFloat;
115
 
            break;
116
 
        case TypeColor:
117
 
            *ct = CompOption::TypeColor;
118
 
            break;
119
 
        case TypeString:
120
 
            *ct = CompOption::TypeString;
121
 
            break;
122
 
        case TypeMatch:
123
 
            *ct = CompOption::TypeMatch;
124
 
            break;
125
 
        case TypeKey:
126
 
            *ct = CompOption::TypeKey;
127
 
            break;
128
 
        case TypeButton:
129
 
            *ct = CompOption::TypeButton;
130
 
            break;
131
 
        case TypeEdge:
132
 
            *ct = CompOption::TypeEdge;
133
 
            break;
134
 
        case TypeBell:
135
 
            *ct = CompOption::TypeBell;
136
 
            break;
137
 
        case TypeList:
138
 
            *ct = CompOption::TypeList;
139
 
            break;
140
 
        default:
141
 
            return false;
142
 
    }
143
 
 
144
 
    return true;
145
 
}
146
 
 
147
 
static void
148
 
ccpConvertPluginList (CCSSetting          *s,
149
 
                      CCSSettingValueList list,
150
 
                      CompOption::Value   *v)
151
 
{
152
 
    CCSStringList       sl, l;
153
 
    int                 i;
154
 
 
155
 
    sl = ccsGetStringListFromValueList (list);
156
 
 
157
 
    while (ccsStringListFind(sl, (char *) "ccp"))
158
 
        sl = ccsStringListRemove (sl, (char *) "ccp", TRUE);
159
 
 
160
 
    while (ccsStringListFind(sl, (char *)"core"))
161
 
        sl = ccsStringListRemove (sl, (char *) "core", TRUE);
162
 
 
163
 
    sl = ccsStringListPrepend (sl, strdup ("ccp"));
164
 
    sl = ccsStringListPrepend (sl, strdup ("core"));
165
 
 
166
 
    CompOption::Value::Vector val (ccsStringListLength (sl));
167
 
 
168
 
    for (l = sl, i = 0; l; l = l->next)
169
 
    {
170
 
        if (l->data)
171
 
            val[i].set (CompString (l->data));
172
 
        i++;
173
 
    }
174
 
 
175
 
    v->set (CompOption::TypeString, val);
176
 
 
177
 
    ccsStringListFree (sl, TRUE);
178
 
}
179
 
 
180
 
static void
181
 
ccpSettingToValue (CCSSetting        *s,
182
 
                   CompOption::Value *v)
183
 
{
184
 
    if (s->type != TypeList)
185
 
        ccpSetValueToValue (s->value, v, s->type);
186
 
    else
187
 
    {
188
 
        CCSSettingValueList list;
189
 
        int                 i = 0;
190
 
        CompOption::Type    type;
191
 
 
192
 
        ccsGetList (s, &list);
193
 
 
194
 
        if (!ccpCCSTypeToCompizType (s->info.forList.listType, &type))
195
 
            type = CompOption::TypeBool;
196
 
 
197
 
        if ((strcmp (s->name, "active_plugins") == 0) &&
198
 
            (strcmp (s->parent->name, CORE_VTABLE_NAME) == 0))
199
 
        {
200
 
            ccpConvertPluginList (s, list, v);
201
 
        }
202
 
        else
203
 
        {
204
 
            CompOption::Value::Vector val (ccsSettingValueListLength (list));
205
 
 
206
 
            while (list)
207
 
            {
208
 
                ccpSetValueToValue (list->data,
209
 
                                    &val[i],
210
 
                                    s->info.forList.listType);
211
 
                list = list->next;
212
 
                i++;
213
 
            }
214
 
 
215
 
            v->set (type, val);
216
 
        }
217
 
    }
218
 
}
219
 
 
220
 
static void
221
 
ccpInitValue (CCSSettingValue   *value,
222
 
              CompOption::Value *from,
223
 
              CCSSettingType    type)
224
 
{
225
 
    switch (type)
226
 
    {
227
 
        case TypeInt:
228
 
            value->value.asInt = from->i ();
229
 
            break;
230
 
        case TypeFloat:
231
 
            value->value.asFloat = from->f ();
232
 
            break;
233
 
        case TypeBool:
234
 
            value->value.asBool = from->b ();
235
 
            break;
236
 
        case TypeColor:
237
 
            {
238
 
                for (unsigned int i = 0; i < 4; i++)
239
 
                    value->value.asColor.array.array[i] = from->c ()[i];
240
 
            }
241
 
            break;
242
 
        case TypeString:
243
 
            value->value.asString = strdup (from->s ().c_str ());
244
 
            break;
245
 
        case TypeMatch:
246
 
            value->value.asMatch = strdup (from->match ().toString ().c_str ());
247
 
            break;
248
 
        case TypeKey:
249
 
            if (from->action ().type () & CompAction::BindingTypeKey)
250
 
            {
251
 
                value->value.asKey.keysym =
252
 
                    XKeycodeToKeysym (screen->dpy (),
253
 
                                      from->action ().key ().keycode (), 0);
254
 
                value->value.asKey.keyModMask =
255
 
                    from->action ().key ().modifiers ();
256
 
            }
257
 
            else
258
 
            {
259
 
                value->value.asKey.keysym = 0;
260
 
                value->value.asKey.keyModMask = 0;
261
 
            }
262
 
        case TypeButton:
263
 
            if (from->action ().type () & CompAction::BindingTypeButton)
264
 
            {
265
 
                value->value.asButton.button =
266
 
                    from->action ().button ().button ();
267
 
                value->value.asButton.buttonModMask =
268
 
                    from->action ().button ().modifiers ();
269
 
                value->value.asButton.edgeMask = 0;
270
 
            }
271
 
            else if (from->action ().type () & CompAction::BindingTypeEdgeButton)
272
 
            {
273
 
                value->value.asButton.button =
274
 
                    from->action ().button ().button ();
275
 
                value->value.asButton.buttonModMask =
276
 
                    from->action ().button ().modifiers ();
277
 
                value->value.asButton.edgeMask = from->action ().edgeMask ();
278
 
            }
279
 
            else
280
 
            {
281
 
                value->value.asButton.button = 0;
282
 
                value->value.asButton.buttonModMask = 0;
283
 
                value->value.asButton.edgeMask = 0;
284
 
            }
285
 
            break;
286
 
        case TypeEdge:
287
 
            value->value.asEdge = from->action ().edgeMask ();
288
 
            break;
289
 
        case TypeBell:
290
 
            value->value.asBell = from->action ().bell ();
291
 
            break;
292
 
        default:
293
 
            break;
294
 
    }
295
 
}
296
 
 
297
 
static void
298
 
ccpValueToSetting (CCSSetting        *s,
299
 
                   CompOption::Value *v)
300
 
{
301
 
    CCSSettingValue *value;
302
 
 
303
 
    value = (CCSSettingValue *) calloc (1, sizeof (CCSSettingValue));
304
 
    if (!value)
305
 
        return;
306
 
 
307
 
    value->parent = s;
308
 
 
309
 
    if (s->type == TypeList)
310
 
    {
311
 
        foreach (CompOption::Value &lv, v->list ())
312
 
        {
313
 
            CCSSettingValue *val;
314
 
 
315
 
            val = (CCSSettingValue *) calloc (1, sizeof (CCSSettingValue));
316
 
            if (val)
317
 
            {
318
 
                val->parent = s;
319
 
                val->isListChild = TRUE;
320
 
                ccpInitValue (val, &lv,
321
 
                              s->info.forList.listType);
322
 
                value->value.asList =
323
 
                    ccsSettingValueListAppend (value->value.asList, val);
324
 
            }
325
 
        }
326
 
    }
327
 
    else
328
 
        ccpInitValue (value, v, s->type);
329
 
 
330
 
    ccsSetValue (s, value);
331
 
    ccsFreeSettingValue (value);
332
 
}
333
 
 
334
 
static bool
335
 
ccpTypeCheck (CCSSetting *s, CompOption *o)
336
 
{
337
 
    CompOption::Type ot;
338
 
 
339
 
    switch (s->type)
340
 
    {
341
 
        case TypeList:
342
 
            return ccpCCSTypeToCompizType (s->type, &ot) && (ot == o->type ()) &&
343
 
                   ccpCCSTypeToCompizType (s->info.forList.listType, &ot) &&
344
 
                   (ot == o->value ().listType ());
345
 
            break;
346
 
        default:
347
 
            return ccpCCSTypeToCompizType (s->type, &ot) && (ot == o->type ());
348
 
            break;
349
 
    }
350
 
 
351
 
    return false;
352
 
}
353
 
 
354
 
void
355
 
CcpScreen::setOptionFromContext (CompOption *o,
356
 
                                 const char *plugin)
357
 
{
358
 
    CCSPlugin         *bsp;
359
 
    CCSSetting        *setting;
360
 
    CompOption::Value value;
361
 
 
362
 
    bsp = ccsFindPlugin (mContext, (plugin) ? plugin : CORE_VTABLE_NAME);
363
 
    if (!bsp)
364
 
        return;
365
 
 
366
 
    setting = ccsFindSetting (bsp, o->name ().c_str ());
367
 
    if (!setting)
368
 
        return;
369
 
 
370
 
    if (!ccpTypeCheck (setting, o))
371
 
        return;
372
 
 
373
 
    ccpSettingToValue (setting, &value);
374
 
 
375
 
    mApplyingSettings = true;
376
 
    screen->setOptionForPlugin (plugin, o->name ().c_str (), value);
377
 
    mApplyingSettings = false;
378
 
}
379
 
 
380
 
void
381
 
CcpScreen::setContextFromOption (CompOption *o, const char *plugin)
382
 
{
383
 
    CCSPlugin       *bsp;
384
 
    CCSSetting      *setting;
385
 
 
386
 
    bsp = ccsFindPlugin (mContext, (plugin) ? plugin : CORE_VTABLE_NAME);
387
 
    if (!bsp)
388
 
        return;
389
 
 
390
 
    setting = ccsFindSetting (bsp, o->name ().c_str ());
391
 
    if (!setting)
392
 
        return;
393
 
 
394
 
    if (!ccpTypeCheck (setting, o))
395
 
        return;
396
 
 
397
 
    ccpValueToSetting (setting, &o->value ());
398
 
    ccsWriteChangedSettings (mContext);
399
 
}
400
 
 
401
 
bool
402
 
CcpScreen::reload ()
403
 
{
404
 
    foreach (CompPlugin *p, CompPlugin::getPlugins ())
405
 
    {
406
 
        foreach (CompOption &o, p->vTable->getOptions ())
407
 
            setOptionFromContext (&o, p->vTable->name ().c_str ());
408
 
    }
409
 
 
410
 
    return false;
411
 
}
412
 
 
413
 
bool
414
 
CcpScreen::timeout ()
415
 
{
416
 
    unsigned int flags = 0;
417
 
 
418
 
    if (CompPlugin::find ("glib"))
419
 
        flags |= ProcessEventsNoGlibMainLoopMask;
420
 
 
421
 
    ccsProcessEvents (mContext, flags);
422
 
 
423
 
    if (ccsSettingListLength (mContext->changedSettings))
424
 
    {
425
 
        CCSSettingList list = mContext->changedSettings;
426
 
        CCSSettingList l = list;        
427
 
        CCSSetting     *s;
428
 
        CompPlugin     *p;
429
 
        CompOption     *o;
430
 
 
431
 
        mContext->changedSettings = NULL;
432
 
 
433
 
        fprintf (stderr, "looping list\n");
434
 
        
435
 
        while (l)
436
 
        {
437
 
            s = l->data;
438
 
            l = l->next;
439
 
 
440
 
            p = CompPlugin::find (s->parent->name);
441
 
 
442
 
            if (!p)
443
 
                continue;
444
 
 
445
 
            o = CompOption::findOption (p->vTable->getOptions (), s->name);
446
 
            if (o)
447
 
                setOptionFromContext (o, s->parent->name);
448
 
            D (D_FULL, "Setting Update \"%s\"\n", s->name);
449
 
        }
450
 
 
451
 
        ccsSettingListFree (list, FALSE);
452
 
        mContext->changedSettings =
453
 
            ccsSettingListFree (mContext->changedSettings, FALSE);
454
 
    }
455
 
 
456
 
    return true;
457
 
}
458
 
 
459
 
bool
460
 
CcpScreen::setOptionForPlugin (const char *plugin,
461
 
                               const char *name,
462
 
                               CompOption::Value &v)
463
 
{
464
 
    bool status;
465
 
 
466
 
    status = screen->setOptionForPlugin (plugin, name, v);
467
 
 
468
 
    if (status && !mApplyingSettings && !mReloadTimer.active ())
469
 
    {
470
 
        CompPlugin *p;
471
 
 
472
 
        p = CompPlugin::find (plugin);
473
 
        if (p)
474
 
        {
475
 
            CompOption *o;
476
 
 
477
 
            o = CompOption::findOption (p->vTable->getOptions (), name);
478
 
            if (o && (o->value () != v))
479
 
                setContextFromOption (o, p->vTable->name ().c_str ());
480
 
        }
481
 
    }
482
 
 
483
 
    return status;
484
 
}
485
 
 
486
 
bool
487
 
CcpScreen::initPluginForScreen (CompPlugin *p)
488
 
{
489
 
    bool status;
490
 
 
491
 
    status = screen->initPluginForScreen (p);
492
 
 
493
 
    if (status)
494
 
    {
495
 
        foreach (CompOption &opt, p->vTable->getOptions ())
496
 
            setOptionFromContext (&opt, p->vTable->name ().c_str ());
497
 
    }
498
 
 
499
 
    return status;
500
 
}
501
 
 
502
 
 
503
 
CcpScreen::CcpScreen (CompScreen *screen) :
504
 
    PluginClassHandler<CcpScreen,CompScreen> (screen),
505
 
    mApplyingSettings (false)
506
 
{
507
 
    ccsSetBasicMetadata (TRUE);
508
 
 
509
 
    mContext = ccsContextNew (screen->screenNum ());
510
 
    ccsReadSettings (mContext);
511
 
 
512
 
    mContext->changedSettings =
513
 
        ccsSettingListFree (mContext->changedSettings, FALSE);
514
 
 
515
 
    mReloadTimer.start (boost::bind (&CcpScreen::reload, this), 0);
516
 
    mTimeoutTimer.start (boost::bind (&CcpScreen::timeout, this),
517
 
                         CCP_UPDATE_MIN_TIMEOUT, CCP_UPDATE_MAX_TIMEOUT);
518
 
 
519
 
    ScreenInterface::setHandler (screen);
520
 
}
521
 
 
522
 
CcpScreen::~CcpScreen ()
523
 
{
524
 
    ccsContextDestroy (mContext);
525
 
}
526
 
 
527
 
bool
528
 
CcpPluginVTable::init ()
529
 
{
530
 
    fprintf (stderr, "plugin init\n");
531
 
 
532
 
    if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
533
 
         return false;
534
 
 
535
 
    return true;
536
 
}