1 /*
2 * Compiz login/logout effect plugin
3 *
4 * loginout.c
5 *
6 * Copyright : (C) 2008 by Dennis Kasprzyk
7 * E-mail : onestone@opencompositing.org
8 *
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 */
21
22 #include <compiz-core.h>
23
24 #include "loginout_options.h"
25
26 static int displayPrivateIndex = 0;
27
28 typedef struct _LoginoutDisplay
29 {
30 MatchExpHandlerChangedProc matchExpHandlerChanged;
31 MatchPropertyChangedProc matchPropertyChanged;
32
33 int screenPrivateIndex;
34
35 Atom kdeLogoutInfoAtom;
36 }
37 LoginoutDisplay;
38
39 typedef struct _LoginoutScreen
40 {
41 int windowPrivateIndex;
42
43 PreparePaintScreenProc preparePaintScreen;
44 DonePaintScreenProc donePaintScreen;
45 PaintWindowProc paintWindow;
46 DrawWindowProc drawWindow;
47
48 int numLoginWin;
49 int numLogoutWin;
50
51 float brightness;
52 float saturation;
53 float opacity;
54
55 float in;
56 float out;
57 }
58 LoginoutScreen;
59
60 typedef struct _LoginoutWindow {
61 Bool login;
62 Bool logout;
63 } LoginoutWindow;
64
65 #define GET_LOGINOUT_DISPLAY(d) \
66 ((LoginoutDisplay *) (d)->base.privates[displayPrivateIndex].ptr)
67
68 #define LOGINOUT_DISPLAY(d) \
69 LoginoutDisplay *ld = GET_LOGINOUT_DISPLAY (d)
70
71 #define GET_LOGINOUT_SCREEN(s, ld) \
72 ((LoginoutScreen *) (s)->base.privates[(ld)->screenPrivateIndex].ptr)
73
74 #define LOGINOUT_SCREEN(s) \
75 LoginoutScreen *ls = GET_LOGINOUT_SCREEN (s, GET_LOGINOUT_DISPLAY (s->display))
76
77 #define GET_LOGINOUT_WINDOW(w, ls) \
78 ((LoginoutWindow *) (w)->base.privates[(ls)->windowPrivateIndex].ptr)
79
80 #define LOGINOUT_WINDOW(w) \
81 LoginoutWindow *lw = GET_LOGINOUT_WINDOW (w, \
82 GET_LOGINOUT_SCREEN (w->screen, \
83 GET_LOGINOUT_DISPLAY (w->screen->display)))
84
85 static void
loginoutUpdateWindowMatch(CompWindow * w)86 loginoutUpdateWindowMatch (CompWindow *w)
87 {
88 Bool curr;
89
90 LOGINOUT_WINDOW (w);
91 LOGINOUT_SCREEN (w->screen);
92
93 curr = matchEval (loginoutGetInMatch (w->screen), w);
94 if (curr != lw->login)
95 {
96 lw->login = curr;
97 if (curr)
98 ls->numLoginWin++;
99 else
100 ls->numLoginWin--;
101 damageScreen (w->screen);
102 }
103 curr = matchEval (loginoutGetOutMatch (w->screen), w);
104 if (curr != lw->logout)
105 {
106 lw->logout = curr;
107 if (curr)
108 ls->numLogoutWin++;
109 else
110 ls->numLogoutWin--;
111 damageScreen (w->screen);
112 }
113 }
114
115 static void
loginoutScreenOptionChanged(CompScreen * s,CompOption * opt,LoginoutScreenOptions num)116 loginoutScreenOptionChanged (CompScreen *s,
117 CompOption *opt,
118 LoginoutScreenOptions num)
119 {
120 CompWindow *w;
121
122 switch (num)
123 {
124 case LoginoutScreenOptionInMatch:
125 case LoginoutScreenOptionOutMatch:
126 for (w = s->windows; w; w = w->next)
127 loginoutUpdateWindowMatch (w);
128
129 damageScreen (s);
130 break;
131
132 default:
133 damageScreen (s);
134 break;
135 }
136 }
137
138 static void
loginoutMatchExpHandlerChanged(CompDisplay * d)139 loginoutMatchExpHandlerChanged (CompDisplay *d)
140 {
141 CompScreen *s;
142 CompWindow *w;
143
144 LOGINOUT_DISPLAY (d);
145
146 UNWRAP (ld, d, matchExpHandlerChanged);
147 (*d->matchExpHandlerChanged) (d);
148 WRAP (ld, d, matchExpHandlerChanged, loginoutMatchExpHandlerChanged);
149
150 /* match options are up to date after the call to matchExpHandlerChanged */
151 for (s = d->screens; s; s = s->next)
152 {
153 for (w = s->windows; w; w = w->next)
154 loginoutUpdateWindowMatch (w);
155 }
156 }
157
158 static void
loginoutMatchPropertyChanged(CompDisplay * d,CompWindow * w)159 loginoutMatchPropertyChanged (CompDisplay *d,
160 CompWindow *w)
161 {
162 LOGINOUT_DISPLAY (d);
163
164 loginoutUpdateWindowMatch (w);
165
166 UNWRAP (ld, d, matchPropertyChanged);
167 (*d->matchPropertyChanged) (d, w);
168 WRAP (ld, d, matchPropertyChanged, loginoutMatchPropertyChanged);
169 }
170
171 static Bool
loginoutPaintWindow(CompWindow * w,const WindowPaintAttrib * attrib,const CompTransform * transform,Region region,unsigned int mask)172 loginoutPaintWindow (CompWindow *w,
173 const WindowPaintAttrib *attrib,
174 const CompTransform *transform,
175 Region region,
176 unsigned int mask)
177 {
178 CompScreen *s = w->screen;
179 Bool status;
180
181 LOGINOUT_WINDOW (w);
182 LOGINOUT_SCREEN (s);
183
184 if ((ls->in > 0.0 || ls->out > 0.0) && !lw->login && !lw->logout &&
185 !(w->wmType & CompWindowTypeDesktopMask) && ls->opacity < 1.0)
186 mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
187
188 UNWRAP (ls, s, paintWindow);
189 status = (*s->paintWindow) (w, attrib, transform, region, mask);
190 WRAP (ls, s, paintWindow, loginoutPaintWindow);
191
192 return status;
193 }
194
195 static Bool
loginoutDrawWindow(CompWindow * w,const CompTransform * transform,const FragmentAttrib * fragment,Region region,unsigned int mask)196 loginoutDrawWindow (CompWindow *w,
197 const CompTransform *transform,
198 const FragmentAttrib *fragment,
199 Region region,
200 unsigned int mask)
201 {
202 Bool status;
203 CompScreen *s = w->screen;
204
205 LOGINOUT_WINDOW (w);
206 LOGINOUT_SCREEN (s);
207
208 if ((ls->in > 0.0 || ls->out > 0.0) && !lw->login && !lw->logout)
209 {
210 FragmentAttrib fA = *fragment;
211
212 if (!(w->wmType & CompWindowTypeDesktopMask))
213 fA.opacity = fragment->opacity * ls->opacity;
214
215 fA.brightness = fragment->brightness * ls->brightness;
216 fA.saturation = fragment->saturation * ls->saturation;
217
218 UNWRAP (ls, s, drawWindow);
219 status = (*s->drawWindow) (w, transform, &fA, region, mask);
220 WRAP (ls, s, drawWindow, loginoutDrawWindow);
221 }
222 else
223 {
224 UNWRAP (ls, s, drawWindow);
225 status = (*s->drawWindow) (w, transform, fragment, region, mask);
226 WRAP (ls, s, drawWindow, loginoutDrawWindow);
227 }
228 return status;
229 }
230
231 static void
loginoutPreparePaintScreen(CompScreen * s,int ms)232 loginoutPreparePaintScreen (CompScreen *s,
233 int ms)
234 {
235 LOGINOUT_SCREEN (s);
236
237 float val, val2;
238
239 val = ((float)ms / 1000.0) / loginoutGetInTime (s);
240
241 if (ls->numLoginWin)
242 ls->in = MIN (1.0, ls->in + val);
243 else
244 ls->in = MAX (0.0, ls->in - val);
245
246 val = ((float)ms / 1000.0) / loginoutGetOutTime (s);
247
248 if (ls->numLogoutWin)
249 ls->out = MIN (1.0, ls->out + val);
250 else
251 ls->out = MAX (0.0, ls->out - val);
252
253 if (ls->in > 0.0 || ls->out > 0.0)
254 {
255 val = (ls->in * loginoutGetInOpacity (s) / 100.0) + (1.0 - ls->in);
256 val2 = (ls->out * loginoutGetOutOpacity (s) / 100.0) + (1.0 - ls->out);
257 ls->opacity = MIN (val, val2);
258
259 val = (ls->in * loginoutGetInSaturation (s) / 100.0) + (1.0 - ls->in);
260 val2 = (ls->out * loginoutGetOutSaturation (s) / 100.0) +
261 (1.0 - ls->out);
262 ls->saturation = MIN (val, val2);
263
264 val = (ls->in * loginoutGetInBrightness (s) / 100.0) +
265 (1.0 - ls->in);
266 val2 = (ls->out * loginoutGetOutBrightness (s) / 100.0) +
267 (1.0 - ls->out);
268 ls->brightness = MIN (val, val2);
269 }
270
271 UNWRAP (ls, s, preparePaintScreen);
272 (*s->preparePaintScreen) (s, ms);
273 WRAP (ls, s, preparePaintScreen, loginoutPreparePaintScreen);
274 }
275
276 static void
loginoutDonePaintScreen(CompScreen * s)277 loginoutDonePaintScreen (CompScreen * s)
278 {
279 LOGINOUT_SCREEN (s);
280
281 if ((ls->in > 0.0 && ls->in < 1.0) || (ls->out > 0.0 && ls->out < 1.0))
282 damageScreen (s);
283
284 UNWRAP (ls, s, donePaintScreen);
285 (*s->donePaintScreen) (s);
286 WRAP (ls, s, donePaintScreen, loginoutDonePaintScreen);
287 }
288
289 static Bool
loginoutInitDisplay(CompPlugin * p,CompDisplay * d)290 loginoutInitDisplay (CompPlugin *p,
291 CompDisplay *d)
292 {
293 LoginoutDisplay *ld;
294
295 if (!checkPluginABI ("core", CORE_ABIVERSION))
296 return FALSE;
297
298 ld = malloc (sizeof (LoginoutDisplay) );
299
300 if (!ld)
301 return FALSE;
302
303 ld->screenPrivateIndex = allocateScreenPrivateIndex (d);
304
305 if (ld->screenPrivateIndex < 0)
306 {
307 free (ld);
308 return FALSE;
309 }
310
311 d->base.privates[displayPrivateIndex].ptr = ld;
312
313 ld->kdeLogoutInfoAtom = XInternAtom (d->display,
314 "_KWIN_LOGOUT_EFFECT", 0);
315
316 WRAP (ld, d, matchExpHandlerChanged, loginoutMatchExpHandlerChanged);
317 WRAP (ld, d, matchPropertyChanged, loginoutMatchPropertyChanged);
318
319 return TRUE;
320 }
321
322 static void
loginoutFiniDisplay(CompPlugin * p,CompDisplay * d)323 loginoutFiniDisplay (CompPlugin *p,
324 CompDisplay *d)
325 {
326 LOGINOUT_DISPLAY (d);
327 freeScreenPrivateIndex (d, ld->screenPrivateIndex);
328
329 UNWRAP (ld, d, matchExpHandlerChanged);
330 UNWRAP (ld, d, matchPropertyChanged);
331
332 free (ld);
333 }
334
335
336 static Bool
loginoutInitScreen(CompPlugin * p,CompScreen * s)337 loginoutInitScreen (CompPlugin *p,
338 CompScreen *s)
339 {
340 LoginoutScreen *ls;
341
342 LOGINOUT_DISPLAY (s->display);
343
344 ls = malloc (sizeof (LoginoutScreen) );
345
346 if (!ls)
347 return FALSE;
348
349 ls->windowPrivateIndex = allocateWindowPrivateIndex (s);
350
351 if (ls->windowPrivateIndex < 0)
352 {
353 free (ls);
354 return FALSE;
355 }
356
357 loginoutSetInMatchNotify (s, loginoutScreenOptionChanged);
358 loginoutSetOutMatchNotify (s, loginoutScreenOptionChanged);
359
360 s->base.privates[ld->screenPrivateIndex].ptr = ls;
361
362 ls->numLoginWin = 0;
363 ls->numLogoutWin = 0;
364
365 ls->saturation = 1.0;
366 ls->brightness = 1.0;
367 ls->opacity = 1.0;
368
369 ls->in = 0.0;
370 ls->out = 0.0;
371
372 WRAP (ls, s, preparePaintScreen, loginoutPreparePaintScreen);
373 WRAP (ls, s, donePaintScreen, loginoutDonePaintScreen);
374 WRAP (ls, s, paintWindow, loginoutPaintWindow);
375 WRAP (ls, s, drawWindow, loginoutDrawWindow);
376
377 /* This is a temporary solution until an official spec will be released */
378 XChangeProperty (s->display->display, s->wmSnSelectionWindow,
379 ld->kdeLogoutInfoAtom, ld->kdeLogoutInfoAtom, 8,
380 PropModeReplace,
381 (unsigned char*)&ld->kdeLogoutInfoAtom, 1);
382
383
384 return TRUE;
385 }
386
387
388 static void
loginoutFiniScreen(CompPlugin * p,CompScreen * s)389 loginoutFiniScreen (CompPlugin *p,
390 CompScreen *s)
391 {
392 LOGINOUT_SCREEN (s);
393 LOGINOUT_DISPLAY (s->display);
394
395 freeWindowPrivateIndex (s, ls->windowPrivateIndex);
396
397 UNWRAP (ls, s, preparePaintScreen);
398 UNWRAP (ls, s, donePaintScreen);
399 UNWRAP (ls, s, paintWindow);
400 UNWRAP (ls, s, drawWindow);
401
402 XDeleteProperty (s->display->display, s->wmSnSelectionWindow,
403 ld->kdeLogoutInfoAtom);
404
405 free (ls);
406 }
407
408 static Bool
loginoutInitWindow(CompPlugin * p,CompWindow * w)409 loginoutInitWindow (CompPlugin *p,
410 CompWindow *w)
411 {
412 LoginoutWindow *lw;
413
414 LOGINOUT_SCREEN (w->screen);
415
416 lw = malloc (sizeof (LoginoutWindow));
417 if (!lw)
418 return FALSE;
419
420 lw->login = FALSE;
421 lw->logout = FALSE;
422
423 w->base.privates[ls->windowPrivateIndex].ptr = lw;
424
425 loginoutUpdateWindowMatch (w);
426
427 return TRUE;
428 }
429
430 static void
loginoutFiniWindow(CompPlugin * p,CompWindow * w)431 loginoutFiniWindow (CompPlugin *p,
432 CompWindow *w)
433 {
434 LOGINOUT_WINDOW (w);
435 LOGINOUT_SCREEN (w->screen);
436
437 if (lw->login)
438 {
439 ls->numLoginWin--;
440 damageScreen (w->screen);
441 }
442 if (lw->logout)
443 {
444 ls->numLogoutWin--;
445 damageScreen (w->screen);
446 }
447
448 free (lw);
449 }
450
451 static Bool
loginoutInit(CompPlugin * p)452 loginoutInit (CompPlugin *p)
453 {
454 displayPrivateIndex = allocateDisplayPrivateIndex ();
455
456 if (displayPrivateIndex < 0)
457 return FALSE;
458
459 return TRUE;
460 }
461
462 static void
loginoutFini(CompPlugin * p)463 loginoutFini (CompPlugin *p)
464 {
465 if (displayPrivateIndex >= 0)
466 freeDisplayPrivateIndex (displayPrivateIndex);
467 }
468
469 static CompBool
loginoutInitObject(CompPlugin * p,CompObject * o)470 loginoutInitObject (CompPlugin *p,
471 CompObject *o)
472 {
473 static InitPluginObjectProc dispTab[] = {
474 (InitPluginObjectProc) 0, /* InitCore */
475 (InitPluginObjectProc) loginoutInitDisplay,
476 (InitPluginObjectProc) loginoutInitScreen,
477 (InitPluginObjectProc) loginoutInitWindow
478 };
479
480 RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o));
481 }
482
483 static void
loginoutFiniObject(CompPlugin * p,CompObject * o)484 loginoutFiniObject (CompPlugin *p,
485 CompObject *o)
486 {
487 static FiniPluginObjectProc dispTab[] = {
488 (FiniPluginObjectProc) 0, /* FiniCore */
489 (FiniPluginObjectProc) loginoutFiniDisplay,
490 (FiniPluginObjectProc) loginoutFiniScreen,
491 (FiniPluginObjectProc) loginoutFiniWindow
492 };
493
494 DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), (p, o));
495 }
496
497 CompPluginVTable loginoutVTable = {
498 "loginout",
499 0,
500 loginoutInit,
501 loginoutFini,
502 loginoutInitObject,
503 loginoutFiniObject,
504 0,
505 0
506 };
507
508 CompPluginVTable *
getCompPluginInfo(void)509 getCompPluginInfo (void)
510 {
511 return &loginoutVTable;
512 }
513