123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533 |
- /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- *
- * This 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 software 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 software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
- #include <stdio.h>
- #include "XserverDesktop.h"
- #include "vncHooks.h"
-
- extern "C" {
- #define class c_class
- #define private c_private
- #include "scrnintstr.h"
- #include "windowstr.h"
- #include "gcstruct.h"
- #include "regionstr.h"
- #include "dixfontstr.h"
- #include "colormapst.h"
- #ifdef RENDER
- #include "picturestr.h"
- #endif
-
- #ifdef GC_HAS_COMPOSITE_CLIP
- #define COMPOSITE_CLIP(gc) ((gc)->pCompositeClip)
- #else
- #include "mfb.h"
- #define COMPOSITE_CLIP(gc) \
- (((mfbPrivGCPtr)((gc)->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip)
- #endif
-
- #undef class
- #undef private
- }
-
- #include "RegionHelper.h"
-
- #define DBGPRINT(x) //(fprintf x)
-
- // MAX_RECTS_PER_OP is the maximum number of rectangles we generate from
- // operations like Polylines and PolySegment. If the operation is more complex
- // than this, we simply use the bounding box. Ideally it would be a
- // command-line option, but that would involve an extra malloc each time, so we
- // fix it here.
- #define MAX_RECTS_PER_OP 5
-
- static unsigned long vncHooksGeneration = 0;
-
- // vncHooksScreenRec and vncHooksGCRec contain pointers to the original
- // functions which we "wrap" in order to hook the screen changes. The screen
- // functions are each wrapped individually, while the GC "funcs" and "ops" are
- // wrapped as a unit.
-
- typedef struct {
- XserverDesktop* desktop;
-
- CloseScreenProcPtr CloseScreen;
- CreateGCProcPtr CreateGC;
- PaintWindowBackgroundProcPtr PaintWindowBackground;
- PaintWindowBorderProcPtr PaintWindowBorder;
- CopyWindowProcPtr CopyWindow;
- ClearToBackgroundProcPtr ClearToBackground;
- RestoreAreasProcPtr RestoreAreas;
- InstallColormapProcPtr InstallColormap;
- StoreColorsProcPtr StoreColors;
- DisplayCursorProcPtr DisplayCursor;
- ScreenBlockHandlerProcPtr BlockHandler;
- #ifdef RENDER
- CompositeProcPtr Composite;
- #endif
- } vncHooksScreenRec, *vncHooksScreenPtr;
-
- typedef struct {
- GCFuncs *wrappedFuncs;
- GCOps *wrappedOps;
- } vncHooksGCRec, *vncHooksGCPtr;
-
- static int vncHooksScreenIndex;
- static int vncHooksGCIndex;
-
-
- // screen functions
-
- static Bool vncHooksCloseScreen(int i, ScreenPtr pScreen);
- static Bool vncHooksCreateGC(GCPtr pGC);
- static void vncHooksPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion,
- int what);
- static void vncHooksPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion,
- int what);
- static void vncHooksCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
- RegionPtr pOldRegion);
- static void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w,
- int h, Bool generateExposures);
- static RegionPtr vncHooksRestoreAreas(WindowPtr pWin, RegionPtr prgnExposed);
- static void vncHooksInstallColormap(ColormapPtr pColormap);
- static void vncHooksStoreColors(ColormapPtr pColormap, int ndef,
- xColorItem* pdef);
- static Bool vncHooksDisplayCursor(ScreenPtr pScreen, CursorPtr cursor);
- static void vncHooksBlockHandler(int i, pointer blockData, pointer pTimeout,
- pointer pReadmask);
- #ifdef RENDER
- static void vncHooksComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask,
- PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask,
- INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height);
- #endif
-
- // GC "funcs"
-
- static void vncHooksValidateGC(GCPtr pGC, unsigned long changes,
- DrawablePtr pDrawable);
- static void vncHooksChangeGC(GCPtr pGC, unsigned long mask);
- static void vncHooksCopyGC(GCPtr src, unsigned long mask, GCPtr dst);
- static void vncHooksDestroyGC(GCPtr pGC);
- static void vncHooksChangeClip(GCPtr pGC, int type, pointer pValue,int nrects);
- static void vncHooksDestroyClip(GCPtr pGC);
- static void vncHooksCopyClip(GCPtr dst, GCPtr src);
-
- static GCFuncs vncHooksGCFuncs = {
- vncHooksValidateGC, vncHooksChangeGC, vncHooksCopyGC, vncHooksDestroyGC,
- vncHooksChangeClip, vncHooksDestroyClip, vncHooksCopyClip,
- };
-
- // GC "ops"
-
- static void vncHooksFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit,
- DDXPointPtr pptInit, int *pwidthInit,
- int fSorted);
- static void vncHooksSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
- DDXPointPtr ppt, int *pwidth, int nspans,
- int fSorted);
- static void vncHooksPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
- int x, int y, int w, int h, int leftPad,
- int format, char *pBits);
- static RegionPtr vncHooksCopyArea(DrawablePtr pSrc, DrawablePtr pDst,
- GCPtr pGC, int srcx, int srcy, int w, int h,
- int dstx, int dsty);
- static RegionPtr vncHooksCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
- GCPtr pGC, int srcx, int srcy, int w, int h,
- int dstx, int dsty, unsigned long plane);
- static void vncHooksPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
- int npt, xPoint *pts);
- static void vncHooksPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
- int npt, DDXPointPtr ppts);
- static void vncHooksPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg,
- xSegment *segs);
- static void vncHooksPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
- xRectangle *rects);
- static void vncHooksPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
- xArc *arcs);
- static void vncHooksFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape,
- int mode, int count, DDXPointPtr pts);
- static void vncHooksPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects,
- xRectangle *rects);
- static void vncHooksPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
- xArc *arcs);
- static int vncHooksPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, char *chars);
- static int vncHooksPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, unsigned short *chars);
- static void vncHooksImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, char *chars);
- static void vncHooksImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, unsigned short *chars);
- static void vncHooksImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
- int y, unsigned int nglyph,
- CharInfoPtr *ppci, pointer pglyphBase);
- static void vncHooksPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
- int y, unsigned int nglyph,
- CharInfoPtr *ppci, pointer pglyphBase);
- static void vncHooksPushPixels(GCPtr pGC, PixmapPtr pBitMap,
- DrawablePtr pDrawable, int w, int h, int x,
- int y);
-
- static GCOps vncHooksGCOps = {
- vncHooksFillSpans, vncHooksSetSpans, vncHooksPutImage, vncHooksCopyArea,
- vncHooksCopyPlane, vncHooksPolyPoint, vncHooksPolylines, vncHooksPolySegment,
- vncHooksPolyRectangle, vncHooksPolyArc, vncHooksFillPolygon,
- vncHooksPolyFillRect, vncHooksPolyFillArc, vncHooksPolyText8,
- vncHooksPolyText16, vncHooksImageText8, vncHooksImageText16,
- vncHooksImageGlyphBlt, vncHooksPolyGlyphBlt, vncHooksPushPixels
- };
-
-
-
- /////////////////////////////////////////////////////////////////////////////
- // vncHooksInit() is called at initialisation time and every time the server
- // resets. It is called once for each screen, but the indexes are only
- // allocated once for each server generation.
-
- Bool vncHooksInit(ScreenPtr pScreen, XserverDesktop* desktop)
- {
- vncHooksScreenPtr vncHooksScreen;
-
- if (vncHooksGeneration != serverGeneration) {
- vncHooksGeneration = serverGeneration;
-
- vncHooksScreenIndex = AllocateScreenPrivateIndex();
- if (vncHooksScreenIndex < 0) {
- ErrorF("vncHooksInit: AllocateScreenPrivateIndex failed\n");
- return FALSE;
- }
-
- vncHooksGCIndex = AllocateGCPrivateIndex();
- if (vncHooksGCIndex < 0) {
- ErrorF("vncHooksInit: AllocateGCPrivateIndex failed\n");
- return FALSE;
- }
- }
-
- if (!AllocateGCPrivate(pScreen, vncHooksGCIndex, sizeof(vncHooksGCRec))) {
- ErrorF("vncHooksInit: AllocateGCPrivate failed\n");
- return FALSE;
- }
-
- vncHooksScreen = (vncHooksScreenPtr)xnfalloc(sizeof(vncHooksScreenRec));
- pScreen->devPrivates[vncHooksScreenIndex].ptr = (pointer)vncHooksScreen;
-
- vncHooksScreen->desktop = desktop;
-
- vncHooksScreen->CloseScreen = pScreen->CloseScreen;
- vncHooksScreen->CreateGC = pScreen->CreateGC;
- vncHooksScreen->PaintWindowBackground = pScreen->PaintWindowBackground;
- vncHooksScreen->PaintWindowBorder = pScreen->PaintWindowBorder;
- vncHooksScreen->CopyWindow = pScreen->CopyWindow;
- vncHooksScreen->ClearToBackground = pScreen->ClearToBackground;
- vncHooksScreen->RestoreAreas = pScreen->RestoreAreas;
- vncHooksScreen->InstallColormap = pScreen->InstallColormap;
- vncHooksScreen->StoreColors = pScreen->StoreColors;
- vncHooksScreen->DisplayCursor = pScreen->DisplayCursor;
- vncHooksScreen->BlockHandler = pScreen->BlockHandler;
- #ifdef RENDER
- PictureScreenPtr ps;
- ps = GetPictureScreenIfSet(pScreen);
- if (ps) {
- vncHooksScreen->Composite = ps->Composite;
- }
- #endif
-
- pScreen->CloseScreen = vncHooksCloseScreen;
- pScreen->CreateGC = vncHooksCreateGC;
- pScreen->PaintWindowBackground = vncHooksPaintWindowBackground;
- pScreen->PaintWindowBorder = vncHooksPaintWindowBorder;
- pScreen->CopyWindow = vncHooksCopyWindow;
- pScreen->ClearToBackground = vncHooksClearToBackground;
- pScreen->RestoreAreas = vncHooksRestoreAreas;
- pScreen->InstallColormap = vncHooksInstallColormap;
- pScreen->StoreColors = vncHooksStoreColors;
- pScreen->DisplayCursor = vncHooksDisplayCursor;
- pScreen->BlockHandler = vncHooksBlockHandler;
- #ifdef RENDER
- if (ps) {
- ps->Composite = vncHooksComposite;
- }
- #endif
-
- return TRUE;
- }
-
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // screen functions
- //
-
- // SCREEN_UNWRAP and SCREEN_REWRAP unwrap and rewrap the given screen function.
- // It would be nice to do this with a C++ class, but each function is of a
- // distinct type, so it would have to use templates, and it's not worth that
- // much pain.
-
- #define SCREEN_UNWRAP(scrn,field) \
- ScreenPtr pScreen = scrn; \
- vncHooksScreenPtr vncHooksScreen \
- = ((vncHooksScreenPtr)pScreen->devPrivates[vncHooksScreenIndex].ptr); \
- pScreen->field = vncHooksScreen->field; \
- DBGPRINT((stderr,"vncHooks" #field " called\n"));
-
- #define SCREEN_REWRAP(field) pScreen->field = vncHooks##field;
-
-
- // CloseScreen - unwrap the screen functions and call the original CloseScreen
- // function
-
- static Bool vncHooksCloseScreen(int i, ScreenPtr pScreen_)
- {
- SCREEN_UNWRAP(pScreen_, CloseScreen);
-
- pScreen->CreateGC = vncHooksScreen->CreateGC;
- pScreen->PaintWindowBackground = vncHooksScreen->PaintWindowBackground;
- pScreen->PaintWindowBorder = vncHooksScreen->PaintWindowBorder;
- pScreen->CopyWindow = vncHooksScreen->CopyWindow;
- pScreen->ClearToBackground = vncHooksScreen->ClearToBackground;
- pScreen->RestoreAreas = vncHooksScreen->RestoreAreas;
- pScreen->InstallColormap = vncHooksScreen->InstallColormap;
- pScreen->StoreColors = vncHooksScreen->StoreColors;
- pScreen->DisplayCursor = vncHooksScreen->DisplayCursor;
- pScreen->BlockHandler = vncHooksScreen->BlockHandler;
-
- xfree((pointer)vncHooksScreen);
-
- DBGPRINT((stderr,"vncHooksCloseScreen: unwrapped screen functions\n"));
-
- return (*pScreen->CloseScreen)(i, pScreen);
- }
-
- // CreateGC - wrap the "GC funcs"
-
- static Bool vncHooksCreateGC(GCPtr pGC)
- {
- SCREEN_UNWRAP(pGC->pScreen, CreateGC);
-
- vncHooksGCPtr vncHooksGC
- = (vncHooksGCPtr)pGC->devPrivates[vncHooksGCIndex].ptr;
-
- Bool ret = (*pScreen->CreateGC) (pGC);
-
- vncHooksGC->wrappedOps = 0;
- vncHooksGC->wrappedFuncs = pGC->funcs;
- pGC->funcs = &vncHooksGCFuncs;
-
- SCREEN_REWRAP(CreateGC);
-
- return ret;
- }
-
- // PaintWindowBackground - changed region is the given region
-
- static void vncHooksPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion,
- int what)
- {
- SCREEN_UNWRAP(pWin->drawable.pScreen, PaintWindowBackground);
-
- RegionHelper changed(pScreen, pRegion);
-
- (*pScreen->PaintWindowBackground) (pWin, pRegion, what);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-
- SCREEN_REWRAP(PaintWindowBackground);
- }
-
- // PaintWindowBorder - changed region is the given region
-
- static void vncHooksPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion,
- int what)
- {
- SCREEN_UNWRAP(pWin->drawable.pScreen, PaintWindowBorder);
-
- RegionHelper changed(pScreen, pRegion);
-
- (*pScreen->PaintWindowBorder) (pWin, pRegion, what);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-
- SCREEN_REWRAP(PaintWindowBorder);
- }
-
- // CopyWindow - destination of the copy is the old region, clipped by
- // borderClip, translated by the delta. This call only does the copy - it
- // doesn't affect any other bits.
-
- static void vncHooksCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
- RegionPtr pOldRegion)
- {
- SCREEN_UNWRAP(pWin->drawable.pScreen, CopyWindow);
-
- RegionHelper copied(pScreen, pOldRegion);
- int dx = pWin->drawable.x - ptOldOrg.x;
- int dy = pWin->drawable.y - ptOldOrg.y;
- REGION_TRANSLATE(pScreen, copied.reg, dx, dy);
- REGION_INTERSECT(pWin->drawable.pScreen, copied.reg, copied.reg,
- &pWin->borderClip);
-
- (*pScreen->CopyWindow) (pWin, ptOldOrg, pOldRegion);
-
- vncHooksScreen->desktop->add_copied(copied.reg, dx, dy);
-
- SCREEN_REWRAP(CopyWindow);
- }
-
- // ClearToBackground - changed region is the given rectangle, clipped by
- // clipList, but only if generateExposures is false.
-
- static void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w,
- int h, Bool generateExposures)
- {
- SCREEN_UNWRAP(pWin->drawable.pScreen, ClearToBackground);
-
- BoxRec box;
- box.x1 = x + pWin->drawable.x;
- box.y1 = y + pWin->drawable.y;
- box.x2 = w ? (box.x1 + w) : (pWin->drawable.x + pWin->drawable.width);
- box.y2 = h ? (box.y1 + h) : (pWin->drawable.y + pWin->drawable.height);
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, &pWin->clipList);
-
- (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures);
-
- if (!generateExposures) {
- vncHooksScreen->desktop->add_changed(changed.reg);
- }
-
- SCREEN_REWRAP(ClearToBackground);
- }
-
- // RestoreAreas - changed region is the given region
-
- static RegionPtr vncHooksRestoreAreas(WindowPtr pWin, RegionPtr pRegion)
- {
- SCREEN_UNWRAP(pWin->drawable.pScreen, RestoreAreas);
-
- RegionHelper changed(pScreen, pRegion);
-
- RegionPtr result = (*pScreen->RestoreAreas) (pWin, pRegion);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-
- SCREEN_REWRAP(RestoreAreas);
-
- return result;
- }
-
- // InstallColormap - get the new colormap
-
- static void vncHooksInstallColormap(ColormapPtr pColormap)
- {
- SCREEN_UNWRAP(pColormap->pScreen, InstallColormap);
-
- (*pScreen->InstallColormap) (pColormap);
-
- vncHooksScreen->desktop->setColormap(pColormap);
-
- SCREEN_REWRAP(InstallColormap);
- }
-
- // StoreColors - get the colormap changes
-
- static void vncHooksStoreColors(ColormapPtr pColormap, int ndef,
- xColorItem* pdef)
- {
- SCREEN_UNWRAP(pColormap->pScreen, StoreColors);
-
- (*pScreen->StoreColors) (pColormap, ndef, pdef);
-
- vncHooksScreen->desktop->setColourMapEntries(pColormap, ndef, pdef);
-
- SCREEN_REWRAP(StoreColors);
- }
-
- // DisplayCursor - get the cursor shape
-
- static Bool vncHooksDisplayCursor(ScreenPtr pScreen_, CursorPtr cursor)
- {
- SCREEN_UNWRAP(pScreen_, DisplayCursor);
-
- Bool ret = (*pScreen->DisplayCursor) (pScreen, cursor);
-
- vncHooksScreen->desktop->setCursor(cursor);
-
- SCREEN_REWRAP(DisplayCursor);
-
- return ret;
- }
-
- // BlockHandler - ignore any changes during the block handler - it's likely
- // these are just drawing the cursor.
-
- static void vncHooksBlockHandler(int i, pointer blockData, pointer pTimeout,
- pointer pReadmask)
- {
- SCREEN_UNWRAP(screenInfo.screens[i], BlockHandler);
-
- vncHooksScreen->desktop->ignoreHooks(true);
-
- (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
-
- vncHooksScreen->desktop->ignoreHooks(false);
-
- SCREEN_REWRAP(BlockHandler);
- }
-
- // Composite - needed for RENDER
-
- #ifdef RENDER
- void vncHooksComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask,
- PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask,
- INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
- {
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
- vncHooksScreenPtr vncHooksScreen = ((vncHooksScreenPtr)pScreen->devPrivates[vncHooksScreenIndex].ptr);
- BoxRec box;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- rfb::Rect rect1, rect2;
-
- rect1.setXYWH(pDst->pDrawable->x + xDst,
- pDst->pDrawable->y + yDst,
- width,
- height);
-
- rect2 = rect1.intersect(vncHooksScreen->desktop->getRect());
- if (!rect2.is_empty()) {
- box.x1 = rect2.tl.x;
- box.y1 = rect2.tl.y;
- box.x2 = rect2.br.x;
- box.y2 = rect2.br.y;
- RegionHelper changed(pScreen, &box, 0);
- vncHooksScreen->desktop->add_changed(changed.reg);
- }
-
- ps->Composite = vncHooksScreen->Composite;
- (*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc,
- xMask, yMask, xDst, yDst, width, height);
- ps->Composite = vncHooksComposite;
- }
-
- #endif /* RENDER */
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // GC "funcs"
- //
-
- // GCFuncUnwrapper is a helper class which unwraps the GC funcs and ops in its
- // constructor and rewraps them in its destructor.
-
- class GCFuncUnwrapper {
- public:
- GCFuncUnwrapper(GCPtr pGC_) : pGC(pGC_) {
- vncHooksGC = (vncHooksGCPtr)pGC->devPrivates[vncHooksGCIndex].ptr;
- pGC->funcs = vncHooksGC->wrappedFuncs;
- if (vncHooksGC->wrappedOps)
- pGC->ops = vncHooksGC->wrappedOps;
- }
- ~GCFuncUnwrapper() {
- vncHooksGC->wrappedFuncs = pGC->funcs;
- pGC->funcs = &vncHooksGCFuncs;
- if (vncHooksGC->wrappedOps) {
- vncHooksGC->wrappedOps = pGC->ops;
- pGC->ops = &vncHooksGCOps;
- }
- }
- GCPtr pGC;
- vncHooksGCPtr vncHooksGC;
- };
-
-
- // ValidateGC - wrap the "ops" if a viewable window
-
- static void vncHooksValidateGC(GCPtr pGC, unsigned long changes,
- DrawablePtr pDrawable)
- {
- GCFuncUnwrapper u(pGC);
-
- DBGPRINT((stderr,"vncHooksValidateGC called\n"));
-
- (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
-
- u.vncHooksGC->wrappedOps = 0;
- if (pDrawable->type == DRAWABLE_WINDOW && ((WindowPtr)pDrawable)->viewable) {
- WindowPtr pWin = (WindowPtr)pDrawable;
- RegionPtr pRegion = &pWin->clipList;
-
- if (pGC->subWindowMode == IncludeInferiors)
- pRegion = &pWin->borderClip;
- if (REGION_NOTEMPTY(pDrawable->pScreen, pRegion)) {
- u.vncHooksGC->wrappedOps = pGC->ops;
- DBGPRINT((stderr,"vncHooksValidateGC: wrapped GC ops\n"));
- }
- }
- }
-
- // Other GC funcs - just unwrap and call on
-
- static void vncHooksChangeGC(GCPtr pGC, unsigned long mask) {
- GCFuncUnwrapper u(pGC);
- (*pGC->funcs->ChangeGC) (pGC, mask);
- }
- static void vncHooksCopyGC(GCPtr src, unsigned long mask, GCPtr dst) {
- GCFuncUnwrapper u(dst);
- (*dst->funcs->CopyGC) (src, mask, dst);
- }
- static void vncHooksDestroyGC(GCPtr pGC) {
- GCFuncUnwrapper u(pGC);
- (*pGC->funcs->DestroyGC) (pGC);
- }
- static void vncHooksChangeClip(GCPtr pGC, int type, pointer pValue, int nrects)
- {
- GCFuncUnwrapper u(pGC);
- (*pGC->funcs->ChangeClip) (pGC, type, pValue, nrects);
- }
- static void vncHooksDestroyClip(GCPtr pGC) {
- GCFuncUnwrapper u(pGC);
- (*pGC->funcs->DestroyClip) (pGC);
- }
- static void vncHooksCopyClip(GCPtr dst, GCPtr src) {
- GCFuncUnwrapper u(dst);
- (*dst->funcs->CopyClip) (dst, src);
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // GC "ops"
- //
-
- // GCOpUnwrapper is a helper class which unwraps the GC funcs and ops in its
- // constructor and rewraps them in its destructor.
-
- class GCOpUnwrapper {
- public:
- GCOpUnwrapper(DrawablePtr pDrawable, GCPtr pGC_)
- : pGC(pGC_), pScreen(pDrawable->pScreen)
- {
- vncHooksGC = (vncHooksGCPtr)pGC->devPrivates[vncHooksGCIndex].ptr;
- oldFuncs = pGC->funcs;
- pGC->funcs = vncHooksGC->wrappedFuncs;
- pGC->ops = vncHooksGC->wrappedOps;
- }
- ~GCOpUnwrapper() {
- vncHooksGC->wrappedOps = pGC->ops;
- pGC->funcs = oldFuncs;
- pGC->ops = &vncHooksGCOps;
- }
- GCPtr pGC;
- vncHooksGCPtr vncHooksGC;
- GCFuncs* oldFuncs;
- ScreenPtr pScreen;
- };
-
- #define GC_OP_UNWRAPPER(pDrawable, pGC, name) \
- GCOpUnwrapper u(pDrawable, pGC); \
- ScreenPtr pScreen = (pDrawable)->pScreen; \
- vncHooksScreenPtr vncHooksScreen \
- = ((vncHooksScreenPtr)pScreen->devPrivates[vncHooksScreenIndex].ptr); \
- DBGPRINT((stderr,"vncHooks" #name " called\n"));
-
-
- // FillSpans - changed region is the whole of borderClip. This is pessimistic,
- // but I believe this function is rarely used so it doesn't matter.
-
- static void vncHooksFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit,
- DDXPointPtr pptInit, int *pwidthInit,
- int fSorted)
- {
- GC_OP_UNWRAPPER(pDrawable, pGC, FillSpans);
-
- RegionHelper changed(pScreen, &((WindowPtr)pDrawable)->borderClip);
-
- (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
- }
-
- // SetSpans - changed region is the whole of borderClip. This is pessimistic,
- // but I believe this function is rarely used so it doesn't matter.
-
- static void vncHooksSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
- DDXPointPtr ppt, int *pwidth, int nspans,
- int fSorted)
- {
- GC_OP_UNWRAPPER(pDrawable, pGC, SetSpans);
-
- RegionHelper changed(pScreen, &((WindowPtr)pDrawable)->borderClip);
-
- (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
- }
-
- // PutImage - changed region is the given rectangle, clipped by pCompositeClip
-
- static void vncHooksPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
- int x, int y, int w, int h, int leftPad,
- int format, char *pBits)
- {
- GC_OP_UNWRAPPER(pDrawable, pGC, PutImage);
-
- BoxRec box;
- box.x1 = x + pDrawable->x;
- box.y1 = y + pDrawable->y;
- box.x2 = box.x1 + w;
- box.y2 = box.y1 + h;
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, leftPad, format,
- pBits);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
- }
-
- // CopyArea - destination of the copy is the dest rectangle, clipped by
- // pCompositeClip. Any parts of the destination which cannot be copied from
- // the source (could be all of it) go into the changed region.
-
- static RegionPtr vncHooksCopyArea(DrawablePtr pSrc, DrawablePtr pDst,
- GCPtr pGC, int srcx, int srcy, int w, int h,
- int dstx, int dsty)
- {
- GC_OP_UNWRAPPER(pDst, pGC, CopyArea);
-
- BoxRec box;
- box.x1 = dstx + pDst->x;
- box.y1 = dsty + pDst->y;
- box.x2 = box.x1 + w;
- box.y2 = box.y1 + h;
-
- RegionHelper dst(pScreen, &box, 0);
- REGION_INTERSECT(pScreen, dst.reg, dst.reg, COMPOSITE_CLIP(pGC));
-
- RegionHelper src(pScreen);
-
- if ((pSrc->type == DRAWABLE_WINDOW) && (pSrc->pScreen == pScreen)) {
- box.x1 = srcx + pSrc->x;
- box.y1 = srcy + pSrc->y;
- box.x2 = box.x1 + w;
- box.y2 = box.y1 + h;
-
- src.init(&box, 0);
- REGION_INTERSECT(pScreen, src.reg, src.reg, &((WindowPtr)pSrc)->clipList);
- REGION_TRANSLATE(pScreen, src.reg,
- dstx + pDst->x - srcx - pSrc->x,
- dsty + pDst->y - srcy - pSrc->y);
- } else {
- src.init(NullBox, 0);
- }
-
- RegionHelper changed(pScreen, NullBox, 0);
- REGION_SUBTRACT(pScreen, changed.reg, dst.reg, src.reg);
- REGION_INTERSECT(pScreen, dst.reg, dst.reg, src.reg);
-
- RegionPtr rgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h,
- dstx, dsty);
-
- if (REGION_NOTEMPTY(pScreen, dst.reg))
- vncHooksScreen->desktop->add_copied(dst.reg,
- dstx + pDst->x - srcx - pSrc->x,
- dsty + pDst->y - srcy - pSrc->y);
-
- if (REGION_NOTEMPTY(pScreen, changed.reg))
- vncHooksScreen->desktop->add_changed(changed.reg);
-
- return rgn;
- }
-
-
- // CopyPlane - changed region is the destination rectangle, clipped by
- // pCompositeClip
-
- static RegionPtr vncHooksCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
- GCPtr pGC, int srcx, int srcy, int w, int h,
- int dstx, int dsty, unsigned long plane)
- {
- GC_OP_UNWRAPPER(pDst, pGC, CopyPlane);
-
- BoxRec box;
- box.x1 = dstx + pDst->x;
- box.y1 = dsty + pDst->y;
- box.x2 = box.x1 + w;
- box.y2 = box.y1 + h;
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- RegionPtr rgn = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h,
- dstx, dsty, plane);
- vncHooksScreen->desktop->add_changed(changed.reg);
-
- return rgn;
- }
-
- // PolyPoint - changed region is the bounding rect, clipped by pCompositeClip
-
- static void vncHooksPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
- int npt, xPoint *pts)
- {
- GC_OP_UNWRAPPER(pDrawable, pGC, PolyPoint);
-
- if (npt == 0) {
- (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts);
- return;
- }
-
- int minX = pts[0].x;
- int maxX = pts[0].x;
- int minY = pts[0].y;
- int maxY = pts[0].y;
-
- if (mode == CoordModePrevious) {
- int x = pts[0].x;
- int y = pts[0].y;
-
- for (int i = 1; i < npt; i++) {
- x += pts[i].x;
- y += pts[i].y;
- if (x < minX) minX = x;
- if (x > maxX) maxX = x;
- if (y < minY) minY = y;
- if (y > maxY) maxY = y;
- }
- } else {
- for (int i = 1; i < npt; i++) {
- if (pts[i].x < minX) minX = pts[i].x;
- if (pts[i].x > maxX) maxX = pts[i].x;
- if (pts[i].y < minY) minY = pts[i].y;
- if (pts[i].y > maxY) maxY = pts[i].y;
- }
- }
-
- BoxRec box;
- box.x1 = minX + pDrawable->x;
- box.y1 = minY + pDrawable->y;
- box.x2 = maxX + 1 + pDrawable->x;
- box.y2 = maxY + 1 + pDrawable->y;
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
- }
-
- // Polylines - changed region is the union of the bounding rects of each line,
- // clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP lines,
- // just use the bounding rect of all the lines.
-
- static void vncHooksPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
- int npt, DDXPointPtr ppts)
- {
- GC_OP_UNWRAPPER(pDrawable, pGC, Polylines);
-
- if (npt == 0) {
- (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts);
- return;
- }
-
- int nRegRects = npt - 1;
- xRectangle regRects[MAX_RECTS_PER_OP];
-
- int lw = pGC->lineWidth;
- if (lw == 0) lw = 1;
-
- if (npt == 1)
- {
- // a single point
- nRegRects = 1;
- regRects[0].x = pDrawable->x + ppts[0].x - lw;
- regRects[0].y = pDrawable->y + ppts[0].y - lw;
- regRects[0].width = 2*lw;
- regRects[0].height = 2*lw;
- }
- else
- {
- /*
- * mitered joins can project quite a way from
- * the line end; the 11 degree miter limit limits
- * this extension to lw / (2 * tan(11/2)), rounded up
- * and converted to int yields 6 * lw
- */
-
- int extra = lw / 2;
- if (pGC->joinStyle == JoinMiter) {
- extra = 6 * lw;
- }
-
- int prevX, prevY, curX, curY;
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
-
- prevX = ppts[0].x + pDrawable->x;
- prevY = ppts[0].y + pDrawable->y;
- minX = maxX = prevX;
- minY = maxY = prevY;
-
- for (int i = 0; i < nRegRects; i++) {
- if (mode == CoordModeOrigin) {
- curX = pDrawable->x + ppts[i+1].x;
- curY = pDrawable->y + ppts[i+1].y;
- } else {
- curX = prevX + ppts[i+1].x;
- curY = prevY + ppts[i+1].y;
- }
-
- if (prevX > curX) {
- rectX1 = curX - extra;
- rectX2 = prevX + extra + 1;
- } else {
- rectX1 = prevX - extra;
- rectX2 = curX + extra + 1;
- }
-
- if (prevY > curY) {
- rectY1 = curY - extra;
- rectY2 = prevY + extra + 1;
- } else {
- rectY1 = prevY - extra;
- rectY2 = curY + extra + 1;
- }
-
- if (nRegRects <= MAX_RECTS_PER_OP) {
- regRects[i].x = rectX1;
- regRects[i].y = rectY1;
- regRects[i].width = rectX2 - rectX1;
- regRects[i].height = rectY2 - rectY1;
- } else {
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
-
- prevX = curX;
- prevY = curY;
- }
-
- if (nRegRects > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nRegRects = 1;
- }
- }
-
- RegionHelper changed(pScreen, nRegRects, regRects);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
- }
-
- // PolySegment - changed region is the union of the bounding rects of each
- // segment, clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP
- // segments, just use the bounding rect of all the segments.
-
- static void vncHooksPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg,
- xSegment *segs)
- {
- GC_OP_UNWRAPPER(pDrawable, pGC, PolySegment);
-
- if (nseg == 0) {
- (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs);
- return;
- }
-
- xRectangle regRects[MAX_RECTS_PER_OP];
- int nRegRects = nseg;
-
- int lw = pGC->lineWidth;
- int extra = lw / 2;
-
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
-
- minX = maxX = segs[0].x1;
- minY = maxY = segs[0].y1;
-
- for (int i = 0; i < nseg; i++) {
- if (segs[i].x1 > segs[i].x2) {
- rectX1 = pDrawable->x + segs[i].x2 - extra;
- rectX2 = pDrawable->x + segs[i].x1 + extra + 1;
- } else {
- rectX1 = pDrawable->x + segs[i].x1 - extra;
- rectX2 = pDrawable->x + segs[i].x2 + extra + 1;
- }
-
- if (segs[i].y1 > segs[i].y2) {
- rectY1 = pDrawable->y + segs[i].y2 - extra;
- rectY2 = pDrawable->y + segs[i].y1 + extra + 1;
- } else {
- rectY1 = pDrawable->y + segs[i].y1 - extra;
- rectY2 = pDrawable->y + segs[i].y2 + extra + 1;
- }
-
- if (nseg <= MAX_RECTS_PER_OP) {
- regRects[i].x = rectX1;
- regRects[i].y = rectY1;
- regRects[i].width = rectX2 - rectX1;
- regRects[i].height = rectY2 - rectY1;
- } else {
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
- }
-
- if (nseg > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nRegRects = 1;
- }
-
- RegionHelper changed(pScreen, nRegRects, regRects);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
- }
-
- // PolyRectangle - changed region is the union of the bounding rects around
- // each side of the outline rectangles, clipped by pCompositeClip. If there
- // are more than MAX_RECTS_PER_OP rectangles, just use the bounding rect of all
- // the rectangles.
-
- static void vncHooksPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
- xRectangle *rects)
- {
- GC_OP_UNWRAPPER(pDrawable, pGC, PolyRectangle);
-
- if (nrects == 0) {
- (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects);
- return;
- }
-
- xRectangle regRects[MAX_RECTS_PER_OP*4];
- int nRegRects = nrects * 4;
-
- int lw = pGC->lineWidth;
- int extra = lw / 2;
-
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
-
- minX = maxX = rects[0].x;
- minY = maxY = rects[0].y;
-
- for (int i = 0; i < nrects; i++) {
- if (nrects <= MAX_RECTS_PER_OP) {
- regRects[i*4].x = rects[i].x - extra + pDrawable->x;
- regRects[i*4].y = rects[i].y - extra + pDrawable->y;
- regRects[i*4].width = rects[i].width + 1 + 2 * extra;
- regRects[i*4].height = 1 + 2 * extra;
-
- regRects[i*4+1].x = rects[i].x - extra + pDrawable->x;
- regRects[i*4+1].y = rects[i].y - extra + pDrawable->y;
- regRects[i*4+1].width = 1 + 2 * extra;
- regRects[i*4+1].height = rects[i].height + 1 + 2 * extra;
-
- regRects[i*4+2].x = rects[i].x + rects[i].width - extra + pDrawable->x;
- regRects[i*4+2].y = rects[i].y - extra + pDrawable->y;
- regRects[i*4+2].width = 1 + 2 * extra;
- regRects[i*4+2].height = rects[i].height + 1 + 2 * extra;
-
- regRects[i*4+3].x = rects[i].x - extra + pDrawable->x;
- regRects[i*4+3].y = rects[i].y + rects[i].height - extra + pDrawable->y;
- regRects[i*4+3].width = rects[i].width + 1 + 2 * extra;
- regRects[i*4+3].height = 1 + 2 * extra;
- } else {
- rectX1 = pDrawable->x + rects[i].x - extra;
- rectY1 = pDrawable->y + rects[i].y - extra;
- rectX2 = pDrawable->x + rects[i].x + rects[i].width + extra+1;
- rectY2 = pDrawable->y + rects[i].y + rects[i].height + extra+1;
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
- }
-
- if (nrects > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nRegRects = 1;
- }
-
- RegionHelper changed(pScreen, nRegRects, regRects);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
- }
-
- // PolyArc - changed region is the union of bounding rects around each arc,
- // clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP
- // arcs, just use the bounding rect of all the arcs.
-
- static void vncHooksPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
- xArc *arcs)
- {
- GC_OP_UNWRAPPER(pDrawable, pGC, PolyArc);
-
- if (narcs == 0) {
- (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs);
- return;
- }
-
- xRectangle regRects[MAX_RECTS_PER_OP];
- int nRegRects = narcs;
-
- int lw = pGC->lineWidth;
- if (lw == 0) lw = 1;
- int extra = lw / 2;
-
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
-
- minX = maxX = arcs[0].x;
- minY = maxY = arcs[0].y;
-
- for (int i = 0; i < narcs; i++) {
- if (narcs <= MAX_RECTS_PER_OP) {
- regRects[i].x = arcs[i].x - extra + pDrawable->x;
- regRects[i].y = arcs[i].y - extra + pDrawable->y;
- regRects[i].width = arcs[i].width + lw;
- regRects[i].height = arcs[i].height + lw;
- } else {
- rectX1 = pDrawable->x + arcs[i].x - extra;
- rectY1 = pDrawable->y + arcs[i].y - extra;
- rectX2 = pDrawable->x + arcs[i].x + arcs[i].width + lw;
- rectY2 = pDrawable->y + arcs[i].y + arcs[i].height + lw;
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
- }
-
- if (narcs > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nRegRects = 1;
- }
-
- RegionHelper changed(pScreen, nRegRects, regRects);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
- }
-
-
- // FillPolygon - changed region is the bounding rect around the polygon,
- // clipped by pCompositeClip
-
- static void vncHooksFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape,
- int mode, int count, DDXPointPtr pts)
- {
- GC_OP_UNWRAPPER(pDrawable, pGC, FillPolygon);
-
- if (count == 0) {
- (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts);
- return;
- }
-
- int minX = pts[0].x;
- int maxX = pts[0].x;
- int minY = pts[0].y;
- int maxY = pts[0].y;
-
- if (mode == CoordModePrevious) {
- int x = pts[0].x;
- int y = pts[0].y;
-
- for (int i = 1; i < count; i++) {
- x += pts[i].x;
- y += pts[i].y;
- if (x < minX) minX = x;
- if (x > maxX) maxX = x;
- if (y < minY) minY = y;
- if (y > maxY) maxY = y;
- }
- } else {
- for (int i = 1; i < count; i++) {
- if (pts[i].x < minX) minX = pts[i].x;
- if (pts[i].x > maxX) maxX = pts[i].x;
- if (pts[i].y < minY) minY = pts[i].y;
- if (pts[i].y > maxY) maxY = pts[i].y;
- }
- }
-
- BoxRec box;
- box.x1 = minX + pDrawable->x;
- box.y1 = minY + pDrawable->y;
- box.x2 = maxX + 1 + pDrawable->x;
- box.y2 = maxY + 1 + pDrawable->y;
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
- }
-
- // PolyFillRect - changed region is the union of the rectangles, clipped by
- // pCompositeClip. If there are more than MAX_RECTS_PER_OP rectangles, just
- // use the bounding rect of all the rectangles.
-
- static void vncHooksPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects,
- xRectangle *rects)
- {
- GC_OP_UNWRAPPER(pDrawable, pGC, PolyFillRect);
-
- if (nrects == 0) {
- (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects);
- return;
- }
-
- xRectangle regRects[MAX_RECTS_PER_OP];
- int nRegRects = nrects;
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
- minX = maxX = rects[0].x;
- minY = maxY = rects[0].y;
-
- for (int i = 0; i < nrects; i++) {
- if (nrects <= MAX_RECTS_PER_OP) {
- regRects[i].x = rects[i].x + pDrawable->x;
- regRects[i].y = rects[i].y + pDrawable->y;
- regRects[i].width = rects[i].width;
- regRects[i].height = rects[i].height;
- } else {
- rectX1 = pDrawable->x + rects[i].x;
- rectY1 = pDrawable->y + rects[i].y;
- rectX2 = pDrawable->x + rects[i].x + rects[i].width;
- rectY2 = pDrawable->y + rects[i].y + rects[i].height;
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
- }
-
- if (nrects > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nRegRects = 1;
- }
-
- RegionHelper changed(pScreen, nRegRects, regRects);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
- }
-
- // PolyFillArc - changed region is the union of bounding rects around each arc,
- // clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP arcs,
- // just use the bounding rect of all the arcs.
-
- static void vncHooksPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
- xArc *arcs)
- {
- GC_OP_UNWRAPPER(pDrawable, pGC, PolyFillArc);
-
- if (narcs == 0) {
- (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs);
- return;
- }
-
- xRectangle regRects[MAX_RECTS_PER_OP];
- int nRegRects = narcs;
-
- int lw = pGC->lineWidth;
- if (lw == 0) lw = 1;
- int extra = lw / 2;
-
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
-
- minX = maxX = arcs[0].x;
- minY = maxY = arcs[0].y;
-
- for (int i = 0; i < narcs; i++) {
- if (narcs <= MAX_RECTS_PER_OP) {
- regRects[i].x = arcs[i].x - extra + pDrawable->x;
- regRects[i].y = arcs[i].y - extra + pDrawable->y;
- regRects[i].width = arcs[i].width + lw;
- regRects[i].height = arcs[i].height + lw;
- } else {
- rectX1 = pDrawable->x + arcs[i].x - extra;
- rectY1 = pDrawable->y + arcs[i].y - extra;
- rectX2 = pDrawable->x + arcs[i].x + arcs[i].width + lw;
- rectY2 = pDrawable->y + arcs[i].y + arcs[i].height + lw;
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
- }
-
- if (narcs > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nRegRects = 1;
- }
-
- RegionHelper changed(pScreen, nRegRects, regRects);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
- }
-
- // GetTextBoundingRect - calculate a bounding rectangle around n chars of a
- // font. Not particularly accurate, but good enough.
-
- static void GetTextBoundingRect(DrawablePtr pDrawable, FontPtr font, int x,
- int y, int nchars, BoxPtr box)
- {
- int ascent = __rfbmax(FONTASCENT(font), FONTMAXBOUNDS(font, ascent));
- int descent = __rfbmax(FONTDESCENT(font), FONTMAXBOUNDS(font, descent));
- int charWidth = __rfbmax(FONTMAXBOUNDS(font,rightSideBearing),
- FONTMAXBOUNDS(font,characterWidth));
-
- box->x1 = pDrawable->x + x;
- box->y1 = pDrawable->y + y - ascent;
- box->x2 = box->x1 + charWidth * nchars;
- box->y2 = box->y1 + ascent + descent;
-
- if (FONTMINBOUNDS(font,leftSideBearing) < 0)
- box->x1 += FONTMINBOUNDS(font,leftSideBearing);
- }
-
- // PolyText8 - changed region is bounding rect around count chars, clipped by
- // pCompositeClip
-
- static int vncHooksPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, char *chars)
- {
- GC_OP_UNWRAPPER(pDrawable, pGC, PolyText8);
-
- if (count == 0)
- return (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
-
- BoxRec box;
- GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- int ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-
- return ret;
- }
-
- // PolyText16 - changed region is bounding rect around count chars, clipped by
- // pCompositeClip
-
- static int vncHooksPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, unsigned short *chars)
- {
- GC_OP_UNWRAPPER(pDrawable, pGC, PolyText16);
-
- if (count == 0)
- return (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
-
- BoxRec box;
- GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- int ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-
- return ret;
- }
-
- // ImageText8 - changed region is bounding rect around count chars, clipped by
- // pCompositeClip
-
- static void vncHooksImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, char *chars)
- {
- GC_OP_UNWRAPPER(pDrawable, pGC, ImageText8);
-
- if (count == 0) {
- (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
- return;
- }
-
- BoxRec box;
- GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
- }
-
- // ImageText16 - changed region is bounding rect around count chars, clipped by
- // pCompositeClip
-
- static void vncHooksImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, unsigned short *chars)
- {
- GC_OP_UNWRAPPER(pDrawable, pGC, ImageText16);
-
- if (count == 0) {
- (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
- return;
- }
-
- BoxRec box;
- GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
- }
-
- // ImageGlyphBlt - changed region is bounding rect around nglyph chars, clipped
- // by pCompositeClip
-
- static void vncHooksImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
- int y, unsigned int nglyph,
- CharInfoPtr *ppci, pointer pglyphBase)
- {
- GC_OP_UNWRAPPER(pDrawable, pGC, ImageGlyphBlt);
-
- if (nglyph == 0) {
- (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase);
- return;
- }
-
- BoxRec box;
- GetTextBoundingRect(pDrawable, pGC->font, x, y, nglyph, &box);
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
- }
-
- // PolyGlyphBlt - changed region is bounding rect around nglyph chars, clipped
- // by pCompositeClip
-
- static void vncHooksPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
- int y, unsigned int nglyph,
- CharInfoPtr *ppci, pointer pglyphBase)
- {
- GC_OP_UNWRAPPER(pDrawable, pGC, PolyGlyphBlt);
-
- if (nglyph == 0) {
- (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase);
- return;
- }
-
- BoxRec box;
- GetTextBoundingRect(pDrawable, pGC->font, x, y, nglyph, &box);
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
- }
-
- // PushPixels - changed region is the given rectangle, clipped by
- // pCompositeClip
-
- static void vncHooksPushPixels(GCPtr pGC, PixmapPtr pBitMap,
- DrawablePtr pDrawable, int w, int h, int x,
- int y)
- {
- GC_OP_UNWRAPPER(pDrawable, pGC, PushPixels);
-
- BoxRec box;
- box.x1 = x + pDrawable->x;
- box.y1 = y + pDrawable->y;
- box.x2 = box.x1 + w;
- box.y2 = box.y1 + h;
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
- }
|