summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--win/tkWinInt.h7
-rw-r--r--win/tkWinWm.c108
-rw-r--r--win/tkWinX.c174
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 <jeffh@ActiveState.com>
+
+ * 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 <mdejong@users.sourceforge.net>
* 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;
}