1 /*
2 * Compiz configuration system library
3 *
4 * Copyright (C) 2007 Danny Baumann <maniac@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 /*
22 * Based on Compiz option.c
23 * Copyright © 2005 Novell, Inc.
24 * Author: David Reveman <davidr@novell.com>
25 */
26
27
28 #define _GNU_SOURCE
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <strings.h>
33 #include <stdio.h>
34 #include <ctype.h>
35 #include <math.h>
36
37 #include <X11/X.h>
38 #include <X11/Xlib.h>
39
40 #include <ccs.h>
41
42 #define CompAltMask (1 << 16)
43 #define CompMetaMask (1 << 17)
44 #define CompSuperMask (1 << 18)
45 #define CompHyperMask (1 << 19)
46 #define CompModeSwitchMask (1 << 20)
47 #define CompNumLockMask (1 << 21)
48 #define CompScrollLockMask (1 << 22)
49
50 #define SCREEN_EDGE_LEFT (1 << 0)
51 #define SCREEN_EDGE_RIGHT (1 << 1)
52 #define SCREEN_EDGE_TOP (1 << 2)
53 #define SCREEN_EDGE_BOTTOM (1 << 3)
54 #define SCREEN_EDGE_TOPLEFT (1 << 4)
55 #define SCREEN_EDGE_TOPRIGHT (1 << 5)
56 #define SCREEN_EDGE_BOTTOMLEFT (1 << 6)
57 #define SCREEN_EDGE_BOTTOMRIGHT (1 << 7)
58
59 struct _Modifier
60 {
61 char *name;
62 int modifier;
63 }
64
65 modifierList[] = {
66 { "<Shift>", ShiftMask },
67 { "<Control>", ControlMask },
68 { "<Mod1>", Mod1Mask },
69 { "<Mod2>", Mod2Mask },
70 { "<Mod3>", Mod3Mask },
71 { "<Mod4>", Mod4Mask },
72 { "<Mod5>", Mod5Mask },
73 { "<Alt>", CompAltMask },
74 { "<Meta>", CompMetaMask },
75 { "<Super>", CompSuperMask },
76 { "<Hyper>", CompHyperMask },
77 { "<ModeSwitch>", CompModeSwitchMask },
78 };
79
80 #define N_MODIFIERS (sizeof (modifierList) / sizeof (struct _Modifier))
81
82 struct _Edge {
83 char *name;
84 char *modName;
85 int modifier;
86 }
87
88 edgeList[] = {
89 { "Left", "<LeftEdge>", SCREEN_EDGE_LEFT },
90 { "Right", "<RightEdge>", SCREEN_EDGE_RIGHT },
91 { "Top", "<TopEdge>", SCREEN_EDGE_TOP },
92 { "Bottom", "<BottomEdge>", SCREEN_EDGE_BOTTOM },
93 { "TopLeft", "<TopLeftEdge>", SCREEN_EDGE_TOPLEFT },
94 { "TopRight", "<TopRightEdge>", SCREEN_EDGE_TOPRIGHT },
95 { "BottomLeft", "<BottomLeftEdge>", SCREEN_EDGE_BOTTOMLEFT },
96 { "BottomRight", "<BottomRightEdge>", SCREEN_EDGE_BOTTOMRIGHT }
97 };
98
99 #define N_EDGES (sizeof (edgeList) / sizeof (edgeList[0]))
100
101 static char *
stringAppend(char * s,char * a)102 stringAppend (char *s,
103 char *a)
104 {
105 char *r;
106 int len;
107
108 if (!a)
109 return s;
110
111 len = strlen (a);
112
113 if (s)
114 len += strlen (s);
115
116 r = malloc (len + 1);
117
118 if (r)
119 {
120 if (s)
121 {
122 sprintf (r, "%s%s", s, a);
123 free (s);
124 }
125 else
126 {
127 sprintf (r, "%s", a);
128 }
129
130 s = r;
131 }
132
133 return s;
134 }
135
136 char *
ccsModifiersToString(unsigned int modMask)137 ccsModifiersToString (unsigned int modMask)
138 {
139 char *binding = NULL;
140 int i;
141
142 for (i = 0; i < N_MODIFIERS; i++)
143 {
144 if (modMask & modifierList[i].modifier)
145 binding = stringAppend (binding, modifierList[i].name);
146 }
147
148 return binding;
149 }
150
151 char *
ccsEdgesToModString(unsigned int edgeMask)152 ccsEdgesToModString (unsigned int edgeMask)
153 {
154 char *binding = NULL;
155 int i;
156
157 for (i = 0; i < N_EDGES; i++)
158 {
159 if (edgeMask & edgeList[i].modifier)
160 binding = stringAppend (binding, edgeList[i].modName);
161 }
162
163 return binding;
164 }
165
166 char *
ccsEdgesToString(unsigned int edgeMask)167 ccsEdgesToString (unsigned int edgeMask)
168 {
169 char *binding = NULL;
170 int i;
171
172 for (i = 0; i < N_EDGES; i++)
173 {
174 if (edgeMask & edgeList[i].modifier)
175 {
176 if (binding)
177 binding = stringAppend (binding, "|");
178 binding = stringAppend (binding, edgeList[i].name);
179 }
180 }
181
182 if (!binding)
183 return strdup ("");
184
185 return binding;
186 }
187
188 char *
ccsKeyBindingToString(CCSSettingKeyValue * key)189 ccsKeyBindingToString (CCSSettingKeyValue *key)
190 {
191 char *binding;
192
193 binding = ccsModifiersToString (key->keyModMask);
194
195 if (key->keysym != NoSymbol)
196 {
197 char *keyname;
198
199 keyname = XKeysymToString (key->keysym);
200 if (keyname)
201 {
202 binding = stringAppend (binding, keyname);
203 }
204 }
205
206 if (!binding)
207 return strdup ("Disabled");
208 return binding;
209 }
210
211 char *
ccsButtonBindingToString(CCSSettingButtonValue * button)212 ccsButtonBindingToString (CCSSettingButtonValue *button)
213 {
214 char *binding;
215 char *edges;
216 char buttonStr[256];
217
218 edges = ccsEdgesToModString (button->edgeMask);
219 binding = stringAppend (edges, ccsModifiersToString (button->buttonModMask));
220
221 if (button->button)
222 {
223 snprintf (buttonStr, 256, "Button%d", button->button);
224 binding = stringAppend (binding, buttonStr);
225 }
226
227 if (!binding)
228 return strdup ("Disabled");
229 return binding;
230 }
231
232 unsigned int
ccsStringToModifiers(const char * binding)233 ccsStringToModifiers (const char *binding)
234 {
235 unsigned int mods = 0;
236 int i;
237
238 for (i = 0; i < N_MODIFIERS; i++)
239 {
240 if (strcasestr (binding, modifierList[i].name))
241 mods |= modifierList[i].modifier;
242 }
243
244 return mods;
245 }
246
247 unsigned int
ccsStringToEdges(const char * binding)248 ccsStringToEdges (const char *binding)
249 {
250 unsigned int edgeMask = 0;
251 const char *needle;
252 int i;
253
254 for (i = 0; i < N_EDGES; i++)
255 {
256 int edgeLen = strlen (edgeList[i].name);
257
258 /* Look for all occurrences of edgeList[i].name in binding */
259 needle = binding;
260 while ((needle = strstr (needle, edgeList[i].name)) != NULL)
261 {
262 if (needle != binding && isalnum (*(needle - 1)))
263 {
264 needle += edgeLen;
265 continue;
266 }
267
268 needle += edgeLen;
269
270 if (*needle && isalnum (*needle))
271 continue;
272
273 edgeMask |= 1 << i;
274 }
275 }
276
277 return edgeMask;
278
279 }
280
281 unsigned int
ccsModStringToEdges(const char * binding)282 ccsModStringToEdges (const char *binding)
283 {
284 unsigned int mods = 0;
285 int i;
286
287 for (i = 0; i < N_EDGES; i++)
288 {
289 if (strcasestr (binding, edgeList[i].modName))
290 mods |= edgeList[i].modifier;
291 }
292
293 return mods;
294 }
295
296 Bool
ccsStringToKeyBinding(const char * binding,CCSSettingKeyValue * value)297 ccsStringToKeyBinding (const char *binding,
298 CCSSettingKeyValue *value)
299 {
300 char *ptr;
301 unsigned int mods;
302 KeySym keysym;
303
304 if (!binding || !strlen(binding) ||
305 strncasecmp (binding, "Disabled", strlen ("Disabled")) == 0)
306 {
307 value->keysym = 0;
308 value->keyModMask = 0;
309 return TRUE;
310 }
311
312 mods = ccsStringToModifiers (binding);
313
314 ptr = strrchr (binding, '>');
315
316 if (ptr)
317 binding = ptr + 1;
318
319 while (*binding && !isalnum (*binding))
320 binding++;
321
322 if (!*binding)
323 {
324 if (mods)
325 {
326 value->keysym = 0;
327 value->keyModMask = mods;
328
329 return TRUE;
330 }
331
332 return FALSE;
333 }
334
335 keysym = XStringToKeysym (binding);
336
337 if (keysym != NoSymbol)
338 {
339 value->keysym = keysym;
340 value->keyModMask = mods;
341
342 return TRUE;
343 }
344
345 return FALSE;
346 }
347
348 Bool
ccsStringToButtonBinding(const char * binding,CCSSettingButtonValue * value)349 ccsStringToButtonBinding (const char *binding,
350 CCSSettingButtonValue *value)
351 {
352 char *ptr;
353 unsigned int mods;
354 unsigned int edges;
355
356 if (!binding || !strlen(binding) ||
357 strncmp (binding, "Disabled", strlen ("Disabled")) == 0)
358 {
359 value->button = 0;
360 value->buttonModMask = 0;
361 value->edgeMask = 0;
362 return TRUE;
363 }
364
365 mods = ccsStringToModifiers (binding);
366 edges = ccsModStringToEdges (binding);
367
368 ptr = strrchr (binding, '>');
369
370 if (ptr)
371 binding = ptr + 1;
372
373 while (*binding && !isalnum (*binding))
374 binding++;
375
376 if (strncmp (binding, "Button", strlen ("Button")) == 0)
377 {
378 int buttonNum;
379
380 if (sscanf (binding + strlen ("Button"), "%d", &buttonNum) == 1)
381 {
382 value->button = buttonNum;
383 value->buttonModMask = mods;
384 value->edgeMask = edges;
385
386 return TRUE;
387 }
388 }
389
390 return FALSE;
391 }
392
393 Bool
ccsStringToColor(const char * value,CCSSettingColorValue * color)394 ccsStringToColor (const char *value,
395 CCSSettingColorValue *color)
396 {
397 int c[4];
398
399 if (sscanf (value, "#%2x%2x%2x%2x", &c[0], &c[1], &c[2], &c[3]) == 4)
400 {
401 color->color.red = c[0] << 8 | c[0];
402 color->color.green = c[1] << 8 | c[1];
403 color->color.blue = c[2] << 8 | c[2];
404 color->color.alpha = c[3] << 8 | c[3];
405
406 return TRUE;
407 }
408
409 return FALSE;
410 }
411
412 char *
ccsColorToString(CCSSettingColorValue * color)413 ccsColorToString (CCSSettingColorValue *color)
414 {
415 char tmp[256];
416
417 snprintf (tmp, 256, "#%.2x%.2x%.2x%.2x",
418 color->color.red >> 8, color->color.green >> 8,
419 color->color.blue >> 8, color->color.alpha >> 8);
420
421 return strdup (tmp);
422 }
423
424