/* * 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 */ #include #include #include #include #include #include #include #include #include #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; }