You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
259 lines
8.5 KiB
259 lines
8.5 KiB
/**************************** Module Header ********************************\
|
|
* Module Name: palette.c
|
|
*
|
|
* Copyright (c) 1985 - 1999, Microsoft Corporation
|
|
*
|
|
* Palette Handling Routines
|
|
*
|
|
* History:
|
|
* 24-May-1993 MikeKe From win3.1
|
|
\***************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
/***************************************************************************\
|
|
* IsTopmostRealApp
|
|
*
|
|
* Returns true if current process is the shell process and this window
|
|
* is the first non-shell/user one we find in zorder. If so, we consider
|
|
* him to be the "palette foreground".
|
|
*
|
|
* History:
|
|
\***************************************************************************/
|
|
|
|
BOOL IsTopmostRealApp(
|
|
PWND pwnd)
|
|
{
|
|
PTHREADINFO ptiCurrent = PtiCurrent();
|
|
PDESKTOPINFO pdeskinfo = pwnd->head.rpdesk->pDeskInfo;
|
|
if ((pdeskinfo->spwndShell == NULL) ||
|
|
(GETPTI(pdeskinfo->spwndShell)->pq != gpqForeground)) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
return (pwnd == NextTopWindow(ptiCurrent,
|
|
NULL,
|
|
NULL,
|
|
NTW_IGNORETOOLWINDOW));
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* _SelectPalette
|
|
*
|
|
* Selects palette into DC. This is a wrapper to gdi where we can perform
|
|
* checks to see if it's a foreground dc.
|
|
*
|
|
* History:
|
|
\***************************************************************************/
|
|
|
|
HPALETTE _SelectPalette(
|
|
HDC hdc,
|
|
HPALETTE hpal,
|
|
BOOL fForceBackground)
|
|
{
|
|
PWND pwndTop;
|
|
BOOL fBackgroundPalette = TRUE;
|
|
PWND pwnd = NULL;
|
|
/*
|
|
* If we are not forcing palette into background, find out where it does
|
|
* actually belong. Don't ever select the default palette in as a
|
|
* foreground palette because this confuses gdi. Many apps do a
|
|
* (oldPal = SelectPalette) (myPal); Draw; SelectObject(oldPal).
|
|
* and we don't want to allow this to go through.
|
|
*/
|
|
if (!fForceBackground &&
|
|
TEST_PUSIF(PUSIF_PALETTEDISPLAY) &&
|
|
(hpal != GreGetStockObject(DEFAULT_PALETTE))) {
|
|
|
|
if (pwnd = WindowFromCacheDC(hdc)) {
|
|
|
|
PWND pwndActive;
|
|
|
|
/*
|
|
* don't "select" palette unless on a palette device
|
|
*/
|
|
pwndTop = GetTopLevelWindow(pwnd);
|
|
|
|
if (!TestWF(pwndTop, WFHASPALETTE)) {
|
|
|
|
if (pwndTop != _GetDesktopWindow())
|
|
GETPTI(pwndTop)->TIF_flags |= TIF_PALETTEAWARE;
|
|
|
|
SetWF(pwndTop, WFHASPALETTE);
|
|
}
|
|
|
|
/*
|
|
* Hack-o-rama:
|
|
* Windows get foreground use of the palette if
|
|
* * They are the foreground's active window
|
|
* * The current process is the shell and they are the
|
|
* topmost valid non-toolwindow in the zorder.
|
|
*
|
|
* This makes our tray friendly on palettized displays.
|
|
* Currently, if you run a palette app and click on the tray,
|
|
* the palette app goes all weird. Broderbund apps go
|
|
* completely black. This is because they get forced to be
|
|
* background always, even though the shell isn't really
|
|
* palettized.
|
|
*
|
|
* Note: this palette architecture isn't very good. Apps get forced to
|
|
* be background palette users even if the foreground thread
|
|
* couldn't care less about the palette. Should go by zorder
|
|
* if so, but in a more clean way than this.
|
|
*
|
|
* We really only care about the tray && the background.
|
|
* Cabinet dudes don't matter so much.
|
|
*/
|
|
pwndActive = (gpqForeground ? gpqForeground->spwndActive : NULL);
|
|
|
|
#if 0
|
|
if (pwndActive &&
|
|
(pwndTop != pwnd->head.rpdesk->pDeskInfo->spwndShell) &&
|
|
((pwndActive == pwnd) || _IsChild(pwndActive, pwnd) || IsTopmostRealApp(pwnd)) &&
|
|
!TestWF(pwnd, WEFTOOLWINDOW)) {
|
|
|
|
fBackgroundPalette = FALSE;
|
|
}
|
|
#else
|
|
if ((pwndTop != pwndTop->head.rpdesk->pDeskInfo->spwnd) &&
|
|
(pwndTop != pwndTop->head.rpdesk->pDeskInfo->spwndShell) &&
|
|
(pwndActive != NULL) &&
|
|
((pwndActive == pwnd) ||
|
|
_IsChild(pwndActive, pwnd) ||
|
|
IsTopmostRealApp(pwnd)) &&
|
|
!TestWF(pwnd, WEFTOOLWINDOW)) {
|
|
|
|
fBackgroundPalette = FALSE;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
return GreSelectPalette(hdc, hpal, fBackgroundPalette);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* xxxRealizePalette
|
|
*
|
|
* Realizes palette to the DC. This is a wrapper to gdi so that we can
|
|
* check for changes prior to sending notifications.
|
|
*
|
|
* History:
|
|
\***************************************************************************/
|
|
|
|
int xxxRealizePalette(
|
|
HDC hdc)
|
|
{
|
|
PWND pwnd;
|
|
DWORD dwNumChanged;
|
|
PWINDOWSTATION pwinsta;
|
|
PDESKTOP pdesk;
|
|
TL tlpwnd;
|
|
|
|
dwNumChanged = GreRealizePalette(hdc);
|
|
|
|
if (HIWORD(dwNumChanged) && IsDCCurrentPalette(hdc)) {
|
|
|
|
pwnd = WindowFromCacheDC(hdc);
|
|
|
|
/*
|
|
* if there is no associated window, don't send the palette change
|
|
* messages since this is a memory hdc.
|
|
*/
|
|
if (pwnd != NULL) {
|
|
/*
|
|
* Ok, send WM_PALETTECHANGED message to everyone. The wParam
|
|
* contains a handle to the currently active window. Send
|
|
* message to the desktop also, so things on the desktop bitmap
|
|
* will paint ok.
|
|
*/
|
|
ThreadLock(pwnd, &tlpwnd);
|
|
xxxBroadcastPaletteChanged(pwnd, FALSE);
|
|
ThreadUnlock(&tlpwnd);
|
|
|
|
/*
|
|
* Mark all other desktops as needing to send out
|
|
* WM_PALETTECHANGED messages.
|
|
*/
|
|
|
|
pwinsta = grpWinStaList;
|
|
|
|
while (pwinsta != NULL) {
|
|
pdesk = pwinsta->rpdeskList;
|
|
while (pdesk != NULL) {
|
|
if (pdesk != pwnd->head.rpdesk) {
|
|
pdesk->dwDTFlags |= DTF_NEEDSPALETTECHANGED;
|
|
}
|
|
pdesk = pdesk->rpdeskNext;
|
|
}
|
|
pwinsta = pwinsta->rpwinstaNext;
|
|
}
|
|
|
|
GreRealizePalette(hdc);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Walk through the SPB list (the saved bitmaps under windows with the
|
|
* CS_SAVEBITS style) discarding all bitmaps
|
|
*/
|
|
if (HIWORD(dwNumChanged)) {
|
|
FreeAllSpbs();
|
|
}
|
|
|
|
return LOWORD(dwNumChanged);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* xxxFlushPalette
|
|
*
|
|
* This resets the palette and lets the next foreground app grab the
|
|
* foreground palette. This is called in such instances when we
|
|
* minimize a window.
|
|
*
|
|
* History:
|
|
* 31-Aug-1995 ChrisWil Created.
|
|
\***************************************************************************/
|
|
|
|
VOID xxxFlushPalette(
|
|
PWND pwnd)
|
|
{
|
|
CheckLock(pwnd);
|
|
/*
|
|
* Broadcast the palette changed messages.
|
|
*/
|
|
GreRealizeDefaultPalette(gpDispInfo->hdcScreen, TRUE);
|
|
xxxBroadcastPaletteChanged(pwnd, TRUE);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* xxxBroadcastPaletteChanged
|
|
*
|
|
* RealizePalette passes FALSE for fForceDesktopso so that it does not
|
|
* cause a loop in case RealizePalette was called by the desktop window.
|
|
* In such a case we don't want to call RealizeDesktop. In all other cases
|
|
* we do want to go to RealizeDesktop to give the desktop a chance to
|
|
* reailze its palette or possibly just repaint.
|
|
*
|
|
* 04/22/97 vadimg created
|
|
\***************************************************************************/
|
|
|
|
VOID xxxBroadcastPaletteChanged(PWND pwnd, BOOL fForceDesktop)
|
|
{
|
|
PWND pwndDesk;
|
|
HWND hwnd = HWq(pwnd);
|
|
|
|
CheckLock(pwnd);
|
|
|
|
pwndDesk = PWNDDESKTOP(pwnd);
|
|
if (fForceDesktop || pwnd != pwndDesk) {
|
|
TL tlpwndDesk;
|
|
ThreadLockAlways(pwndDesk, &tlpwndDesk);
|
|
xxxRealizeDesktop(pwndDesk);
|
|
ThreadUnlock(&tlpwndDesk);
|
|
}
|
|
|
|
xxxSendNotifyMessage(PWND_BROADCAST, WM_PALETTECHANGED, (WPARAM)hwnd, 0L);
|
|
}
|