All pastes #401734 Raw Edit

Unnamed

public text v1 · immutable
·published 2007-03-19 14:36 UTC
rendered paste body
diff --git a/plugins/switcher.c b/plugins/switcher.c
index 3018711..e68276a 100644
--- a/plugins/switcher.c
+++ b/plugins/switcher.c
@@ -48,6 +48,19 @@
 #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   1.5f
 #define SWITCH_SPEED_MIN       0.1f
 #define SWITCH_SPEED_MAX       50.0f
@@ -88,6 +101,36 @@
 
 #define SWITCH_AUTO_ROTATE_DEFAULT FALSE
 
+#define SWITCH_RING_ALL_TRANSPARENT_DEFAULT TRUE
+
+#define SWITCH_RING_WIDTH_MIN	    0.01f
+#define SWITCH_RING_WIDTH_MAX	    1.0f
+#define SWITCH_RING_WIDTH_DEFAULT   0.6f
+#define SWITCH_RING_WIDTH_PRECISION 0.01f
+
+#define SWITCH_RING_HEIGHT_MIN	     0.01f
+#define SWITCH_RING_HEIGHT_MAX	     1.0f
+#define SWITCH_RING_HEIGHT_DEFAULT   0.50f
+#define SWITCH_RING_HEIGHT_PRECISION 0.01f
+
+#define SWITCH_RING_MIN_BRIGHTNESS_MIN		0.1f
+#define SWITCH_RING_MIN_BRIGHTNESS_MAX		1.0f
+#define SWITCH_RING_MIN_BRIGHTNESS_DEFAULT	0.5f
+#define SWITCH_RING_MIN_BRIGHTNESS_PRECISION	0.01f
+
+#define SWITCH_RING_MIN_SCALE_MIN		0.1f
+#define SWITCH_RING_MIN_SCALE_MAX		1.0f
+#define SWITCH_RING_MIN_SCALE_DEFAULT		0.4f
+#define SWITCH_RING_MIN_SCALE_PRECISION		0.01f
+
+#define SWITCH_RING_THUMBNAIL_WIDTH_MIN	        10
+#define SWITCH_RING_THUMBNAIL_WIDTH_MAX	        1024
+#define SWITCH_RING_THUMBNAIL_WIDTH_DEFAULT	300
+
+#define SWITCH_RING_THUMBNAIL_HEIGHT_MIN	10
+#define SWITCH_RING_THUMBNAIL_HEIGHT_MAX	1024
+#define SWITCH_RING_THUMBNAIL_HEIGHT_DEFAULT	250
+
 #define ZOOMED_WINDOW_MASK (1 << 0)
 #define NORMAL_WINDOW_MASK (1 << 1)
 
@@ -99,7 +142,11 @@ static int displayPrivateIndex;
 #define SWITCH_DISPLAY_OPTION_PREV_ALL	     3
 #define SWITCH_DISPLAY_OPTION_NEXT_NO_POPUP  4
 #define SWITCH_DISPLAY_OPTION_PREV_NO_POPUP  5
