diff options
author | Danny Baumann <dannybaumann@web.de> | 2007-04-03 16:20:45 +0200 |
---|---|---|
committer | Danny Baumann <dannybaumann@web.de> | 2007-04-03 16:20:45 +0200 |
commit | 3faff911d83637c189d77538422532dccdd0e106 (patch) | |
tree | 27b731289349b0d1d32b89b31875b4ed8e8093bf | |
parent | 4a09f19dfcd83d93b594803e014f8792ea923aac (diff) | |
download | beryl-premerge-3faff911d83637c189d77538422532dccdd0e106.tar.gz beryl-premerge-3faff911d83637c189d77538422532dccdd0e106.tar.bz2 |
added trailfocus
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/trailfocus.c | 482 | ||||
-rw-r--r-- | src/trailfocus.options | 75 |
3 files changed, 562 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 51db733..69ebd33 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,6 +13,10 @@ libring_la_LDFLAGS = $(PFLAGS) libring_la_LIBADD = @COMPIZ_LIBS@ libring_la_SOURCES = ring_options.c ring.c +libtrailfocus_la_LDFLAGS = $(PFLAGS) +libtrailfocus_la_LIBADD = @COMPIZ_LIBS@ +libtrailfocus_la_SOURCES = trailfocus_options.c trailfocus.c + if WALL_PLUGIN libwall_la_LDFLAGS = $(PFLAGS) libwall_la_LIBADD = @COMPIZ_LIBS@ @WALL_LIBS@ -lGLU @@ -95,6 +99,7 @@ module_LTLIBRARIES = \ libthumbnail.la \ libsnap.la \ libshowdesktop.la \ + libtrailfocus.la \ libbench.la \ $(libwall_module) \ $(libimgjpeg_module) \ diff --git a/src/trailfocus.c b/src/trailfocus.c new file mode 100644 index 0000000..41dc471 --- /dev/null +++ b/src/trailfocus.c @@ -0,0 +1,482 @@ +/** + * 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. + * + */ + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <math.h> +#include <X11/Xatom.h> +#include <X11/extensions/Xrender.h> +#include <compiz.h> +#include "trailfocus_options.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 GET_TRAILFOCUS_WINDOW(w, ts) \ + ((TrailfocusWindow *) (w)->privates[(ts)->windowPrivateIndex].ptr) +#define TRAILFOCUS_WINDOW(w) \ + TrailfocusWindow *tw = GET_TRAILFOCUS_WINDOW (w, GET_TRAILFOCUS_SCREEN(w->screen, GET_TRAILFOCUS_DISPLAY (w->screen->display))) + +static int displayPrivateIndex = 0; + +typedef struct _TrailfocusDisplay +{ + int screenPrivateIndex; + HandleEventProc handleEvent; +} TrailfocusDisplay; + +typedef struct _TfWindowAttributes +{ + GLushort opacity; + GLushort brightness; + GLushort saturation; +} TfAttrib; + +typedef struct _TrailfocusScreen +{ + int windowPrivateIndex; + + Window *win; + TfAttrib *inc; + Bool initialized; + + PaintWindowProc paintWindow; +} TrailfocusScreen; + +typedef struct _TrailfocusWindow +{ + Bool isTfWindow; + TfAttrib attribs; +} TrailfocusWindow; + +/* Core trailfocus functions. These do the real work. ---------------*/ + +/* 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 setWindows(CompScreen * s) +{ + CompWindow *w; + + TRAILFOCUS_SCREEN(s); + int i = 0; + int winMax = trailfocusGetWindowsCount(s); + + for (w = s->windows; w; w = w->next) + { + TRAILFOCUS_WINDOW(w); + tw->isTfWindow = FALSE; + + if (w->invisible || w->hidden || w->minimized) + continue; + + if (!matchEval(trailfocusGetWindowMatch(s), w)) + continue; + + for (i = 0; i < winMax; i++) + if (w->id == ts->win[i]) + break; + + tw->isTfWindow = TRUE; + tw->attribs = ts->inc[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 *pushWindow(CompDisplay * d, Window id) +{ + int i; + int tmp, winMax; + CompWindow *w; + + w = findWindowAtDisplay(d, id); + if (!w) + return NULL; + + TRAILFOCUS_SCREEN(w->screen); + + if (!matchEval(trailfocusGetWindowMatch(w->screen), w)) + return NULL; + + tmp = winMax = trailfocusGetWindowsCount(w->screen); + for (i = 0; i < winMax; i++) + if (ts->win[i] == id) + break; + + if (i == 0) + return NULL; + + for (; i > 0; i--) + ts->win[i] = ts->win[i - 1]; + + ts->win[0] = id; + return w->screen; +} + +/* 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 *findWindow(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 cleanList(CompScreen * s) +{ + TRAILFOCUS_SCREEN(s); + CompWindow *w; + int i, j, length; + int winMax; + + winMax = trailfocusGetWindowsCount(s); + + for (i = 0; i < winMax; i++) + { + w = findWindow(s, ts->win[i]); + if (!w || !matchEval(trailfocusGetWindowMatch(s), w)) + ts->win[i] = 0; + } + + length = winMax; + 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 < winMax; 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 = pushWindow(d, event->xfocus.window); + if (s) + setWindows(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 recalculateAttributes(CompScreen * s) +{ + TRAILFOCUS_SCREEN(s); + TfAttrib tmp, min, max; + int i; + int start; + int winMax; + + start = trailfocusGetWindowsStart(s) - 1; + winMax = trailfocusGetWindowsCount(s); + + if (start >= winMax) + { + fprintf(stderr, + "trailfocus: WARNING: Attempting to define start higher than max windows.\n"); + start = winMax - 1; + } + + min.opacity = trailfocusGetMinOpacity(s) * OPAQUE / 100; + min.brightness = trailfocusGetMinBrightness(s) * OPAQUE / 100; + min.saturation = trailfocusGetMinSaturation(s) * OPAQUE / 100; + max.opacity = trailfocusGetMaxOpacity(s) * OPAQUE / 100; + max.brightness = trailfocusGetMaxBrightness(s) * OPAQUE / 100; + max.saturation = trailfocusGetMaxSaturation(s) * OPAQUE / 100; + + ts->win = realloc(ts->win, sizeof(Window) * (winMax + 1)); + ts->inc = realloc(ts->inc, sizeof(TfAttrib) * (winMax + 1)); + + tmp.opacity = (max.opacity - min.opacity) / ((winMax - start)); + tmp.brightness = + (max.brightness - min.brightness) / ((winMax - start)); + tmp.saturation = + (max.saturation - min.saturation) / ((winMax - start)); + + for (i = 0; i < start; ++i) + ts->inc[i] = max; + + for (i = 0; i + start <= winMax; i++) + { + ts->inc[i + start].opacity = max.opacity - (tmp.opacity * i); + ts->inc[i + start].brightness = max.brightness - (tmp.brightness * i); + ts->inc[i + start].saturation = max.saturation - (tmp.saturation * i); + ts->win[i + start] = 0; + } +// ts->inc[i+start] = min; +} + +static Bool trailfocusPaintWindow(CompWindow *w, const WindowPaintAttrib *attrib, + const CompTransform *transform, + Region region, unsigned int mask) +{ + Bool status; + TRAILFOCUS_WINDOW(w); + TRAILFOCUS_SCREEN(w->screen); + + if (!ts->initialized) + { + setWindows(w->screen); + ts->initialized = TRUE; + } + + if (tw->isTfWindow) + { + WindowPaintAttrib wAttrib = *attrib; + + wAttrib.opacity = tw->attribs.opacity; + wAttrib.brightness = tw->attribs.brightness; + wAttrib.saturation = tw->attribs.brightness; + + UNWRAP(ts, w->screen, paintWindow); + status = (*w->screen->paintWindow) (w, &wAttrib, transform, region, mask); + WRAP(ts, w->screen, paintWindow, trailfocusPaintWindow); + } + else + { + UNWRAP(ts, w->screen, paintWindow); + status = (*w->screen->paintWindow) (w, attrib, transform, region, mask); + WRAP(ts, w->screen, paintWindow, trailfocusPaintWindow); + } + + return status; +} + +/* Configuration, initliazation, boring stuff. ----------------------- */ + +static void trailfocusScreenOptionChanged(CompScreen *s, CompOption *opt, TrailfocusScreenOptions num) +{ + switch (num) + { + case TrailfocusScreenOptionMinOpacity: + case TrailfocusScreenOptionMaxOpacity: + case TrailfocusScreenOptionMinSaturation: + case TrailfocusScreenOptionMaxSaturation: + case TrailfocusScreenOptionMinBrightness: + case TrailfocusScreenOptionMaxBrightness: + case TrailfocusScreenOptionWindowsStart: + case TrailfocusScreenOptionWindowsCount: + recalculateAttributes(s); + break; + default: + break; + } + + cleanList(s); + pushWindow(s->display, s->display->activeWindow); + setWindows(s); +} + +static Bool trailfocusInitWindow(CompPlugin *p, CompWindow *w) +{ + TRAILFOCUS_SCREEN(w->screen); + + TrailfocusWindow *tw = (TrailfocusWindow *) calloc(1, sizeof(TrailfocusWindow)); + w->privates[ts->windowPrivateIndex].ptr = tw; + + tw->isTfWindow = FALSE; + + return TRUE; +} + +static void trailfocusFiniWindow(CompPlugin *p, CompWindow *w) +{ + TRAILFOCUS_WINDOW(w); + + free(tw); +} + +/* Remember to reset windows to some sane value when we unload */ +static void trailfocusFiniScreen(CompPlugin * p, CompScreen * s) +{ + TRAILFOCUS_SCREEN(s); + + if (ts->win) + free(ts->win); + if (ts->inc) + free(ts->inc); + + UNWRAP(ts, s, paintWindow); + + free(ts); +} + +/* 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)); + + ts->windowPrivateIndex = allocateWindowPrivateIndex(s); + if (ts->windowPrivateIndex < 0) + { + free(ts); + return FALSE; + } + + trailfocusSetWindowMatchNotify(s, trailfocusScreenOptionChanged); + trailfocusSetWindowsCountNotify(s, trailfocusScreenOptionChanged); + trailfocusSetWindowsStartNotify(s, trailfocusScreenOptionChanged); + trailfocusSetMinOpacityNotify(s, trailfocusScreenOptionChanged); + trailfocusSetMaxOpacityNotify(s, trailfocusScreenOptionChanged); + trailfocusSetMinSaturationNotify(s, trailfocusScreenOptionChanged); + trailfocusSetMaxSaturationNotify(s, trailfocusScreenOptionChanged); + trailfocusSetMinBrightnessNotify(s, trailfocusScreenOptionChanged); + trailfocusSetMaxBrightnessNotify(s, trailfocusScreenOptionChanged); + + s->privates[td->screenPrivateIndex].ptr = ts; + + WRAP(ts, s, paintWindow, trailfocusPaintWindow); + + recalculateAttributes(s); + pushWindow(s->display, s->display->activeWindow); + + ts->initialized = FALSE; + + return TRUE; +} + +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); +} + +static int trailfocusGetVersion(CompPlugin *p, int version) +{ + return ABIVERSION; +} + +CompPluginDep trailfocusDeps[] = { + {CompPluginRuleAfter, "fade"} +}; + +CompPluginVTable trailfocusVTable = { + "trailfocus", + N_("Trailfocus"), + N_("Adjust the opacity, saturation and brightness of windows based on when they last had focus."), + trailfocusGetVersion, + trailfocusInit, + trailfocusFini, + trailfocusInitDisplay, + trailfocusFiniDisplay, + trailfocusInitScreen, + trailfocusFiniScreen, + trailfocusInitWindow, + trailfocusFiniWindow, + 0, // trailfocusGetDisplayOptions, + 0, // trailfocusSetDisplayOptions, + 0, + 0, + trailfocusDeps, + sizeof(trailfocusDeps) / sizeof(trailfocusDeps[0]), + 0, + 0 +}; + +CompPluginVTable *getCompPluginInfo(void) +{ + return &trailfocusVTable; +} diff --git a/src/trailfocus.options b/src/trailfocus.options new file mode 100644 index 0000000..081aab9 --- /dev/null +++ b/src/trailfocus.options @@ -0,0 +1,75 @@ +<plugin name="trailfocus"> + <screen> + <group name="Behaviour"> + <option name="window_match" type="match"> + <short>Window Types</short> + <long>Window types that should be handled by Trailfocus</long> + <default>(type=toolbar | type=utility | type=dialog | type=normal) & !(state=skiptaskbar | state=skippager)</default> + </option> + <option name="windows_count" type="int"> + <short>Number of Windows to Track</short> + <long>Number of windows Trailfocus will keep track of. Windows that had focus this amount of windows ago or more will be considered completly unfocused.</long> + <default>5</default> + <min>1</min> + <max>150</max> + </option> + <option name="windows_start" type="int"> + <short>Window to Start Fading</short> + <long>This defines when Trailfocus will start fading windows. This lets you set up trailfocus to treat the N first Windows as fully focused.</long> + <default>2</default> + <min>1</min> + <max>20</max> + </option> + </group> + <group name="Appearance"> + <subgroup name="Opacity"> + <option name="max_opacity" type="int"> + <short>Opacity Level of Focused Windows</short> + <long>Opacity of the currently focused window. Windows will get opacity levels between the focused and minimum.</long> + <default>100</default> + <min>1</min> + <max>100</max> + </option> + <option name="min_opacity" type="int"> + <short>Opacity Level of Unfocused Windows</short> + <long>Opacity of the least focused window. Windows will get opacity levels between the focused and minimum.</long> + <default>70</default> + <min>1</min> + <max>100</max> + </option> + </subgroup> + <subgroup name="Brightness"> + <option name="max_brightness" type="int"> + <short>Brightness Level of Focused Windows</short> + <long>Brightness of the currently focused window. Windows will get opacity levels between the focused and minimum.</long> + <default>100</default> + <min>1</min> + <max>100</max> + </option> + <option name="min_brightness" type="int"> + <short>Brightness Level of Unfocused Windows</short> + <long>Brightness of the least focused window. Windows will get opacity levels between the focused and minimum.</long> + <default>100</default> + <min>1</min> + <max>100</max> + </option> + </subgroup> + <subgroup name="Saturation"> + <option name="max_saturation" type="int"> + <short>Saturation Level of Focused Windows</short> + <long>Saturation of the currently focused window. Windows will get opacity levels between the focused and minimum.</long> + <default>100</default> + <min>1</min> + <max>100</max> + </option> + <option name="min_saturation" type="int"> + <short>Saturation Level of Unfocused Windows</short> + <long>Saturation of the least focused window. Windows will get opacity levels between the focused and minimum.</long> + <default>100</default> + <min>1</min> + <max>100</max> + </option> + </subgroup> + </group> + </screen> +</plugin> |