/*
* Copyright © 2005 Novell, Inc.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Author: David Reveman <davidr@novell.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <sys/types.h>
#include <unistd.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xrender.h>
#include <beryl.h>
#define SWITCH_NEXT_KEY_DEFAULT "Tab"
#define SWITCH_NEXT_MODIFIERS_DEFAULT CompAltMask
#define SWITCH_PREV_KEY_DEFAULT "Tab"
#define SWITCH_PREV_MODIFIERS_DEFAULT (CompAltMask | ShiftMask)
#define SWITCH_NEXT_ALL_KEY_DEFAULT "Tab"
#define SWITCH_NEXT_ALL_MODIFIERS_DEFAULT (CompAltMask | ControlMask)
#define SWITCH_PREV_ALL_KEY_DEFAULT "Tab"
#define SWITCH_PREV_ALL_MODIFIERS_DEFAULT \
(CompAltMask | ControlMask | ShiftMask)
#define SWITCH_RING_NEXT_KEY_DEFAULT "Tab"
#define SWITCH_RING_NEXT_MODIFIERS_DEFAULT CompSuperMask
#define SWITCH_RING_PREV_KEY_DEFAULT "Tab"
#define SWITCH_RING_PREV_MODIFIERS_DEFAULT (CompSuperMask | ShiftMask)
#define SWITCH_RING_NEXT_ALL_KEY_DEFAULT "Tab"
#define SWITCH_RING_NEXT_ALL_MODIFIERS_DEFAULT (CompSuperMask | ControlMask)
#define SWITCH_RING_PREV_ALL_KEY_DEFAULT "Tab"
#define SWITCH_RING_PREV_ALL_MODIFIERS_DEFAULT \
(CompSuperMask | ControlMask | ShiftMask)
#define SWITCH_SPEED_DEFAULT 2.5f
#define SWITCH_SPEED_MIN 0.1f
#define SWITCH_SPEED_MAX 50.0f
#define SWITCH_SPEED_PRECISION 0.1f
#define SWITCH_TIMESTEP_DEFAULT 1.1f
#define SWITCH_TIMESTEP_MIN 0.1f
#define SWITCH_TIMESTEP_MAX 50.0f
#define SWITCH_TIMESTEP_PRECISION 0.1f
#define SWITCH_MIPMAP_DEFAULT FALSE
#define SWITCH_BRINGTOFRONT_DEFAULT TRUE
#define SWITCH_SWITCH_FOCUS_INSTANTLY_DEFAULT FALSE
#define SWITCH_SATURATION_DEFAULT 100
#define SWITCH_SATURATION_MIN 0
#define SWITCH_SATURATION_MAX 100
#define SWITCH_BRIGHTNESS_DEFAULT 65
#define SWITCH_BRIGHTNESS_MIN 0
#define SWITCH_BRIGHTNESS_MAX 100
#define SWITCH_OPACITY_DEFAULT 40
#define SWITCH_OPACITY_MIN 0
#define SWITCH_OPACITY_MAX 100
#define SWITCH_ZOOM_DEFAULT 0.0f
#define SWITCH_ZOOM_MIN 0.0f
#define SWITCH_ZOOM_MAX 50.0f
#define SWITCH_ZOOM_PRECISION 0.1f
#define SWITCH_ICON_DEFAULT TRUE
#define SWITCH_MINIMIZED_DEFAULT TRUE
#define SWITCH_SHOW_WINDOW_LIST_DEFAULT TRUE
#define SWITCH_TEMP_UNMINIMIZE_DEFAULT FALSE
#define SWITCH_AUTO_ROTATE_DEFAULT FALSE
#define SWITCH_RING_ALL_TRANSPARENT_DEFAULT TRUE
#define SWITCH_ELLIPSE_WIDTH_MIN 0.01f
#define SWITCH_ELLIPSE_WIDTH_MAX 1.0f
#define SWITCH_ELLIPSE_WIDTH_DEFAULT 0.6f
#define SWITCH_ELLIPSE_HEIGHT_MIN 0.01f
#define SWITCH_ELLIPSE_HEIGHT_MAX 1.0f
#define SWITCH_ELLIPSE_HEIGHT_DEFAULT 0.25f
#define SWITCH_ELLIPSE_PRECISION 0.001f
#define SWITCH_THUMBNAIL_WIDTH_MIN 10
#define SWITCH_THUMBNAIL_WIDTH_MAX 1024
#define SWITCH_THUMBNAIL_WIDTH_DEFAULT 212
#define SWITCH_THUMBNAIL_HEIGHT_MIN 10
#define SWITCH_THUMBNAIL_HEIGHT_MAX 1024
#define SWITCH_THUMBNAIL_HEIGHT_DEFAULT 192
typedef enum _SwitcherMode
{
ApplicationSwitcher = 0,
RingSwitcher
} SwitcherMode;
typedef enum _IconCornerMode
{
BottomRight = 0,
BottomLeft,
TopRight,
TopLeft,
Center
} IconCornerMode;
static char *iconCornerModes[] = {
N_("Bottom Right"),
N_("Bottom Left"),
N_("Top Right"),
N_("Top Left"),
N_("Center")
};
static char *winType[] = {
N_("Utility"),
N_("Dialog"),
N_("ModalDialog"),
N_("Fullscreen"),
N_("Normal")
};
#define SWITCH_ICON_CORNER_DEFAULT BottomRight
#define N_ICON_CORNER_MODES (sizeof(iconCornerModes) / sizeof(iconCornerModes[0]))
#define N_WIN_TYPE (sizeof (winType) / sizeof (winType[0]))
static int displayPrivateIndex;
#define SWITCH_DISPLAY_OPTION_NEXT 0
#define SWITCH_DISPLAY_OPTION_PREV 1
#define SWITCH_DISPLAY_OPTION_NEXT_ALL 2
#define SWITCH_DISPLAY_OPTION_PREV_ALL 3
#define SWITCH_DISPLAY_OPTION_RING_NEXT 4
#define SWITCH_DISPLAY_OPTION_RING_PREV 5
#define SWITCH_DISPLAY_OPTION_RING_NEXT_ALL 6
#define SWITCH_DISPLAY_OPTION_RING_PREV_ALL 7
#define SWITCH_DISPLAY_OPTION_NUM 8
typedef struct _SwitchDisplay
{
int screenPrivateIndex;
HandleEventProc handleEvent;
CompOption opt[SWITCH_DISPLAY_OPTION_NUM];
Atom selectWinAtom;
} SwitchDisplay;
#define SWITCH_SCREEN_OPTION_SHOW_WINDOW_LIST 0
#define SWITCH_SCREEN_OPTION_SPEED 1
#define SWITCH_SCREEN_OPTION_TIMESTEP 2
#define SWITCH_SCREEN_OPTION_BRINGTOFRONT 3
#define SWITCH_SCREEN_OPTION_AUTO_ROTATE 4
#define SWITCH_SCREEN_OPTION_SWITCH_FOCUS_INSTANTLY 5
#define SWITCH_SCREEN_OPTION_ZOOM 6
#define SWITCH_SCREEN_OPTION_WINDOW_TYPE 7
#define SWITCH_SCREEN_OPTION_MINIMIZED 8
#define SWITCH_SCREEN_OPTION_TEMP_UNMINIMIZE 9
#define SWITCH_SCREEN_OPTION_SATURATION 10
#define SWITCH_SCREEN_OPTION_BRIGHTNESS 11
#define SWITCH_SCREEN_OPTION_OPACITY 12
#define SWITCH_SCREEN_OPTION_MIPMAP 13
#define SWITCH_SCREEN_OPTION_ICON 14
#define SWITCH_SCREEN_OPTION_ICON_CORNER 15
#define SWITCH_SCREEN_OPTION_ELLIPSE_WIDTH 16
#define SWITCH_SCREEN_OPTION_ELLIPSE_HEIGHT 17
#define SWITCH_SCREEN_OPTION_THUMBNAIL_WIDTH 18
#define SWITCH_SCREEN_OPTION_THUMBNAIL_HEIGHT 19
#define SWITCH_SCREEN_OPTION_RING_TRANSPARENT_ALL 20
#define SWITCH_SCREEN_OPTION_NUM 21
typedef struct _SwitchScreen
{
PreparePaintScreenProc preparePaintScreen;
DonePaintScreenProc donePaintScreen;
PaintScreenProc paintScreen;
PaintWindowProc paintWindow;
DamageWindowRectProc damageWindowRect;
CompOption opt[SWITCH_SCREEN_OPTION_NUM];
Window popupWindow;
Window selectedWindow;
Window zoomedWindow;
unsigned int lastActiveNum;
float speed;
float timestep;
float zoom;
unsigned int wMask;
int grabIndex;
Bool switching;
Bool zooming;
int moreAdjust;
GLfloat mVelocity;
GLfloat tVelocity;
GLfloat sVelocity;
CompWindow **windows;
int windowsSize;
int nWindows;
int pos;
int move;
float translate;
float sTranslate;
GLushort saturation;
GLushort brightness;
GLushort opacity;
Bool bringToFront;
Bool allWindows;
Bool showWindowList;
Bool autoRotate;
Bool tempUnMinimize;
SwitcherMode switchMode;
IconCornerMode iconCorner;
int head;
CompWindow *prevMin;
int insideAtom;
} SwitchScreen;
#define MwmHintsDecorations (1L << 1)
typedef struct
{
unsigned long flags;
unsigned long functions;
unsigned long decorations;
} MwmHints;
#define SELECT_WIN_PROP "_SWITCH_SELECT_WINDOW"
#define WIDTH 212
#define HEIGHT 192
#define SPACE 10
#define BOX_WIDTH 3
#define ELLIPSE_ROTA(outputRect) int ellipse_a = (outputRect.width*ss->opt[SWITCH_SCREEN_OPTION_ELLIPSE_WIDTH].value.f)/2.0f;
#define ELLIPSE_ROTB(outputRect) int ellipse_b = (outputRect.height*ss->opt[SWITCH_SCREEN_OPTION_ELLIPSE_HEIGHT].value.f)/2.0f;
#define ELLIPSE_ROT(outputRect) ELLIPSE_ROTA(outputRect)\
ELLIPSE_ROTB(outputRect)
#define DIST_ROT int dist=(4*ellipse_a)/(ss->nWindows)
static float _boxVertices[] = {
-(WIDTH >> 1), 0,
-(WIDTH >> 1), BOX_WIDTH,
(WIDTH >> 1), BOX_WIDTH,
(WIDTH >> 1), 0,
-(WIDTH >> 1), BOX_WIDTH,
-(WIDTH >> 1), HEIGHT - BOX_WIDTH,
-(WIDTH >> 1) + BOX_WIDTH, HEIGHT - BOX_WIDTH,
-(WIDTH >> 1) + BOX_WIDTH, 0,
(WIDTH >> 1) - BOX_WIDTH, BOX_WIDTH,
(WIDTH >> 1) - BOX_WIDTH, HEIGHT - BOX_WIDTH,
(WIDTH >> 1), HEIGHT - BOX_WIDTH,
(WIDTH >> 1), 0,
-(WIDTH >> 1), HEIGHT - BOX_WIDTH,
-(WIDTH >> 1), HEIGHT,
(WIDTH >> 1), HEIGHT,
(WIDTH >> 1), HEIGHT - BOX_WIDTH
};
#define WINDOW_WIDTH(count) (WIDTH * (count) + (SPACE << 1))
#define WINDOW_HEIGHT (HEIGHT + (SPACE << 1))
#define GET_SWITCH_DISPLAY(d) \
((SwitchDisplay *) (d)->privates[displayPrivateIndex].ptr)
#define SWITCH_DISPLAY(d) \
SwitchDisplay *sd = GET_SWITCH_DISPLAY (d)
#define GET_SWITCH_SCREEN(s, sd) \
((SwitchScreen *) (s)->privates[(sd)->screenPrivateIndex].ptr)
#define SWITCH_SCREEN(s) \
SwitchScreen *ss = GET_SWITCH_SCREEN (s, GET_SWITCH_DISPLAY (s->display))
#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
static Bool
switchSetScreenOption(CompScreen * screen,
char *name, CompOptionValue * value)
{
CompOption *o;
int index;
SWITCH_SCREEN(screen);
o = compFindOption(ss->opt, NUM_OPTIONS(ss), name, &index);
if (!o)
return FALSE;
switch (index)
{
case SWITCH_SCREEN_OPTION_SPEED:
if (compSetFloatOption(o, value))
{
ss->speed = o->value.f;
return TRUE;
}
break;
case SWITCH_SCREEN_OPTION_TIMESTEP:
if (compSetFloatOption(o, value))
{
ss->timestep = o->value.f;
return TRUE;
}
break;
case SWITCH_SCREEN_OPTION_WINDOW_TYPE:
if (compSetOptionList(o, value))
{
ss->wMask = compWindowTypeMaskFromStringList(&o->value);
return TRUE;
}
break;
case SWITCH_SCREEN_OPTION_MIPMAP:
case SWITCH_SCREEN_OPTION_ICON:
case SWITCH_SCREEN_OPTION_MINIMIZED:
case SWITCH_SCREEN_OPTION_SWITCH_FOCUS_INSTANTLY:
case SWITCH_SCREEN_OPTION_RING_TRANSPARENT_ALL :
if (compSetBoolOption(o, value))
return TRUE;
break;
case SWITCH_SCREEN_OPTION_SHOW_WINDOW_LIST:
if (compSetBoolOption(o, value))
{
ss->showWindowList = o->value.b;
return TRUE;
}
break;
case SWITCH_SCREEN_OPTION_AUTO_ROTATE:
if (compSetBoolOption(o, value))
{
ss->autoRotate = o->value.b;
return TRUE;
}
break;
case SWITCH_SCREEN_OPTION_TEMP_UNMINIMIZE:
if (compSetBoolOption(o, value))
{
ss->tempUnMinimize = o->value.b;
return TRUE;
}
break;
case SWITCH_SCREEN_OPTION_ICON_CORNER:
if (compSetStringOption(o, value))
{
int i;
ss->iconCorner = SWITCH_ICON_CORNER_DEFAULT;
for (i = 0; i < o->rest.s.nString; i++)
if (strcmp(iconCornerModes[i], o->value.s) == 0)
ss->iconCorner = (IconCornerMode) i;
return TRUE;
}
break;
case SWITCH_SCREEN_OPTION_SATURATION:
if (compSetIntOption(o, value))
{
ss->saturation = (COLOR * o->value.i) / 100;
return TRUE;
}
break;
case SWITCH_SCREEN_OPTION_BRIGHTNESS:
if (compSetIntOption(o, value))
{
ss->brightness = (0xffff * o->value.i) / 100;
return TRUE;
}
break;
case SWITCH_SCREEN_OPTION_OPACITY:
if (compSetIntOption(o, value))
{
ss->opacity = (OPAQUE * o->value.i) / 100;
return TRUE;
}
break;
case SWITCH_SCREEN_OPTION_BRINGTOFRONT:
if (compSetBoolOption(o, value))
{
ss->bringToFront = o->value.b;
return TRUE;
}
break;
case SWITCH_SCREEN_OPTION_ZOOM:
if (compSetFloatOption(o, value))
{
if (o->value.f < 0.05f)
{
ss->zooming = FALSE;
ss->zoom = 0.0f;
}
else
{
ss->zooming = TRUE;
ss->zoom = o->value.f / 30.0f;
}
return TRUE;
}
break;
case SWITCH_SCREEN_OPTION_ELLIPSE_WIDTH:
case SWITCH_SCREEN_OPTION_ELLIPSE_HEIGHT:
if(compSetFloatOption(o, value))
return TRUE;
break;
case SWITCH_SCREEN_OPTION_THUMBNAIL_WIDTH:
case SWITCH_SCREEN_OPTION_THUMBNAIL_HEIGHT:
if(compSetIntOption(o, value))
return TRUE;
break;
default:
break;
}
return FALSE;
}
static void switchScreenInitOptions(SwitchScreen * ss)
{
CompOption *o;
int i;
o = &ss->opt[SWITCH_SCREEN_OPTION_SHOW_WINDOW_LIST];
o->advanced = False;
o->name = "show_window_list";
o->group = N_("Misc. Options");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Show Window List");
o->longDesc = N_("Show the Window List box in center of the screen.");
o->type = CompOptionTypeBool;
o->value.b = SWITCH_SHOW_WINDOW_LIST_DEFAULT;
o = &ss->opt[SWITCH_SCREEN_OPTION_SPEED];
o->advanced = False;
o->name = "speed";
o->group = N_("Misc. Options");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Speed");
o->longDesc = N_("How fast the Switcher moves thumbnails.");
o->type = CompOptionTypeFloat;
o->value.f = SWITCH_SPEED_DEFAULT;
o->rest.f.min = SWITCH_SPEED_MIN;
o->rest.f.max = SWITCH_SPEED_MAX;
o->rest.f.precision = SWITCH_SPEED_PRECISION;
o = &ss->opt[SWITCH_SCREEN_OPTION_TIMESTEP];
o->advanced = False;
o->name = "timestep";
o->group = N_("Misc. Options");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Switcher Timestep");
o->longDesc = N_("Switcher Timestep.");
o->type = CompOptionTypeFloat;
o->value.f = SWITCH_TIMESTEP_DEFAULT;
o->rest.f.min = SWITCH_TIMESTEP_MIN;
o->rest.f.max = SWITCH_TIMESTEP_MAX;
o->rest.f.precision = SWITCH_TIMESTEP_PRECISION;
o = &ss->opt[SWITCH_SCREEN_OPTION_WINDOW_TYPE];
o->advanced = False;
o->name = "window_types";
o->group = N_("Behaviour");
o->subGroup = N_("Window handling");
o->displayHints = "";
o->shortDesc = N_("Window Types");
o->longDesc = N_("Window Types that should be shown in Switcher.");
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;
ss->wMask = compWindowTypeMaskFromStringList(&o->value);
o = &ss->opt[SWITCH_SCREEN_OPTION_MIPMAP];
o->advanced = False;
o->name = "mipmap";
o->group = N_("Appearance");
o->subGroup = N_("Quality Settings");
o->displayHints = "";
o->shortDesc = N_("Mipmap");
o->longDesc =
N_("Generate Mipmaps when possible for higher quality "
"Scaling.");
o->type = CompOptionTypeBool;
o->value.b = SWITCH_MIPMAP_DEFAULT;
o = &ss->opt[SWITCH_SCREEN_OPTION_SATURATION];
o->advanced = False;
o->name = "saturation";
o->group = N_("Appearance");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Saturation");
o->longDesc = N_("Saturation of unfocused windows in percent.");
o->type = CompOptionTypeInt;
o->value.i = SWITCH_SATURATION_DEFAULT;
o->rest.i.min = SWITCH_SATURATION_MIN;
o->rest.i.max = SWITCH_SATURATION_MAX;
o = &ss->opt[SWITCH_SCREEN_OPTION_BRIGHTNESS];
o->advanced = False;
o->name = "brightness";
o->group = N_("Appearance");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Brightness");
o->longDesc = N_("Brightness of the background desktop in percent.");
o->type = CompOptionTypeInt;
o->value.i = SWITCH_BRIGHTNESS_DEFAULT;
o->rest.i.min = SWITCH_BRIGHTNESS_MIN;
o->rest.i.max = SWITCH_BRIGHTNESS_MAX;
o = &ss->opt[SWITCH_SCREEN_OPTION_OPACITY];
o->advanced = False;
o->name = "opacity";
o->group = N_("Appearance");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Opacity");
o->longDesc = N_("Opacity of unfocused windows in percent.");
o->type = CompOptionTypeInt;
o->value.i = SWITCH_OPACITY_DEFAULT;
o->rest.i.min = SWITCH_OPACITY_MIN;
o->rest.i.max = SWITCH_OPACITY_MAX;
o = &ss->opt[SWITCH_SCREEN_OPTION_BRINGTOFRONT];
o->advanced = False;
o->name = "bring_to_front";
o->group = N_("Behaviour");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Bring To Front");
o->longDesc = N_("Bring selected window to Front.");
o->type = CompOptionTypeBool;
o->value.b = SWITCH_BRINGTOFRONT_DEFAULT;
o = &ss->opt[SWITCH_SCREEN_OPTION_ICON_CORNER];
o->advanced = False;
o->name = "icon_corner_mode";
o->group = N_("Appearance");
o->subGroup = N_("Icon Options");
o->displayHints = "";
o->shortDesc = N_("Icon Corner");
o->longDesc = N_("Icon Placement.");
o->type = CompOptionTypeString;
o->value.s = strdup(iconCornerModes[SWITCH_ICON_CORNER_DEFAULT]);
o->rest.s.string = iconCornerModes;
o->rest.s.nString = N_ICON_CORNER_MODES;
o = &ss->opt[SWITCH_SCREEN_OPTION_ZOOM];
o->advanced = False;
o->name = "zoom";
o->group = N_("Behaviour");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Zoom");
o->longDesc = N_("Distance desktop should be Zoom out while "
"Switching windows.");
o->type = CompOptionTypeFloat;
o->value.f = SWITCH_ZOOM_DEFAULT;
o->rest.f.min = SWITCH_ZOOM_MIN;
o->rest.f.max = SWITCH_ZOOM_MAX;
o->rest.f.precision = SWITCH_ZOOM_PRECISION;
o = &ss->opt[SWITCH_SCREEN_OPTION_ICON];
o->advanced = False;
o->name = "icon";
o->group = N_("Appearance");
o->subGroup = N_("Icon Options");
o->displayHints = "";
o->shortDesc = N_("Icon");
o->longDesc = N_("Show Icon next to thumbnail.");
o->type = CompOptionTypeBool;
o->value.b = SWITCH_ICON_DEFAULT;
o = &ss->opt[SWITCH_SCREEN_OPTION_MINIMIZED];
o->advanced = False;
o->name = "minimized";
o->group = N_("Behaviour");
o->subGroup = N_("Window handling");
o->displayHints = "";
o->shortDesc = N_("Show Minimized");
o->longDesc = N_("Show Minimized windows.");
o->type = CompOptionTypeBool;
o->value.b = SWITCH_MINIMIZED_DEFAULT;
o = &ss->opt[SWITCH_SCREEN_OPTION_AUTO_ROTATE];
o->advanced = False;
o->name = "auto_rotate";
o->group = N_("Behaviour");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Auto Rotate");
o->longDesc = N_("Rotate to active window Automatically.");
o->type = CompOptionTypeBool;
o->value.b = SWITCH_AUTO_ROTATE_DEFAULT;
o = &ss->opt[SWITCH_SCREEN_OPTION_TEMP_UNMINIMIZE];
o->advanced = False;
o->name = "temp_unminimize";
o->group = N_("Behaviour");
o->subGroup = N_("Window handling");
o->displayHints = "";
o->shortDesc = N_("Temp UnMinimize");
o->longDesc = N_("Temporarily Un-Minimize minimized windows.");
o->type = CompOptionTypeBool;
o->value.b = SWITCH_TEMP_UNMINIMIZE_DEFAULT;
o = &ss->opt[SWITCH_SCREEN_OPTION_SWITCH_FOCUS_INSTANTLY];
o->advanced = False;
o->name = "switch_focus_instantly";
o->group = N_("Behaviour");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Switch Focus Instantly");
o->longDesc = N_("If enabled, the Focus is Switched to the window immediately"
"on activation; otherwise on Application Switcher termination.");
o->type = CompOptionTypeBool;
o->value.b = SWITCH_SWITCH_FOCUS_INSTANTLY_DEFAULT;
o = &ss->opt[SWITCH_SCREEN_OPTION_ELLIPSE_WIDTH];
o->advanced = False;
o->name = "ellipse_width";
o->group = N_("Appearance");
o->subGroup = N_("Rotating List");
o->displayHints = "";
o->shortDesc = N_("Ellipse Width");
o->longDesc = N_("Changes the proportions of the circle (1.0 means "
"the width is 100% of the screen width).");
o->type = CompOptionTypeFloat;
o->value.f = SWITCH_ELLIPSE_WIDTH_DEFAULT;
o->rest.f.min = SWITCH_ELLIPSE_WIDTH_MIN;
o->rest.f.max = SWITCH_ELLIPSE_WIDTH_MAX;
o->rest.f.precision = SWITCH_ELLIPSE_PRECISION;
o = &ss->opt[SWITCH_SCREEN_OPTION_ELLIPSE_HEIGHT];
o->advanced = False;
o->name = "ellipse_height";
o->group = N_("Appearance");
o->subGroup = N_("Rotating List");
o->displayHints = "";
o->shortDesc = N_("Ellipse Height");
o->longDesc = N_("Changes the proportions of the circle (1.0 means "
"the height is 100% of the screen height).");
o->type = CompOptionTypeFloat;
o->value.f = SWITCH_ELLIPSE_HEIGHT_DEFAULT;
o->rest.f.min = SWITCH_ELLIPSE_HEIGHT_MIN;
o->rest.f.max = SWITCH_ELLIPSE_HEIGHT_MAX;
o->rest.f.precision = SWITCH_ELLIPSE_PRECISION;
o = &ss->opt[SWITCH_SCREEN_OPTION_THUMBNAIL_WIDTH];
o->advanced = False;
o->name = "thumbnail_width";
o->group = N_("Appearance");
o->subGroup = N_("Rotating List");
o->displayHints = "";
o->shortDesc = N_("Thumbnail Width");
o->longDesc = N_("Changes the horizontal size of the unscaled Thumbnail.");
o->type = CompOptionTypeInt;
o->value.i = SWITCH_THUMBNAIL_WIDTH_DEFAULT;
o->rest.i.min = SWITCH_THUMBNAIL_WIDTH_MIN;
o->rest.i.max = SWITCH_THUMBNAIL_WIDTH_MAX;
o = &ss->opt[SWITCH_SCREEN_OPTION_THUMBNAIL_HEIGHT];
o->advanced = False;
o->name = "thumbnail_height";
o->group = N_("Appearance");
o->subGroup = N_("Rotating List");
o->displayHints = "";
o->shortDesc = N_("Thumbnail Height");
o->longDesc = N_("Changes the vertical size of the unscaled Thumbnail.");
o->type = CompOptionTypeInt;
o->value.i = SWITCH_THUMBNAIL_HEIGHT_DEFAULT;
o->rest.i.min = SWITCH_THUMBNAIL_HEIGHT_MIN;
o->rest.i.max = SWITCH_THUMBNAIL_HEIGHT_MAX;
o = &ss->opt[SWITCH_SCREEN_OPTION_RING_TRANSPARENT_ALL];
o->advanced = False;
o->name = "ring_transparent_all";
o->group = N_("Appearance");
o->subGroup = N_("Rotating List");
o->displayHints = "";
o->shortDesc = N_("Fade windows out when using Ring Switcher");
o->longDesc = N_("When using ring switcher mode fade actual windows out");
o->type = CompOptionTypeBool;
o->value.b = SWITCH_RING_ALL_TRANSPARENT_DEFAULT;
}
static CompOption *switchGetScreenOptions(CompScreen * screen, int *count)
{
if (screen)
{
SWITCH_SCREEN(screen);
*count = NUM_OPTIONS(ss);
return ss->opt;
}
else
{
SwitchScreen *ss = malloc(sizeof(SwitchScreen));
switchScreenInitOptions(ss);
*count = NUM_OPTIONS(ss);
return ss->opt;
}
}
static void setSelectedWindowHint(CompScreen * s)
{
SWITCH_DISPLAY(s->display);
SWITCH_SCREEN(s);
/* if we don't set this property, the switcher window won't be
decorated by the DM - exactly what we want for the ring switcher */
if (ss->switchMode == ApplicationSwitcher)
{
XChangeProperty(s->display->display, ss->popupWindow,
sd->selectWinAtom, XA_WINDOW, 32, PropModeReplace,
(unsigned char *)&ss->selectedWindow, 1);
}
else
{
XDeleteProperty(s->display->display, ss->popupWindow,
sd->selectWinAtom);
}
}
static Bool isSwitchWin(CompWindow * w)
{
SWITCH_SCREEN(w->screen);
if (w->state & CompWindowStateOffscreenMask)
return FALSE;
if (!w->mapNum || w->attrib.map_state != IsViewable)
{
if (ss->opt[SWITCH_SCREEN_OPTION_MINIMIZED].value.b)
{
if (!((w->minimized || w->inShowDesktopMode)
&& (w->state & CompWindowStateHiddenMask)) && !w->shaded)
return FALSE;
}
else
{
return FALSE;
}
}
if (w->attrib.override_redirect)
return FALSE;
if (!(ss->wMask & w->type))
return FALSE;
if (w->wmType & (CompWindowTypeDockMask | CompWindowTypeDesktopMask))
return FALSE;
if (w->state & CompWindowStateSkipTaskbarMask)
return FALSE;
if (!ss->allWindows)
{
if (!w->mapNum || w->attrib.map_state != IsViewable)
{
if (w->serverX + w->width <= 0 ||
w->serverY + w->height <= 0 ||
w->serverX >= w->screen->width ||
w->serverY >= w->screen->height)
return FALSE;
}
else
{
if (!(*w->screen->focusWindow) (w))
return FALSE;
}
}
return TRUE;
}
static int compareWindows(const void *elem1, const void *elem2)
{
CompWindow *w1 = *((CompWindow **) elem1);
CompWindow *w2 = *((CompWindow **) elem2);
if (w1->mapNum && !w2->mapNum)
return -1;
if (w2->mapNum && !w1->mapNum)
return 1;
return w2->activeNum - w1->activeNum;
}
static void switchAddWindowToList(CompScreen * s, CompWindow * w)
{
SWITCH_SCREEN(s);
if (ss->windowsSize <= ss->nWindows)
{
ss->windows = realloc(ss->windows,
sizeof(CompWindow *) * (ss->nWindows + 32));
if (!ss->windows)
return;
ss->windowsSize = ss->nWindows + 32;
}
ss->windows[ss->nWindows++] = w;
}
static void switchUpdateWindowList(CompScreen * s, int count)
{
SWITCH_SCREEN(s);
if (count > 1)
{
count -= (count + 1) & 1;
if (count < 3)
count = 3;
}
if (ss->switchMode == RingSwitcher)
{
XRectangle outputRect;
screenGetOutputDevRect(s, ss->head, &outputRect);
ELLIPSE_ROTA(outputRect);
ss->pos = ellipse_a;
}
else
{
ss->pos = ((count >> 1) - ss->nWindows) * WIDTH;
}
ss->move = 0;
ss->selectedWindow = ss->windows[0]->id;
if (ss->popupWindow)
{
XRectangle outputRect;
screenGetOutputDevRect(s, ss->head, &outputRect);
XMoveResizeWindow(s->display->display, ss->popupWindow,
outputRect.x + outputRect.width / 2 - WINDOW_WIDTH(count) / 2,
outputRect.y + outputRect.height / 2 - WINDOW_HEIGHT / 2,
WINDOW_WIDTH(count), WINDOW_HEIGHT);
}
}
static void switchCreateWindowList(CompScreen * s, int count)
{
CompWindow *w;
SWITCH_SCREEN(s);
ss->nWindows = 0;
for (w = s->windows; w; w = w->next)
{
if (isSwitchWin(w))
switchAddWindowToList(s, w);
}
qsort(ss->windows, ss->nWindows, sizeof(CompWindow *), compareWindows);
if ((ss->switchMode == ApplicationSwitcher) && (ss->nWindows == 2))
{
switchAddWindowToList(s, ss->windows[0]);
switchAddWindowToList(s, ss->windows[1]);
}
switchUpdateWindowList(s, count);
}
static void switchToWindow(CompScreen * s, Bool toNext)
{
CompWindow *w;
int cur;
SWITCH_SCREEN(s);
if (!ss->grabIndex)
return;
for (cur = 0; cur < ss->nWindows; cur++)
{
if (ss->windows[cur]->id == ss->selectedWindow)
break;
}
if (cur == ss->nWindows)
return;
if (toNext)
w = ss->windows[(cur + 1) % ss->nWindows];
else
w = ss->windows[(cur + ss->nWindows - 1) % ss->nWindows];
if (w)
{
Window old = ss->selectedWindow;
ss->lastActiveNum = w->activeNum;
ss->selectedWindow = w->id;
if (!ss->zoomedWindow)
ss->zoomedWindow = ss->selectedWindow;
if (old != w->id)
{
if (toNext)
{
if (ss->switchMode == RingSwitcher)
{
XRectangle outputRect;
screenGetOutputDevRect(s, ss->head, &outputRect);
ELLIPSE_ROTA(outputRect);
DIST_ROT;
ss->move -= dist;
}
else
{
ss->move -= WIDTH;
}
}
else
{
if (ss->switchMode == RingSwitcher)
{
XRectangle outputRect;
screenGetOutputDevRect(s, ss->head, &outputRect);
ELLIPSE_ROTA(outputRect);
DIST_ROT;
ss->move += dist;
}
else
{
ss->move += WIDTH;
}
}
ss->moreAdjust = 1;
}
if (ss->popupWindow)
{
CompWindow *popup;
popup = findWindowAtScreen(s, ss->popupWindow);
if (popup)
addWindowDamage(popup);
setSelectedWindowHint(s);
}
if (ss->tempUnMinimize)
{
if (ss->prevMin != NULL)
{
minimizeWindow(ss->prevMin);
ss->prevMin = NULL;
}
if (w->minimized)
ss->prevMin = w;
}
if (ss->autoRotate)
changeToWindowViewport(s, ss->selectedWindow, w);
if (ss->tempUnMinimize && w->minimized)
unminimizeWindow(w);
if (ss->opt[SWITCH_SCREEN_OPTION_SWITCH_FOCUS_INSTANTLY].value.b)
sendWindowActivationRequest(w->screen, w->id);
addWindowDamage(w);
if ((w = findWindowAtScreen(s, old)))
{
addWindowDamage(w);
}
}
}
static int switchCountWindows(CompScreen * s)
{
CompWindow *w;
int count = 0;
XRectangle outputRect;
// SWITCH_SCREEN(s);
for (w = s->windows; w && count < 5; w = w->next)
if (isSwitchWin(w))
count++;
int head = screenGetCurrentOutputDev(s);
screenGetOutputDevRect(s, head, &outputRect);
if (count == 5 && outputRect.width <= WINDOW_WIDTH(5))
count = 3;
return count;
}
static Visual *findArgbVisual(Display * dpy, int scr)
{
XVisualInfo *xvi;
XVisualInfo template;
int nvi;
int i;
XRenderPictFormat *format;
Visual *visual;
template.screen = scr;
template.depth = 32;
template.class = TrueColor;
xvi = XGetVisualInfo(dpy,
VisualScreenMask |
VisualDepthMask | VisualClassMask, &template, &nvi);
if (!xvi)
return 0;
visual = 0;
for (i = 0; i < nvi; i++)
{
format = XRenderFindVisualFormat(dpy, xvi[i].visual);
if (format->type == PictTypeDirect && format->direct.alphaMask)
{
visual = xvi[i].visual;
break;
}
}
XFree(xvi);
return visual;
}
static void switchUpdatePopupWindow(CompScreen *s, int head,
int count, SwitcherMode switchMode)
{
SWITCH_SCREEN(s);
Display *dpy = s->display->display;
if ((switchMode != ss->switchMode) && ss->popupWindow)
{
XDestroyWindow(s->display->display, ss->popupWindow);
ss->popupWindow = None;
}
if ((!ss->popupWindow && ss->showWindowList) || head != ss->head)
{
XRectangle outputRect;
XSizeHints xsh;
XWMHints xwmh;
XSetWindowAttributes attr;
Visual *visual;
Atom mwmHintsAtom;
MwmHints mwmHints;
Atom type;
Atom state[5];
int nState = 0;
visual = findArgbVisual(dpy, s->screenNum);
if (!visual)
return;
if (count > 1)
{
count -= (count + 1) & 1;
if (count < 3)
count = 3;
}
xsh.flags = PSize | PPosition;
xsh.width = WINDOW_WIDTH(count);
xsh.height = WINDOW_HEIGHT;
xwmh.flags = InputHint;
xwmh.input = 0;
attr.background_pixel = 0;
attr.border_pixel = 0;
attr.colormap = XCreateColormap(dpy, s->root, visual, AllocNone);
if (ss->showWindowList)
{
if (ss->popupWindow)
{
XDestroyWindow(s->display->display, ss->popupWindow);
ss->popupWindow = None;
}
screenGetOutputDevRect(s, head, &outputRect);
ss->popupWindow =
XCreateWindow(dpy, s->root,
outputRect.x + outputRect.width / 2 - xsh.width / 2,
outputRect.y + outputRect.height / 2 - xsh.height / 2,
xsh.width, xsh.height, 0, 32, InputOutput, visual,
CWBackPixel | CWBorderPixel | CWColormap, &attr);
XSetWMProperties(dpy, ss->popupWindow, NULL, NULL,
getProgramArgv(),
getProgramArgc(), &xsh, &xwmh, NULL);
mwmHintsAtom = XInternAtom(dpy, "_MOTIF_WM_HINTS", 0);
memset(&mwmHints, 0, sizeof(mwmHints));
mwmHints.flags = MwmHintsDecorations;
mwmHints.decorations = 0;
XChangeProperty(dpy, ss->popupWindow, mwmHintsAtom,
mwmHintsAtom, 8, PropModeReplace,
(unsigned char *)&mwmHints, sizeof(mwmHints));
type = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_SPLASH", 0);
XChangeProperty(dpy, ss->popupWindow,
XInternAtom(dpy,
"_NET_WM_WINDOW_TYPE",
0), XA_ATOM, 32,
PropModeReplace, (unsigned char *)&type, 1);
setWindowProp(s->display, ss->popupWindow,
s->display->winDesktopAtom, 0xffffffff);
state[nState++] = s->display->winStateAboveAtom;
state[nState++] = s->display->winStateStickyAtom;
state[nState++] = s->display->winStateSkipTaskbarAtom;
state[nState++] = s->display->winStateSkipPagerAtom;
if (switchMode == RingSwitcher)
state[nState++] = s->display->winStateFullscreenAtom;
XChangeProperty(dpy, ss->popupWindow,
XInternAtom(dpy, "_NET_WM_STATE", 0), XA_ATOM, 32,
PropModeReplace, (unsigned char *)state, nState);
}
}
}
static void switchInitiate(CompScreen * s, Bool allWindows, SwitcherMode switchMode)
{
int count;
SWITCH_SCREEN(s);
if (otherScreenGrabExist(s, "scale", "cube", 0))
return;
ss->allWindows = allWindows;
count = switchCountWindows(s);
if (count < 1)
return;
int head = screenGetCurrentOutputDev(s);
switchUpdatePopupWindow(s, head, count, switchMode);
ss->switchMode = switchMode;
ss->head = head;
if (!ss->showWindowList && ss->popupWindow)
{
XUnmapWindow(s->display->display, ss->popupWindow);
}
if (!ss->grabIndex)
ss->grabIndex = pushScreenGrab(s, s->invisibleCursor, "switcher");
if (ss->grabIndex)
{
if (!ss->switching)
{
ss->lastActiveNum = s->activeNum;
switchCreateWindowList(s, count);
ss->sTranslate = ss->zoom;
if (ss->showWindowList && ss->popupWindow)
{
CompWindow *w;
w = findWindowAtScreen(s, ss->popupWindow);
if (w && (w->state & CompWindowStateHiddenMask))
{
w->hidden = FALSE;
showWindow(w);
}
else
{
XMapWindow(s->display->display, ss->popupWindow);
}
setSelectedWindowHint(s);
}
}
damageScreen(s);
ss->switching = TRUE;
ss->moreAdjust = 1;
}
}
static Bool
switchTerminate(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
CompScreen *s;
Window xid;
xid = getIntOptionNamed(option, nOption, "root", 0);
for (s = d->screens; s; s = s->next)
{
SWITCH_SCREEN(s);
if (xid && s->root != xid)
continue;
if (ss->tempUnMinimize)
ss->prevMin = NULL;
if (ss->grabIndex)
{
CompWindow *w;
if (ss->popupWindow)
{
w = findWindowAtScreen(s, ss->popupWindow);
if (w && w->managed && w->mapNum)
{
w->hidden = TRUE;
hideWindow(w);
}
else
{
XUnmapWindow(s->display->display, ss->popupWindow);
}
}
ss->switching = FALSE;
if (!ss->opt[SWITCH_SCREEN_OPTION_SWITCH_FOCUS_INSTANTLY].value.b)
{
if (state && ss->selectedWindow)
{
w = findWindowAtScreen(s, ss->selectedWindow);
if (w)
sendWindowActivationRequest(w->screen, w->id);
}
}
removeScreenGrab(s, ss->grabIndex, 0);
ss->grabIndex = 0;
if (!ss->zooming)
{
ss->selectedWindow = None;
ss->zoomedWindow = None;
}
else
{
ss->moreAdjust = 1;
}
ss->lastActiveNum = 0;
damageScreen(s);
}
}
if (action)
action->state &=
~(CompActionStateTermKey | CompActionStateTermButton);
return FALSE;
}
static Bool
switchDoSwitch(CompDisplay * d, CompAction * action, CompActionState state,
CompOption * option, int nOption, Bool next, Bool allWindows, SwitcherMode switchMode)
{
CompScreen *s;
Window xid;
xid = getIntOptionNamed(option, nOption, "root", 0);
s = findScreenAtDisplay(d, xid);
if (s)
{
SWITCH_SCREEN(s);
if (!ss->switching)
{
switchInitiate(s, allWindows, switchMode);
if (state & CompActionStateInitKey)
action->state |= CompActionStateTermKey;
if (state & CompActionStateInitButton)
action->state |= CompActionStateTermButton;
}
switchToWindow(s, next);
}
return FALSE;
}
static Bool
switchNext(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
return switchDoSwitch(d, action, state, option, nOption, TRUE, FALSE, ApplicationSwitcher);
}
static Bool
switchPrev(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
return switchDoSwitch(d, action, state, option, nOption, FALSE, FALSE, ApplicationSwitcher);
}
static Bool
switchNextAll(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
return switchDoSwitch(d, action, state, option, nOption, TRUE, TRUE, ApplicationSwitcher);
}
static Bool
switchPrevAll(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
return switchDoSwitch(d, action, state, option, nOption, FALSE, TRUE, ApplicationSwitcher);
}
static Bool
switchNextRing(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
return switchDoSwitch(d, action, state, option, nOption, TRUE, FALSE, RingSwitcher);
}
static Bool
switchPrevRing(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
return switchDoSwitch(d, action, state, option, nOption, FALSE, FALSE, RingSwitcher);
}
static Bool
switchNextAllRing(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
return switchDoSwitch(d, action, state, option, nOption, TRUE, TRUE, RingSwitcher);
}
static Bool
switchPrevAllRing(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
return switchDoSwitch(d, action, state, option, nOption, FALSE, TRUE, RingSwitcher);
}
static void switchWindowRemove(CompDisplay * d, Window id)
{
CompWindow *w;
w = findWindowAtDisplay(d, id);
if (w)
{
Bool inList = FALSE;
int count, j, i = 0;
Window selected, old;
SWITCH_SCREEN(w->screen);
if (isSwitchWin(w))
return;
old = selected = ss->selectedWindow;
while (i < ss->nWindows)
{
if (ss->windows[i] == w)
{
inList = TRUE;
if (w->id == selected)
{
if (i < ss->nWindows)
selected = ss->windows[i + 1]->id;
else
selected = ss->windows[0]->id;
}
ss->nWindows--;
for (j = i; j < ss->nWindows; j++)
ss->windows[j] = ss->windows[j + 1];
}
else
{
i++;
}
}
if (!inList)
return;
count = ss->nWindows;
if (ss->nWindows == 2)
{
if (ss->windows[0] == ss->windows[1])
{
ss->nWindows--;
count = 1;
}
else
{
switchAddWindowToList(w->screen, ss->windows[0]);
switchAddWindowToList(w->screen, ss->windows[1]);
}
}
if (ss->nWindows == 0)
{
CompOption o;
o.type = CompOptionTypeInt;
o.name = "root";
o.value.i = w->screen->root;
switchTerminate(d, NULL, 0, &o, 1);
return;
}
if (!ss->grabIndex)
return;
switchUpdateWindowList(w->screen, count);
for (i = 0; i < ss->nWindows; i++)
{
ss->selectedWindow = ss->windows[i]->id;
if (ss->selectedWindow == selected)
break;
ss->pos -= WIDTH;
if (ss->pos < -ss->nWindows * WIDTH)
ss->pos += ss->nWindows * WIDTH;
}
if (ss->popupWindow)
{
CompWindow *popup;
popup = findWindowAtScreen(w->screen, ss->popupWindow);
if (popup)
addWindowDamage(popup);
setSelectedWindowHint(w->screen);
}
if (old != ss->selectedWindow)
{
addWindowDamage(w);
w = findWindowAtScreen(w->screen, old);
if (w)
addWindowDamage(w);
ss->moreAdjust = 1;
}
}
}
static void switchHandleEvent(CompDisplay * d, XEvent * event)
{
SWITCH_DISPLAY(d);
UNWRAP(sd, d, handleEvent);
(*d->handleEvent) (d, event);
WRAP(sd, d, handleEvent, switchHandleEvent);
switch (event->type)
{
case UnmapNotify:
switchWindowRemove(d, event->xunmap.window);
break;
case DestroyNotify:
switchWindowRemove(d, event->xdestroywindow.window);
default:
break;
}
}
static int adjustSwitchVelocity(CompScreen * s)
{
float dx, adjust, amount;
SWITCH_SCREEN(s);
dx = ss->move;
adjust = dx * 0.15f;
amount = fabs(dx) * 1.5f;
if (amount < 0.2f)
amount = 0.2f;
else if (amount > 2.0f)
amount = 2.0f;
ss->mVelocity = (amount * ss->mVelocity + adjust) / (amount + 1.0f);
if (ss->zooming)
{
float dt, ds;
if (ss->switching)
dt = ss->zoom - ss->translate;
else
dt = 0.0f - ss->translate;
adjust = dt * 0.15f;
amount = fabs(dt) * 1.5f;
if (amount < 0.2f)
amount = 0.2f;
else if (amount > 2.0f)
amount = 2.0f;
ss->tVelocity = (amount * ss->tVelocity + adjust) / (amount + 1.0f);
if (ss->selectedWindow == ss->zoomedWindow)
ds = ss->zoom - ss->sTranslate;
else
ds = 0.0f - ss->sTranslate;
adjust = ds * 0.5f;
amount = fabs(ds) * 5.0f;
if (amount < 1.0f)
amount = 1.0f;
else if (amount > 6.0f)
amount = 6.0f;
ss->sVelocity = (amount * ss->sVelocity + adjust) / (amount + 1.0f);
if (ss->selectedWindow == ss->zoomedWindow)
{
if (fabs(dx) < 0.1f && fabs(ss->mVelocity) < 0.2f
&& fabs(dt) < 0.002f
&& fabs(ss->tVelocity) < 0.002f
&& fabs(ds) < 0.002f && fabs(ss->sVelocity) < 0.002f)
{
ss->mVelocity = ss->tVelocity = ss->sVelocity = 0.0f;
return 0;
}
}
}
else
{
if (fabs(dx) < 0.1f && fabs(ss->mVelocity) < 0.2f)
{
ss->mVelocity = 0.0f;
return 0;
}
}
return 1;
}
static void switchPreparePaintScreen(CompScreen * s, int msSinceLastPaint)
{
SWITCH_SCREEN(s);
if (ss->moreAdjust)
{
int steps, m;
float amount, chunk;
amount = msSinceLastPaint * 0.05f * ss->speed;
steps = amount / (0.5f * ss->timestep);
if (!steps)
steps = 1;
chunk = amount / (float)steps;
while (steps--)
{
ss->moreAdjust = adjustSwitchVelocity(s);
if (!ss->moreAdjust)
{
ss->pos += ss->move;
ss->move = 0;
if (ss->zooming)
{
if (ss->switching)
{
ss->translate = ss->zoom;
ss->sTranslate = ss->zoom;
}
else
{
ss->translate = 0.0f;
ss->sTranslate = ss->zoom;
ss->selectedWindow = None;
ss->zoomedWindow = None;
if (ss->grabIndex)
{
removeScreenGrab(s, ss->grabIndex, 0);
ss->grabIndex = 0;
}
}
}
break;
}
m = ss->mVelocity * chunk;
if (!m)
{
if (ss->mVelocity)
m = (ss->move > 0) ? 1 : -1;
}
ss->move -= m;
ss->pos += m;
if (ss->switchMode == ApplicationSwitcher)
{
if (ss->pos < -ss->nWindows * WIDTH)
ss->pos += ss->nWindows * WIDTH;
else if (ss->pos > 0)
ss->pos -= ss->nWindows * WIDTH;
}
ss->translate += ss->tVelocity * chunk;
ss->sTranslate += ss->sVelocity * chunk;
if (ss->selectedWindow != ss->zoomedWindow)
{
if (ss->sTranslate < 0.01f)
ss->zoomedWindow = ss->selectedWindow;
}
}
}
UNWRAP(ss, s, preparePaintScreen);
(*s->preparePaintScreen) (s, msSinceLastPaint);
WRAP(ss, s, preparePaintScreen, switchPreparePaintScreen);
}
static Bool
switchPaintScreen(CompScreen * s,
const ScreenPaintAttrib * sAttrib,
Region region, int output, unsigned int mask)
{
Bool status;
SWITCH_SCREEN(s);
if (ss->grabIndex || (ss->zooming && ss->translate > 0.001f))
{
ScreenPaintAttrib sa = *sAttrib;
CompWindow *zoomed;
CompWindow *switcher;
Window zoomedAbove = None;
Bool saveDestroyed = FALSE;
if (ss->zooming || (ss->switchMode == RingSwitcher))
{
mask &= ~PAINT_SCREEN_REGION_MASK;
mask |= PAINT_SCREEN_TRANSFORMED_MASK | PAINT_SCREEN_CLEAR_MASK;
sa.zCamera -= ss->translate;
}
switcher = findWindowAtScreen(s, ss->popupWindow);
if (switcher)
{
saveDestroyed = switcher->destroyed;
switcher->destroyed = TRUE;
}
if (ss->bringToFront)
{
zoomed = findWindowAtScreen(s, ss->zoomedWindow);
if (zoomed)
{
CompWindow *w;
for (w = zoomed->prev; w && w->id <= 1; w = w->prev);
zoomedAbove = (w) ? w->id : None;
unhookWindowFromScreen(s, zoomed);
insertWindowIntoScreen(s, zoomed, s->reverseWindows->id);
}
}
else
{
zoomed = NULL;
}
UNWRAP(ss, s, paintScreen);
status = (*s->paintScreen) (s, &sa, region, output, mask);
WRAP(ss, s, paintScreen, switchPaintScreen);
if (zoomed)
{
unhookWindowFromScreen(s, zoomed);
insertWindowIntoScreen(s, zoomed, zoomedAbove);
}
if (switcher)
{
switcher->destroyed = saveDestroyed;
glPushMatrix();
prepareXCoords(s, output, -DEFAULT_Z_CAMERA);
if (!switcher->destroyed &&
switcher->attrib.map_state == IsViewable && switcher->damaged)
{
(*s->paintWindow) (switcher,
&switcher->paint, getInfiniteRegion(), 0);
}
glPopMatrix();
}
}
else
{
UNWRAP(ss, s, paintScreen);
status = (*s->paintScreen) (s, sAttrib, region, output, mask);
WRAP(ss, s, paintScreen, switchPaintScreen);
}
return status;
}
static void switchDonePaintScreen(CompScreen * s)
{
SWITCH_SCREEN(s);
if ((ss->grabIndex || ss->zooming) && ss->moreAdjust)
{
if (ss->zooming || (ss->switchMode == RingSwitcher))
{
damageScreen(s);
}
else
{
CompWindow *w;
w = findWindowAtScreen(s, ss->popupWindow);
if (w)
addWindowDamage(w);
}
}
UNWRAP(ss, s, donePaintScreen);
(*s->donePaintScreen) (s);
WRAP(ss, s, donePaintScreen, switchDonePaintScreen);
}
static void
switchPaintThumb(CompWindow * w,
const WindowPaintAttrib * attrib,
unsigned int mask, int x, int y, int x1, int x2, float scale)
{
DrawWindowGeometryProc oldDrawWindowGeometry;
AddWindowGeometryProc oldAddWindowGeometry;
WindowPaintAttrib sAttrib = *attrib;
int wx, wy;
float width, height;
CompIcon *icon = NULL;
SWITCH_SCREEN(w->screen);
/* Wrap drawWindowGeometry to make sure the general
drawWindowGeometry function is used */
oldDrawWindowGeometry = w->screen->drawWindowGeometry;
w->screen->drawWindowGeometry = getBaseDrawWindowGeometry();
oldAddWindowGeometry = w->screen->addWindowGeometry;
w->screen->addWindowGeometry = getBaseAddWindowGeometry();
mask |= PAINT_WINDOW_TRANSFORMED_MASK;
if (w->mapNum || w->thumbPixmap)
{
int ww, wh;
if (ss->switchMode == RingSwitcher)
{
width = ss->opt[SWITCH_SCREEN_OPTION_THUMBNAIL_WIDTH].value.i;
height = ss->opt[SWITCH_SCREEN_OPTION_THUMBNAIL_HEIGHT].value.i;
}
else
{
width = WIDTH - (SPACE << 1);
height = HEIGHT - (SPACE << 1);
}
ww = w->width + w->input.left + w->input.right;
wh = w->height + w->input.top + w->input.bottom;
if (ww > width)
sAttrib.xScale = width / ww;
else
sAttrib.xScale = 1.0f;
if (wh > height)
sAttrib.yScale = height / wh;
else
sAttrib.yScale = 1.0f;
if (sAttrib.xScale < sAttrib.yScale)
sAttrib.yScale = sAttrib.xScale;
else
sAttrib.xScale = sAttrib.yScale;
width = ww * sAttrib.xScale;
height = wh * sAttrib.yScale;
if (ss->switchMode == RingSwitcher)
{
sAttrib.xScale *= scale;
sAttrib.yScale *= scale;
x -= ((w->width * sAttrib.xScale) / 2.0f);
wx = x;
wy = y;
}
else
{
wx = x + SPACE + ((WIDTH - (SPACE << 1)) - width) / 2;
wy = y + SPACE + ((HEIGHT - (SPACE << 1)) - height) / 2;
}
sAttrib.xTranslate =
wx - w->attrib.x + w->input.left * sAttrib.xScale;
sAttrib.yTranslate = wy - w->attrib.y + w->input.top * sAttrib.yScale;
(w->screen->drawWindow) (w, &sAttrib, getInfiniteRegion(), mask);
if (ss->opt[SWITCH_SCREEN_OPTION_ICON].value.b)
{
icon = getWindowIcon(w, 96, 96);
if (!icon)
icon = getWindowIcon(w, 128, 128);
if (!icon)
icon = getWindowIcon(w, 256, 256);
if (!icon)
icon = getWindowIcon(w, 512, 512);
if (icon)
{
if (icon->width > 96)
{
sAttrib.xScale = sAttrib.yScale =
MIN((48.0f /
(float)icon->width),
(48.0f / (float)icon->height));
}
else
sAttrib.xScale = sAttrib.yScale = 1.0f * scale;
float wwidth, wspace, iwidth;
float wheight, iheight;
if (ss->switchMode == RingSwitcher)
{
wwidth = width * scale;
wheight = height * scale;
wspace = 0;
iwidth = icon->width * scale;
iheight = icon->height * scale;
}
else
{
wx = x + WIDTH - icon->width * sAttrib.xScale - SPACE;
wwidth = WIDTH;
wheight = HEIGHT;
wspace = SPACE;
iwidth = icon->width;
iheight = icon->height;
}
switch(ss->iconCorner)
{
case BottomRight:
wx = x + (wwidth - wspace) - iwidth;
wy = y + (wheight - wspace) - iheight;
break;
case BottomLeft:
wx = x + wspace;
wy = y + (wheight - wspace) - iheight;
break;
case TopRight:
wx = x + (wwidth - wspace) - iwidth;
wy = y + wspace;
break;
case TopLeft:
wx = x + wspace;
wy = y + wspace;
break;
case Center:
wx = x + (wwidth / 2) - (iwidth / 2);
wy = y + (wheight / 2) - (iheight / 2);
break;
}
}
}
}
else
{
if (ss->switchMode == RingSwitcher)
{
width = ss->opt[SWITCH_SCREEN_OPTION_THUMBNAIL_WIDTH].value.i;
height = ss->opt[SWITCH_SCREEN_OPTION_THUMBNAIL_HEIGHT].value.i;
}
else
{
width = WIDTH;
height = HEIGHT;
}
width *= 0.75f;
height *= 0.75f;
icon = getWindowIcon(w, width, height);
if (!icon)
icon = w->screen->defaultIcon;
if (icon)
{
int iw, ih;
iw = width - SPACE;
ih = height - SPACE;
if (icon->width < (iw >> 1))
sAttrib.xScale = (iw / icon->width);
else
sAttrib.xScale = 1.0f;
if (icon->height < (ih >> 1))
sAttrib.yScale = (ih / icon->height);
else
sAttrib.yScale = 1.0f;
if (sAttrib.xScale < sAttrib.yScale)
sAttrib.yScale = sAttrib.xScale;
else
sAttrib.xScale = sAttrib.yScale;
width = icon->width * sAttrib.xScale;
height = icon->height * sAttrib.yScale;
if (ss->switchMode == RingSwitcher)
{
sAttrib.xScale *= scale;
sAttrib.yScale *= scale;
wx = x + SPACE + ((ss->opt[SWITCH_SCREEN_OPTION_THUMBNAIL_WIDTH].value.i - (SPACE << 1)) - width) / 2;
wy = y + SPACE + ((ss->opt[SWITCH_SCREEN_OPTION_THUMBNAIL_HEIGHT].value.i - (SPACE << 1)) - height) / 2;
}
else
{
wx = x + SPACE + ((WIDTH - (SPACE << 1)) - width) / 2;
wy = y + SPACE + ((HEIGHT - (SPACE << 1)) - height) / 2;
}
}
}
if (icon && (icon->texture.name || iconToTexture(w->screen, icon)))
{
REGION iconReg;
CompMatrix matrix;
mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
iconReg.rects = &iconReg.extents;
iconReg.numRects = 1;
iconReg.extents.x1 = w->attrib.x;
iconReg.extents.y1 = w->attrib.y;
iconReg.extents.x2 = w->attrib.x + icon->width;
iconReg.extents.y2 = w->attrib.y + icon->height;
matrix = icon->texture.matrix;
matrix.x0 -= (w->attrib.x * icon->texture.matrix.xx);
matrix.y0 -= (w->attrib.y * icon->texture.matrix.yy);
sAttrib.xTranslate = wx - w->attrib.x;
sAttrib.yTranslate = wy - w->attrib.y;
w->vCount = 0;
addWindowGeometry(w, &matrix, 1, &iconReg, getInfiniteRegion());
if (w->vCount)
(*w->screen->drawWindowTexture) (w,
&icon->texture, &sAttrib, mask);
}
w->screen->drawWindowGeometry = oldDrawWindowGeometry;
w->screen->addWindowGeometry = oldAddWindowGeometry;
}
static float calc_ellipse(float x,float a, float b)
{
return sqrt((b*b)*(1-((x*x)/(a*a))));
}
typedef struct
{
float y;
float x;
float scale;
int index;
} ArrayElement;
static int compareElements(const void *elem1, const void *elem2)
{
ArrayElement *a1 = (ArrayElement *) elem1;
ArrayElement *a2 = (ArrayElement *) elem2;
if(a1->y < a2->y)
return -1;
else if(a1->y > a2->y)
return 1;
else
return 0;
}
static Bool
switchPaintWindow(CompWindow * w,
const WindowPaintAttrib * attrib,
Region region, unsigned int mask)
{
CompScreen *s = w->screen;
Bool status;
ArrayElement *draw_array = NULL;
XRectangle outputRect;
int xo, yo;
SWITCH_SCREEN(s);
if (ss->switchMode == RingSwitcher)
{
screenGetOutputDevRect(s, ss->head, &outputRect);
xo = outputRect.x + outputRect.width/2.0f;
yo = outputRect.y + (outputRect.height/2.0f) - (outputRect.height/5.0f);
draw_array = malloc(ss->nWindows*sizeof(ArrayElement));
}
if (w->id == ss->popupWindow)
{
GLenum filter;
int x, y, x1, x2, cx, i;
if (mask & PAINT_WINDOW_SOLID_MASK)
return FALSE;
UNWRAP(ss, s, paintWindow);
status = (*s->paintWindow) (w, attrib, region, mask);
WRAP(ss, s, paintWindow, switchPaintWindow);
if (!(mask & PAINT_WINDOW_TRANSFORMED_MASK) && region->numRects == 0)
return TRUE;
x1 = w->attrib.x + SPACE;
x2 = w->attrib.x + w->width - SPACE;
x = x1 + ss->pos;
y = w->attrib.y + SPACE;
filter = s->display->textureFilter;
if (ss->opt[SWITCH_SCREEN_OPTION_MIPMAP].value.b)
s->display->textureFilter = GL_LINEAR_MIPMAP_LINEAR;
glPushAttrib(GL_SCISSOR_BIT);
glEnable(GL_SCISSOR_TEST);
glScissor(x1, 0, x2 - x1, w->screen->height);
if (ss->switchMode == RingSwitcher)
{
int x_pos = x;
Bool front = FALSE;
int tmp = 0;
ELLIPSE_ROTA(outputRect);
ELLIPSE_ROTB(outputRect);
DIST_ROT;
int sw = 0;
float y_max = calc_ellipse(0,ellipse_a,ellipse_b);
for (i = 0; i < ss->nWindows; i++)
{
tmp = x + (i * dist);
sw = (abs(tmp) / (2 * ellipse_a)) % 2;
switch(sw)
{
case 0:
x_pos = ellipse_a - (abs(tmp) % (2 * ellipse_a));
front = (tmp >= 0);
break;
case 1:
if(tmp < 0)
{
x_pos = ((abs(tmp) % (2*ellipse_a))-ellipse_a);
front = TRUE;
}
else
{
x_pos = -1 * (ellipse_a - (abs(tmp) % (2 * ellipse_a)));
front = FALSE;
}
break;
}
if (front)
{
draw_array[i].x = x_pos + xo;
draw_array[i].y = calc_ellipse(x_pos, ellipse_a, ellipse_b) + yo;
draw_array[i].scale = 1.0f + ((draw_array[i].y - yo) / y_max) / 0.9f;
draw_array[i].index = i;
}
else
{
draw_array[i].x = x_pos + xo;
draw_array[i].y = -1 * calc_ellipse(x_pos, ellipse_a, ellipse_b) + yo;
draw_array[i].scale = 1.0f - ((-1 * (draw_array[i].y - yo)) / y_max) + 0.4f;
draw_array[i].index = i;
}
}
qsort(draw_array, ss->nWindows, sizeof(ArrayElement), compareElements);
for (i = 0; i < ss->nWindows; i++)
{
switchPaintThumb(ss->windows[draw_array[i].index],
&w->lastPaint, mask, draw_array[i].x,
draw_array[i].y , x1, x2,draw_array[i].scale);
}
}
else
{
for (i = 0; i < ss->nWindows; i++)
{
if (x + WIDTH > x1)
switchPaintThumb(ss->windows[i], &w->lastPaint,
mask, x, y, x1, x2, 1.0f);
x += WIDTH;
}
for (i = 0; i < ss->nWindows; i++)
{
if (x > x2)
break;
switchPaintThumb(ss->windows[i], &w->lastPaint,
mask, x, y, x1, x2, 1.0f);
x += WIDTH;
}
}
glPopAttrib();
s->display->textureFilter = filter;
cx = w->attrib.x + (w->width >> 1);
if (ss->switchMode == ApplicationSwitcher)
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_BLEND);
glColor4us(0, 0, 0, w->lastPaint.opacity);
glPushMatrix();
glTranslatef(cx, y, 0.0f);
glVertexPointer(2, GL_FLOAT, 0, _boxVertices);
glDrawArrays(GL_QUADS, 0, 16);
glPopMatrix();
glColor4usv(defaultColor);
glDisable(GL_BLEND);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
}
else if (w->id == ss->selectedWindow)
{
glPushMatrix();
if (ss->bringToFront)
{
if ((ss->selectedWindow == ss->zoomedWindow) &&
!IPCS_GetBool(IPCS_OBJECT(s), ss->insideAtom))
glTranslatef(0.0f, 0.0f, MIN(ss->translate, ss->sTranslate));
}
if (((ss->wMask & w->type) && ss->opacity != OPAQUE) &&
(ss->opt[SWITCH_SCREEN_OPTION_RING_TRANSPARENT_ALL].value.b &&
(ss->switchMode == RingSwitcher)))
{
status = TRUE;
}
else
{
UNWRAP(ss, s, paintWindow);
status = (*s->paintWindow) (w, attrib, region, mask);
WRAP(ss, s, paintWindow, switchPaintWindow);
}
glPopMatrix();
}
else if (ss->switching)
{
WindowPaintAttrib sAttrib = *attrib;
if (ss->saturation != COLOR)
sAttrib.saturation = (sAttrib.saturation * ss->saturation) >> 16;
if (ss->brightness != 0xffff)
sAttrib.brightness = (sAttrib.brightness * ss->brightness) >> 16;
if ((ss->wMask & w->type) && ss->opacity != OPAQUE)
sAttrib.opacity = (sAttrib.opacity * ss->opacity) >> 16;
if (((ss->wMask & w->type) && ss->opacity != OPAQUE) &&
(ss->opt[SWITCH_SCREEN_OPTION_RING_TRANSPARENT_ALL].value.b &&
(ss->switchMode == RingSwitcher)))
{
status = TRUE;
}
else
{
if (ss->bringToFront && w->id == ss->zoomedWindow)
{
glPushMatrix();
glTranslatef(0.0f, 0.0f, MIN(ss->translate, ss->sTranslate));
UNWRAP(ss, s, paintWindow);
status = (*s->paintWindow) (w, &sAttrib, region, mask);
WRAP(ss, s, paintWindow, switchPaintWindow);
glPopMatrix();
}
else
{
UNWRAP(ss, s, paintWindow);
status = (*s->paintWindow) (w, &sAttrib, region, mask);
WRAP(ss, s, paintWindow, switchPaintWindow);
}
}
}
else
{
UNWRAP(ss, s, paintWindow);
status = (*s->paintWindow) (w, attrib, region, mask);
WRAP(ss, s, paintWindow, switchPaintWindow);
}
if (draw_array)
free(draw_array);
return status;
}
static Bool switchDamageWindowRect(CompWindow * w, Bool initial, BoxPtr rect)
{
Bool status;
SWITCH_SCREEN(w->screen);
if (ss->grabIndex)
{
CompWindow *popup;
int i;
for (i = 0; i < ss->nWindows; i++)
{
if (ss->windows[i] == w)
{
popup = findWindowAtScreen(w->screen, ss->popupWindow);
if (popup)
addWindowDamage(popup);
break;
}
}
}
UNWRAP(ss, w->screen, damageWindowRect);
status = (*w->screen->damageWindowRect) (w, initial, rect);
WRAP(ss, w->screen, damageWindowRect, switchDamageWindowRect);
return status;
}
static Bool
switchSetDisplayOption(CompDisplay * display,
char *name, CompOptionValue * value)
{
CompOption *o;
int index;
SWITCH_DISPLAY(display);
o = compFindOption(sd->opt, NUM_OPTIONS(sd), name, &index);
if (!o)
return FALSE;
switch (index)
{
case SWITCH_DISPLAY_OPTION_NEXT:
case SWITCH_DISPLAY_OPTION_NEXT_ALL:
case SWITCH_DISPLAY_OPTION_PREV:
case SWITCH_DISPLAY_OPTION_PREV_ALL:
case SWITCH_DISPLAY_OPTION_RING_NEXT:
case SWITCH_DISPLAY_OPTION_RING_NEXT_ALL:
case SWITCH_DISPLAY_OPTION_RING_PREV:
case SWITCH_DISPLAY_OPTION_RING_PREV_ALL:
if (setDisplayAction(display, o, value))
return TRUE;
default:
break;
}
return FALSE;
}
static void switchDisplayInitOptions(SwitchDisplay * sd)
{
CompOption *o;
o = &sd->opt[SWITCH_DISPLAY_OPTION_NEXT];
o->advanced = False;
o->name = "next";
o->group = N_("Bindings");
o->subGroup = N_("Current workspace");
o->displayHints = "";
o->shortDesc = N_("Next Window");
o->longDesc = N_("Popup Switcher if not visible and "
"select Next Window.");
o->type = CompOptionTypeAction;
o->value.action.initiate = switchNext;
o->value.action.terminate = switchTerminate;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
o->value.action.state = CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
o->value.action.type = CompBindingTypeKey;
o->value.action.key.modifiers = SWITCH_NEXT_MODIFIERS_DEFAULT;
o->value.action.key.keysym = XStringToKeysym(SWITCH_NEXT_KEY_DEFAULT);
o = &sd->opt[SWITCH_DISPLAY_OPTION_PREV];
o->advanced = False;
o->name = "prev";
o->group = N_("Bindings");
o->subGroup = N_("Current workspace");
o->displayHints = "";
o->shortDesc = N_("Prev Window");
o->longDesc = N_("Popup Switcher if not visible and "
"select Previous Window.");
o->type = CompOptionTypeAction;
o->value.action.initiate = switchPrev;
o->value.action.terminate = switchTerminate;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
o->value.action.state = CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
o->value.action.type = CompBindingTypeKey;
o->value.action.key.modifiers = SWITCH_PREV_MODIFIERS_DEFAULT;
o->value.action.key.keysym = XStringToKeysym(SWITCH_PREV_KEY_DEFAULT);
o = &sd->opt[SWITCH_DISPLAY_OPTION_NEXT_ALL];
o->advanced = False;
o->name = "next_all";
o->group = N_("Bindings");
o->subGroup = N_("All workspaces");
o->displayHints = "";
o->shortDesc = N_("Next Window (All Workspaces)");
o->longDesc = N_("Popup Switcher if not visible and "
"select Next Window out of All Windows.");
o->type = CompOptionTypeAction;
o->value.action.initiate = switchNextAll;
o->value.action.terminate = switchTerminate;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
o->value.action.state = CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
o->value.action.type = CompBindingTypeKey;
o->value.action.key.modifiers = SWITCH_NEXT_ALL_MODIFIERS_DEFAULT;
o->value.action.key.keysym = XStringToKeysym(SWITCH_NEXT_ALL_KEY_DEFAULT);
o = &sd->opt[SWITCH_DISPLAY_OPTION_PREV_ALL];
o->advanced = False;
o->name = "prev_all";
o->group = N_("Bindings");
o->subGroup = N_("All workspaces");
o->displayHints = "";
o->shortDesc = N_("Prev Window (All Workspaces)");
o->longDesc = N_("Popup Switcher if not visible and "
"select Previous Window out of All Windows.");
o->type = CompOptionTypeAction;
o->value.action.initiate = switchPrevAll;
o->value.action.terminate = switchTerminate;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
o->value.action.state = CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
o->value.action.type = CompBindingTypeKey;
o->value.action.key.modifiers = SWITCH_PREV_ALL_MODIFIERS_DEFAULT;
o->value.action.key.keysym = XStringToKeysym(SWITCH_PREV_ALL_KEY_DEFAULT);
o = &sd->opt[SWITCH_DISPLAY_OPTION_RING_NEXT];
o->advanced = False;
o->name = "next_ring";
o->group = N_("Bindings (Ring)");
o->subGroup = N_("Current workspace");
o->displayHints = "";
o->shortDesc = N_("Next Window");
o->longDesc = N_("Popup Switcher if not visible and "
"select Next Window.");
o->type = CompOptionTypeAction;
o->value.action.initiate = switchNextRing;
o->value.action.terminate = switchTerminate;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
o->value.action.state = CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
o->value.action.type = CompBindingTypeKey;
o->value.action.key.modifiers = SWITCH_RING_NEXT_MODIFIERS_DEFAULT;
o->value.action.key.keysym = XStringToKeysym(SWITCH_RING_NEXT_KEY_DEFAULT);
o = &sd->opt[SWITCH_DISPLAY_OPTION_RING_PREV];
o->advanced = False;
o->name = "prev_ring";
o->group = N_("Bindings (Ring)");
o->subGroup = N_("Current workspace");
o->displayHints = "";
o->shortDesc = N_("Prev Window");
o->longDesc = N_("Popup Switcher if not visible and "
"select Previous Window.");
o->type = CompOptionTypeAction;
o->value.action.initiate = switchPrevRing;
o->value.action.terminate = switchTerminate;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
o->value.action.state = CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
o->value.action.type = CompBindingTypeKey;
o->value.action.key.modifiers = SWITCH_RING_PREV_MODIFIERS_DEFAULT;
o->value.action.key.keysym = XStringToKeysym(SWITCH_RING_PREV_KEY_DEFAULT);
o = &sd->opt[SWITCH_DISPLAY_OPTION_RING_NEXT_ALL];
o->advanced = False;
o->name = "next_all_ring";
o->group = N_("Bindings (Ring)");
o->subGroup = N_("All workspaces");
o->displayHints = "";
o->shortDesc = N_("Next Window (All Workspaces)");
o->longDesc = N_("Popup Switcher if not visible and "
"select Next Window out of All Windows.");
o->type = CompOptionTypeAction;
o->value.action.initiate = switchNextAllRing;
o->value.action.terminate = switchTerminate;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
o->value.action.state = CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
o->value.action.type = CompBindingTypeKey;
o->value.action.key.modifiers = SWITCH_RING_NEXT_ALL_MODIFIERS_DEFAULT;
o->value.action.key.keysym = XStringToKeysym(SWITCH_RING_NEXT_ALL_KEY_DEFAULT);
o = &sd->opt[SWITCH_DISPLAY_OPTION_RING_PREV_ALL];
o->advanced = False;
o->name = "prev_all_ring";
o->group = N_("Bindings (Ring)");
o->subGroup = N_("All workspaces");
o->displayHints = "";
o->shortDesc = N_("Prev Window (All Workspaces)");
o->longDesc = N_("Popup Switcher if not visible and "
"select Previous Window out of All Windows.");
o->type = CompOptionTypeAction;
o->value.action.initiate = switchPrevAllRing;
o->value.action.terminate = switchTerminate;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
o->value.action.state = CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
o->value.action.type = CompBindingTypeKey;
o->value.action.key.modifiers = SWITCH_RING_PREV_ALL_MODIFIERS_DEFAULT;
o->value.action.key.keysym = XStringToKeysym(SWITCH_RING_PREV_ALL_KEY_DEFAULT);
}
static CompOption *switchGetDisplayOptions(CompDisplay * display, int *count)
{
if (display)
{
SWITCH_DISPLAY(display);
*count = NUM_OPTIONS(sd);
return sd->opt;
}
else
{
SwitchDisplay *sd = malloc(sizeof(SwitchDisplay));
switchDisplayInitOptions(sd);
*count = NUM_OPTIONS(sd);
return sd->opt;
}
}
static Bool switchInitDisplay(CompPlugin * p, CompDisplay * d)
{
SwitchDisplay *sd;
sd = malloc(sizeof(SwitchDisplay));
if (!sd)
return FALSE;
sd->screenPrivateIndex = allocateScreenPrivateIndex(d);
if (sd->screenPrivateIndex < 0)
{
free(sd);
return FALSE;
}
sd->selectWinAtom = XInternAtom(d->display, SELECT_WIN_PROP, 0);
switchDisplayInitOptions(sd);
WRAP(sd, d, handleEvent, switchHandleEvent);
d->privates[displayPrivateIndex].ptr = sd;
return TRUE;
}
static void switchFiniDisplay(CompPlugin * p, CompDisplay * d)
{
SWITCH_DISPLAY(d);
freeScreenPrivateIndex(d, sd->screenPrivateIndex);
UNWRAP(sd, d, handleEvent);
free(sd);
}
static Bool switchInitScreen(CompPlugin * p, CompScreen * s)
{
SwitchScreen *ss;
SWITCH_DISPLAY(s->display);
ss = malloc(sizeof(SwitchScreen));
if (!ss)
return FALSE;
ss->popupWindow = None;
ss->selectedWindow = None;
ss->zoomedWindow = None;
ss->lastActiveNum = 0;
ss->windows = 0;
ss->nWindows = 0;
ss->windowsSize = 0;
ss->pos = ss->move = 0;
ss->switching = FALSE;
ss->prevMin = NULL;
ss->grabIndex = 0;
ss->speed = SWITCH_SPEED_DEFAULT;
ss->timestep = SWITCH_TIMESTEP_DEFAULT;
ss->zoom = SWITCH_ZOOM_DEFAULT / 30.0f;
ss->zooming = (SWITCH_ZOOM_DEFAULT > 0.05f) ? TRUE : FALSE;
ss->moreAdjust = 0;
ss->mVelocity = 0.0f;
ss->tVelocity = 0.0f;
ss->sVelocity = 0.0f;
ss->translate = 0.0f;
ss->sTranslate = 0.0f;
ss->saturation = (COLOR * SWITCH_SATURATION_DEFAULT) / 100;
ss->brightness = (0xffff * SWITCH_BRIGHTNESS_DEFAULT) / 100;
ss->opacity = (OPAQUE * SWITCH_OPACITY_DEFAULT) / 100;
ss->bringToFront = SWITCH_BRINGTOFRONT_DEFAULT;
ss->showWindowList = SWITCH_SHOW_WINDOW_LIST_DEFAULT;
ss->autoRotate = SWITCH_AUTO_ROTATE_DEFAULT;
ss->autoRotate = SWITCH_TEMP_UNMINIMIZE_DEFAULT;
ss->allWindows = FALSE;
ss->head = 0;
ss->tempUnMinimize = FALSE;
ss->switchMode = ApplicationSwitcher;
ss->iconCorner = SWITCH_ICON_CORNER_DEFAULT;
ss->insideAtom = IPCS_GetAtom(IPCS_OBJECT(s), IPCS_BOOL, "INSIDE", TRUE);
switchScreenInitOptions(ss);
addScreenAction(s, &sd->opt[SWITCH_DISPLAY_OPTION_NEXT].value.action);
addScreenAction(s, &sd->opt[SWITCH_DISPLAY_OPTION_PREV].value.action);
addScreenAction(s, &sd->opt[SWITCH_DISPLAY_OPTION_NEXT_ALL].value.action);
addScreenAction(s, &sd->opt[SWITCH_DISPLAY_OPTION_PREV_ALL].value.action);
addScreenAction(s, &sd->opt[SWITCH_DISPLAY_OPTION_RING_NEXT].value.action);
addScreenAction(s, &sd->opt[SWITCH_DISPLAY_OPTION_RING_PREV].value.action);
addScreenAction(s, &sd->opt[SWITCH_DISPLAY_OPTION_RING_NEXT_ALL].value.action);
addScreenAction(s, &sd->opt[SWITCH_DISPLAY_OPTION_RING_PREV_ALL].value.action);
WRAP(ss, s, preparePaintScreen, switchPreparePaintScreen);
WRAP(ss, s, donePaintScreen, switchDonePaintScreen);
WRAP(ss, s, paintScreen, switchPaintScreen);
WRAP(ss, s, paintWindow, switchPaintWindow);
WRAP(ss, s, damageWindowRect, switchDamageWindowRect);
s->privates[sd->screenPrivateIndex].ptr = ss;
return TRUE;
}
static void switchFiniScreen(CompPlugin * p, CompScreen * s)
{
SWITCH_SCREEN(s);
SWITCH_DISPLAY(s->display);
UNWRAP(ss, s, preparePaintScreen);
UNWRAP(ss, s, donePaintScreen);
UNWRAP(ss, s, paintScreen);
UNWRAP(ss, s, paintWindow);
UNWRAP(ss, s, damageWindowRect);
removeScreenAction(s, &sd->opt[SWITCH_DISPLAY_OPTION_NEXT].value.action);
removeScreenAction(s, &sd->opt[SWITCH_DISPLAY_OPTION_PREV].value.action);
removeScreenAction(s, &sd->opt[SWITCH_DISPLAY_OPTION_NEXT_ALL].value.action);
removeScreenAction(s, &sd->opt[SWITCH_DISPLAY_OPTION_PREV_ALL].value.action);
removeScreenAction(s, &sd->opt[SWITCH_DISPLAY_OPTION_RING_NEXT].value.action);
removeScreenAction(s, &sd->opt[SWITCH_DISPLAY_OPTION_RING_PREV].value.action);
removeScreenAction(s, &sd->opt[SWITCH_DISPLAY_OPTION_RING_NEXT_ALL].value.action);
removeScreenAction(s, &sd->opt[SWITCH_DISPLAY_OPTION_RING_PREV_ALL].value.action);
if (ss->popupWindow)
XDestroyWindow(s->display->display, ss->popupWindow);
if (ss->windowsSize)
free(ss->windows);
free(ss);
}
static Bool switchInit(CompPlugin * p)
{
displayPrivateIndex = allocateDisplayPrivateIndex();
if (displayPrivateIndex < 0)
return FALSE;
return TRUE;
}
static void switchFini(CompPlugin * p)
{
if (displayPrivateIndex >= 0)
freeDisplayPrivateIndex(displayPrivateIndex);
}
CompPluginDep setDeps[] = {
{CompPluginRuleAfter, "cube"},
{CompPluginRuleAfter, "decoration"},
};
CompPluginVTable switchVTable = {
"switcher",
N_("Application Window Switcher"),
N_("Application Window Switcher"),
switchInit,
switchFini,
switchInitDisplay,
switchFiniDisplay,
switchInitScreen,
switchFiniScreen,
0,
0,
switchGetDisplayOptions,
switchSetDisplayOption,
switchGetScreenOptions,
switchSetScreenOption,
setDeps,
sizeof(setDeps) / sizeof(setDeps[0]),
0,
0,
BERYL_ABI_INFO,
"beryl-plugins",
"wm",
0,
0,
True,
};
CompPluginVTable *getCompPluginInfo(void)
{
return &switchVTable;
}
syntax highlighted by Code2HTML, v. 0.9.1