From 68271be9690735d4117ea37b838e775048e00b35 Mon Sep 17 00:00:00 2001 From: hobbs Date: Thu, 23 Sep 2004 01:49:07 +0000 Subject: * win/tkWinInt.h (TkWinDisplayChanged): added decl * win/tkWinX.c (TkWinDisplayChanged, TkpOpenDisplay): Correctly * win/tkWinWm.c (InvalidateSubTreeDepth, WmProc): handle color and screen resolution changes. Tested for 16/24/32 bpp changes on XP. May need more fixes for 8bpp switch, use of special colormaps, or other special palette handling cases. [Bug 223689] --- ChangeLog | 9 +++ win/tkWinInt.h | 7 ++- win/tkWinWm.c | 108 ++++++++++++++++++++++++++++++++++- win/tkWinX.c | 174 +++++++++++++++++++++++++++++++++++---------------------- 4 files changed, 228 insertions(+), 70 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3eb4d79..be7bfd4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2004-09-22 Jeff Hobbs + + * win/tkWinInt.h (TkWinDisplayChanged): added decl + * win/tkWinX.c (TkWinDisplayChanged, TkpOpenDisplay): Correctly + * win/tkWinWm.c (InvalidateSubTreeDepth, WmProc): handle color + and screen resolution changes. Tested for 16/24/32 bpp changes on + XP. May need more fixes for 8bpp switch, use of special + colormaps, or other special palette handling cases. [Bug 223689] + 2004-09-22 Mo DeJong * generic/tkInt.decls: Add decl for TkWinGetPlatformTheme. diff --git a/win/tkWinInt.h b/win/tkWinInt.h index 7a1d1d7..d041db0 100644 --- a/win/tkWinInt.h +++ b/win/tkWinInt.h @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinInt.h,v 1.14.2.4 2004/09/23 00:56:15 mdejong Exp $ + * RCS: @(#) $Id: tkWinInt.h,v 1.14.2.5 2004/09/23 01:49:08 hobbs Exp $ */ #ifndef _TKWININT @@ -172,6 +172,11 @@ EXTERN void TkWinUpdatingClipboard(int mode); EXTERN HICON TkWinGetIcon(Tk_Window tkw, DWORD iconsize); /* + * Used by tkWinX.c on for certain system display change messages + */ +EXTERN void TkWinDisplayChanged(Display *display); + +/* * The following structure keeps track of whether we are using the * multi-byte or the wide-character interfaces to the operating system. * System calls should be made through the following function table. diff --git a/win/tkWinWm.c b/win/tkWinWm.c index 67cfad2..acb0bcf 100644 --- a/win/tkWinWm.c +++ b/win/tkWinWm.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinWm.c,v 1.54.2.12 2004/09/23 00:35:09 mdejong Exp $ + * RCS: @(#) $Id: tkWinWm.c,v 1.54.2.13 2004/09/23 01:49:08 hobbs Exp $ */ #include "tkWinInt.h" @@ -416,6 +416,7 @@ static int InstallColormaps _ANSI_ARGS_((HWND hwnd, int message, int isForemost)); static void InvalidateSubTree _ANSI_ARGS_((TkWindow *winPtr, Colormap colormap)); +static void InvalidateSubTreeDepth _ANSI_ARGS_((TkWindow *winPtr)); static int ParseGeometry _ANSI_ARGS_((Tcl_Interp *interp, char *string, TkWindow *winPtr)); static void RefreshColormap _ANSI_ARGS_((Colormap colormap, @@ -5829,6 +5830,13 @@ Tk_GetVRootGeometry(tkwin, xPtr, yPtr, widthPtr, heightPtr) { TkWindow *winPtr = (TkWindow *) tkwin; + /* + * XXX: This is not correct for multiple monitors. There may be many + * changes required to get this right, and it may effect existing + * applications that don't consider possible <0 vroot. See + * http://msdn.microsoft.com/library/en-us/gdi/monitor_3lrn.asp + * for more info. + */ *xPtr = 0; *yPtr = 0; *widthPtr = DisplayWidth(winPtr->display, winPtr->screenNum); @@ -6858,6 +6866,62 @@ InvalidateSubTree(winPtr, colormap) /* *---------------------------------------------------------------------- * + * InvalidateSubTreeDepth -- + * + * This function recursively updates depth info for a window and + * all of its children that belong to the same toplevel. + * + * Results: + * None. + * + * Side effects: + * Sets the depth of each window to that of the display. + * + *---------------------------------------------------------------------- + */ + +static void +InvalidateSubTreeDepth(winPtr) + TkWindow *winPtr; +{ + Display *display = Tk_Display(winPtr); + int screenNum = Tk_ScreenNumber(winPtr); + TkWindow *childPtr; + + winPtr->depth = DefaultDepth(display, screenNum); + +#if 0 + /* + * XXX: What other elements may require changes? Changing just + * the depth works for standard windows and 16/24/32-bpp changes. + * I suspect 8-bit (palettized) displays may require colormap and/or + * visual changes as well. + */ + + if (winPtr->window) { + InvalidateRect(Tk_GetHWND(winPtr->window), NULL, FALSE); + } + winPtr->visual = DefaultVisual(display, screenNum); + winPtr->atts.colormap = DefaultColormap(display, screenNum); + winPtr->dirtyAtts |= CWColormap; +#endif + + for (childPtr = winPtr->childList; childPtr != NULL; + childPtr = childPtr->nextPtr) { + /* + * We can stop the descent when we hit a toplevel window, as it + * should get its own message. + */ + + if (!Tk_TopWinHierarchy(childPtr)) { + InvalidateSubTreeDepth(childPtr); + } + } +} + +/* + *---------------------------------------------------------------------- + * * TkWinGetSystemPalette -- * * Retrieves the currently installed foreground palette. @@ -7145,6 +7209,48 @@ WmProc(hwnd, message, wParam, lParam) result = 0; goto done; + case WM_DISPLAYCHANGE: + /* display and/or color resolution changed */ + winPtr = GetTopLevel(hwnd); + if (winPtr) { + Screen *screen = Tk_Screen(winPtr); + if (screen->root_depth != (int) wParam) { + /* + * Color resolution changed, so do extensive rebuild of + * display parameters. This will affect the display for + * all Tk windows. We will receive this event for each + * toplevel, but this check makes us update only once, for + * the first toplevel that receives the message. + */ + TkWinDisplayChanged(Tk_Display(winPtr)); + } else { + HDC dc = GetDC(NULL); + screen->width = LOWORD(lParam); /* horizontal res */ + screen->height = HIWORD(lParam); /* vertical res */ + screen->mwidth = MulDiv(screen->width, 254, + GetDeviceCaps(dc, LOGPIXELSX) * 10); + screen->mheight = MulDiv(screen->height, 254, + GetDeviceCaps(dc, LOGPIXELSY) * 10); + ReleaseDC(NULL, dc); + } + if (Tk_Depth(winPtr) != (int) wParam) { + /* + * Defer the window depth check to here so that each + * toplevel will properly update depth info. + */ + InvalidateSubTreeDepth(winPtr); + } + } + result = 0; + goto done; + + case WM_SYSCOLORCHANGE: + /* + * XXX: Called when system color changes. We need to + * update any widgets that use a system color. + */ + break; + case WM_PALETTECHANGED: result = InstallColormaps(hwnd, WM_PALETTECHANGED, hwnd == (HWND)wParam); diff --git a/win/tkWinX.c b/win/tkWinX.c index 94b3c6c..da65e26 100644 --- a/win/tkWinX.c +++ b/win/tkWinX.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinX.c,v 1.25.2.3 2004/09/23 00:56:15 mdejong Exp $ + * RCS: @(#) $Id: tkWinX.c,v 1.25.2.4 2004/09/23 01:49:08 hobbs Exp $ */ #include "tkWinInt.h" @@ -348,7 +348,7 @@ TkWinXCleanup(hInstance) *---------------------------------------------------------------------- */ -int +int TkWinGetPlatformId() { if (tkPlatformId == 0) { @@ -406,7 +406,7 @@ TkWinGetPlatformId() *---------------------------------------------------------------------- */ -int +int TkWinGetPlatformTheme() { if (tkPlatformId == 0) { @@ -446,6 +446,100 @@ TkGetDefaultScreenName(interp, screenName) /* *---------------------------------------------------------------------- * + * TkWinDisplayChanged -- + * + * Called to set up initial screen info or when an event indicated + * display (screen) change. + * + * Results: + * None. + * + * Side effects: + * May change info regarding the screen. + * + *---------------------------------------------------------------------- + */ + +void +TkWinDisplayChanged(Display *display) +{ + HDC dc; + Screen *screen; + + if (display == NULL || display->screens == NULL) { + return; + } + screen = display->screens; + + dc = GetDC(NULL); + screen->width = GetDeviceCaps(dc, HORZRES); + screen->height = GetDeviceCaps(dc, VERTRES); + screen->mwidth = MulDiv(screen->width, 254, + GetDeviceCaps(dc, LOGPIXELSX) * 10); + screen->mheight = MulDiv(screen->height, 254, + GetDeviceCaps(dc, LOGPIXELSY) * 10); + + /* + * On windows, when creating a color bitmap, need two pieces of + * information: the number of color planes and the number of pixels per + * plane. Need to remember both quantities so that when constructing an + * HBITMAP for offscreen rendering, we can specify the correct value for + * the number of planes. Otherwise the HBITMAP won't be compatible with + * the HWND and we'll just get blank spots copied onto the screen. + */ + + screen->ext_data = (XExtData *) GetDeviceCaps(dc, PLANES); + screen->root_depth = GetDeviceCaps(dc, BITSPIXEL) * (int) screen->ext_data; + + if (screen->root_visual != NULL) { + ckfree((char *) screen->root_visual); + } + screen->root_visual = (Visual *) ckalloc(sizeof(Visual)); + screen->root_visual->visualid = 0; + if (GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE) { + screen->root_visual->map_entries = GetDeviceCaps(dc, SIZEPALETTE); + screen->root_visual->class = PseudoColor; + screen->root_visual->red_mask = 0x0; + screen->root_visual->green_mask = 0x0; + screen->root_visual->blue_mask = 0x0; + } else if (screen->root_depth == 4) { + screen->root_visual->class = StaticColor; + screen->root_visual->map_entries = 16; + } else if (screen->root_depth == 8) { + screen->root_visual->class = StaticColor; + screen->root_visual->map_entries = 256; + } else if (screen->root_depth == 12) { + screen->root_visual->class = TrueColor; + screen->root_visual->map_entries = 32; + screen->root_visual->red_mask = 0xf0; + screen->root_visual->green_mask = 0xf000; + screen->root_visual->blue_mask = 0xf00000; + } else if (screen->root_depth == 16) { + screen->root_visual->class = TrueColor; + screen->root_visual->map_entries = 64; + screen->root_visual->red_mask = 0xf8; + screen->root_visual->green_mask = 0xfc00; + screen->root_visual->blue_mask = 0xf80000; + } else if (screen->root_depth >= 24) { + screen->root_visual->class = TrueColor; + screen->root_visual->map_entries = 256; + screen->root_visual->red_mask = 0xff; + screen->root_visual->green_mask = 0xff00; + screen->root_visual->blue_mask = 0xff0000; + } + screen->root_visual->bits_per_rgb = screen->root_depth; + ReleaseDC(NULL, dc); + + if (screen->cmap != None) { + XFreeColormap(display, screen->cmap); + } + screen->cmap = XCreateColormap(display, None, screen->root_visual, + AllocNone); +} + +/* + *---------------------------------------------------------------------- + * * TkpOpenDisplay -- * * Create the Display structure and fill it with device @@ -465,7 +559,6 @@ TkpOpenDisplay(display_name) CONST char *display_name; { Screen *screen; - HDC dc; TkWinDrawable *twdPtr; Display *display; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) @@ -487,21 +580,14 @@ TkpOpenDisplay(display_name) strcpy(display->display_name, display_name); display->cursor_font = 1; - display->nscreens = 1; - display->request = 1; - display->qlen = 0; + display->nscreens = 1; + display->request = 1; + display->qlen = 0; screen = (Screen *) ckalloc(sizeof(Screen)); + ZeroMemory(screen, sizeof(Screen)); screen->display = display; - dc = GetDC(NULL); - screen->width = GetDeviceCaps(dc, HORZRES); - screen->height = GetDeviceCaps(dc, VERTRES); - screen->mwidth = MulDiv(screen->width, 254, - GetDeviceCaps(dc, LOGPIXELSX) * 10); - screen->mheight = MulDiv(screen->height, 254, - GetDeviceCaps(dc, LOGPIXELSY) * 10); - /* * Set up the root window. */ @@ -516,72 +602,24 @@ TkpOpenDisplay(display_name) screen->root = (Window)twdPtr; /* - * On windows, when creating a color bitmap, need two pieces of - * information: the number of color planes and the number of - * pixels per plane. Need to remember both quantities so that - * when constructing an HBITMAP for offscreen rendering, we can - * specify the correct value for the number of planes. Otherwise - * the HBITMAP won't be compatible with the HWND and we'll just - * get blank spots copied onto the screen. - */ - - screen->ext_data = (XExtData *) GetDeviceCaps(dc, PLANES); - screen->root_depth = GetDeviceCaps(dc, BITSPIXEL) * (int) screen->ext_data; - - screen->root_visual = (Visual *) ckalloc(sizeof(Visual)); - screen->root_visual->visualid = 0; - if (GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE) { - screen->root_visual->map_entries = GetDeviceCaps(dc, SIZEPALETTE); - screen->root_visual->class = PseudoColor; - screen->root_visual->red_mask = 0x0; - screen->root_visual->green_mask = 0x0; - screen->root_visual->blue_mask = 0x0; - } else { - if (screen->root_depth == 4) { - screen->root_visual->class = StaticColor; - screen->root_visual->map_entries = 16; - } else if (screen->root_depth == 8) { - screen->root_visual->class = StaticColor; - screen->root_visual->map_entries = 256; - } else if (screen->root_depth == 12) { - screen->root_visual->class = TrueColor; - screen->root_visual->map_entries = 32; - screen->root_visual->red_mask = 0xf0; - screen->root_visual->green_mask = 0xf000; - screen->root_visual->blue_mask = 0xf00000; - } else if (screen->root_depth == 16) { - screen->root_visual->class = TrueColor; - screen->root_visual->map_entries = 64; - screen->root_visual->red_mask = 0xf8; - screen->root_visual->green_mask = 0xfc00; - screen->root_visual->blue_mask = 0xf80000; - } else if (screen->root_depth >= 24) { - screen->root_visual->class = TrueColor; - screen->root_visual->map_entries = 256; - screen->root_visual->red_mask = 0xff; - screen->root_visual->green_mask = 0xff00; - screen->root_visual->blue_mask = 0xff0000; - } - } - screen->root_visual->bits_per_rgb = screen->root_depth; - ReleaseDC(NULL, dc); - - /* * Note that these pixel values are not palette relative. */ screen->white_pixel = RGB(255, 255, 255); screen->black_pixel = RGB(0, 0, 0); + screen->cmap = None; display->screens = screen; display->nscreens = 1; display->default_screen = 0; - screen->cmap = XCreateColormap(display, None, screen->root_visual, - AllocNone); + + TkWinDisplayChanged(display); + tsdPtr->winDisplay = (TkDisplay *) ckalloc(sizeof(TkDisplay)); ZeroMemory(tsdPtr->winDisplay, sizeof(TkDisplay)); tsdPtr->winDisplay->display = display; tsdPtr->updatingClipboard = FALSE; + return tsdPtr->winDisplay; } -- cgit v0.12