diff --git a/miext/rootless/rootlessCommon.c b/miext/rootless/rootlessCommon.c index 8fd922d4a..fc22b1b89 100644 --- a/miext/rootless/rootlessCommon.c +++ b/miext/rootless/rootlessCommon.c @@ -34,6 +34,7 @@ #endif #include "rootlessCommon.h" +#include "colormapst.h" unsigned int rootless_CopyBytes_threshold = 0; unsigned int rootless_FillBytes_threshold = 0; @@ -95,6 +96,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 3bf6af02f..b00221400 100644 --- a/miext/rootless/rootlessCommon.h +++ b/miext/rootless/rootlessCommon.h @@ -32,6 +32,7 @@ #include #endif +#include #ifndef _ROOTLESSCOMMON_H #define _ROOTLESSCOMMON_H @@ -104,13 +105,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; @@ -251,6 +259,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 356fec798..b3145815d 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) @@ -616,6 +678,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 84aa91dbf..cf324267a 100644 --- a/miext/rootless/rootlessWindow.c +++ b/miext/rootless/rootlessWindow.c @@ -447,6 +447,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 @@ -505,6 +511,9 @@ RootlessEnsureFrame(WindowPtr pWin) return NULL; } + if (pWin->drawable.depth == 8) + RootlessFlushWindowColormap(pWin); + #ifdef SHAPE if (pShape != NULL) REGION_UNINIT(pScreen, &shape); @@ -1458,6 +1467,25 @@ 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.