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); }