summaryrefslogtreecommitdiff
path: root/beryl-plugins/src/trailfocus2.c
diff options
context:
space:
mode:
authorkristian <kristian@d7aaf104-2d23-0410-ae22-9d23157bf5a3>2007-01-16 23:20:41 +0000
committerkristian <kristian@d7aaf104-2d23-0410-ae22-9d23157bf5a3>2007-01-16 23:20:41 +0000
commit7bab4104823f35f1c5176bcc2db879c0eb023cf6 (patch)
tree6cd9268fa12601200517a373a3e544156aad6134 /beryl-plugins/src/trailfocus2.c
parenta8760d3ebd9676d69b40072451d3c83db4edcec1 (diff)
downloadmarex-dev-7bab4104823f35f1c5176bcc2db879c0eb023cf6.tar.gz
marex-dev-7bab4104823f35f1c5176bcc2db879c0eb023cf6.tar.bz2
Merge trailfocus2 to trunk. Adjust BSM icon-name. Remove old trailfocus.
git-svn-id: file:///beryl/trunk@2739 d7aaf104-2d23-0410-ae22-9d23157bf5a3
Diffstat (limited to 'beryl-plugins/src/trailfocus2.c')
-rw-r--r--beryl-plugins/src/trailfocus2.c716
1 files changed, 716 insertions, 0 deletions
diff --git a/beryl-plugins/src/trailfocus2.c b/beryl-plugins/src/trailfocus2.c
new file mode 100644
index 0000000..14ec593
--- /dev/null
+++ b/beryl-plugins/src/trailfocus2.c
@@ -0,0 +1,716 @@
+/**
+ * Beryl Trailfocus - take three
+ *
+ * Copyright (c) 2006 Kristian Lyngstøl <kristian@beryl-project.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This version is completly rewritten from scratch with opacify as a
+ * basic template. The original trailfocus was written by:
+ * François Ingelrest <Athropos@gmail.com> and rewritten by:
+ * Dennis Kasprzyk <onestone@beryl-project.org>
+ *
+ *
+ * Trailfocus modifies the opacity, brightness and saturation on a window
+ * based on when it last had focus.
+ *
+ * TODO:
+ * - Binding for ignore-toggeling? This should not be necesarry with
+ * the new paint-attrib system (hopefully).
+ * - Compare behavior with the old trailfocus.
+ * - Use the new paint-attrib-changing method when it is defined.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/Xrender.h>
+#include <beryl.h>
+
+#define GET_TRAILFOCUS_DISPLAY(d) \
+ ((TrailfocusDisplay *) (d)->privates[displayPrivateIndex].ptr)
+#define TRAILFOCUS_DISPLAY(d) \
+ TrailfocusDisplay *td = GET_TRAILFOCUS_DISPLAY (d)
+#define GET_TRAILFOCUS_SCREEN(s, td) \
+ ((TrailfocusScreen *) (s)->privates[(td)->screenPrivateIndex].ptr)
+#define TRAILFOCUS_SCREEN(s) \
+ TrailfocusScreen *ts = GET_TRAILFOCUS_SCREEN (s, GET_TRAILFOCUS_DISPLAY (s->display))
+
+#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
+#define N_WIN_TYPE (sizeof (winType) / sizeof (winType[0]))
+
+static int displayPrivateIndex = 0;
+
+static char *winType[] = {
+ N_("Toolbar"),
+ N_("Utility"),
+ N_("Dialog"),
+ N_("ModalDialog"),
+ N_("Fullscreen"),
+ N_("Normal")
+};
+
+typedef enum _TfOpt
+{
+ SOPT_MAX_OPACITY = 0,
+ SOPT_MAX_BRIGHTNESS,
+ SOPT_MAX_SATURATION,
+ SOPT_MIN_OPACITY,
+ SOPT_MIN_BRIGHTNESS,
+ SOPT_MIN_SATURATION,
+ SOPT_WINDOWS,
+ SOPT_WINDOW_TYPE,
+ SOPT_EXCLUDE_LIST,
+ SOPT_IGNORE_SKIPTASKBAR,
+ SOPT_IGNORE_SKIPPAGER,
+ SOPT_NUM
+} TrailfocusScreenOptions;
+
+typedef struct _TrailfocusDisplay
+{
+ int screenPrivateIndex;
+ HandleEventProc handleEvent;
+} TrailfocusDisplay;
+
+typedef struct _TfWindowAttributes
+{
+ GLushort opacity;
+ GLushort brightness;
+ GLushort saturation;
+} TfAttrib;
+
+typedef struct _TrailfocusScreen
+{
+ int wMask;
+ Window *win;
+ int win_max;
+ TfAttrib *inc;
+ CompOption opt[SOPT_NUM];
+} TrailfocusScreen;
+
+/* Core trailfocus functions. These do the real work. ---------------*/
+
+/* Checks if a window is a window trailfocus is supposed to touch or not. */
+static Bool is_trailfocus_window(TrailfocusScreen * ts, CompWindow * w)
+{
+ int i;
+ CompOption *o;
+
+ if (!(w->type & ts->wMask))
+ return False;
+ o = &ts->opt[SOPT_EXCLUDE_LIST];
+ for (i = 0; i < o->value.list.nValue; i++)
+ {
+ if (w->resClass
+ && (strcmp(o->value.list.value[i].s, w->resClass) == 0))
+ return False;
+ }
+
+ if (ts->opt[SOPT_IGNORE_SKIPTASKBAR].value.b
+ && w->state & CompWindowStateSkipTaskbarMask)
+ return False;
+ if (ts->opt[SOPT_IGNORE_SKIPPAGER].value.b
+ && w->state & CompWindowStateSkipPagerMask)
+ return False;
+
+ return True;
+}
+
+/* The set_[opacity|brightness|saturation] functions of
+ * trailfocus modifies the atoms if necesarry. These modify the actual
+ * atom, and also do not check if the window supplied is valid.
+ * FIXME: These are not permanent. We should not have to change the atom.
+ */
+static void set_opacity(CompWindow * w, int opacity)
+{
+ if (w->paint.opacity == opacity && w->opacity == opacity)
+ return;
+ if(set_default_window_opacity(w, opacity, PL_NO_LOCK))
+ set_window_opacity(w, opacity, PL_NO_LOCK);
+}
+
+static void set_brightness(CompWindow * w, int brightness)
+{
+ if (w->paint.brightness == brightness && w->brightness == brightness)
+ return;
+ if(set_default_window_brightness(w, brightness, PL_NO_LOCK))
+ set_window_brightness(w, brightness, PL_NO_LOCK);
+}
+
+static void set_saturation(CompWindow * w, int sat)
+{
+ if (w->paint.saturation == sat && w->saturation == sat)
+ return;
+ if(set_default_window_saturation(w, sat, PL_NO_LOCK))
+ set_window_saturation(w, sat, PL_NO_LOCK);
+}
+
+/* Resets a window's paint attribute when we're bailing out. Ideally this should
+ * reset to the atom, we're waiting for a proper paint-backend. In the meanwhile
+ * we're doing 0xFFFF. This is meant for plugin unload or when we are suddenly
+ * no longer handeling a window.
+ * FIXME: These are NOT PERMANENT AND NOT CORRECT. This is merely a
+ * place-holder until a more proper system has been put in place.
+ */
+static void bail_out_window(CompWindow * w)
+{
+ if (UNLIKELY(!w))
+ return;
+ set_window_bailout_opacity(w, PL_NO_LOCK);
+ set_window_bailout_saturation(w, PL_NO_LOCK);
+ set_window_bailout_brightness(w, PL_NO_LOCK);
+ reset_window_opacity(w, PL_NO_LOCK);
+ reset_window_saturation(w, PL_NO_LOCK);
+ reset_window_brightness(w, PL_NO_LOCK);
+}
+
+/* Meant for unload. Reset all windows handled by us. */
+static void bail_out_tf(CompScreen * s)
+{
+ CompWindow *w;
+
+ TRAILFOCUS_SCREEN(s);
+
+ for (w = s->windows; w; w = w->next)
+ if (is_trailfocus_window(ts, w))
+ bail_out_window(w);
+}
+
+/* Meant for option change. Reset all windows not handled by us.
+ * Ideally we should have a window-diff here, but alas... we don't.
+ * So we reset all we don't handle. Room for improvement if necesarry.
+ */
+static void bail_out_non_tf(CompScreen * s)
+{
+ CompWindow *w;
+
+ TRAILFOCUS_SCREEN(s);
+
+ for (w = s->windows; w; w = w->next)
+ if (!is_trailfocus_window(ts, w))
+ bail_out_window(w);
+}
+
+/* Sets the opacity, saturation and brightness to that of a window
+ * that had focus N times ago.
+ */
+static inline void set_window(TrailfocusScreen * ts, CompWindow * w, int n)
+{
+ set_opacity(w, ts->inc[n].opacity);
+ set_saturation(w, ts->inc[n].saturation);
+ set_brightness(w, ts->inc[n].brightness);
+}
+
+/* Walks through the window-list and sets the opacity-levels for
+ * all windows. The inner loop will result in ts->win[i] either
+ * representing a recently focused window, or the least
+ * focused window.
+ */
+static void set_windows(CompScreen * s)
+{
+ CompWindow *w;
+
+ TRAILFOCUS_SCREEN(s);
+ int i = 0;
+
+ for (w = s->windows; w; w = w->next)
+ {
+ if (w->invisible || w->hidden || w->minimized)
+ continue;
+ if (!is_trailfocus_window(ts, w))
+ continue;
+ for (i = 0; i < ts->win_max; i++)
+ if (w->id == ts->win[i])
+ break;
+ set_window(ts, w, i);
+ }
+}
+
+/* Push a new window-id on the trailfocus window-stack (not to be
+ * confused with the real window stack). Only keep one copy of a
+ * window on the stack. If the window allready exist on the stack,
+ * move it to the top.
+ */
+static CompScreen *push_window(CompDisplay * d, Window id)
+{
+ int i;
+ short int tmp;
+ CompWindow *w;
+ CompScreen *s;
+
+ w = findWindowAtDisplay(d, id);
+ if (UNLIKELY(!w))
+ return NULL;
+ s = w->screen;
+ if (UNLIKELY(!s))
+ return NULL;
+ TRAILFOCUS_SCREEN(s);
+ if (!is_trailfocus_window(ts, w))
+ return NULL;
+
+ tmp = ts->win_max;
+ for (i = 0; i < ts->win_max; i++)
+ if (ts->win[i] == id)
+ break;
+
+ if (UNLIKELY(i == 0))
+ return NULL;
+
+ for (; i > 0; i--)
+ ts->win[i] = ts->win[i - 1];
+
+ ts->win[0] = id;
+ return s;
+}
+
+/* Find a window on a screen.... Unlike the findWindowAtScreen which
+ * core provides, we don't intend to search for the same window several
+ * times in a row so we optimize for* the normal situation of searching for
+ * a window only once in a row.
+ */
+static CompWindow *find_window(CompScreen * s, Window id)
+{
+ CompWindow *w;
+
+ for (w = s->windows; w; w = w->next)
+ if (w->id == id)
+ return w;
+ return NULL;
+}
+
+/* Walks through the existing stack and removes windows that should
+ * (no longer) be there. Used for option-change.
+ */
+static void clean_list(CompScreen * s)
+{
+ TRAILFOCUS_SCREEN(s);
+ CompWindow *w;
+ int i, j, length;
+
+ for (i = 0; i < ts->win_max; i++)
+ {
+ w = find_window(s, ts->win[i]);
+ if (!w || !is_trailfocus_window(ts, w))
+ ts->win[i] = 0;
+ }
+ length = ts->win_max;
+ for (i = 0; i < length; i++)
+ {
+ if (!ts->win[i])
+ {
+ for (j = i; j < length - 1; j++)
+ ts->win[j] = ts->win[j + 1];
+ length--;
+ }
+ }
+ for (; length < ts->win_max; length++)
+ ts->win[length] = 0;
+}
+
+/* Handles the event if it was a FocusIn event. */
+static void trailfocusHandleEvent(CompDisplay * d, XEvent * event)
+{
+ TRAILFOCUS_DISPLAY(d);
+ CompScreen *s;
+ switch (event->type)
+ {
+ case FocusIn:
+ s = push_window(d, event->xfocus.window);
+ if (s && !otherScreenGrabExist(s,0))
+ set_windows(s);
+ break;
+ default:
+ break;
+ }
+
+
+ UNWRAP(td, d, handleEvent);
+ (*d->handleEvent) (d, event);
+ WRAP(td, d, handleEvent, trailfocusHandleEvent);
+}
+
+/* Settings changed. Reallocate rs->inc and re-populate it and the
+ * rest of the TrailfocusScreen (-wMask).
+ */
+static void recalculate_attributes(TrailfocusScreen * ts)
+{
+ TfAttrib tmp, min, max;
+ int i;
+
+ ts->win_max = ts->opt[SOPT_WINDOWS].value.i;
+ min.opacity = ts->opt[SOPT_MIN_OPACITY].value.i * OPAQUE / 100;
+ min.brightness = ts->opt[SOPT_MIN_BRIGHTNESS].value.i * OPAQUE / 100;
+ min.saturation = ts->opt[SOPT_MIN_SATURATION].value.i * OPAQUE / 100;
+ max.opacity = ts->opt[SOPT_MAX_OPACITY].value.i * OPAQUE / 100;
+ max.brightness = ts->opt[SOPT_MAX_BRIGHTNESS].value.i * OPAQUE / 100;
+ max.saturation = ts->opt[SOPT_MAX_SATURATION].value.i * OPAQUE / 100;
+
+ ts->win = realloc(ts->win, sizeof(Window) * (ts->win_max + 1));
+ ts->inc = realloc(ts->inc, sizeof(TfAttrib) * (ts->win_max + 1));
+ tmp.opacity = (max.opacity - min.opacity) / ts->win_max;
+ tmp.brightness = (max.brightness - min.brightness) / ts->win_max;
+ tmp.saturation = (max.saturation - min.saturation) / ts->win_max;
+
+ for (i = 0; i < ts->win_max; i++)
+ {
+ ts->inc[i].opacity = max.opacity - (tmp.opacity * i);
+ ts->inc[i].brightness = max.brightness - (tmp.brightness * i);
+ ts->inc[i].saturation = max.saturation - (tmp.saturation * i);
+ ts->win[i] = 0;
+ }
+ ts->inc[i] = min;
+}
+
+/* Unlike the traditional setScreenOptions, we return on failure in the
+ * switch, so we can execute a couple of common functions at the end.
+ */
+static Bool trailfocusSetScreenOptions(CompScreen * screen, char *name,
+ CompOptionValue * value)
+{
+ CompOption *o;
+ int index;
+
+ TRAILFOCUS_SCREEN(screen);
+ o = compFindOption(ts->opt, NUM_OPTIONS(ts), name, &index);
+ if (!o)
+ return FALSE;
+
+ switch (index)
+ {
+ case SOPT_MAX_OPACITY:
+ case SOPT_MAX_BRIGHTNESS:
+ case SOPT_MAX_SATURATION:
+ case SOPT_MIN_OPACITY:
+ case SOPT_MIN_BRIGHTNESS:
+ case SOPT_MIN_SATURATION:
+ case SOPT_WINDOWS:
+ if (!compSetIntOption(o, value))
+ return FALSE;
+ recalculate_attributes(ts);
+ break;
+ case SOPT_WINDOW_TYPE:
+ if (!compSetOptionList(o, value))
+ return FALSE;
+ ts->wMask = compWindowTypeMaskFromStringList(&o->value);
+ break;
+ case SOPT_EXCLUDE_LIST:
+ if (!compSetOptionList(o, value))
+ return FALSE;
+ break;
+ case SOPT_IGNORE_SKIPPAGER:
+ case SOPT_IGNORE_SKIPTASKBAR:
+ if (!compSetBoolOption(o, value))
+ return FALSE;
+ break;
+ default:
+ return FALSE;
+ break;
+ }
+ bail_out_non_tf(screen);
+ clean_list(screen);
+ push_window(screen->display, screen->display->activeWindow);
+ set_windows(screen);
+
+ return TRUE;
+}
+
+/* Configuration, initliazation, boring stuff. ----------------------- */
+
+/* Remember to reset windows to some sane value when we unload */
+static void trailfocusFiniScreen(CompPlugin * p, CompScreen * s)
+{
+ TRAILFOCUS_SCREEN(s);
+ bail_out_tf(s);
+ if (ts->opt[SOPT_WINDOW_TYPE].value.list.value)
+ free(ts->opt[SOPT_WINDOW_TYPE].value.list.value);
+ free(ts);
+}
+
+static void trailfocusScreenInitOptions(TrailfocusScreen * ts)
+{
+ CompOption *o;
+ int i;
+
+ o = &ts->opt[SOPT_MAX_OPACITY];
+ o->name = "max_opacity";
+ o->group = N_("Appearance");
+ o->subGroup = N_("Opacity");
+ o->displayHints = "";
+ o->shortDesc = N_("Opacity level of completly focused windows");
+ o->longDesc = N_("Opacity of the currently focused window. Windows "
+ "will get opacity levels between the focused "
+ "and min. ");
+ o->type = CompOptionTypeInt;
+ o->value.i = 100;
+ o->rest.i.min = 1;
+ o->rest.i.max = 100;
+ o->advanced = False;
+
+ o = &ts->opt[SOPT_MAX_BRIGHTNESS];
+ o->name = "max_brightness";
+ o->group = N_("Appearance");
+ o->subGroup = N_("Brightness");
+ o->displayHints = "";
+ o->shortDesc = N_("Brightness level of completly focused windows");
+ o->longDesc = N_("Brightness of the currently focused window. Windows "
+ "will get brightness levels between the focused "
+ "and min. ");
+ o->type = CompOptionTypeInt;
+ o->value.i = 100;
+ o->rest.i.min = 1;
+ o->rest.i.max = 100;
+ o->advanced = False;
+
+ o = &ts->opt[SOPT_MAX_SATURATION];
+ o->name = "max_saturation";
+ o->group = N_("Appearance");
+ o->subGroup = N_("Saturation");
+ o->displayHints = "";
+ o->shortDesc = N_("Saturation level of completly focused windows");
+ o->longDesc = N_("Saturation of the currently focused window. Windows "
+ "will get saturation levels between the focused "
+ "and min. ");
+ o->type = CompOptionTypeInt;
+ o->value.i = 100;
+ o->rest.i.min = 1;
+ o->rest.i.max = 100;
+ o->advanced = False;
+
+ o = &ts->opt[SOPT_MIN_OPACITY];
+ o->name = "min_opacity";
+ o->group = N_("Appearance");
+ o->subGroup = N_("Opacity");
+ o->displayHints = "";
+ o->shortDesc = N_("Opacity level of completly unfocused windows");
+ o->longDesc = N_("Opacity of the least focused windows. Windows "
+ "will get opacity levels between the focused "
+ "and min. ");
+ o->type = CompOptionTypeInt;
+ o->value.i = 70;
+ o->rest.i.min = 1;
+ o->rest.i.max = 100;
+ o->advanced = False;
+
+ o = &ts->opt[SOPT_MIN_BRIGHTNESS];
+ o->name = "min_brightness";
+ o->group = N_("Appearance");
+ o->subGroup = N_("Brightness");
+ o->displayHints = "";
+ o->shortDesc = N_("Brightness level of completly unfocused windows");
+ o->longDesc = N_("Brightness of the least focused windows. Windows "
+ "will get brightness levels between the focused "
+ "and min. ");
+ o->type = CompOptionTypeInt;
+ o->value.i = 90;
+ o->rest.i.min = 1;
+ o->rest.i.max = 100;
+ o->advanced = False;
+
+ o = &ts->opt[SOPT_MIN_SATURATION];
+ o->name = "min_saturation";
+ o->group = N_("Appearance");
+ o->subGroup = N_("Saturation");
+ o->displayHints = "";
+ o->shortDesc = N_("Saturation level of completly unfocused windows");
+ o->longDesc = N_("Saturation of the least focused windows. Windows "
+ "will get saturation levels between the focused "
+ "and min. ");
+ o->type = CompOptionTypeInt;
+ o->value.i = 90;
+ o->rest.i.min = 1;
+ o->rest.i.max = 100;
+ o->advanced = False;
+
+ o = &ts->opt[SOPT_WINDOWS];
+ o->name = "windows";
+ o->group = N_("Behaviour");
+ o->subGroup = N_("");
+ o->displayHints = "";
+ o->shortDesc = N_("Number of windows to track");
+ o->longDesc =
+ N_
+ ("Number of windows trailfocus will keep track of. Windows had focus "
+ " this amount of windows ago or more, will be considered completly"
+ " unfocused.");
+ o->type = CompOptionTypeInt;
+ o->value.i = 5;
+ o->rest.i.min = 1;
+ o->rest.i.max = 150;
+ o->advanced = False;
+ ts->win_max = 5;
+
+
+ o = &ts->opt[SOPT_WINDOW_TYPE];
+ o->name = "window_types";
+ o->group = N_("Behaviour");
+ o->subGroup = N_("");
+ o->displayHints = "";
+ o->shortDesc = N_("Window Types");
+ o->longDesc = N_("Window types that should be handled by trailfocus");
+ o->type = CompOptionTypeList;
+ o->value.list.type = CompOptionTypeString;
+ o->value.list.nValue = N_WIN_TYPE;
+ o->value.list.value = malloc(sizeof(CompOptionValue) * N_WIN_TYPE);
+ for (i = 0; i < N_WIN_TYPE; i++)
+ o->value.list.value[i].s = strdup(winType[i]);
+ o->rest.s.string = (char **)windowTypeString;
+ o->rest.s.nString = nWindowTypeString;
+ o->advanced = True;
+
+ o = &ts->opt[SOPT_EXCLUDE_LIST];
+ o->advanced = False;
+ o->name = "exclude_list";
+ o->group = N_("Behaviour");
+ o->subGroup = N_("");
+ o->displayHints = "";
+ o->shortDesc = N_("WM_CLASS to exclude");
+ o->longDesc =
+ N_
+ ("Windows classes to exclude from trailfocusing. Use xprop to find window class.");
+ o->type = CompOptionTypeList;
+ o->value.list.type = CompOptionTypeString;
+ o->value.list.nValue = 0;
+ o->value.list.value = 0;
+ o->rest.s.string = 0;
+ o->rest.s.nString = 0;
+
+ o = &ts->opt[SOPT_IGNORE_SKIPTASKBAR];
+ o->advanced = True;
+ o->name = "ignore_skiptaskbar";
+ o->group = N_("Behaviour");
+ o->subGroup = N_("");
+ o->displayHints = "";
+ o->shortDesc = N_("Ignore \"SkipTaskbar\" Windows");
+ o->longDesc = N_("Ignore \"SkipTaskbar\" Windows");
+ o->type = CompOptionTypeBool;
+ o->value.b = True;
+
+ o = &ts->opt[SOPT_IGNORE_SKIPPAGER];
+ o->advanced = True;
+ o->name = "ignore_skippager";
+ o->group = N_("Behaviour");
+ o->subGroup = N_("");
+ o->displayHints = "";
+ o->shortDesc = N_("Ignore \"SkipPager\" Windows");
+ o->longDesc = N_("Ignore \"SkipPager\" Windows");
+ o->type = CompOptionTypeBool;
+ o->value.b = True;
+}
+
+/* Remember to populate the TrailFocus screen properly, and push the
+ * active window on the stack, then set windows.
+ */
+static Bool trailfocusInitScreen(CompPlugin * p, CompScreen * s)
+{
+ TRAILFOCUS_DISPLAY(s->display);
+ TrailfocusScreen *ts =
+ (TrailfocusScreen *) calloc(1, sizeof(TrailfocusScreen));
+ s->privates[td->screenPrivateIndex].ptr = ts;
+ trailfocusScreenInitOptions(ts);
+ ts->wMask =
+ compWindowTypeMaskFromStringList(&ts->opt[SOPT_WINDOW_TYPE].
+ value);
+ recalculate_attributes(ts);
+ push_window(s->display, s->display->activeWindow);
+ set_windows(s);
+ return TRUE;
+}
+
+static CompOption *trailfocusGetScreenOptions(CompScreen * screen, int *count)
+{
+ if (screen)
+ {
+ TRAILFOCUS_SCREEN(screen);
+ *count = NUM_OPTIONS(ts);
+ return ts->opt;
+ }
+ else
+ {
+ TrailfocusScreen *ts = malloc(sizeof(TrailfocusScreen));
+
+ trailfocusScreenInitOptions(ts);
+ *count = NUM_OPTIONS(ts);
+ return ts->opt;
+ }
+}
+
+static Bool trailfocusInitDisplay(CompPlugin * p, CompDisplay * d)
+{
+ TrailfocusDisplay *td =
+ (TrailfocusDisplay *) malloc(sizeof(TrailfocusDisplay));
+
+ td->screenPrivateIndex = allocateScreenPrivateIndex(d);
+ if (td->screenPrivateIndex < 0)
+ {
+ free(td);
+ return FALSE;
+ }
+ d->privates[displayPrivateIndex].ptr = td;
+ WRAP(td, d, handleEvent, trailfocusHandleEvent);
+ return TRUE;
+}
+
+static void trailfocusFiniDisplay(CompPlugin * p, CompDisplay * d)
+{
+ TRAILFOCUS_DISPLAY(d);
+ UNWRAP(td, d, handleEvent);
+ freeScreenPrivateIndex(d, td->screenPrivateIndex);
+ free(td);
+}
+
+static Bool trailfocusInit(CompPlugin * p)
+{
+ displayPrivateIndex = allocateDisplayPrivateIndex();
+ if (displayPrivateIndex < 0)
+ return FALSE;
+ return TRUE;
+}
+
+static void trailfocusFini(CompPlugin * p)
+{
+ if (displayPrivateIndex >= 0)
+ freeDisplayPrivateIndex(displayPrivateIndex);
+}
+
+CompPluginVTable trailfocusVTable = {
+ "trailfocus2",
+ N_("Trailfocus"),
+ N_("Adjust the opacity, saturation and brightness of windows based on when they last had focus."),
+ trailfocusInit,
+ trailfocusFini,
+ trailfocusInitDisplay,
+ trailfocusFiniDisplay,
+ trailfocusInitScreen,
+ trailfocusFiniScreen,
+ 0,
+ 0,
+ 0, // trailfocusGetDisplayOptions,
+ 0, // trailfocusSetDisplayOptions,
+ trailfocusGetScreenOptions,
+ trailfocusSetScreenOptions,
+ 0,
+ 0,
+ 0,
+ 0,
+ BERYL_ABI_INFO,
+ "beryl-plugins",
+ "effects",
+ 0,
+ 0,
+ False,
+};
+
+CompPluginVTable *getCompPluginInfo(void)
+{
+ return &trailfocusVTable;
+}