diff --git a/miext/rootless/rootlessCommon.c b/miext/rootless/rootlessCommon.c index 9cbb7fa1b..03842e4be 100644 --- a/miext/rootless/rootlessCommon.c +++ b/miext/rootless/rootlessCommon.c @@ -37,6 +37,7 @@ #include /* For CHAR_BIT */ #include "rootlessCommon.h" +#include "colormapst.h" unsigned int rootless_CopyBytes_threshold = 0; unsigned int rootless_FillBytes_threshold = 0; @@ -98,6 +99,41 @@ IsFramedWindow(WindowPtr pWin) return (top && WINREC(top)); } +Bool +RootlessResolveColormap (ScreenPtr pScreen, int first_color, + int n_colors, uint32_t *colors) +{ + int last, i; + ColormapPtr map; + + map = RootlessGetColormap (pScreen); + if (map == NULL || map->class != PseudoColor) return FALSE; + + last = MIN (map->pVisual->ColormapEntries, first_color + n_colors); + for (i = MAX (0, first_color); i < last; i++) { + Entry *ent = map->red + i; + uint16_t red, green, blue; + + if (!ent->refcnt) continue; + if (ent->fShared) { + red = ent->co.shco.red->color; + green = ent->co.shco.green->color; + blue = ent->co.shco.blue->color; + } else { + red = ent->co.local.red; + green = ent->co.local.green; + blue = ent->co.local.blue; + } + + colors[i - first_color] = (0xFF000000UL + | ((uint32_t) red & 0xff00) << 8 + | (green & 0xff00) + | (blue >> 8)); + } + + return TRUE; +} + /* * RootlessStartDrawing diff --git a/miext/rootless/rootlessCommon.h b/miext/rootless/rootlessCommon.h index b7f11bd14..d6a0161ce 100644 --- a/miext/rootless/rootlessCommon.h +++ b/miext/rootless/rootlessCommon.h @@ -32,6 +32,7 @@ #include #endif +#include #ifndef _ROOTLESSCOMMON_H #define _ROOTLESSCOMMON_H @@ -106,13 +107,20 @@ typedef struct _RootlessScreenRec { GlyphsProcPtr Glyphs; #endif + InstallColormapProcPtr InstallColormap; + UninstallColormapProcPtr UninstallColormap; + StoreColorsProcPtr StoreColors; + void *pixmap_data; unsigned int pixmap_data_size; + ColormapPtr colormap; + void *redisplay_timer; unsigned int redisplay_timer_set :1; unsigned int redisplay_queued :1; unsigned int redisplay_expired :1; + unsigned int colormap_changed :1; } RootlessScreenRec, *RootlessScreenPtr; @@ -253,6 +261,16 @@ void RootlessRedisplayScreen(ScreenPtr pScreen); void RootlessQueueRedisplay(ScreenPtr pScreen); +/* Return the colormap currently installed on the given screen. */ +ColormapPtr RootlessGetColormap (ScreenPtr pScreen); + +/* Convert colormap to ARGB. */ +Bool RootlessResolveColormap (ScreenPtr pScreen, int first_color, + int n_colors, uint32_t *colors); + +void RootlessFlushWindowColormap (WindowPtr pWin); +void RootlessFlushScreenColormaps (ScreenPtr pScreen); + // Move a window to its proper location on the screen. void RootlessRepositionWindow(WindowPtr pWin); diff --git a/miext/rootless/rootlessScreen.c b/miext/rootless/rootlessScreen.c index 489d3fb23..6b54042a8 100644 --- a/miext/rootless/rootlessScreen.c +++ b/miext/rootless/rootlessScreen.c @@ -42,6 +42,7 @@ #include "propertyst.h" #include "mivalidate.h" #include "picturestr.h" +#include "colormapst.h" #include #include @@ -469,6 +470,67 @@ RootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, return result; } +ColormapPtr +RootlessGetColormap (ScreenPtr pScreen) +{ + RootlessScreenRec *s = SCREENREC (pScreen); + + return s->colormap; +} + +static void +RootlessInstallColormap (ColormapPtr pMap) +{ + ScreenPtr pScreen = pMap->pScreen; + RootlessScreenRec *s = SCREENREC (pScreen); + + SCREEN_UNWRAP(pScreen, InstallColormap); + + if (s->colormap != pMap) { + s->colormap = pMap; + s->colormap_changed = TRUE; + RootlessQueueRedisplay (pScreen); + } + + pScreen->InstallColormap (pMap); + + SCREEN_WRAP (pScreen, InstallColormap); +} + +static void +RootlessUninstallColormap (ColormapPtr pMap) +{ + ScreenPtr pScreen = pMap->pScreen; + RootlessScreenRec *s = SCREENREC (pScreen); + + SCREEN_UNWRAP(pScreen, UninstallColormap); + + if (s->colormap == pMap) + s->colormap = NULL; + + pScreen->UninstallColormap (pMap); + + SCREEN_WRAP(pScreen, UninstallColormap); +} + +static void +RootlessStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef) +{ + ScreenPtr pScreen = pMap->pScreen; + RootlessScreenRec *s = SCREENREC (pScreen); + + SCREEN_UNWRAP(pScreen, StoreColors); + + if (s->colormap == pMap && ndef > 0) { + s->colormap_changed = TRUE; + RootlessQueueRedisplay (pScreen); + } + + pScreen->StoreColors (pMap, ndef, pdef); + + SCREEN_WRAP(pScreen, StoreColors); +} + static CARD32 RootlessRedisplayCallback(OsTimerPtr timer, CARD32 time, void *arg) @@ -614,6 +676,9 @@ RootlessWrap(ScreenPtr pScreen) WRAP(MarkOverlappedWindows); WRAP(ValidateTree); WRAP(ChangeWindowAttributes); + WRAP(InstallColormap); + WRAP(UninstallColormap); + WRAP(StoreColors); #ifdef SHAPE WRAP(SetShape); diff --git a/miext/rootless/rootlessWindow.c b/miext/rootless/rootlessWindow.c index 89c02f8c7..3074a3fc5 100644 --- a/miext/rootless/rootlessWindow.c +++ b/miext/rootless/rootlessWindow.c @@ -445,6 +445,12 @@ RootlessInitializeFrame(WindowPtr pWin, RootlessWindowRec *winRec) } +Bool +RootlessColormapCallback (void *data, int first_color, int n_colors, uint32_t *colors) +{ + return RootlessResolveColormap (data, first_color, n_colors, colors); +} + /* * RootlessEnsureFrame * Make sure the given window is framed. If the window doesn't have a @@ -503,6 +509,9 @@ RootlessEnsureFrame(WindowPtr pWin) return NULL; } + if (pWin->drawable.depth == 8) + RootlessFlushWindowColormap(pWin); + #ifdef SHAPE if (pShape != NULL) REGION_UNINIT(pScreen, &shape); @@ -1455,6 +1464,115 @@ out: } } + +void +RootlessFlushWindowColormap (WindowPtr pWin) +{ + RootlessWindowRec *winRec = WINREC (pWin); + xp_window_changes wc; + + if (winRec == NULL) + return; + + RootlessStopDrawing (pWin, FALSE); + + /* This is how we tell xp that the colormap may have changed. */ + + wc.colormap = RootlessColormapCallback; + wc.colormap_data = pWin->drawable.pScreen; + + configure_window (winRec->wid, XP_COLORMAP, &wc); +} + +/* + * SetPixmapOfAncestors + * Set the Pixmaps on all ParentRelative windows up the ancestor chain. + */ +static void +SetPixmapOfAncestors(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr topWin = TopLevelParent(pWin); + RootlessWindowRec *topWinRec = WINREC(topWin); + + while (pWin->backgroundState == ParentRelative) { + if (pWin == topWin) { + // disallow ParentRelative background state on top level + XID pixel = 0; + ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); + RL_DEBUG_MSG("Cleared ParentRelative on 0x%x.\n", pWin); + break; + } + + pWin = pWin->parent; + pScreen->SetWindowPixmap(pWin, topWinRec->pixmap); + } +} + + +/* + * RootlessPaintWindowBackground + */ +void +RootlessPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion, int what) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (IsRoot(pWin)) + return; + + RL_DEBUG_MSG("paintwindowbackground start (win 0x%x, framed %i) ", + pWin, IsFramedWindow(pWin)); + + if (IsFramedWindow(pWin)) { + RootlessStartDrawing(pWin); + RootlessDamageRegion(pWin, pRegion); + + // For ParentRelative windows, we have to make sure the window + // pixmap is set correctly all the way up the ancestor chain. + if (pWin->backgroundState == ParentRelative) { + SetPixmapOfAncestors(pWin); + } + } + + SCREEN_UNWRAP(pScreen, PaintWindowBackground); + pScreen->PaintWindowBackground(pWin, pRegion, what); + SCREEN_WRAP(pScreen, PaintWindowBackground); + + RL_DEBUG_MSG("paintwindowbackground end\n"); +} + + +/* + * RootlessPaintWindowBorder + */ +void +RootlessPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion, int what) +{ + RL_DEBUG_MSG("paintwindowborder start (win 0x%x) ", pWin); + + if (IsFramedWindow(pWin)) { + RootlessStartDrawing(pWin); + RootlessDamageRegion(pWin, pRegion); + + // For ParentRelative windows with tiled borders, we have to make + // sure the window pixmap is set correctly all the way up the + // ancestor chain. + if (!pWin->borderIsPixel && + pWin->backgroundState == ParentRelative) + { + SetPixmapOfAncestors(pWin); + } + } + + SCREEN_UNWRAP(pWin->drawable.pScreen, PaintWindowBorder); + pWin->drawable.pScreen->PaintWindowBorder(pWin, pRegion, what); + SCREEN_WRAP(pWin->drawable.pScreen, PaintWindowBorder); + + RL_DEBUG_MSG("paintwindowborder end\n"); +} + + /* * RootlessChangeBorderWidth * FIXME: untested! @@ -1516,20 +1634,20 @@ RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width) void RootlessOrderAllWindows (void) { - int i; - WindowPtr pWin; - - RL_DEBUG_MSG("RootlessOrderAllWindows() "); - for (i = 0; i < screenInfo.numScreens; i++) { - if (screenInfo.screens[i] == NULL) continue; - pWin = WindowTable[i]; - if (pWin == NULL) continue; + int i; + WindowPtr pWin; + + RL_DEBUG_MSG("RootlessOrderAllWindows() "); + for (i = 0; i < screenInfo.numScreens; i++) { + if (screenInfo.screens[i] == NULL) continue; + pWin = WindowTable[i]; + if (pWin == NULL) continue; - for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) { - if (!pWin->realized) continue; - if (RootlessEnsureFrame(pWin) == NULL) continue; - RootlessReorderWindow (pWin); + for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) { + if (!pWin->realized) continue; + if (RootlessEnsureFrame(pWin) == NULL) continue; + RootlessReorderWindow (pWin); + } } - } - RL_DEBUG_MSG("RootlessOrderAllWindows() done"); + RL_DEBUG_MSG("RootlessOrderAllWindows() done"); }