/** * * Beryl pager plugin * * pager.c * * Copyright (c) 2007 Atie H. * * * 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. * **/ /* Pager Features: - pager by hsize * vsize - pager orientation - toggle to display pager - default super+alt+p Pager TODO: - draggable pager? - size option for pager / resize w/ mouse if possible - repaint pager when hsize or vsize updated - manipulate vsize if =1 by dividing hsize(>=4) so 4x1 becomes 2x2 - perspective view of pager - miniview of viewports - switch viewport by click / swap viewport by drag-out : wall's job? - animation for toggle pager ? - animation for switch/swap viewport */ #include #include #include #include #include #include #include #define PI 3.14159265359f #define PAGER_TOGGLE_KEY_DEFAULT "p" #define PAGER_TOGGLE_MODIFIERS_DEFAULT (CompAltMask | CompSuperMask) static int displayPrivateIndex; enum { PAGER_DISPLAY_OPTION_TOGGLE, PAGER_DISPLAY_OPTION_WIDTH, PAGER_DISPLAY_OPTION_HEIGHT, PAGER_DISPLAY_OPTION_GRAVITY, PAGER_DISPLAY_OPTION_OFFSET, PAGER_DISPLAY_OPTION_NUM }; typedef enum _PagerGravity { PagerGravityNorthWest = 0, PagerGravityNorthEast, PagerGravitySouthEast, PagerGravitySouthWest, PagerGravityNum } PagerGravity; #define PAGER_GRAVITY_DEFAULT PagerGravitySouthEast static char *pagerGravities[] = { N_("NorthWest"), N_("NorthEast"), N_("SouthEast"), N_("SouthWest") }; #define PAGER_GRAVITY_OFFSET_DEFAULT 5 #define PAGER_GRAVITY_OFFSET_MIN 0 #define PAGER_GRAVITY_OFFSET_MAX 50 #define PAGER_WIDTH_DEFAULT 300 #define PAGER_WIDTH_MIN 50 #define PAGER_WIDTH_MAX 500 #define PAGER_HEIGHT_DEFAULT 200 #define PAGER_HEIGHT_MIN 50 #define PAGER_HEIGHT_MAX 500 typedef struct _PagerCairoContext { Pixmap pixmap; CompTexture texture; cairo_surface_t *surface; cairo_t *cr; int width; int height; } PagerCairoContext; typedef struct _PagerDisplay { int screenPrivateIndex; HandleEventProc handleEvent; Bool togglePager; int pagerGravity; int offset; int pagerWidth; int pagerHeight; CompOption opt[PAGER_DISPLAY_OPTION_NUM]; } PagerDisplay; typedef struct _PagerScreen { DonePaintScreenProc donePaintScreen; PaintScreenProc paintScreen; PreparePaintScreenProc preparePaintScreen; PaintTransformedScreenProc paintTransformedScreen; float firstViewportX; float firstViewportY; float viewportWidth; float viewportHeight; float viewportBorder; WindowPaintAttrib mSAttribs; float mSzCamera; PagerCairoContext *pagerContext; PagerCairoContext *thumbContext; } PagerScreen; /* Helpers */ #define GET_PAGER_DISPLAY(d) \ ((PagerDisplay *) (d)->privates[displayPrivateIndex].ptr) #define PAGER_DISPLAY(d) \ PagerDisplay *pd = GET_PAGER_DISPLAY(d); #define GET_PAGER_SCREEN(s, pd) \ ((PagerScreen *) (s)->privates[(pd)->screenPrivateIndex].ptr) #define PAGER_SCREEN(s) \ PagerScreen *ps = GET_PAGER_SCREEN(s, GET_PAGER_DISPLAY(s->display)); #define NUM_OPTIONS(d) (sizeof ((d)->opt) / sizeof (CompOption)) static void pagerDrawPager(CompScreen *s) { PAGER_SCREEN(s); cairo_t * cr = ps->pagerContext->cr; cairo_save(cr); cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); cairo_paint(cr); cairo_restore(cr); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_save(cr); int hsize = s->hsize; int vsize = s->vsize; float border = 10.0f; float outline = 2.0f; float width = (float) ps->pagerContext->width; width -= outline; float height = (float) ps->pagerContext->height; height -= outline; cairo_pattern_t *pattern; cairo_translate(cr, outline/2.0f, outline/2.0f); // set the pattern for the pager's background pattern = cairo_pattern_create_linear(0, 0, width, height); cairo_pattern_add_color_stop_rgba(pattern, 0.0f, 0.80, 0.80, 0.90 ,0.85); cairo_pattern_add_color_stop_rgba(pattern, 0.65f, 0.95, 0.95, 1.0f, 0.85); cairo_pattern_add_color_stop_rgba(pattern, 0.85f, 0.85, 0.85, 0.85 ,0.85); cairo_set_source(cr, pattern); // draw the border's shape cairo_arc(cr, border, border, border, PI, 1.5f*PI); cairo_arc(cr, border+width-2*border, border, border, 1.5f*PI, 2.0*PI); cairo_arc(cr, width-border, height-border, border, 0, PI/2.0f); cairo_arc(cr, border, height-border, border, PI/2.0f, PI); cairo_close_path(cr); // apply pattern to pager cairo_fill_preserve(cr); // draw an outline cairo_set_line_width(cr, outline); cairo_set_source_rgba(cr, 0.2,0.2,0.2,0.85); cairo_stroke(cr); cairo_pattern_destroy(pattern); float viewportWidth = floor((width - border*(s->hsize+1))/hsize); float viewportHeight = floor((height - border*(s->vsize+1))/vsize); ps->viewportWidth = viewportWidth; ps->viewportHeight = viewportHeight; ps->viewportBorder = border; cairo_translate(cr, border, border); int i, j; float vpX, vpY; for (i = 0; i < hsize; i++) { for (j = 0; j < vsize; j++) { vpX = i*(viewportWidth+border); vpY = j*(viewportHeight+border); // this cuts a hole into our background cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); cairo_rectangle(cr, vpX, vpY, viewportWidth, viewportHeight); cairo_fill_preserve(cr); cairo_set_operator(cr, CAIRO_OPERATOR_XOR); cairo_fill(cr); } } cairo_restore(cr); } static void pagerDrawThumb(CompScreen *s) { PAGER_SCREEN(s); cairo_t * cr = ps->thumbContext->cr; cairo_save(cr); cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); cairo_paint(cr); cairo_restore(cr); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_save(cr); float border = 10.0f; float outline = 2.0f; float width = (float) ps->thumbContext->width; float height = (float) ps->thumbContext->height; ps->viewportWidth = width; ps->viewportHeight = height; ps->viewportBorder = border; width -= outline; height -= outline; cairo_translate(cr, outline/2.0f, outline/2.0f); cairo_pattern_t *pattern; pattern = cairo_pattern_create_linear(0, 0, width, height); cairo_pattern_add_color_stop_rgba(pattern, 0.0f, 0.2, 0.2, 0.2 ,0.35); cairo_pattern_add_color_stop_rgba(pattern, 1.0f, 0.25, 0.25, 0.25, 0.25); // apply the patter for thumb background cairo_set_source(cr, pattern); cairo_rectangle(cr, 0, 0, width, height); cairo_fill_preserve(cr); cairo_set_line_width(cr, outline); cairo_set_source_rgba(cr, 0.2, 0.2, 0.2, 0.65); cairo_stroke(cr); cairo_pattern_destroy(pattern); cairo_restore(cr); } static void pagerSetupCairoContext(CompScreen *s, PagerCairoContext *context) { XRenderPictFormat * format; Screen * screen; screen = ScreenOfDisplay(s->display->display, s->screenNum); int width, height; width = context->width; height = context->height; initTexture(s, &context->texture); format = XRenderFindStandardFormat(s->display->display, PictStandardARGB32); context->pixmap = XCreatePixmap(s->display->display, s->root, width, height, 32); if (!bindPixmapToTexture(s, &context->texture, context->pixmap, width, height, 32)) printf("Couldn't create cairo context for pager\n"); context->surface = cairo_xlib_surface_create_with_xrender_format(s->display->display, context->pixmap, screen, format, width, height); context->cr = cairo_create(context->surface); cairo_t *cr = context->cr; cairo_save(cr); cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); cairo_paint(cr); cairo_restore(cr); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); } static void pagerDestroyCairoContext(CompScreen *s, PagerCairoContext *context) { if (context->cr) cairo_destroy(context->cr); if (context->surface) cairo_surface_destroy(context->surface); finiTexture(s, &context->texture); if (context->pixmap) XFreePixmap(s->display->display, context->pixmap); } static void pagerDrawCairoTextureOnScreen(CompScreen *s, int output, Region region) { PAGER_SCREEN(s); PAGER_DISPLAY(s->display); glPushMatrix(); prepareXCoords(s, output, -DEFAULT_Z_CAMERA); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glEnable(GL_BLEND); float border = 10.0f; float width = (float) ps->pagerContext->width; float height = (float) ps->pagerContext->height; float topleftx = 0; float toplefty = 0; //?FIXME somehow need to read display options here again pd->offset = pd->opt[PAGER_DISPLAY_OPTION_OFFSET].value.i; pd->pagerWidth = pd->opt[PAGER_DISPLAY_OPTION_WIDTH].value.i; pd->pagerHeight = pd->opt[PAGER_DISPLAY_OPTION_HEIGHT].value.i; //FIXME, gravity doesn't the value from settings at init pd->pagerGravity = PagerGravitySouthEast; switch (pd->pagerGravity) { case PagerGravityNorthWest: topleftx = pd->offset; toplefty = pd->offset; break; case PagerGravityNorthEast: topleftx = s->width - pd->pagerWidth - pd->offset; toplefty = pd->offset; break; case PagerGravitySouthEast: topleftx = s->width - pd->pagerWidth - pd->offset; toplefty = s->height - pd->pagerHeight - pd->offset; break; case PagerGravitySouthWest: topleftx = pd->offset; toplefty = s->height - pd->pagerHeight - pd->offset; break; default: break; } //draw pager enableTexture(s, &ps->pagerContext->texture, COMP_TEXTURE_FILTER_GOOD); CompMatrix matrix = ps->pagerContext->texture.matrix; matrix.x0 -= topleftx * matrix.xx; matrix.y0 -= toplefty * matrix.yy; BOX box; box.x1 = topleftx; box.x2 = box.x1 + width; box.y1 = toplefty; box.y2 = box.y1 + height; glBegin(GL_QUADS); glTexCoord2f(COMP_TEX_COORD_X(&matrix, box.x1), COMP_TEX_COORD_Y(&matrix, box.y2)); glVertex2i(box.x1, box.y2); glTexCoord2f(COMP_TEX_COORD_X(&matrix, box.x2), COMP_TEX_COORD_Y(&matrix, box.y2)); glVertex2i(box.x2, box.y2); glTexCoord2f(COMP_TEX_COORD_X(&matrix, box.x2), COMP_TEX_COORD_Y(&matrix, box.y1)); glVertex2i(box.x2, box.y1); glTexCoord2f(COMP_TEX_COORD_X(&matrix, box.x1), COMP_TEX_COORD_Y(&matrix, box.y1)); glVertex2i(box.x1, box.y1); glEnd(); disableTexture(s, &ps->pagerContext->texture); //draw thumb width = (float) ps->thumbContext->width; height = (float) ps->thumbContext->height; int i,j; enableTexture(s, &ps->thumbContext->texture, COMP_TEXTURE_FILTER_GOOD); glBegin(GL_QUADS); for (i = 0; i < s->hsize; i++) { for (j = 0; j < s->vsize; j++) { box.x1 = i*(width+border); box.x1 += topleftx + border; box.x2 = box.x1 + width; box.y1 = j*(height+border); box.y1 += toplefty + border; box.y2 = box.y1 + height; matrix = ps->thumbContext->texture.matrix; matrix.x0 -= box.x1 * matrix.xx; matrix.y0 -= box.y1 * matrix.yy; glTexCoord2f(COMP_TEX_COORD_X(&matrix, box.x1), COMP_TEX_COORD_Y(&matrix, box.y2)); glVertex2i(box.x1, box.y2); glTexCoord2f(COMP_TEX_COORD_X(&matrix, box.x2), COMP_TEX_COORD_Y(&matrix, box.y2)); glVertex2i(box.x2, box.y2); glTexCoord2f(COMP_TEX_COORD_X(&matrix, box.x2), COMP_TEX_COORD_Y(&matrix, box.y1)); glVertex2i(box.x2, box.y1); glTexCoord2f(COMP_TEX_COORD_X(&matrix, box.x1), COMP_TEX_COORD_Y(&matrix, box.y1)); glVertex2i(box.x1, box.y1); } } glEnd(); disableTexture(s, &ps->thumbContext->texture); glDisable(GL_BLEND); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glPopMatrix(); screenTexEnvMode(s, GL_REPLACE); glColor4usv(defaultColor); } static Bool pagerPaintScreen(CompScreen *s, const ScreenPaintAttrib * sAttrib, const CompTransform *transform, Region region, int output, unsigned int mask) { Bool status; PAGER_SCREEN(s); PAGER_DISPLAY(s->display); UNWRAP(ps, s, paintScreen); status = (*s->paintScreen) (s, sAttrib, transform, region, output, mask); WRAP(ps, s, paintScreen, pagerPaintScreen); if (pd->togglePager) { pagerDrawCairoTextureOnScreen(s, output, region); int i,j; int origVX = s->x; int origVY = s->y; moveScreenViewport(s, s->x, s->y, FALSE); for (j = 0; j < s->vsize; j++) { for (i = 0; i < s->hsize; i++) { float mx = ps->firstViewportX + (i * (ps->viewportWidth + ps->viewportBorder)); float my = ps->firstViewportY + (i * (ps->viewportHeight + ps->viewportBorder)); float mw = ps->viewportWidth; float mh = ps->viewportHeight; ps->mSAttribs.xTranslate = mx / s->outputDev[output].width; ps->mSAttribs.yTranslate = -my / s->outputDev[output].height; ps->mSAttribs.xScale = mw / s->width; ps->mSAttribs.yScale = mh / s->height; /* FIXME (*s->paintTransformedScreen) (s, sAttrib, transform, region, output, mask | PAINT_SCREEN_TRANSFORMED_MASK); */ moveScreenViewport(s, -1, 0, FALSE); } moveScreenViewport(s, 0, -1, FALSE); } moveScreenViewport(s, -origVX, -origVY, FALSE); } return status; } static void pagerPaintTransformedScreen(CompScreen * s, const ScreenPaintAttrib * sAttrib, const CompTransform *transform, Region region, int output, unsigned int mask) { PAGER_SCREEN(s); CompTransform sTransform = *transform; //move each screen to the correct output position matrixTranslate(&sTransform, -s->outputDev[output].region.extents.x1 / s->outputDev[output].width, s->outputDev[output].region.extents.y1 / s->outputDev[output].height, 0.0f); matrixTranslate(&sTransform, 0.0f, 0.0f, -DEFAULT_Z_CAMERA); matrixTranslate(&sTransform, ps->mSAttribs.xTranslate, ps->mSAttribs.yTranslate, ps->mSzCamera); // move orgin to top left matrixTranslate(&sTransform, -0.5f, 0.5f, 0.0f); matrixScale(&sTransform, ps->mSAttribs.xScale, ps->mSAttribs.yScale, 1.0); // revert prepareXCoords region shift. Now all screens display the same matrixTranslate(&sTransform, 0.5f, 0.5f, DEFAULT_Z_CAMERA); matrixTranslate(&sTransform, s->outputDev[output].region.extents.x1 / s->outputDev[output].width, -s->outputDev[output].region.extents.y2 / s->outputDev[output].height, 0.0f); UNWRAP(ps, s, paintTransformedScreen); (*s->paintTransformedScreen) (s, sAttrib, &sTransform, &s->region, output, mask); WRAP(ps, s, paintTransformedScreen, pagerPaintTransformedScreen); } static void pagerHandleEvent(CompDisplay * d, XEvent * event) { PAGER_DISPLAY(d); UNWRAP(pd, d, handleEvent); (*d->handleEvent) (d, event); WRAP(pd, d, handleEvent, pagerHandleEvent); } static Bool pagerToggle(CompDisplay * d, CompAction * action, CompActionState state, CompOption * option, int nOption) { CompScreen *s; Window xid; PAGER_DISPLAY(d); pd->togglePager = !pd->togglePager; xid = getIntOptionNamed(option, nOption, "root", 0); s = findScreenAtDisplay(d, xid); damageScreen(s); return TRUE; } static void pagerDisplayInitOptions(PagerDisplay *pd) { CompOption *o; o = &pd->opt[PAGER_DISPLAY_OPTION_TOGGLE]; o->advanced = False; o->name = "toggle_display"; o->group = N_("Bindings"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Toggle Pager"); o->longDesc = N_("Toggle to display pager."); o->type = CompOptionTypeAction; o->value.action.initiate = pagerToggle; o->value.action.terminate = 0; o->value.action.bell = 0; o->value.action.edgeMask = 0; o->value.action.state = CompActionStateInitKey; o->value.action.type = CompBindingTypeKey; o->value.action.key.modifiers = PAGER_TOGGLE_MODIFIERS_DEFAULT; o->value.action.key.keysym = XStringToKeysym(PAGER_TOGGLE_KEY_DEFAULT); o = &pd->opt[PAGER_DISPLAY_OPTION_WIDTH]; o->advanced = False; o->name = "pager_width"; o->group = N_("Pager"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Pager Width"); o->longDesc = N_("Pager Width."); o->type = CompOptionTypeInt; o->value.i = PAGER_WIDTH_DEFAULT; o->rest.i.min = PAGER_WIDTH_MIN; o->rest.i.max = PAGER_WIDTH_MAX; o = &pd->opt[PAGER_DISPLAY_OPTION_HEIGHT]; o->advanced = False; o->name = "pager_height"; o->group = N_("Pager"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Pager Height"); o->longDesc = N_("Pager Height."); o->type = CompOptionTypeInt; o->value.i = PAGER_HEIGHT_DEFAULT; o->rest.i.min = PAGER_HEIGHT_MIN; o->rest.i.max = PAGER_HEIGHT_MAX; o = &pd->opt[PAGER_DISPLAY_OPTION_GRAVITY]; o->advanced = False; o->name = "pager_gravity"; o->group = N_("Pager"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Pager Gravity"); o->longDesc = N_("Orientation of pager."); o->type = CompOptionTypeString; o->value.s = strdup(pagerGravities[PAGER_GRAVITY_DEFAULT]); o->rest.s.string = pagerGravities; o->rest.s.nString = PagerGravityNum; o = &pd->opt[PAGER_DISPLAY_OPTION_OFFSET]; o->advanced = False; o->name = "offset"; o->group = N_("Pager"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Offset"); o->longDesc = N_("Offset from corner."); o->type = CompOptionTypeInt; o->value.i = PAGER_GRAVITY_OFFSET_DEFAULT; o->rest.i.min = PAGER_GRAVITY_OFFSET_MIN; o->rest.i.max = PAGER_GRAVITY_OFFSET_MAX; } static CompOption *pagerGetDisplayOptions(CompDisplay * d, int *count) { if (d) { PAGER_DISPLAY(d); *count = NUM_OPTIONS(pd); return pd->opt; } else { PagerDisplay *pd = malloc(sizeof(PagerDisplay)); pagerDisplayInitOptions(pd); *count = NUM_OPTIONS(pd); return pd->opt; } } static Bool pagerSetDisplayOption(CompDisplay *d, char *name, CompOptionValue *value) { CompOption *o; int index; PAGER_DISPLAY(d); o = compFindOption(pd->opt, NUM_OPTIONS(pd), name, &index); if (!o) return FALSE; switch (index) { case PAGER_DISPLAY_OPTION_TOGGLE: if (setDisplayAction(d, o, value)) return TRUE; break; case PAGER_DISPLAY_OPTION_WIDTH: if (compSetIntOption(o, value)) { pd->pagerWidth = o->value.i; return TRUE; } break; case PAGER_DISPLAY_OPTION_HEIGHT: if (compSetIntOption(o, value)) { pd->pagerHeight = o->value.i; return TRUE; } break; case PAGER_DISPLAY_OPTION_GRAVITY: if (compSetStringOption(o, value)) { int i; for (i = 0; i < PagerGravityNum; i++) { if (strcmp(o->value.s, pagerGravities[i]) == 0) { pd->pagerGravity = i; return TRUE; } } } break; case PAGER_DISPLAY_OPTION_OFFSET: if (compSetIntOption(o, value)) { pd->offset = o->value.i; return TRUE; } break; default: break; } return FALSE; } static Bool pagerInitScreen(CompPlugin * p, CompScreen * s) { PagerScreen *ps; PAGER_DISPLAY(s->display); ps = malloc(sizeof(PagerScreen)); if (!ps) return FALSE; addScreenAction(s, &pd->opt[PAGER_DISPLAY_OPTION_TOGGLE].value.action); WRAP(ps, s, paintScreen, pagerPaintScreen); s->privates[pd->screenPrivateIndex].ptr = ps; ps->viewportWidth = 0.0f; ps->viewportHeight = 0.0f; ps->viewportBorder = 0.0f; ps->pagerContext = (PagerCairoContext*) malloc(sizeof(PagerCairoContext)); ps->pagerContext->width = pd->opt[PAGER_DISPLAY_OPTION_WIDTH].value.i; ps->pagerContext->height = pd->opt[PAGER_DISPLAY_OPTION_HEIGHT].value.i; pagerSetupCairoContext(s, ps->pagerContext); pagerDrawPager(s); float border = 10.0f; ps->thumbContext = (PagerCairoContext*) malloc(sizeof(PagerCairoContext)); ps->thumbContext->width = (int) (pd->opt[PAGER_DISPLAY_OPTION_WIDTH].value.i - border*(s->hsize+1)) / s->hsize; ps->thumbContext->height = (int) (pd->opt[PAGER_DISPLAY_OPTION_HEIGHT].value.i - border*(s->vsize+1)) / s->vsize; pagerSetupCairoContext(s, ps->thumbContext); pagerDrawThumb(s); return TRUE; } static void pagerFiniScreen(CompPlugin * p, CompScreen * s) { PAGER_SCREEN(s); PAGER_DISPLAY(s->display); pagerDestroyCairoContext(s, ps->pagerContext); pagerDestroyCairoContext(s, ps->thumbContext); removeScreenAction(s, &pd->opt[PAGER_DISPLAY_OPTION_TOGGLE].value.action); UNWRAP(ps, s, paintScreen); free(ps); } static Bool pagerInitDisplay(CompPlugin * p, CompDisplay * d) { PagerDisplay *pd; pd = malloc(sizeof(PagerDisplay)); if (!pd) return FALSE; pd->screenPrivateIndex = allocateScreenPrivateIndex(d); if (pd->screenPrivateIndex < 0) { free(pd); return FALSE; } pagerDisplayInitOptions(pd); pd->togglePager = TRUE; WRAP(pd, d, handleEvent, pagerHandleEvent); d->privates[displayPrivateIndex].ptr = pd; return TRUE; } static void pagerFiniDisplay(CompPlugin * p, CompDisplay * d) { PAGER_DISPLAY(d); UNWRAP(pd, d, handleEvent); freeScreenPrivateIndex(d, pd->screenPrivateIndex); free(pd); } static Bool pagerInit(CompPlugin * p) { displayPrivateIndex = allocateDisplayPrivateIndex(); if (displayPrivateIndex < 0) return FALSE; return TRUE; } static void pagerFini(CompPlugin * p) { if (displayPrivateIndex >= 0) freeDisplayPrivateIndex(displayPrivateIndex); } CompPluginVTable pagerVTable = { "pager", N_("Pager"), N_("Beryl pager plugin"), pagerInit, pagerFini, pagerInitDisplay, pagerFiniDisplay, pagerInitScreen, pagerFiniScreen, 0, /* pagerInitWindow */ 0, /* pagerFiniWindow */ pagerGetDisplayOptions, pagerSetDisplayOption, 0, /* pagerGetScreenOptions */ 0, /* pagerSetScreenOption */ 0, /* updateLibraryFunction */ 0, /* deps */ 0, /* nDeps */ 0, /* features */ 0, /* nFeatures */ BERYL_ABI_INFO, "beryl-plugins-unsupported", /* gettext domain */ "desktop", /* category */ 0, /* groupDesc */ 0, /*nGroupDesc */ False, /* defaultEnabled */ }; CompPluginVTable *getCompPluginInfo(void) { return &pagerVTable; }