-#define SWITCH_DISPLAY_OPTION_NUM	     6
+#define SWITCH_DISPLAY_OPTION_NEXT_RING      6
+#define SWITCH_DISPLAY_OPTION_PREV_RING      7
+#define SWITCH_DISPLAY_OPTION_NEXT_RING_ALL  8
+#define SWITCH_DISPLAY_OPTION_PREV_RING_ALL  9
+#define SWITCH_DISPLAY_OPTION_NUM	     10
 
 typedef struct _SwitchDisplay {
     int		    screenPrivateIndex;
@@ -110,19 +157,41 @@ typedef struct _SwitchDisplay {
     Atom selectWinAtom;
 } SwitchDisplay;
 
-#define SWITCH_SCREEN_OPTION_SPEED	  0
-#define SWITCH_SCREEN_OPTION_TIMESTEP	  1
-#define SWITCH_SCREEN_OPTION_WINDOW_MATCH 2
-#define SWITCH_SCREEN_OPTION_MIPMAP	  3
-#define SWITCH_SCREEN_OPTION_SATURATION	  4
-#define SWITCH_SCREEN_OPTION_BRIGHTNESS	  5
-#define SWITCH_SCREEN_OPTION_OPACITY	  6
-#define SWITCH_SCREEN_OPTION_BRINGTOFRONT 7
-#define SWITCH_SCREEN_OPTION_ZOOM	  8
-#define SWITCH_SCREEN_OPTION_ICON	  9
-#define SWITCH_SCREEN_OPTION_MINIMIZED	  10
-#define SWITCH_SCREEN_OPTION_AUTO_ROTATE  11
-#define SWITCH_SCREEN_OPTION_NUM	  12
+#define SWITCH_SCREEN_OPTION_SPEED	               0
+#define SWITCH_SCREEN_OPTION_TIMESTEP	               1
+#define SWITCH_SCREEN_OPTION_WINDOW_MATCH              2
+#define SWITCH_SCREEN_OPTION_MIPMAP	               3
+#define SWITCH_SCREEN_OPTION_SATURATION	               4
+#define SWITCH_SCREEN_OPTION_BRIGHTNESS	               5
+#define SWITCH_SCREEN_OPTION_OPACITY	               6
+#define SWITCH_SCREEN_OPTION_BRINGTOFRONT              7
+#define SWITCH_SCREEN_OPTION_ZOOM	               8
+#define SWITCH_SCREEN_OPTION_ICON	               9
+#define SWITCH_SCREEN_OPTION_MINIMIZED	               10
+#define SWITCH_SCREEN_OPTION_AUTO_ROTATE               11
+#define SWITCH_SCREEN_OPTION_RING_WIDTH                12
+#define SWITCH_SCREEN_OPTION_RING_HEIGHT               13
+#define SWITCH_SCREEN_OPTION_RING_THUMB_WIDTH          14
+#define SWITCH_SCREEN_OPTION_RING_THUMB_HEIGHT         15
+#define SWITCH_SCREEN_OPTION_RING_TRANSPARENT_ALL      16
+#define SWITCH_SCREEN_OPTION_RING_MIN_BRIGHTNESS       17
+#define SWITCH_SCREEN_OPTION_RING_MIN_SCALE            18
+#define SWITCH_SCREEN_OPTION_NUM	               19
+
+typedef enum _SwitcherMode
+{
+	ApplicationSwitcher = 0,
+	RingSwitcher
+} SwitcherMode;
+
+typedef struct
+{
+	int index;
+	float x;
+	float y;
+	float scale;
+	float brightness;
+} DrawArrayElement;
 
 typedef struct _SwitchScreen {
     PreparePaintScreenProc preparePaintScreen;
@@ -155,13 +224,20 @@ typedef struct _SwitchScreen {
     GLfloat tVelocity;
     GLfloat sVelocity;
 
-    CompWindow **windows;
-    int        windowsSize;
-    int        nWindows;
+    CompWindow       **windows;
+    DrawArrayElement *ringDrawArray;
+    int              windowsSize;
+    int              nWindows;
 
+    /* these two have different meanings in application switcher
+       and ring switcher mode: in application switcher mode, their
+       unit is pixels, while in ring switcher mode, the unit is
+       (degrees * 100) */
     int pos;
     int move;
 
+    SwitcherMode switchMode;
+
     float translate;
     float sTranslate;
 
@@ -219,6 +295,13 @@ static float _boxVertices[] =
 #define WINDOW_WIDTH(count) (WIDTH * (count) + (SPACE << 1))
 #define WINDOW_HEIGHT (HEIGHT + (SPACE << 1))
 
+#define PI 3.1415926
+#define ELLIPSE_ROTA(outputRect) int ellipseA = (outputRect.width * \
+		 ss->opt[SWITCH_SCREEN_OPTION_RING_WIDTH].value.f) / 2.0f;
+#define ELLIPSE_ROTB(outputRect) int ellipseB = (outputRect.height * \
+		ss->opt[SWITCH_SCREEN_OPTION_RING_HEIGHT].value.f) / 2.0f;
+#define DIST_ROT (36000 / ss->nWindows)
+
 #define GET_SWITCH_DISPLAY(d)				       \
     ((SwitchDisplay *) (d)->privates[displayPrivateIndex].ptr)
 
@@ -280,6 +363,7 @@ switchSetScreenOption (CompScreen      *screen,
     case SWITCH_SCREEN_OPTION_ICON:
     case SWITCH_SCREEN_OPTION_MINIMIZED:
     case SWITCH_SCREEN_OPTION_AUTO_ROTATE:
+    case SWITCH_SCREEN_OPTION_RING_TRANSPARENT_ALL:
 	if (compSetBoolOption (o, value))
 	    return TRUE;
 	break;
@@ -327,6 +411,19 @@ switchSetScreenOption (CompScreen      *screen,
 
 	    return TRUE;
 	}
+	break;
+    case SWITCH_SCREEN_OPTION_RING_WIDTH:
+    case SWITCH_SCREEN_OPTION_RING_HEIGHT:
+    case SWITCH_SCREEN_OPTION_RING_MIN_BRIGHTNESS:
+    case SWITCH_SCREEN_OPTION_RING_MIN_SCALE:
+	if(compSetFloatOption(o, value))
+	    return TRUE;
+	break;
+    case SWITCH_SCREEN_OPTION_RING_THUMB_WIDTH:
+    case SWITCH_SCREEN_OPTION_RING_THUMB_HEIGHT:
+	if(compSetIntOption(o, value))
+    	    return TRUE;
+	break;
     default:
 	break;
     }
@@ -441,6 +538,86 @@ switchScreenInitOptions (SwitchScreen *ss)
     o->longDesc	  = N_("Rotate to the selected window while switching");
     o->type	  = CompOptionTypeBool;
     o->value.b    = SWITCH_AUTO_ROTATE_DEFAULT;
+
+    o = &ss->opt[SWITCH_SCREEN_OPTION_RING_WIDTH];
+    o->name = "ring_width";
+    o->shortDesc = N_("Ring 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_RING_WIDTH_DEFAULT;
+    o->rest.f.min = SWITCH_RING_WIDTH_MIN;
+    o->rest.f.max = SWITCH_RING_WIDTH_MAX;
+    o->rest.f.precision = SWITCH_RING_WIDTH_PRECISION;
+
+    o = &ss->opt[SWITCH_SCREEN_OPTION_RING_HEIGHT];
+    o->name = "ring_height";
+    o->shortDesc = N_("Ring 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_RING_HEIGHT_DEFAULT;
+    o->rest.f.min = SWITCH_RING_HEIGHT_MIN;
+    o->rest.f.max = SWITCH_RING_HEIGHT_MAX;
+    o->rest.f.precision = SWITCH_RING_HEIGHT_PRECISION;
+
+    o = &ss->opt[SWITCH_SCREEN_OPTION_RING_THUMB_WIDTH];
+    o->name = "ring_thumbnail_width";
+    o->shortDesc = N_("Ring Thumbnail Width");
+    o->longDesc = N_("Changes the horizontal size of the unscaled Thumbnail.");
+    o->type = CompOptionTypeInt;
+    o->value.i = SWITCH_RING_THUMBNAIL_WIDTH_DEFAULT;
+    o->rest.i.min = SWITCH_RING_THUMBNAIL_WIDTH_MIN;
+    o->rest.i.max = SWITCH_RING_THUMBNAIL_WIDTH_MAX;
+    
+    o = &ss->opt[SWITCH_SCREEN_OPTION_RING_THUMB_HEIGHT];
+    o->name = "ring_thumbnail_height";
+    o->shortDesc = N_("Ring Thumbnail Height");
+    o->longDesc = N_("Changes the vertical size of the unscaled Thumbnail.");
+    o->type = CompOptionTypeInt;
+    o->value.i = SWITCH_RING_THUMBNAIL_HEIGHT_DEFAULT;
+    o->rest.i.min = SWITCH_RING_THUMBNAIL_HEIGHT_MIN;
+    o->rest.i.max = SWITCH_RING_THUMBNAIL_HEIGHT_MAX;
+
+    o = &ss->opt[SWITCH_SCREEN_OPTION_RING_TRANSPARENT_ALL];
+    o->name = "ring_transparent_all";
+    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;
+    
+    o = &ss->opt[SWITCH_SCREEN_OPTION_RING_MIN_BRIGHTNESS];
+    o->name = "ring_min_brightness";
+    o->shortDesc = N_("Minimum brightness factor");
+    o->longDesc = N_("Changes the mimimum brightness factor for windows in the ring."
+		     "The farer away windows are, the less bright they are.");
+    o->type = CompOptionTypeFloat;
+    o->value.f = SWITCH_RING_MIN_BRIGHTNESS_DEFAULT;
+    o->rest.f.min = SWITCH_RING_MIN_BRIGHTNESS_MIN;
+    o->rest.f.max = SWITCH_RING_MIN_BRIGHTNESS_MAX;
+    o->rest.f.precision = SWITCH_RING_MIN_BRIGHTNESS_PRECISION;
+    
+    o = &ss->opt[SWITCH_SCREEN_OPTION_RING_MIN_SCALE];
+    o->name = "ring_min_scale";
+    o->shortDesc = N_("Minimum scale factor");
+    o->longDesc = N_("Changes the scale brightness factor for windows in the ring."
+		     "Smaller values give the impression of a larger depth.");
+    o->type = CompOptionTypeFloat;
+    o->value.f = SWITCH_RING_MIN_SCALE_DEFAULT;
+    o->rest.f.min = SWITCH_RING_MIN_SCALE_MIN;
+    o->rest.f.max = SWITCH_RING_MIN_SCALE_MAX;
+    o->rest.f.precision = SWITCH_RING_MIN_SCALE_PRECISION;
+}
+
+static inline float 
+switchLinearInterpolation(float valX, 
+			  float minX, 
+			  float maxX, 
+			  float minY, 
+			  float maxY)
+{
+    double factor = (maxY - minY) / (maxX - minX);
+    return (minY + (factor * (valX - minX)));
 }
 
 static void
@@ -449,6 +626,11 @@ setSelectedWindowHint (CompScreen *s)
     SWITCH_DISPLAY (s->display);
     SWITCH_SCREEN (s);
 
+    /* only set the selected window hint for the application
+       window switcher */
+    if (ss->switchMode != ApplicationSwitcher)
+	return;
+
     XChangeProperty (s->display->display, ss->popupWindow, sd->selectWinAtom,
 		     XA_WINDOW, 32, PropModeReplace,
 		     (unsigned char *) &ss->selectedWindow, 1);
@@ -520,6 +702,84 @@ compareWindows (const void *elem1,
     return w2->activeNum - w1->activeNum;
 }
 
+static int
+compareRingSwitcherWindows (const void *elem1,
+			    const void *elem2)
+{
+    DrawArrayElement *a1 = (DrawArrayElement *) elem1;
+    DrawArrayElement *a2 = (DrawArrayElement *) elem2;
+
+    if(a1->y < a2->y)
+	return -1;
+    else if(a1->y > a2->y)
+	return 1;
+    else
+	return 0;
+}
+
+static void 
+switchCalculateRingSwitcherPositions (CompScreen *s)
+{
+    SWITCH_SCREEN(s);
+    
+    int i;
+    XRectangle outputRect;
+
+    getWorkareaForOutput(s, s->currentOutputDev, &outputRect);
+
+    /* the center of the ellipse is in the middle 
+       of the used output device */
+    int centerX = outputRect.x + (outputRect.width / 2);
+    int centerY = outputRect.y + (outputRect.height / 2);
+
+    ELLIPSE_ROTA(outputRect);
+    ELLIPSE_ROTB(outputRect);
+
+    /* baseAngle is the 'offset angle' marking 
+       the current rotation position; ss->pos contains
+       the current rotation angle multiplied by
+       100 for the sake of rounding issues */
+    float baseAngle = (2 * PI * ss->pos) / 36000;
+    float angleIncrement;
+    float currentAngle;
+
+    /* divide the ellipse into equally sized sectors for each window */
+    angleIncrement = 2 * PI / ss->nWindows;
+
+    for (i = 0; i < ss->nWindows; i++)
+    {
+	/* we subtract the angle from the base angle 
+	   to order the windows clockwise */
+	currentAngle = baseAngle - (i * angleIncrement);
+
+	ss->ringDrawArray[i].index = i;
+	ss->ringDrawArray[i].x = centerX + (ellipseA * sin(currentAngle));
+	ss->ringDrawArray[i].y = centerY + (ellipseB * cos(currentAngle));
+
+	/* scale and brightness are obtained by doing a linear inter-
+	   polation - the y positions are the x values for the interpolation
+	   (the larger Y is, the nearer is the window), and scale/brightness
+	   are the y values for the interpolation */
+	ss->ringDrawArray[i].scale = switchLinearInterpolation(
+			ss->ringDrawArray[i].y,
+			centerY - ellipseB, 
+			centerY + ellipseB, 
+			ss->opt[SWITCH_SCREEN_OPTION_RING_MIN_SCALE].value.f, 1.0f);
+
+	ss->ringDrawArray[i].brightness = switchLinearInterpolation(
+			ss->ringDrawArray[i].y, 
+			centerY - ellipseB, 
+			centerY + ellipseB,
+			ss->opt[SWITCH_SCREEN_OPTION_RING_MIN_BRIGHTNESS].value.f, 1.0f);
+    }
+    
+    /* sort the draw list so that the windows with the 
+       lowest Y value (the windows being farest away)
+       are drawn first */
+    qsort(ss->ringDrawArray, ss->nWindows, sizeof(DrawArrayElement), 
+	  compareRingSwitcherWindows);
+}
+
 static void
 switchAddWindowToList (CompScreen *s,
 		       CompWindow *w)
@@ -533,6 +793,13 @@ switchAddWindowToList (CompScreen *s,
 	if (!ss->windows)
 	    return;
 
+	ss->ringDrawArray = realloc (ss->ringDrawArray,
+				     sizeof (DrawArrayElement) * 
+				     (ss->nWindows + 32));
+
+	if (!ss->ringDrawArray)
+	    return;
+
 	ss->windowsSize = ss->nWindows + 32;
     }
 
@@ -547,14 +814,20 @@ switchUpdateWindowList (CompScreen *s,
 
     SWITCH_SCREEN (s);
 
-    if (count > 1)
+    if (ss->switchMode == ApplicationSwitcher)
     {
-	count -= (count + 1) & 1;
-	if (count < 3)
-	    count = 3;
+    	if (count > 1)
+	{
+	    count -= (count + 1) & 1;
+    	    if (count < 3)
+    		count = 3;
+	}
+
+    	ss->pos  = ((count >> 1) - ss->nWindows) * WIDTH;
     }
+    else
+	ss->pos = 0;
 
-    ss->pos  = ((count >> 1) - ss->nWindows) * WIDTH;
     ss->move = 0;
 
     ss->selectedWindow = ss->windows[0]->id;
@@ -564,12 +837,19 @@ switchUpdateWindowList (CompScreen *s,
     y = s->outputDev[s->currentOutputDev].region.extents.y1 +
 	s->outputDev[s->currentOutputDev].height / 2;
 
-    if (ss->popupWindow)
-	XMoveResizeWindow (s->display->display, ss->popupWindow,
-			   x - WINDOW_WIDTH (count) / 2,
-			   y - WINDOW_HEIGHT / 2,
-			   WINDOW_WIDTH (count),
-			   WINDOW_HEIGHT);
+    if (ss->switchMode == ApplicationSwitcher)
+    {
+    	if (ss->popupWindow)
+    	    XMoveResizeWindow (s->display->display, ss->popupWindow,
+    			       x - WINDOW_WIDTH (count) / 2,
+    			       y - WINDOW_HEIGHT / 2,
+    			       WINDOW_WIDTH (count),
+    			       WINDOW_HEIGHT);
+    }
+    else
+    {
+	switchCalculateRingSwitcherPositions (s);
+    }
 }
 
 static void
@@ -590,7 +870,8 @@ switchCreateWindowList (CompScreen *s,
 
     qsort (ss->windows, ss->nWindows, sizeof (CompWindow *), compareWindows);
 
-    if (ss->nWindows == 2)
+    if ((ss->switchMode == ApplicationSwitcher) &&
+	(ss->nWindows == 2))
     {
 	switchAddWindowToList (s, ss->windows[0]);
 	switchAddWindowToList (s, ss->windows[1]);
@@ -662,10 +943,16 @@ switchToWindow (CompScreen *s,
 
 	if (old != w->id)
 	{
+	    int offset;
+	    if (ss->switchMode == RingSwitcher)
+		offset = DIST_ROT;
+	    else
+		offset = -WIDTH;
+
 	    if (toNext)
-		ss->move -= WIDTH;
+		ss->move += offset;
 	    else
-		ss->move += WIDTH;
+		ss->move -= offset;
 
 	    ss->moreAdjust = 1;
 	}
@@ -695,6 +982,7 @@ switchToWindow (CompScreen *s,
 static int
 switchCountWindows (CompScreen *s)
 {
+    SWITCH_SCREEN(s);
     CompWindow *w;
     int	       count = 0;
 
@@ -702,8 +990,14 @@ switchCountWindows (CompScreen *s)
 	if (isSwitchWin (w))
 	    count++;
 
-    if (count == 5 && s->width <= WINDOW_WIDTH (5))
-	count = 3;
+    if (ss->switchMode == ApplicationSwitcher)
+    {
+	if (count > 5)
+	    count = 5;
+
+    	if (count == 5 && s->width <= WINDOW_WIDTH (5))
+    	    count = 3;
+    }
 
     return count;
 }
@@ -748,9 +1042,10 @@ findArgbVisual (Display *dpy, int scr)
 }
 
 static void
-switchInitiate (CompScreen *s,
-		Bool	   allWindows,
-		Bool	   showPopup)
+switchInitiate (CompScreen   *s,
+		Bool	     allWindows,
+		Bool	     showPopup,
+		SwitcherMode switchMode)
 {
     int count;
 
@@ -761,6 +1056,17 @@ switchInitiate (CompScreen *s,
 
     ss->allWindows = allWindows;
 
+    /* if the switcher mode has been changed, we have to destroy
+       the popup window so the window properly reflects the
+       attributes specific to the switcher mode */
+    if (ss->popupWindow && (ss->switchMode != switchMode))
+    {
+	XDestroyWindow(s->display->display, ss->popupWindow);
+	ss->popupWindow = None;
+    }
+
+    ss->switchMode = switchMode;
+
     count = switchCountWindows (s);
     if (count < 1)
 	return;
@@ -770,8 +1076,9 @@ switchInitiate (CompScreen *s,
 	Display		     *dpy = s->display->display;
 	XSizeHints	     xsh;
 	XWMHints	     xwmh;
-	Atom		     state[4];
+	Atom		     state[5];
 	int		     nState = 0;
+	unsigned int         winCenterX, winCenterY;
 	XSetWindowAttributes attr;
 	Visual		     *visual;
 
@@ -779,16 +1086,31 @@ switchInitiate (CompScreen *s,
 	if (!visual)
 	    return;
 
-	if (count > 1)
+	xsh.flags  = PSize | PPosition;
+
+	if (ss->switchMode == ApplicationSwitcher)
 	{
-	    count -= (count + 1) & 1;
-	    if (count < 3)
-		count = 3;
+    	    if (count > 1)
+    	    {
+    		count -= (count + 1) & 1;
+    		if (count < 3)
+    		    count = 3;
+    	    }
+
+    	    xsh.width  = WINDOW_WIDTH (count);
+    	    xsh.height = WINDOW_HEIGHT;
+
+	    winCenterX = s->width / 2;
+	    winCenterY = s->height / 2;
 	}
+	else
+	{
+	    xsh.width  = s->outputDev[s->currentOutputDev].width;
+	    xsh.height = s->outputDev[s->currentOutputDev].height;
 
-	xsh.flags  = PSize | PPosition;
-	xsh.width  = WINDOW_WIDTH (count);
-	xsh.height = WINDOW_HEIGHT;
+	    winCenterX = s->outputDev[s->currentOutputDev].region.extents.x1;
+	    winCenterY = s->outputDev[s->currentOutputDev].region.extents.y1;
+	}
 
 	xwmh.flags = InputHint;
 	xwmh.input = 0;
@@ -800,8 +1122,8 @@ switchInitiate (CompScreen *s,
 
 	ss->popupWindow =
 	    XCreateWindow (dpy, s->root,
-			   s->width  / 2 - xsh.width / 2,
-			   s->height / 2 - xsh.height / 2,
+			   winCenterX - xsh.width / 2,
+			   winCenterY - xsh.height / 2,
 			   xsh.width, xsh.height, 0,
 			   32, InputOutput, visual,
 			   CWBackPixel | CWBorderPixel | CWColormap, &attr);
@@ -815,6 +1137,9 @@ switchInitiate (CompScreen *s,
 	state[nState++] = s->display->winStateSkipTaskbarAtom;
 	state[nState++] = s->display->winStateSkipPagerAtom;
 
+	if (ss->switchMode == RingSwitcher)
+	    state[nState++] = s->display->winStateFullscreenAtom;
+
 	XChangeProperty (dpy, ss->popupWindow,
 			 XInternAtom (dpy, "_NET_WM_STATE", 0),
 			 XA_ATOM, 32, PropModeReplace,
@@ -940,11 +1265,15 @@ switchTerminate (CompDisplay     *d,
 }
 
 static Bool
-switchNext (CompDisplay     *d,
-	    CompAction      *action,
-	    CompActionState state,
-	    CompOption      *option,
-	    int	            nOption)
+switchDoSwitch (CompDisplay     *d,
+		CompAction      *action,
+		CompActionState state,
+		CompOption      *option,
+		int             nOption,
+		Bool            toNext,
+		Bool            allWindows,
+		Bool            showPopup,
+		SwitcherMode    switchMode)
 {
     CompScreen *s;
     Window     xid;
@@ -958,7 +1287,7 @@ switchNext (CompDisplay     *d,
 
 	if (!ss->switching)
 	{
-	    switchInitiate (s, FALSE, TRUE);
+	    switchInitiate (s, allWindows, showPopup, switchMode);
 
 	    if (state & CompActionStateInitKey)
 		action->state |= CompActionStateTermKey;
@@ -971,47 +1300,32 @@ switchNext (CompDisplay     *d,
 
 	}
 
-	switchToWindow (s, TRUE);
+	switchToWindow (s, toNext);
     }
 
     return FALSE;
 }
-
 static Bool
-switchPrev (CompDisplay     *d,
+switchNext (CompDisplay     *d,
 	    CompAction      *action,
 	    CompActionState state,
 	    CompOption      *option,
 	    int	            nOption)
 {
-    CompScreen *s;
-    Window     xid;
-
-    xid = getIntOptionNamed (option, nOption, "root", 0);
-
-    s = findScreenAtDisplay (d, xid);
-    if (s)
-    {
-	SWITCH_SCREEN (s);
-
-	if (!ss->switching)
-	{
-	    switchInitiate (s, FALSE, TRUE);
-
-	    if (state & CompActionStateInitKey)
-		action->state |= CompActionStateTermKey;
-
-	    if (state & CompActionStateInitButton)
-		action->state |= CompActionStateTermButton;
-
-	    if (state & CompActionStateInitEdge)
-		action->state |= CompActionStateTermEdge;
-	}
+    return switchDoSwitch (d, action, state, option, nOption,
+			   TRUE, FALSE, TRUE, ApplicationSwitcher);
+}
 
-	switchToWindow (s, FALSE);
-    }
 
-    return FALSE;
+static Bool
+switchPrev (CompDisplay     *d,
+	    CompAction      *action,
+	    CompActionState state,
+	    CompOption      *option,
+	    int	            nOption)
+{
+    return switchDoSwitch (d, action, state, option, nOption,
+			   FALSE, FALSE, TRUE, ApplicationSwitcher);
 }
 
 static Bool
@@ -1021,34 +1335,8 @@ switchNextAll (CompDisplay     *d,
 	       CompOption      *option,
 	       int	       nOption)
 {
-    CompScreen *s;
-    Window     xid;
-
-    xid = getIntOptionNamed (option, nOption, "root", 0);
-
-    s = findScreenAtDisplay (d, xid);
-    if (s)
-    {
-	SWITCH_SCREEN (s);
-
-	if (!ss->switching)
-	{
-	    switchInitiate (s, TRUE, TRUE);
-
-	    if (state & CompActionStateInitKey)
-		action->state |= CompActionStateTermKey;
-
-	    if (state & CompActionStateInitButton)
-		action->state |= CompActionStateTermButton;
-
-	    if (state & CompActionStateInitEdge)
-		action->state |= CompActionStateTermEdge;
-	}
-
-	switchToWindow (s, TRUE);
-    }
-
-    return FALSE;
+    return switchDoSwitch (d, action, state, option, nOption,
+			   TRUE, TRUE, TRUE, ApplicationSwitcher);
 }
 
 static Bool
@@ -1058,34 +1346,8 @@ switchPrevAll (CompDisplay     *d,
 	       CompOption      *option,
 	       int	       nOption)
 {
-    CompScreen *s;
-    Window     xid;
-
-    xid = getIntOptionNamed (option, nOption, "root", 0);
-
-    s = findScreenAtDisplay (d, xid);
-    if (s)
-    {
-	SWITCH_SCREEN (s);
-
-	if (!ss->switching)
-	{
-	    switchInitiate (s, TRUE, TRUE);
-
-	    if (state & CompActionStateInitKey)
-		action->state |= CompActionStateTermKey;
-
-	    if (state & CompActionStateInitButton)
-		action->state |= CompActionStateTermButton;
-
-	    if (state & CompActionStateInitEdge)
-		action->state |= CompActionStateTermEdge;
-	}
-
-	switchToWindow (s, FALSE);
-    }
-
-    return FALSE;
+    return switchDoSwitch (d, action, state, option, nOption,
+			   FALSE, TRUE, TRUE, ApplicationSwitcher);
 }
 
 static Bool
@@ -1095,35 +1357,8 @@ switchNextNoPopup (CompDisplay     *d,
 		   CompOption      *option,
 		   int	           nOption)
 {
-    CompScreen *s;
-    Window     xid;
-
-    xid = getIntOptionNamed (option, nOption, "root", 0);
-
-    s = findScreenAtDisplay (d, xid);
-    if (s)
-    {
-	SWITCH_SCREEN (s);
-
-	if (!ss->switching)
-	{
-	    switchInitiate (s, FALSE, FALSE);
-
-	    if (state & CompActionStateInitKey)
-		action->state |= CompActionStateTermKey;
-
-	    if (state & CompActionStateInitButton)
-		action->state |= CompActionStateTermButton;
-
-	    if (state & CompActionStateInitEdge)
-		action->state |= CompActionStateTermEdge;
-
-	}
-
-	switchToWindow (s, TRUE);
-    }
-
-    return FALSE;
+    return switchDoSwitch (d, action, state, option, nOption,
+			   TRUE, FALSE, FALSE, ApplicationSwitcher);
 }
 
 static Bool
@@ -1133,34 +1368,51 @@ switchPrevNoPopup (CompDisplay     *d,
 		   CompOption      *option,
 		   int	           nOption)
 {
-    CompScreen *s;
-    Window     xid;
-
-    xid = getIntOptionNamed (option, nOption, "root", 0);
-
-    s = findScreenAtDisplay (d, xid);
-    if (s)
-    {
-	SWITCH_SCREEN (s);
-
-	if (!ss->switching)
-	{
-	    switchInitiate (s, FALSE, FALSE);
-
-	    if (state & CompActionStateInitKey)
-		action->state |= CompActionStateTermKey;
-
-	    if (state & CompActionStateInitButton)
-		action->state |= CompActionStateTermButton;
+    return switchDoSwitch (d, action, state, option, nOption,
+			   FALSE, FALSE, FALSE, ApplicationSwitcher);
+}
 
-	    if (state & CompActionStateInitEdge)
-		action->state |= CompActionStateTermEdge;
-	}
+static Bool
+switchNextRing (CompDisplay     *d,
+	     	CompAction      *action,
+	     	CompActionState state,
+	     	CompOption      *option,
+	     	int	           nOption)
+{
+    return switchDoSwitch (d, action, state, option, nOption,
+			   TRUE, FALSE, TRUE, RingSwitcher);
+}
 
-	switchToWindow (s, FALSE);
-    }
+static Bool
+switchPrevRing (CompDisplay     *d,
+	     	CompAction      *action,
+	     	CompActionState state,
+	     	CompOption      *option,
+	     	int	           nOption)
+{
+    return switchDoSwitch (d, action, state, option, nOption,
+			   FALSE, FALSE, TRUE, RingSwitcher);
+}
+static Bool
+switchNextRingAll (CompDisplay     *d,
+		   CompAction      *action,
+		   CompActionState state,
+		   CompOption      *option,
+		   int	           nOption)
+{
+    return switchDoSwitch (d, action, state, option, nOption,
+			   TRUE, TRUE, TRUE, RingSwitcher);
+}
 
-    return FALSE;
+static Bool
+switchPrevRingAll (CompDisplay     *d,
+		   CompAction      *action,
+		   CompActionState state,
+		   CompOption      *option,
+		   int	           nOption)
+{
+    return switchDoSwitch (d, action, state, option, nOption,
+			   FALSE, TRUE, TRUE, RingSwitcher);
 }
 
 static void
@@ -1212,7 +1464,8 @@ switchWindowRemove (CompDisplay *d,
 
 	count = ss->nWindows;
 
-	if (ss->nWindows == 2)
+	if ((ss->switchMode == ApplicationSwitcher) && 
+	    (ss->nWindows == 2))
 	{
 	    if (ss->windows[0] == ss->windows[1])
 	    {
@@ -1243,6 +1496,9 @@ switchWindowRemove (CompDisplay *d,
 
 	switchUpdateWindowList (w->screen, count);
 
+	if (ss->switchMode == RingSwitcher)
+	    ss->pos = 0;
+
 	for (i = 0; i < ss->nWindows; i++)
 	{
 	    ss->selectedWindow = ss->windows[i]->id;
@@ -1250,9 +1506,14 @@ switchWindowRemove (CompDisplay *d,
 	    if (ss->selectedWindow == selected)
 		break;
 
-	    ss->pos -= WIDTH;
-	    if (ss->pos < -ss->nWindows * WIDTH)
-		ss->pos += ss->nWindows * WIDTH;
+	    if (ss->switchMode == RingSwitcher)
+		ss->pos += DIST_ROT;
+	    else
+	    {
+    		ss->pos -= WIDTH;
+    		if (ss->pos < -ss->nWindows * WIDTH)
+    		    ss->pos += ss->nWindows * WIDTH;
+	    }
 	}
 
 	if (ss->popupWindow)
@@ -1431,10 +1692,14 @@ switchPreparePaintScreen (CompScreen *s,
 
 	    ss->move -= m;
 	    ss->pos  += m;
-	    if (ss->pos < -ss->nWindows * WIDTH)
-		ss->pos += ss->nWindows * WIDTH;
-	    else if (ss->pos > 0)
-		ss->pos -= ss->nWindows * WIDTH;
+
+	    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;
@@ -1445,6 +1710,9 @@ switchPreparePaintScreen (CompScreen *s,
 		    ss->zoomedWindow = ss->selectedWindow;
 	    }
 	}
+
+	if (ss->switchMode == RingSwitcher)
+	    switchCalculateRingSwitcherPositions (s);
     }
 
     UNWRAP (ss, s, preparePaintScreen);
@@ -1601,7 +1869,9 @@ switchPaintThumb (CompWindow		  *w,
 		  int			  x,
 		  int			  y,
 		  int			  x1,
-		  int			  x2)
+		  int			  x2,
+		  float                   scale,
+		  float                   brightness)
 {
     WindowPaintAttrib sAttrib = *attrib;
     int		      wx, wy;
@@ -1625,8 +1895,16 @@ switchPaintThumb (CompWindow		  *w,
 
 	SWITCH_SCREEN (w->screen);
 
-	width  = WIDTH  - (SPACE << 1);
-	height = HEIGHT - (SPACE << 1);
+	if (ss->switchMode == RingSwitcher)
+	{
+	    width = ss->opt[SWITCH_SCREEN_OPTION_RING_THUMB_WIDTH].value.i;
+    	    height = ss->opt[SWITCH_SCREEN_OPTION_RING_THUMB_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;
@@ -1646,14 +1924,32 @@ switchPaintThumb (CompWindow		  *w,
 	else
 	    sAttrib.xScale = sAttrib.yScale;
 
+	sAttrib.xScale     *= scale;
+	sAttrib.yScale     *= scale;
+	sAttrib.brightness *= brightness;
+
 	width  = ww * sAttrib.xScale;
 	height = wh * sAttrib.yScale;
 
-	wx = x + SPACE + ((WIDTH  - (SPACE << 1)) - width)  / 2;
-	wy = y + SPACE + ((HEIGHT - (SPACE << 1)) - height) / 2;
+	if (ss->switchMode == RingSwitcher)
+	{
+	    /* ring switcher uses center coordinates */
+	    x -= (width / 2);
+	    y -= (height / 2);
+
+	    sAttrib.xTranslate = x - w->attrib.x;
+	    sAttrib.yTranslate = y - w->attrib.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;
+    	    sAttrib.xTranslate = wx - w->attrib.x + 
+		                 w->input.left * sAttrib.xScale;
+    	    sAttrib.yTranslate = wy - w->attrib.y + 
+		                 w->input.top  * sAttrib.yScale;
+	}
 
 	initFragmentAttrib (&fragment, &sAttrib);
 
@@ -1686,17 +1982,38 @@ switchPaintThumb (CompWindow		  *w,
 	    icon = getWindowIcon (w, ICON_SIZE, ICON_SIZE);
 	    if (icon)
 	    {
-		sAttrib.xScale = sAttrib.yScale = 1.0f;
+		sAttrib.xScale = sAttrib.yScale = 1.0f * scale;
 
-		wx = x + WIDTH  - icon->width  - SPACE;
-		wy = y + HEIGHT - icon->height - SPACE;
+		if (ss->switchMode == RingSwitcher)
+		{
+		    wx = x + width  - (icon->width * scale);
+		    wy = y + height - (icon->height * scale);
+		}
+		else
+		{
+    		    wx = x + WIDTH  - icon->width  - SPACE;
+    		    wy = y + HEIGHT - icon->height - SPACE;
+		}
 	    }
 	}
     }
     else
     {
-	width  = WIDTH  - (WIDTH  >> 2);
-	height = HEIGHT - (HEIGHT >> 2);
+	SWITCH_SCREEN (w->screen);
+
+	if (ss->switchMode == RingSwitcher)
+	{
+	    width = ss->opt[SWITCH_SCREEN_OPTION_RING_THUMB_WIDTH].value.i;
+    	    height = ss->opt[SWITCH_SCREEN_OPTION_RING_THUMB_HEIGHT].value.i;
+	}
+	else
+	{
+	    width  = WIDTH;
+	    height = HEIGHT;
+	}
+
+	width  -= (width / 4);
+	height -= (height / 4);
 
 	icon = getWindowIcon (w, width, height);
 	if (!icon)
@@ -1724,11 +2041,23 @@ switchPaintThumb (CompWindow		  *w,
 	    else
 		sAttrib.xScale = sAttrib.yScale;
 
+	    sAttrib.xScale     *= scale;
+	    sAttrib.yScale     *= scale;
+	    sAttrib.brightness *= brightness;
+
 	    width  = icon->width  * sAttrib.xScale;
 	    height = icon->height * sAttrib.yScale;
 
-	    wx = x + SPACE + ((WIDTH  - (SPACE << 1)) - width)  / 2;
-	    wy = y + SPACE + ((HEIGHT - (SPACE << 1)) - height) / 2;
+	    if (ss->switchMode == RingSwitcher)
+	    {
+		wx = x - (width / 2);
+		wy = y - (width / 2);
+	    }
+	    else
+	    {
+    		wx = x + SPACE + ((WIDTH  - (SPACE << 1)) - width)  / 2;
+    		wy = y + SPACE + ((HEIGHT - (SPACE << 1)) - height) / 2;
+	    }
 	}
     }
 
@@ -1826,46 +2155,65 @@ switchPaintWindow (CompWindow		   *w,
 	glEnable (GL_SCISSOR_TEST);
 	glScissor (x1, 0, x2 - x1, w->screen->height);
 
-	for (i = 0; i < ss->nWindows; i++)
+	if (ss->switchMode == RingSwitcher)
 	{
-	    if (x + WIDTH > x1)
-		switchPaintThumb (ss->windows[i], &w->lastPaint, transform,
-				  mask, x, y, x1, x2);
-
-	    x += WIDTH;
+	    for (i = 0; i < ss->nWindows; i++)
+	    {
+		switchPaintThumb(ss->windows[ss->ringDrawArray[i].index],
+				 &w->lastPaint, transform, mask, 
+				 ss->ringDrawArray[i].x, ss->ringDrawArray[i].y,
+				 x1, x2, ss->ringDrawArray[i].scale,
+				 ss->ringDrawArray[i].brightness);
+	    }
 	}
-
-	for (i = 0; i < ss->nWindows; i++)
+	else
 	{
-	    if (x > x2)
-		break;
+    	    for (i = 0; i < ss->nWindows; i++)
+    	    {
+    		if (x + WIDTH > x1)
+    		    switchPaintThumb (ss->windows[i], &w->lastPaint, transform,
+    				      mask, x, y, x1, x2, 1.0, 1.0);
+
+    		x += WIDTH;
+    	    }
+
+    	    for (i = 0; i < ss->nWindows; i++)
+    	    {
+    		if (x > x2)
+    		    break;
 
-	    switchPaintThumb (ss->windows[i], &w->lastPaint, transform, mask,
-			      x, y, x1, x2);
+    		switchPaintThumb (ss->windows[i], &w->lastPaint, transform, mask,
+    				  x, y, x1, x2, 1.0, 1.0);
 
-	    x += WIDTH;
+    		x += WIDTH;
+    	    }
 	}
 
 	glPopAttrib ();
 
 	s->display->textureFilter = filter;
 
-	cx = w->attrib.x + (w->width >> 1);
-
-	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);
+	if (ss->switchMode == ApplicationSwitcher)
+	{
+    	    cx = w->attrib.x + (w->width >> 1);
+
+    	    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)
     {
+	WindowPaintAttrib wAttrib = *attrib;
+
 	if (ss->bringToFront && ss->selectedWindow == ss->zoomedWindow)
 	    zoomType = ZOOMED_WINDOW_MASK;
 
@@ -1873,8 +2221,14 @@ switchPaintWindow (CompWindow		   *w,
 	    return (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK) ?
 		FALSE : TRUE;
 
+	if ((ss->switchMode == RingSwitcher) &&
+	    (ss->opt[SWITCH_SCREEN_OPTION_RING_TRANSPARENT_ALL].value.b))
+	{
+	    wAttrib.opacity = 0;
+	}
+
 	UNWRAP (ss, s, paintWindow);
-	status = (*s->paintWindow) (w, attrib, transform, region, mask);
+	status = (*s->paintWindow) (w, &wAttrib, transform, region, mask);
 	WRAP (ss, s, paintWindow, switchPaintWindow);
     }
     else if (ss->switching)
@@ -1893,6 +2247,13 @@ switchPaintWindow (CompWindow		   *w,
 		sAttrib.opacity = (sAttrib.opacity * ss->opacity) >> 16;
 	}
 
+	if ((ss->switchMode == RingSwitcher) &&
+	    (ss->opt[SWITCH_SCREEN_OPTION_RING_TRANSPARENT_ALL].value.b) &&
+	    (matchEval (&ss->opt[SWITCH_SCREEN_OPTION_WINDOW_MATCH].value.match, w)))
+	{
+	    sAttrib.opacity = 0;
+	}
+
 	if (ss->bringToFront && w->id == ss->zoomedWindow)
 	    zoomType = ZOOMED_WINDOW_MASK;
 
@@ -1983,6 +2344,10 @@ switchSetDisplayOption (CompDisplay     *display,
     case SWITCH_DISPLAY_OPTION_PREV:
     case SWITCH_DISPLAY_OPTION_PREV_ALL:
     case SWITCH_DISPLAY_OPTION_PREV_NO_POPUP:
+    case SWITCH_DISPLAY_OPTION_NEXT_RING:
+    case SWITCH_DISPLAY_OPTION_PREV_RING:
+    case SWITCH_DISPLAY_OPTION_NEXT_RING_ALL:
+    case SWITCH_DISPLAY_OPTION_PREV_RING_ALL:
 	if (setDisplayAction (display, o, value))
 	    return TRUE;
     default:
@@ -2097,7 +2462,82 @@ switchDisplayInitOptions (SwitchDisplay *sd,
     o->value.action.state     = CompActionStateInitKey;
     o->value.action.state    |= CompActionStateInitButton;
     o->value.action.type      = 0;
-}
+
+   o = &sd->opt[SWITCH_DISPLAY_OPTION_NEXT_RING];
+   o->name                       = "next_ring";
+   o->shortDesc                  = N_("Next Window (Ring)");
+   o->longDesc                   = N_("Popup Ring 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.keycode   = 
+       XKeysymToKeycode (display,
+			 XStringToKeysym(SWITCH_RING_NEXT_KEY_DEFAULT));
+
+   o = &sd->opt[SWITCH_DISPLAY_OPTION_PREV_RING];
+   o->name                       = "prev_ring";
+   o->shortDesc                  = N_("Prev Window (Ring)");
+   o->longDesc                   = N_("Popup Ring 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.keycode   = 
+       XKeysymToKeycode (display,
+			 XStringToKeysym(SWITCH_RING_PREV_KEY_DEFAULT));
+
+   o = &sd->opt[SWITCH_DISPLAY_OPTION_NEXT_RING_ALL];
+   o->name                       = "next_all_ring";
+   o->shortDesc                  = N_("Next Window (Ring - All Workspaces)");
+   o->longDesc                   = N_("Popup Ring Switcher if not visible and "
+				      "select Next Window out of All Windows.");
+   o->type		         = CompOptionTypeAction;
+   o->value.action.initiate      = switchNextRingAll;
+   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.keycode   = 
+       XKeysymToKeycode (display,
+			 XStringToKeysym(SWITCH_RING_NEXT_ALL_KEY_DEFAULT));
+ 
+   o = &sd->opt[SWITCH_DISPLAY_OPTION_PREV_RING_ALL];
+   o->name                       = "prev_all_ring";
+   o->shortDesc                  = N_("Prev Window (Ring - All Workspaces)");
+   o->longDesc                   = N_("Popup Ring Switcher if not visible and "
+				      "select Previous Window out of All Windows.");
+   o->type		         = CompOptionTypeAction;
+   o->value.action.initiate      = switchPrevRingAll;
+   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.keycode   = 
+       XKeysymToKeycode (display,
+			 XStringToKeysym(SWITCH_RING_PREV_ALL_KEY_DEFAULT));
+ }
+
+
+
 
 static Bool
 switchInitDisplay (CompPlugin  *p,
@@ -2159,9 +2599,10 @@ switchInitScreen (CompPlugin *p,
 
     ss->lastActiveNum  = 0;
 
-    ss->windows     = 0;
-    ss->nWindows    = 0;
-    ss->windowsSize = 0;
+    ss->windows       = NULL;
+    ss->ringDrawArray = NULL;
+    ss->nWindows      = 0;
+    ss->windowsSize   = 0;
 
     ss->pos = ss->move = 0;
 
@@ -2192,6 +2633,7 @@ switchInitScreen (CompPlugin *p,
 
     ss->bringToFront = SWITCH_BRINGTOFRONT_DEFAULT;
     ss->allWindows   = FALSE;
+    ss->switchMode   = ApplicationSwitcher;
 
     switchScreenInitOptions (ss);
 
@@ -2204,6 +2646,10 @@ switchInitScreen (CompPlugin *p,
     addScreenAction (s, &sd->opt[SWITCH_DISPLAY_OPTION_PREV_ALL].value.action);
     addScreenAction (s, &sd->opt[SWITCH_DISPLAY_OPTION_NEXT_NO_POPUP].value.action);
     addScreenAction (s, &sd->opt[SWITCH_DISPLAY_OPTION_PREV_NO_POPUP].value.action);
+    addScreenAction (s, &sd->opt[SWITCH_DISPLAY_OPTION_NEXT_RING].value.action);
+    addScreenAction (s, &sd->opt[SWITCH_DISPLAY_OPTION_PREV_RING].value.action);
+    addScreenAction (s, &sd->opt[SWITCH_DISPLAY_OPTION_NEXT_RING_ALL].value.action);
+    addScreenAction (s, &sd->opt[SWITCH_DISPLAY_OPTION_PREV_RING_ALL].value.action);
 
     WRAP (ss, s, preparePaintScreen, switchPreparePaintScreen);
     WRAP (ss, s, donePaintScreen, switchDonePaintScreen);
@@ -2230,9 +2676,12 @@ switchFiniScreen (CompPlugin *p,
     UNWRAP (ss, s, paintWindow);
     UNWRAP (ss, s, damageWindowRect);
 
-    if (ss->windowsSize)
+    if (ss->windows)
 	free (ss->windows);
 
+    if (ss->ringDrawArray)
+	free (ss->ringDrawArray);
+
     free (ss);
 }