Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

fullscr.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: fullscr.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * This module contains all the fullscreen code for the USERSRV.DLL. 00007 * 00008 * History: 00009 * 12-Dec-1991 mikeke Created 00010 \***************************************************************************/ 00011 00012 #include "precomp.h" 00013 #pragma hdrstop 00014 00015 /***************************************************************************\ 00016 * We can only have one fullscreen window at a time so this information can 00017 * be store globally 00018 * 00019 * We partially use busy waiting to set the state of the hardware. 00020 * The problem is that while we are in the middle of a fullscreen switch, 00021 * we leave the critical section ! So someone else could come in and change 00022 * the state of the fullscreen stuff. 00023 * In order to keep the system from getting confused about the state of the 00024 * device, we actually "post" the request. 00025 * 00026 * What we do with external requests for switching, is that we will do busy 00027 * waiting on these state variables. 00028 * So an app won't be able to request a fullscreen switch while one is under 00029 * way. This is a way to make the system completely reentrant for state 00030 * switches. 00031 * 00032 * The state variables themselves can only be touched while owning the 00033 * critical section. We are guaranteed that we will not busy wait forever 00034 * since the switch operations (although long) will eventually finish. 00035 * 00036 * 20-Mar-1996 andreva Created 00037 \***************************************************************************/ 00038 00039 LONG TraceFullscreenSwitch; 00040 00041 #define NOSWITCHER ((HANDLE)-1) 00042 00043 HANDLE idSwitcher = NOSWITCHER; 00044 BOOL fRedoFullScreenSwitch; 00045 BOOL fGdiEnabled = TRUE; 00046 POINT gptCursorFullScreen; 00047 00048 extern ULONG InitSafeBootMode; // imported from NTOS (init.c), must use a pointer to reference the data 00049 00050 void SetVDMCursorBounds(LPRECT lprc); 00051 00052 00053 VOID UserSetDelayedChangeBroadcastForAllDesktops(PDESKTOP pCurrentDesktop); 00054 00055 00056 VOID UserSetDelayedChangeBroadcastForAllDesktops( 00057 PDESKTOP pCurrentDesktop) 00058 { 00059 PWINDOWSTATION pwinsta; 00060 PDESKTOP pdesk; 00061 00062 /* 00063 * Get a pointer to the windowstation so we can change display 00064 * setting for all of its destops. 00065 */ 00066 if ((pwinsta = grpWinStaList) == NULL) { 00067 RIPMSG0(RIP_WARNING, "UserSaveCurrentModeForAllDesktops - No interactive WindowStation!!!\n"); 00068 return; 00069 } 00070 00071 /* 00072 * Walk all the desktops of the winstation and, for each of them, 00073 * just set its delayed Broadcast indicator to TRUE so that 00074 * next switch to that destop will force Display Settings change 00075 * messages to be broadcasted to windows of that desktop. 00076 */ 00077 pdesk = pwinsta->rpdeskList; 00078 00079 while (pdesk != NULL) { 00080 if (pdesk != pCurrentDesktop) { 00081 pdesk->dwDTFlags |= DF_NEWDISPLAYSETTINGS; 00082 } 00083 pdesk = pdesk->rpdeskNext; 00084 } 00085 } 00086 00087 00088 /***************************************************************************\ 00089 * FullScreenCleanup 00090 * 00091 * This is called during thread cleanup, we test to see if we died during a 00092 * full screen switch and switch back to the GDI desktop if we did. 00093 * 00094 * NOTE: 00095 * All the variables touched here are guaranteed to be touched under 00096 * the CritSect. 00097 * 00098 * 12-Dec-1991 mikeke Created 00099 \***************************************************************************/ 00100 00101 void FullScreenCleanup() 00102 { 00103 if (PsGetCurrentThread()->Cid.UniqueThread == idSwitcher) { 00104 00105 /* 00106 * correct the full screen state 00107 */ 00108 00109 if (fGdiEnabled) { 00110 00111 TRACE_SWITCH(("Switching: FullScreenCleanup: Gdi Enabled\n")); 00112 00113 /* 00114 * gdi is enabled, we are switching away from gdi the only thing we 00115 * could have done so far is locking the screen so unlock it. 00116 */ 00117 CLEAR_PUDF(PUDF_LOCKFULLSCREEN); 00118 LockWindowUpdate2(NULL, TRUE); 00119 00120 } else { 00121 00122 /* 00123 * GDI is not enabled . This means we were switching from a full 00124 * screen to another fullscreen or back to GDI. Or we could have 00125 * disabled gdi and sent a message to the new full screen which 00126 * never got completed. 00127 * 00128 * In any case this probably means the fullscreen guy is gone so 00129 * we will switch back to gdi. 00130 * 00131 * delete any left over saved screen state stuff 00132 * set the fullscreen to nothing and then send a message that will 00133 * cause us to switch back to the gdi desktop 00134 */ 00135 TL tlpwndT; 00136 00137 TRACE_SWITCH(("Switching: FullScreenCleanup: Gdi Disabled\n")); 00138 00139 Unlock(&gspwndFullScreen); 00140 gbFullScreen = FULLSCREEN; 00141 00142 ThreadLock(grpdeskRitInput->pDeskInfo->spwnd, &tlpwndT); 00143 xxxSendNotifyMessage( 00144 grpdeskRitInput->pDeskInfo->spwnd, WM_FULLSCREEN, 00145 GDIFULLSCREEN, (LPARAM)HW(grpdeskRitInput->pDeskInfo->spwnd)); 00146 ThreadUnlock(&tlpwndT); 00147 } 00148 00149 idSwitcher = NOSWITCHER; 00150 fRedoFullScreenSwitch = FALSE; 00151 } 00152 } 00153 00154 /***************************************************************************\ 00155 * xxxMakeWindowForegroundWithState 00156 * 00157 * Syncs the screen graphics mode with the mode of the specified (foreground) 00158 * window 00159 * 00160 * We make sure only one thread is going through this code by checking 00161 * idSwitcher. If idSwticher is non-null someone is allready in this code 00162 * 00163 * 12-Dec-1991 mikeke Created 00164 \***************************************************************************/ 00165 00166 BOOL xxxMakeWindowForegroundWithState( 00167 PWND pwnd, 00168 BYTE NewState) 00169 { 00170 PWND pwndNewFG; 00171 TL tlpwndNewFG; 00172 00173 TRACE_SWITCH(("Switching: xxxMakeWindowForeground: Enter\n")); 00174 TRACE_SWITCH(("\t \t pwnd = %08lx\n", pwnd)); 00175 TRACE_SWITCH(("\t \t NewState = %d\n", NewState)); 00176 00177 CheckLock(pwnd); 00178 UserAssert(IsWinEventNotifyDeferredOK()); 00179 00180 /* 00181 * If we should switch to a specific window save that window 00182 */ 00183 00184 if (pwnd != NULL) { 00185 00186 if (NewState == GDIFULLSCREEN) { 00187 Lock(&gspwndShouldBeForeground, pwnd); 00188 } 00189 00190 /* 00191 * Change to the new state 00192 */ 00193 00194 SetFullScreen(pwnd, NewState); 00195 00196 if (NewState == FULLSCREEN && 00197 (gpqForeground == NULL || 00198 gpqForeground->spwndActive != pwnd)) { 00199 00200 SetFullScreen(pwnd, FULLSCREENMIN); 00201 } 00202 } 00203 00204 // 00205 // Since we leave the critical section during the switch, some other 00206 // thread could come into this routine and request a switch. The global 00207 // will be reset, and we will use the loop to perform the next switch. 00208 // 00209 00210 if (idSwitcher != NOSWITCHER) { 00211 fRedoFullScreenSwitch = TRUE; 00212 TRACE_SWITCH(("Switching: xxxMakeWindowForeground was posted: Exit\n")); 00213 00214 return TRUE; 00215 } 00216 00217 UserAssert(!fRedoFullScreenSwitch); 00218 idSwitcher = PsGetCurrentThread()->Cid.UniqueThread; 00219 00220 /* 00221 * We loop, switching full screens until all states have stabilized 00222 */ 00223 00224 while (TRUE) { 00225 /* 00226 * figure out who should be foreground 00227 */ 00228 fRedoFullScreenSwitch = FALSE; 00229 00230 if (gspwndShouldBeForeground != NULL) { 00231 pwndNewFG = gspwndShouldBeForeground; 00232 Unlock(&gspwndShouldBeForeground); 00233 } else { 00234 if (gpqForeground != NULL && 00235 gpqForeground->spwndActive != NULL) { 00236 00237 pwndNewFG = gpqForeground->spwndActive; 00238 00239 if (GetFullScreen(pwndNewFG) == WINDOWED || 00240 GetFullScreen(pwndNewFG) == FULLSCREENMIN) { 00241 00242 pwndNewFG = PWNDDESKTOP(pwndNewFG); 00243 } 00244 } else { 00245 /* 00246 * No active window, switch to current desktop 00247 */ 00248 pwndNewFG = grpdeskRitInput->pDeskInfo->spwnd; 00249 } 00250 } 00251 00252 /* 00253 * We don't need to switch if the right window is already foreground 00254 */ 00255 if (pwndNewFG == gspwndFullScreen) { 00256 break; 00257 } 00258 00259 ThreadLock(pwndNewFG, &tlpwndNewFG); 00260 00261 { 00262 BYTE bStateNew = GetFullScreen(pwndNewFG); 00263 TL tlpwndOldFG; 00264 PWND pwndOldFG = gspwndFullScreen; 00265 BYTE bStateOld = gbFullScreen; 00266 00267 ThreadLock(pwndOldFG, &tlpwndOldFG); 00268 00269 Lock(&gspwndFullScreen, pwndNewFG); 00270 gbFullScreen = bStateNew; 00271 00272 UserAssert(!HMIsMarkDestroy(gspwndFullScreen)); 00273 00274 /* 00275 * If the old screen was GDIFULLSCREEN and we are switching to 00276 * GDIFULLSCREEN then just repaint 00277 */ 00278 00279 /* 00280 * BUG 231647: For remote sessions it can happen that 00281 * pwndOldFG is NULL but the display is enabled therefore a 00282 * call to DrvEnableMDEV would confuse the Drv* code. The way 00283 * this happens is when gspwndFullScreen was the desktop window 00284 * of a desktop that got destroyed after we switched away from it. 00285 */ 00286 00287 if ((pwndOldFG != NULL || gbRemoteSession) && 00288 bStateOld == GDIFULLSCREEN && 00289 bStateNew == GDIFULLSCREEN) { 00290 00291 xxxRedrawWindow(pwndNewFG, NULL, NULL, 00292 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE | RDW_ERASENOW); 00293 00294 ThreadUnlock(&tlpwndOldFG); 00295 00296 } else { 00297 00298 /* 00299 * tell old 'foreground' window it is losing control of the screen 00300 */ 00301 if (pwndOldFG != NULL) { 00302 switch (bStateOld) { 00303 case FULLSCREEN: 00304 if (GetFullScreen(pwndOldFG) == FULLSCREEN) { 00305 SetFullScreen(pwndOldFG, FULLSCREENMIN); 00306 } 00307 xxxSendMessage(pwndOldFG, WM_FULLSCREEN, FALSE, 0); 00308 xxxCapture(GETPTI(pwndOldFG), NULL, FULLSCREEN_CAPTURE); 00309 SetVDMCursorBounds(NULL); 00310 break; 00311 00312 case GDIFULLSCREEN: 00313 /* 00314 * Lock out other windows from drawing while we are fullscreen 00315 */ 00316 LockWindowUpdate2(pwndOldFG, TRUE); 00317 SET_PUDF(PUDF_LOCKFULLSCREEN); 00318 00319 UserAssert(fGdiEnabled == TRUE); 00320 00321 if (!DrvDisableMDEV(gpDispInfo->pmdev, TRUE)) { 00322 /* 00323 * Restore the previous state before bailing. 00324 */ 00325 CLEAR_PUDF(PUDF_LOCKFULLSCREEN); 00326 LockWindowUpdate2(NULL, TRUE); 00327 00328 Lock(&gspwndFullScreen, pwndOldFG); 00329 gbFullScreen = bStateOld; 00330 00331 ThreadUnlock(&tlpwndOldFG); 00332 ThreadUnlock(&tlpwndNewFG); 00333 00334 idSwitcher = NOSWITCHER; 00335 00336 return FALSE; 00337 } 00338 00339 gptCursorFullScreen = gpsi->ptCursor; 00340 fGdiEnabled = FALSE; 00341 break; 00342 00343 default: 00344 RIPMSG0(RIP_ERROR, "xxxDoFullScreenSwitch: bad screen state"); 00345 break; 00346 00347 } 00348 } 00349 00350 ThreadUnlock(&tlpwndOldFG); 00351 00352 switch (bStateNew) { 00353 case FULLSCREEN: 00354 xxxCapture(GETPTI(pwndNewFG), pwndNewFG, FULLSCREEN_CAPTURE); 00355 xxxSendMessage(pwndNewFG, WM_FULLSCREEN, TRUE, 0); 00356 break; 00357 00358 case GDIFULLSCREEN: 00359 if (ISTS() && pwndOldFG != NULL) { 00360 UserAssert(fGdiEnabled == FALSE); 00361 } 00362 00363 DrvEnableMDEV(gpDispInfo->pmdev, TRUE); 00364 fGdiEnabled = TRUE; 00365 00366 /* 00367 * Return the cursor to it's old state. Reset the screen saver mouse 00368 * position or it'll go away by accident. 00369 */ 00370 gpqCursor = NULL; 00371 gpcurPhysCurrent = NULL; 00372 gpcurLogCurrent = NULL; 00373 SetPointer(FALSE); 00374 gptSSCursor = gptCursorFullScreen; 00375 00376 /* 00377 * No need to DeferWinEventNotify() - we use only globals, 00378 * then make an xxx call below. 00379 */ 00380 zzzInternalSetCursorPos(gptCursorFullScreen.x, 00381 gptCursorFullScreen.y 00382 ); 00383 00384 CLEAR_PUDF(PUDF_LOCKFULLSCREEN); 00385 LockWindowUpdate2(NULL, TRUE); 00386 00387 xxxRedrawWindow(pwndNewFG, NULL, NULL, 00388 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE | RDW_ERASENOW); 00389 break; 00390 00391 default: 00392 RIPMSG0(RIP_ERROR, "xxxDoFullScreenSwitch: bad screen state\n"); 00393 break; 00394 } 00395 } 00396 } 00397 00398 ThreadUnlock(&tlpwndNewFG); 00399 00400 if (!fRedoFullScreenSwitch) { 00401 break; 00402 } 00403 } 00404 00405 TRACE_SWITCH(("Switching: xxxMakeWindowForeground: Exit\n")); 00406 00407 idSwitcher = NOSWITCHER; 00408 return TRUE; 00409 } 00410 00411 /***************************************************************************\ 00412 * MonitorFromHdev 00413 \***************************************************************************/ 00414 00415 PMONITOR MonitorFromHdev(HANDLE hdev) 00416 { 00417 PMONITOR pMonitor; 00418 00419 for (pMonitor = gpDispInfo->pMonitorFirst; pMonitor != NULL; 00420 pMonitor = pMonitor->pMonitorNext) { 00421 if (pMonitor->hDev == hdev) { 00422 return pMonitor; 00423 } 00424 } 00425 return NULL; 00426 } 00427 00428 /***************************************************************************\ 00429 * HdevFromMonitor 00430 \***************************************************************************/ 00431 00432 ULONG HdevFromMonitor(PMONITOR pMonitor) 00433 { 00434 PMDEV pmdev = gpDispInfo->pmdev; 00435 ULONG i; 00436 00437 for (i = 0; i < pmdev->chdev; i++) { 00438 if (pmdev->Dev[i].hdev == pMonitor->hDev) { 00439 return i; 00440 } 00441 } 00442 return -1; 00443 } 00444 00445 /***************************************************************************\ 00446 * CreateMonitor 00447 \***************************************************************************/ 00448 00449 PMONITOR CreateMonitor(void) 00450 { 00451 PMONITOR pMonitor; 00452 00453 pMonitor = (PMONITOR)HMAllocObject(NULL, NULL, TYPE_MONITOR, sizeof(MONITOR)); 00454 00455 if (pMonitor == NULL) { 00456 RIPERR0(ERROR_NOT_ENOUGH_MEMORY, RIP_WARNING, "CreateMonitor failed"); 00457 } 00458 00459 return pMonitor; 00460 } 00461 00462 /***************************************************************************\ 00463 * CreateCachedMonitor 00464 \***************************************************************************/ 00465 00466 PMONITOR CreateCachedMonitor(VOID) 00467 { 00468 if (gpMonitorCached == NULL) { 00469 gpMonitorCached = CreateMonitor(); 00470 } 00471 00472 return gpMonitorCached; 00473 } 00474 00475 /***************************************************************************\ 00476 * SetMonitorData 00477 \***************************************************************************/ 00478 00479 PMONITOR SetMonitorData(PMONITOR pMonitor, ULONG iDev) 00480 { 00481 PMDEV pmdev = gpDispInfo->pmdev; 00482 HDEV hdev = pmdev->Dev[iDev].hdev; 00483 BOOL fVisible = TRUE; 00484 BOOL fPrimary = FALSE; 00485 HDC hdcTmp; 00486 00487 UserAssert(iDev < pmdev->chdev); 00488 00489 if (hdcTmp = GreCreateDisplayDC(hdev, DCTYPE_DIRECT, FALSE)) { 00490 if (GreGetDeviceCaps(hdcTmp, CAPS1) & C1_MIRROR_DEVICE) { 00491 fVisible = FALSE; 00492 } 00493 GreDeleteDC(hdcTmp); 00494 } 00495 00496 if (fVisible && (pmdev->Dev[iDev].rect.top == 0) && 00497 (pmdev->Dev[iDev].rect.left == 0)) { 00498 fPrimary = TRUE; 00499 } 00500 00501 if (pMonitor == NULL) { 00502 if (fPrimary) { 00503 UserAssert(gpMonitorCached != NULL); 00504 pMonitor = gpMonitorCached; 00505 gpMonitorCached = NULL; 00506 } else { 00507 pMonitor = CreateMonitor(); 00508 } 00509 } 00510 00511 if (pMonitor == NULL) { 00512 return NULL; 00513 } 00514 00515 SET_OR_CLEAR_FLAG(pMonitor->dwMONFlags, MONF_VISIBLE, fVisible); 00516 00517 /* 00518 * When the monitor rect is changing, size the work area so the same 00519 * amount as before is clipped off each edge. 00520 */ 00521 if (!EqualRect(&pMonitor->rcMonitor, &pmdev->Dev[iDev].rect)) { 00522 pMonitor->rcWork.left = pmdev->Dev[iDev].rect.left - 00523 (pMonitor->rcMonitor.left - pMonitor->rcWork.left); 00524 pMonitor->rcWork.top = pmdev->Dev[iDev].rect.top - 00525 (pMonitor->rcMonitor.top - pMonitor->rcWork.top); 00526 pMonitor->rcWork.right = pmdev->Dev[iDev].rect.right - 00527 (pMonitor->rcMonitor.right - pMonitor->rcWork.right); 00528 pMonitor->rcWork.bottom = pmdev->Dev[iDev].rect.bottom - 00529 (pMonitor->rcMonitor.bottom - pMonitor->rcWork.bottom); 00530 } 00531 pMonitor->rcMonitor = pmdev->Dev[iDev].rect; 00532 pMonitor->hDev = hdev; 00533 00534 if (fPrimary) { 00535 gpDispInfo->pMonitorPrimary = pMonitor; 00536 } 00537 00538 return pMonitor; 00539 } 00540 00541 /***************************************************************************\ 00542 * 00543 * Is this still TRUE ? 00544 * 00545 * When a window becomes FULLSCREEN, it is minimized and 00546 * treated like any other minimized window. Whenever the 00547 * minimized window is restored, by double clicking, menu 00548 * or keyboard, it remains minimized and the application 00549 * is given control of the screen device. 00550 * 00551 * 12-Dec-1991 mikeke Created 00552 \***************************************************************************/ 00553 00554 00555 /***************************************************************************\ 00556 * UpdateUserScreen 00557 * 00558 * Updates USER information associated with the screen 00559 * 00560 * History: 00561 * 28-Sep-1996 adams Created. 00562 \***************************************************************************/ 00563 00564 BOOL UpdateUserScreen(void) 00565 { 00566 PMDEV pmdev = gpDispInfo->pmdev; 00567 ULONG i; 00568 PMONITOR pMonitor; 00569 TEXTMETRIC tm; 00570 int iRgn; 00571 PWINDOWSTATION pwinsta; 00572 PDESKTOP pdesk; 00573 HRGN hrgn; 00574 BOOL fPaletteDisplay; 00575 RECT rc; 00576 PMONITOR pMonitorNext = gpDispInfo->pMonitorFirst; 00577 PMONITOR *ppMonitorLast = &gpDispInfo->pMonitorFirst; 00578 00579 00580 TRACE_INIT(("UpdateUserScreen\n")); 00581 00582 UserAssert(gpDispInfo->hdcScreen); 00583 UserAssert(gpMonitorCached != NULL); 00584 00585 /* 00586 * Keep HMONITOR for the hdev that is the same. Delete the 00587 * monitors that weren't found in the new hdev list. 00588 */ 00589 while (pMonitorNext != NULL) { 00590 pMonitor = pMonitorNext; 00591 pMonitorNext = pMonitor->pMonitorNext; 00592 00593 if ((i = HdevFromMonitor(pMonitor)) == -1) { 00594 DestroyMonitor(pMonitor); 00595 } else { 00596 SetMonitorData(pMonitor, i); 00597 ppMonitorLast = &pMonitor->pMonitorNext; 00598 } 00599 } 00600 00601 /* 00602 * Create monitors for the hdevs that aren't yet on the monitor list. 00603 */ 00604 for (i = 0; i < pmdev->chdev; i++) { 00605 if ((pMonitor = MonitorFromHdev(pmdev->Dev[i].hdev)) == NULL) { 00606 00607 /* 00608 * Try to create a new monitor. 00609 */ 00610 pMonitor = SetMonitorData(NULL, i); 00611 00612 if (pMonitor != NULL) { 00613 *ppMonitorLast = pMonitor; 00614 ppMonitorLast = &pMonitor->pMonitorNext; 00615 } 00616 } 00617 } 00618 00619 UserAssert(gpDispInfo->pMonitorFirst != NULL); 00620 UserAssert(gpDispInfo->pMonitorPrimary != NULL); 00621 00622 /* 00623 * For now, all monitors have the same display format. 00624 */ 00625 SYSMET(SAMEDISPLAYFORMAT) = (pmdev->ulFlags & MDEV_MISMATCH_COLORDEPTH) ? FALSE : TRUE; 00626 fPaletteDisplay = GreGetDeviceCaps(gpDispInfo->hdcScreen, RASTERCAPS) & RC_PALETTE; 00627 gpDispInfo->fAnyPalette = !!fPaletteDisplay; 00628 00629 /* 00630 * Determine the coordinates of the virtual desktop. 00631 * Compute cMonitors as the number of visible monitors. 00632 */ 00633 SetRectEmpty(&rc); 00634 00635 gpDispInfo->cMonitors = 0; 00636 for (pMonitor = gpDispInfo->pMonitorFirst; 00637 pMonitor; 00638 pMonitor = pMonitor->pMonitorNext) { 00639 00640 /* 00641 * Only visible monitors contribute to the desktop area 00642 */ 00643 if (pMonitor->dwMONFlags & MONF_VISIBLE) { 00644 rc.left = min(rc.left, pMonitor->rcMonitor.left); 00645 rc.top = min(rc.top, pMonitor->rcMonitor.top); 00646 rc.right = max(rc.right, pMonitor->rcMonitor.right); 00647 rc.bottom = max(rc.bottom, pMonitor->rcMonitor.bottom); 00648 00649 gpDispInfo->cMonitors++; 00650 } 00651 00652 if (SYSMET(SAMEDISPLAYFORMAT)) { 00653 SET_OR_CLEAR_FLAG(pMonitor->dwMONFlags, MONF_PALETTEDISPLAY, fPaletteDisplay); 00654 } else { 00655 if (GreIsPaletteDisplay(pMonitor->hDev)) { 00656 pMonitor->dwMONFlags |= MONF_PALETTEDISPLAY; 00657 gpDispInfo->fAnyPalette = TRUE; 00658 } 00659 } 00660 } 00661 UserAssert(gpDispInfo->pMonitorPrimary != NULL); 00662 gpDispInfo->rcScreen = rc; 00663 00664 /* 00665 * Update system metrics 00666 */ 00667 SYSMET(CXSCREEN) = gpDispInfo->pMonitorPrimary->rcMonitor.right; 00668 SYSMET(CYSCREEN) = gpDispInfo->pMonitorPrimary->rcMonitor.bottom; 00669 SYSMET(XVIRTUALSCREEN) = gpDispInfo->rcScreen.left; 00670 SYSMET(YVIRTUALSCREEN) = gpDispInfo->rcScreen.top; 00671 SYSMET(CXVIRTUALSCREEN) = gpDispInfo->rcScreen.right - gpDispInfo->rcScreen.left; 00672 SYSMET(CYVIRTUALSCREEN) = gpDispInfo->rcScreen.bottom - gpDispInfo->rcScreen.top; 00673 SYSMET(CXMAXTRACK) = SYSMET(CXVIRTUALSCREEN) + (2 * (SYSMET(CXSIZEFRAME) + SYSMET(CXEDGE))); 00674 SYSMET(CYMAXTRACK) = SYSMET(CYVIRTUALSCREEN) + (2 * (SYSMET(CYSIZEFRAME) + SYSMET(CYEDGE))); 00675 SYSMET(CMONITORS) = gpDispInfo->cMonitors; 00676 00677 /* 00678 * Bug 281219: flush out the mouse move points if a mode change occured 00679 */ 00680 RtlZeroMemory(gaptMouse, MAX_MOUSEPOINTS * sizeof(MOUSEMOVEPOINT)); 00681 00682 SetDesktopMetrics(); 00683 00684 gpDispInfo->dmLogPixels = (WORD)GreGetDeviceCaps(gpDispInfo->hdcScreen, LOGPIXELSY); 00685 00686 UserAssert(gpDispInfo->dmLogPixels != 0); 00687 00688 /* 00689 * Get per-monitor or sum of monitor information, including: 00690 * The desktop region. 00691 * The region of each monitor. 00692 * Min bit counts - Not for NT SP2. 00693 * Same color format - Not for NT SP2. 00694 */ 00695 00696 SetOrCreateRectRgnIndirectPublic(&gpDispInfo->hrgnScreen, PZERO(RECT)); 00697 00698 if (gpDispInfo->hrgnScreen) { 00699 00700 for (pMonitor = gpDispInfo->pMonitorFirst; 00701 pMonitor; 00702 pMonitor = pMonitor->pMonitorNext) { 00703 00704 /* 00705 * We want to set up hrgnMonitor for all monitors, visible or not 00706 */ 00707 if (SetOrCreateRectRgnIndirectPublic(&pMonitor->hrgnMonitor, 00708 &pMonitor->rcMonitor)) { 00709 00710 /* 00711 * But we want only visible monitors to contribute to hrgnScreen 00712 */ 00713 if (pMonitor->dwMONFlags & MONF_VISIBLE) { 00714 iRgn = UnionRgn(gpDispInfo->hrgnScreen, 00715 gpDispInfo->hrgnScreen, 00716 pMonitor->hrgnMonitor); 00717 } 00718 00719 } 00720 } 00721 00722 gpDispInfo->fDesktopIsRect = (iRgn == SIMPLEREGION); 00723 } 00724 00725 00726 /* 00727 * Reset the window region of desktop windows. 00728 */ 00729 hrgn = (gpDispInfo->fDesktopIsRect) ? NULL : gpDispInfo->hrgnScreen; 00730 for (pwinsta = grpWinStaList; pwinsta; pwinsta = pwinsta->rpwinstaNext) { 00731 for (pdesk = pwinsta->rpdeskList; pdesk; pdesk = pdesk->rpdeskNext) { 00732 if (pdesk->pDispInfo == gpDispInfo) { 00733 pdesk->pDeskInfo->spwnd->hrgnClip = hrgn; 00734 } 00735 } 00736 } 00737 00738 /* 00739 * Updated information stored in gpsi. 00740 */ 00741 gpsi->Planes = (BYTE)GreGetDeviceCaps(gpDispInfo->hdcScreen, PLANES); 00742 gpsi->BitsPixel = (BYTE)GreGetDeviceCaps(gpDispInfo->hdcScreen, BITSPIXEL); 00743 gpsi->BitCount = gpsi->Planes * gpsi->BitsPixel; 00744 gpDispInfo->BitCountMax = gpsi->BitCount; 00745 SET_OR_CLEAR_PUSIF(PUSIF_PALETTEDISPLAY, fPaletteDisplay); 00746 gpsi->dmLogPixels = gpDispInfo->dmLogPixels; 00747 gpsi->rcScreen = gpDispInfo->rcScreen; 00748 gpsi->cxSysFontChar = GetCharDimensions(HDCBITS(), &tm, &gpsi->cySysFontChar); 00749 gpsi->tmSysFont = tm; 00750 00751 EnforceColorDependentSettings(); 00752 00753 #if DBG 00754 VerifyVisibleMonitorCount(); 00755 #endif 00756 00757 return TRUE; 00758 } 00759 00760 00761 /**************************************************************************\ 00762 * InitUserScreen 00763 * 00764 * Initializes user variables at startup. 00765 * 00766 * BUGBUG (adams): This function needs to handle failures. 00767 * BUGBUG (adams): Where do these variables get inited for 00768 * DISPLAYINFOs other than gpDispInfo? 00769 * 00770 * 12-Jan-1994 andreva Created 00771 * 23-Jan-1995 ChrisWil ChangeDisplaySettings work. 00772 \**************************************************************************/ 00773 00774 BOOL 00775 InitUserScreen() 00776 { 00777 int i; 00778 TL tlName; 00779 PUNICODE_STRING pProfileUserName = CreateProfileUserName(&tlName); 00780 BOOL fSuccess = TRUE; 00781 00782 TRACE_INIT(("UserInit: Initialize Screen\n")); 00783 00784 /* 00785 * Create screen and memory dcs. 00786 */ 00787 gpDispInfo->hdcScreen = GreCreateDisplayDC(gpDispInfo->hDev, DCTYPE_DIRECT, FALSE); 00788 00789 if (gpDispInfo->hdcScreen == NULL) { 00790 RIPMSG0(RIP_WARNING, "Fail to create gpDispInfo->hdcScreen"); 00791 fSuccess = FALSE; 00792 goto Exit; 00793 } 00794 00795 GreSelectFont(gpDispInfo->hdcScreen, GreGetStockObject(SYSTEM_FONT)); 00796 GreSetDCOwner(gpDispInfo->hdcScreen, OBJECT_OWNER_PUBLIC); 00797 00798 HDCBITS() = GreCreateCompatibleDC(gpDispInfo->hdcScreen); 00799 00800 if (HDCBITS() == NULL) { 00801 RIPMSG0(RIP_WARNING, "Fail to create HDCBITS()"); 00802 fSuccess = FALSE; 00803 goto Exit; 00804 } 00805 00806 GreSelectFont(HDCBITS(), GreGetStockObject(SYSTEM_FONT)); 00807 GreSetDCOwner(HDCBITS(), OBJECT_OWNER_PUBLIC); 00808 00809 ghdcMem = GreCreateCompatibleDC(gpDispInfo->hdcScreen); 00810 fSuccess &= !!ghdcMem; 00811 00812 ghdcMem2 = GreCreateCompatibleDC(gpDispInfo->hdcScreen); 00813 fSuccess &= !!ghdcMem2; 00814 00815 if (!fSuccess) { 00816 RIPMSG0(RIP_WARNING, "Fail to create ghdcMem or ghdcMem2"); 00817 goto Exit; 00818 } 00819 00820 GreSetDCOwner(ghdcMem, OBJECT_OWNER_PUBLIC); 00821 GreSetDCOwner(ghdcMem2, OBJECT_OWNER_PUBLIC); 00822 00823 if (CreateCachedMonitor() == NULL) { 00824 fSuccess = FALSE; 00825 goto Exit; 00826 } 00827 00828 if (!UpdateUserScreen()) { 00829 RIPMSG0(RIP_WARNING, "UpdateUserScreen failed"); 00830 fSuccess = FALSE; 00831 goto Exit; 00832 } 00833 00834 /* 00835 * Do some initialization so we create the system colors. 00836 */ 00837 00838 /* 00839 * Set the window sizing border width to something reasonable. 00840 */ 00841 gpsi->gclBorder = 1; 00842 00843 /* 00844 * Init InternalInvalidate globals 00845 */ 00846 ghrgnInv0 = CreateEmptyRgnPublic(); // For InternalInvalidate() 00847 fSuccess &= !!ghrgnInv0; 00848 00849 ghrgnInv1 = CreateEmptyRgnPublic(); // For InternalInvalidate() 00850 fSuccess &= !!ghrgnInv1; 00851 00852 ghrgnInv2 = CreateEmptyRgnPublic(); // For InternalInvalidate() 00853 fSuccess &= !!ghrgnInv2; 00854 00855 /* 00856 * Initialize SPB globals 00857 */ 00858 ghrgnSPB1 = CreateEmptyRgnPublic(); 00859 fSuccess &= !!ghrgnSPB1; 00860 00861 ghrgnSPB2 = CreateEmptyRgnPublic(); 00862 fSuccess &= !!ghrgnSPB2; 00863 00864 ghrgnSCR = CreateEmptyRgnPublic(); 00865 fSuccess &= !!ghrgnSCR; 00866 00867 /* 00868 * Initialize ScrollWindow/ScrollDC globals 00869 */ 00870 ghrgnSW = CreateEmptyRgnPublic(); 00871 fSuccess &= !!ghrgnSW; 00872 00873 ghrgnScrl1 = CreateEmptyRgnPublic(); 00874 fSuccess &= !!ghrgnScrl1; 00875 00876 ghrgnScrl2 = CreateEmptyRgnPublic(); 00877 fSuccess &= !!ghrgnScrl2; 00878 00879 ghrgnScrlVis = CreateEmptyRgnPublic(); 00880 fSuccess &= !!ghrgnScrlVis; 00881 00882 ghrgnScrlSrc = CreateEmptyRgnPublic(); 00883 fSuccess &= !!ghrgnScrlSrc; 00884 00885 ghrgnScrlDst = CreateEmptyRgnPublic(); 00886 fSuccess &= !!ghrgnScrlDst; 00887 00888 ghrgnScrlValid = CreateEmptyRgnPublic(); 00889 fSuccess &= !!ghrgnScrlValid; 00890 00891 /* 00892 * Initialize SetWindowPos() 00893 */ 00894 ghrgnInvalidSum = CreateEmptyRgnPublic(); 00895 fSuccess &= !!ghrgnInvalidSum; 00896 00897 ghrgnVisNew = CreateEmptyRgnPublic(); 00898 fSuccess &= !!ghrgnVisNew; 00899 00900 ghrgnSWP1 = CreateEmptyRgnPublic(); 00901 fSuccess &= !!ghrgnSWP1; 00902 00903 ghrgnValid = CreateEmptyRgnPublic(); 00904 fSuccess &= !!ghrgnValid; 00905 00906 ghrgnValidSum = CreateEmptyRgnPublic(); 00907 fSuccess &= !!ghrgnValidSum; 00908 00909 ghrgnInvalid = CreateEmptyRgnPublic(); 00910 fSuccess &= !!ghrgnInvalid; 00911 00912 /* 00913 * Initialize DC cache 00914 */ 00915 ghrgnGDC = CreateEmptyRgnPublic(); 00916 fSuccess &= !!ghrgnGDC; 00917 00918 for (i = 0; i < DCE_SIZE_CACHEINIT; i++) { 00919 fSuccess &= !!CreateCacheDC(NULL, DCX_INVALID | DCX_CACHE, NULL); 00920 } 00921 00922 if (!fSuccess) { 00923 RIPMSG0(RIP_WARNING, "CreateCacheDC failed"); 00924 goto Exit; 00925 } 00926 00927 /* 00928 * Let engine know that the display must be secure. 00929 */ 00930 00931 GreMarkDCUnreadable(gpDispInfo->hdcScreen); 00932 00933 /* 00934 * LATER mikeke - if ghfontsys is changed anywhere but here 00935 * we need to fix SetNCFont() 00936 */ 00937 ghFontSys = (HFONT)GreGetStockObject(SYSTEM_FONT); 00938 00939 #if DBG 00940 SYSMET(DEBUG) = TRUE; 00941 #else 00942 SYSMET(DEBUG) = FALSE; 00943 #endif 00944 00945 SYSMET(CLEANBOOT) = **((PULONG *)&InitSafeBootMode); 00946 00947 SYSMET(SLOWMACHINE) = 0; 00948 00949 /* 00950 * Initialize system colors from registry. 00951 */ 00952 xxxODI_ColorInit(pProfileUserName); 00953 00954 /* 00955 * Paint the screen background. 00956 */ 00957 FillRect(gpDispInfo->hdcScreen, &gpDispInfo->rcScreen, SYSHBR(DESKTOP)); 00958 00959 UserAssert(fSuccess); 00960 00961 Exit: 00962 FreeProfileUserName(pProfileUserName, &tlName); 00963 00964 return fSuccess; 00965 } 00966 00967 00968 /***************************************************************************\ 00969 * xxxResetSharedDesktops 00970 * 00971 * Resets the attributes for other desktops which share the DISPINFO that 00972 * was just changed. We need to resize all visrgns of the other desktops 00973 * so that clipping is allright. 00974 * 00975 * NOTE: For now, we have to change all the desktop even though we keep 00976 * track of the devmode on a per desktop basis, because we can switch 00977 * back to a desktop that has a different resolution and paint it before 00978 * we can change the resolution again. 00979 * There is also an issue with CDS_FULLSCREEN where we currently loose track 00980 * of whether or not the desktop settings need to be reset or not. [andreva] 00981 * 00982 * 19-Feb-1996 ChrisWil Created. 00983 \***************************************************************************/ 00984 00985 VOID ResetSharedDesktops( 00986 PDISPLAYINFO pDIChanged, 00987 PDESKTOP pdeskChanged) 00988 { 00989 PWINDOWSTATION pwinsta = _GetProcessWindowStation(NULL); 00990 PDESKTOP pdesk; 00991 HRGN hrgn; 00992 POINT pt; 00993 PRECT prc; 00994 UserAssert(IsWinEventNotifyDeferredOK()); 00995 00996 /* 00997 * If this is CSRSS doing the dynamic resolution change then use 00998 * WinSta0 since the process windowstation is NULL for CSRSS. 00999 */ 01000 if (gbRemoteSession && pwinsta == NULL && PsGetCurrentProcess() == gpepCSRSS) { 01001 pwinsta = grpWinStaList; 01002 } 01003 01004 if (pwinsta == NULL) { 01005 01006 if (PtiCurrent()->TIF_flags & (TIF_CSRSSTHREAD|TIF_SYSTEMTHREAD)) 01007 { 01008 pwinsta = grpdeskRitInput->rpwinstaParent; 01009 } 01010 else 01011 { 01012 TRACE_SWITCH(("ResetSharedDesktops - NULL window station !\n")); 01013 return; 01014 } 01015 } 01016 01017 for (pdesk = pwinsta->rpdeskList; pdesk; pdesk = pdesk->rpdeskNext) { 01018 01019 /* 01020 * Make sure this is a shared DISPINFO. 01021 */ 01022 if (pdesk->pDispInfo == pDIChanged) { 01023 01024 #if 0 01025 /* 01026 * This is the preferable method to set the desktop-window. 01027 * However, this causes synchronization problems where we 01028 * leave the critical-section allowing other apps to call 01029 * ChangeDisplaySettings() and thus mucking up the works. 01030 * 01031 * By calculating the vis-rgn ourselves, we can assure that 01032 * the clipping is current for the desktop even when we leave 01033 * the section. 01034 */ 01035 { 01036 TL tlpwnd; 01037 01038 ThreadLockAlways(pdesk->pDeskInfo->spwnd, &tlpwnd); 01039 xxxSetWindowPos(pdesk->pDeskInfo->spwnd, 01040 PWND_TOP, 01041 pDIChanged->rcScreen.left, 01042 pDIChanged->rcScreen.top, 01043 pDIChanged->rcScreen.right - pDIChanged->rcScreen.left, 01044 pDIChanged->rcScreen.bottom - pDIChanged->rcScreen.top, 01045 SWP_NOZORDER | SWP_NOACTIVATE); 01046 ThreadUnlock(&tlpwnd); 01047 } 01048 #else 01049 CopyRect(&pdesk->pDeskInfo->spwnd->rcWindow, &pDIChanged->rcScreen); 01050 CopyRect(&pdesk->pDeskInfo->spwnd->rcClient, &pDIChanged->rcScreen); 01051 #endif 01052 } 01053 } 01054 01055 /* 01056 * Recalc the desktop visrgn. Since the hdcScreen is shared amoungts 01057 * all the 01058 */ 01059 hrgn = CreateEmptyRgn(); 01060 CalcVisRgn(&hrgn, 01061 pdeskChanged->pDeskInfo->spwnd, 01062 pdeskChanged->pDeskInfo->spwnd, 01063 DCX_WINDOW); 01064 01065 GreSelectVisRgn(pDIChanged->hdcScreen, hrgn, SVR_DELETEOLD); 01066 01067 /* 01068 * Invalidate all DCE's visrgns. 01069 */ 01070 zzzInvalidateDCCache(pdeskChanged->pDeskInfo->spwnd, 0); 01071 01072 /* 01073 * Position mouse so that it is within the new visrgn, once we 01074 * recalc it. 01075 */ 01076 if (grpdeskRitInput->pDispInfo == pDIChanged) { 01077 prc = &pDIChanged->pMonitorPrimary->rcMonitor; 01078 pt.x = (prc->right - prc->left) / 2; 01079 pt.y = (prc->bottom - prc->top) / 2; 01080 01081 /* 01082 * Remember new mouse pos. Makes sure we don't wake the screensaver. 01083 */ 01084 gptSSCursor = pt; 01085 zzzInternalSetCursorPos(pt.x, pt.y); 01086 } 01087 } 01088 01089 /***************************************************************************\ 01090 * DestroyMonitorDCs 01091 * 01092 * 03/03/1998 vadimg created 01093 \***************************************************************************/ 01094 01095 void DestroyMonitorDCs(void) 01096 { 01097 PDCE pdce; 01098 PDCE *ppdce; 01099 01100 /* 01101 * Scan the DC cache to find any monitor DC's that need to be destroyed. 01102 */ 01103 for (ppdce = &gpDispInfo->pdceFirst; *ppdce != NULL; ) { 01104 01105 pdce = *ppdce; 01106 01107 if (pdce->pMonitor != NULL) { 01108 DestroyCacheDC(ppdce, pdce->hdc); 01109 } 01110 01111 /* 01112 * Step to the next DC. If the DC was deleted, there 01113 * is no need to calculate address of the next entry. 01114 */ 01115 if (pdce == *ppdce) 01116 ppdce = &pdce->pdceNext; 01117 } 01118 } 01119 01120 /***************************************************************************\ 01121 * ResetSystemColors 01122 * 01123 * Reset all system colors to make sure magic colors are reset and 01124 * solid system colors are indeed solid after a mode change. 01125 \***************************************************************************/ 01126 01127 VOID ResetSystemColors(VOID) 01128 { 01129 INT i; 01130 INT colorIndex[COLOR_MAX]; 01131 COLORREF colorValue[COLOR_MAX]; 01132 01133 for (i = 0; i < COLOR_MAX; i++) { 01134 colorIndex[i] = i; 01135 colorValue[i] = gpsi->argbSystem[i]; 01136 } 01137 01138 BEGINATOMICCHECK(); 01139 xxxSetSysColors(NULL, i, colorIndex, colorValue, SSCF_FORCESOLIDCOLOR | 01140 SSCF_SETMAGICCOLORS); 01141 ENDATOMICCHECK(); 01142 } 01143 01144 /***************************************************************************\ 01145 * xxxResetDisplayDevice 01146 * 01147 * Resets the user-globals with the new hdev settings. 01148 * 01149 * 19-Feb-1996 ChrisWil Created. 01150 \***************************************************************************/ 01151 01152 VOID xxxResetDisplayDevice( 01153 PDESKTOP pdesk, 01154 PDISPLAYINFO pDI, 01155 DWORD CDS_Flags) 01156 { 01157 WORD wOldBpp; 01158 PMONITORRECTS pmr = NULL; 01159 TL tlPool; 01160 PTHREADINFO ptiCurrent = PtiCurrent(); 01161 01162 /* 01163 * BUGBUG: Correctly update work area for each monitor. 01164 */ 01165 wOldBpp = gpsi->BitCount; 01166 01167 if (!(CDS_Flags & CDS_FULLSCREEN)) { 01168 01169 pmr = SnapshotMonitorRects(); 01170 01171 if (pmr) { 01172 ThreadLockPool(ptiCurrent, pmr, &tlPool); 01173 } 01174 } 01175 01176 /* 01177 * Cleanup any monitor specific DCs we gave out. 01178 */ 01179 DestroyMonitorDCs(); 01180 01181 UpdateUserScreen(); 01182 ResetSharedDesktops(pDI, pdesk); 01183 01184 ResetSystemColors(); 01185 01186 if (ghbmCaption) { 01187 GreDeleteObject(ghbmCaption); 01188 ghbmCaption = CreateCaptionStrip(); 01189 } 01190 01191 zzzClipCursor(&pDI->rcScreen); 01192 01193 /* 01194 * Adjust window positions to fit new resolutions and 01195 * positions of monitors. 01196 */ 01197 if (pmr) { 01198 xxxDesktopRecalc(pmr); 01199 ThreadUnlockAndFreePool(PtiCurrent(), &tlPool); 01200 } 01201 01202 /* 01203 * Change the wallpaper metrics. 01204 * Don't reload the wallpaper when in cleanup since that may 01205 * go to the client for and we can't do that. 01206 */ 01207 if (!(ptiCurrent->TIF_flags & TIF_INCLEANUP) && ghbmWallpaper) { 01208 TL tlName; 01209 PUNICODE_STRING pProfileUserName = CreateProfileUserName(&tlName); 01210 xxxSetDeskWallpaper(pProfileUserName, SETWALLPAPER_METRICS); 01211 FreeProfileUserName(pProfileUserName, &tlName); 01212 } 01213 01214 /* 01215 * Recreate cached bitmaps. 01216 */ 01217 CreateBitmapStrip(); 01218 01219 /* 01220 * Broadcast that the display has changed resolution. 01221 * Also broadcast a color-change if we were not in fullscreen, and a 01222 * color-change took effect. 01223 */ 01224 if (!(CDS_Flags & CDS_FULLSCREEN) && (gpsi->BitCount != wOldBpp)) { 01225 xxxBroadcastDisplaySettingsChange(pdesk, TRUE); 01226 01227 } else { 01228 xxxBroadcastDisplaySettingsChange(pdesk, FALSE); 01229 } 01230 01231 /* 01232 * If the user performed a CTL-ESC, it is possible that the 01233 * tray-window is then in the menu-loop. We want to clear this 01234 * out so that we don't leave improper menu positioning. 01235 */ 01236 if (gpqForeground && gpqForeground->spwndCapture) 01237 QueueNotifyMessage(gpqForeground->spwndCapture, WM_CANCELMODE, 0, 0l); 01238 } 01239 01240 /***************************************************************************\ 01241 * TrackFullscreenMode 01242 * 01243 * Remember the process going into the fullscreen mode, so that 01244 * the mode can be restored if the process doesn't clean up upon 01245 * exit. If some other mode change, clear the global since that 01246 * means we're definitely out of the fullscreen mode. 01247 * 01248 * 1/12/1999 vadimg created 01249 \***************************************************************************/ 01250 01251 VOID TrackFullscreenMode(DWORD dwFlags) 01252 { 01253 if (dwFlags & CDS_FULLSCREEN) { 01254 gppiFullscreen = PtiCurrent()->ppi; 01255 } else { 01256 gppiFullscreen = NULL; 01257 } 01258 } 01259 01260 /***************************************************************************\ 01261 * NtUserChangeDisplaySettings 01262 * 01263 * ChangeDisplaySettings API 01264 * 01265 * 01-Sep-1995 andreva Created 01266 * 19-Feb-1996 ChrisWil Implemented Dynamic-Resolution changes. 01267 \***************************************************************************/ 01268 01269 01270 01271 01272 LONG 01273 xxxUserChangeDisplaySettings( 01274 IN PUNICODE_STRING pstrDeviceName, 01275 IN LPDEVMODEW pDevMode, 01276 IN HWND hwnd, 01277 IN PDESKTOP pdesk, 01278 IN DWORD dwFlags, 01279 IN PVOID lParam, 01280 IN MODE PreviousMode) 01281 { 01282 BOOL bSwitchMode; 01283 PDESKTOP pdesktop; 01284 LONG status; 01285 PMDEV pmdev; 01286 01287 /* 01288 * BUGBUG: Has lParam been properly captured? 01289 */ 01290 01291 lParam; 01292 01293 TRACE_INIT(("ChangeDisplaySettings - Entering\n")); 01294 TRACE_SWITCH(("ChangeDisplaySettings - Entering\n")); 01295 01296 TRACE_INIT((" Flags -")); 01297 01298 if (dwFlags & CDS_UPDATEREGISTRY) TRACE_INIT((" CDS_UPDATEREGISTRY - ")); 01299 if (dwFlags & CDS_TEST) TRACE_INIT((" CDS_TEST - ")); 01300 if (dwFlags & CDS_FULLSCREEN) TRACE_INIT((" CDS_FULLSCREEN - ")); 01301 if (dwFlags & CDS_GLOBAL) TRACE_INIT((" CDS_GLOBAL - ")); 01302 if (dwFlags & CDS_SET_PRIMARY) TRACE_INIT((" CDS_SET_PRIMARY - ")); 01303 if (dwFlags & CDS_RESET) TRACE_INIT((" CDS_RESET - ")); 01304 if (dwFlags & CDS_NORESET) TRACE_INIT((" CDS_NORESET - ")); 01305 if (dwFlags & CDS_VIDEOPARAMETERS) TRACE_INIT((" CDS_VIDEOPARAMETERS - ")); 01306 TRACE_INIT(("\n")); 01307 01308 #if ((DISP_CHANGE_SUCCESSFUL != GRE_DISP_CHANGE_SUCCESSFUL) || \ 01309 (DISP_CHANGE_RESTART != GRE_DISP_CHANGE_RESTART) || \ 01310 (DISP_CHANGE_FAILED != GRE_DISP_CHANGE_FAILED) || \ 01311 (DISP_CHANGE_BADMODE != GRE_DISP_CHANGE_BADMODE) || \ 01312 (DISP_CHANGE_NOTUPDATED != GRE_DISP_CHANGE_NOTUPDATED) || \ 01313 (DISP_CHANGE_BADFLAGS != GRE_DISP_CHANGE_BADFLAGS) || \ 01314 (DISP_CHANGE_BADPARAM != GRE_DISP_CHANGE_BADPARAM)) 01315 #error "inconsistent header files" 01316 #endif 01317 01318 /* 01319 * Perform Error Checking to verify flag combinations are valid. 01320 */ 01321 if (dwFlags & (~CDS_VALID)) { 01322 01323 //BUGBUG 01324 //RIPMSG0(RIP_ERROR, "ChangeDisplaySettings: invalid flags specified\n"); 01325 return DISP_CHANGE_BADFLAGS; 01326 } 01327 01328 /* 01329 * CDS_GLOBAL and CDS_NORESET can only be specified if UPDAREREGISTRY 01330 * is specified. 01331 */ 01332 01333 if ((dwFlags & (CDS_GLOBAL | CDS_NORESET)) && 01334 (!(dwFlags & CDS_UPDATEREGISTRY))) { 01335 01336 //BUGBUG 01337 //RIPMSG0(RIP_ERROR, "ChangeDisplaySettings: invalid registry flags specified\n"); 01338 return DISP_CHANGE_BADFLAGS; 01339 } 01340 01341 if ((dwFlags & CDS_NORESET) && 01342 (dwFlags & CDS_RESET)) { 01343 01344 //BUGBUG 01345 //RIPMSG0(RIP_ERROR, "ChangeDisplaySettings: RESET and NORESET can not be put together\n"); 01346 return DISP_CHANGE_BADFLAGS; 01347 } 01348 01349 if ((dwFlags & CDS_EXCLUSIVE) && (dwFlags & CDS_FULLSCREEN) && (dwFlags & CDS_RESET)) { 01350 01351 //BUGBUG 01352 //RIPMSG0(RIP_ERROR, "ChangeDisplaySettings: invalid flags specified\n"); 01353 return DISP_CHANGE_BADFLAGS; 01354 } 01355 01356 if (hwnd) { 01357 return DISP_CHANGE_BADPARAM; 01358 } 01359 01360 /* 01361 * For now, don't allow dynamic-resolution changes to occur 01362 * when GDI is in fullscreen. We should almost never hit this 01363 * condition, except for rare stress cases. 01364 */ 01365 01366 01367 /* 01368 * Allow mode change if this is a CSRSS of a remote 01369 * session. This means we are changing display settings when 01370 * reconnecting a session with a diferent resolution. 01371 */ 01372 if (TEST_PUDF(PUDF_LOCKFULLSCREEN)) { 01373 if (!(ISCSRSS() && gbRemoteSession)) { 01374 return DISP_CHANGE_FAILED; 01375 } 01376 } 01377 01378 01379 /* 01380 * If the modeset is being done on a non-active desktop, we don't want 01381 * it too happen. 01382 * 01383 * PtiCurrent()->rpdesk can be NULL !!! (in the case of thread shutdown). 01384 */ 01385 01386 if (pdesk) { 01387 pdesktop = pdesk; 01388 } else { 01389 pdesktop = PtiCurrent()->rpdesk; 01390 } 01391 01392 if (pdesktop != grpdeskRitInput) { 01393 RIPMSG0(RIP_WARNING, "ChangeDisplaySettings on wrong desktop pdesk\n"); 01394 return DISP_CHANGE_FAILED; 01395 } 01396 01397 bSwitchMode = !(dwFlags & (CDS_NORESET | CDS_TEST)); 01398 01399 /* 01400 * Turn off cursor and free the spb's prior to calling the mode-change. 01401 * This will make sure off-screen memory is cleaned up for gdi. 01402 * while mucking with the resolution changes. 01403 */ 01404 if (bSwitchMode) { 01405 01406 if (CreateCachedMonitor() == NULL) { 01407 return DISP_CHANGE_FAILED; 01408 } 01409 01410 SetPointer(FALSE); 01411 FreeAllSpbs(); 01412 } 01413 01414 /* 01415 * Before calling gdi to change the mode, we should kill the fade sprite. This is 01416 * so that we won't keep pointers to gdi sprites during the mode change because 01417 * the sprites could be reallocated. 01418 */ 01419 01420 if (gfade.hbm != NULL) { 01421 StopFade(); 01422 } 01423 01424 /* 01425 * Similarly, we should kill the sprites associated with the drag rect (if any 01426 * exist) before the mode change. 01427 */ 01428 01429 bSetDevDragRect(gpDispInfo->hDev, NULL, NULL); 01430 01431 /* 01432 * Lets capture our parameters. They are both required. 01433 * 01434 * If the input string is not NULL, then we are trying to affect another 01435 * Device. The device name is the same as for EnumDisplaySettings. 01436 */ 01437 01438 status = DrvChangeDisplaySettings(pstrDeviceName, 01439 gpDispInfo->pMonitorPrimary->hDev, 01440 pDevMode, 01441 LongToPtr( pdesktop->dwDesktopId ), 01442 PreviousMode, 01443 (dwFlags & CDS_UPDATEREGISTRY), 01444 bSwitchMode, 01445 gpDispInfo->pmdev, 01446 &pmdev, 01447 (dwFlags & CDS_RAWMODE) ? GRE_RAWMODE : GRE_DEFAULT, 01448 (dwFlags & CDS_TRYCLOSEST)); 01449 01450 01451 if (bSwitchMode) { 01452 01453 /* 01454 * If the caller wanted a reset, but the mode is identical, just 01455 * reset the current mode. 01456 */ 01457 01458 if (status == GRE_DISP_CHANGE_NO_CHANGE) { 01459 01460 TrackFullscreenMode(dwFlags); 01461 01462 if (pmdev != NULL) { 01463 GreFreePool(pmdev); 01464 } 01465 01466 if (dwFlags & CDS_RESET) { 01467 01468 if (DrvDisableMDEV(gpDispInfo->pmdev, TRUE)) { 01469 DrvEnableMDEV(gpDispInfo->pmdev, TRUE); 01470 } 01471 01472 xxxUserResetDisplayDevice(); 01473 } 01474 01475 status = DISP_CHANGE_SUCCESSFUL; 01476 01477 } else if (status == DISP_CHANGE_SUCCESSFUL) { 01478 01479 TrackFullscreenMode(dwFlags); 01480 01481 /* 01482 * ChangeDisplaySettings automatically destroys the old MDEV. 01483 * We only have to delete it here. 01484 */ 01485 GreFreePool(gpDispInfo->pmdev); 01486 gpDispInfo->pmdev = pmdev; 01487 xxxResetDisplayDevice(pdesktop, gpDispInfo, dwFlags); 01488 01489 /* 01490 * set delayed change indicator for 01491 * currently background desktops. 01492 */ 01493 UserSetDelayedChangeBroadcastForAllDesktops(pdesktop); 01494 01495 } else if (status < DISP_CHANGE_SUCCESSFUL) { 01496 UserAssert(pmdev == NULL); 01497 xxxUserResetDisplayDevice(); 01498 } 01499 01500 /* 01501 * Inline so we can specify which desktop this should happen on. 01502 * xxxRedrawScreen(); 01503 */ 01504 xxxInternalInvalidate(pdesktop->pDeskInfo->spwnd, 01505 HRGN_FULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN); 01506 01507 /* 01508 * Bring back the cursor-shape. 01509 */ 01510 SetPointer(TRUE); 01511 zzzUpdateCursorImage(); 01512 } 01513 01514 /* 01515 * TV-Out Support 01516 */ 01517 01518 if (NT_SUCCESS(status) && (dwFlags & CDS_VIDEOPARAMETERS)) 01519 { 01520 if (lParam == NULL) { 01521 status = DISP_CHANGE_BADPARAM; 01522 } else { 01523 status = DrvSetVideoParameters(pstrDeviceName, 01524 gpDispInfo->pMonitorPrimary->hDev, 01525 PreviousMode, 01526 lParam); 01527 } 01528 } 01529 01530 TRACE_INIT(("ChangeDisplaySettings - Leaving, Status = %d\n", status)); 01531 01532 return status; 01533 } 01534 01535 01536 /***************************************************************************\ 01537 * xxxbFullscreenSwitch 01538 * 01539 * Switch in and out of fullscreen console mode 01540 * 01541 * 15-Apr-1997 andreva Created 01542 \***************************************************************************/ 01543 01544 BOOL 01545 xxxbFullscreenSwitch( 01546 BOOL bFullscreenSwitch, 01547 HWND hwnd) 01548 { 01549 01550 PWND pwnd; 01551 TL tlpwnd; 01552 BOOL bStat = TRUE; 01553 01554 pwnd = ValidateHwnd(hwnd); 01555 01556 if (!pwnd) { 01557 return DISP_CHANGE_BADPARAM; 01558 } 01559 01560 /* 01561 * Lock the PWND, if it is provided 01562 */ 01563 01564 ThreadLock(pwnd, &tlpwnd); 01565 01566 /* 01567 * We don't want our mode switch to be posted on the looping thread. 01568 * So let's loop until the system has settled down and no mode switch 01569 * is currently occuring. 01570 */ 01571 01572 while (idSwitcher != NOSWITCHER) { 01573 /* 01574 * Make sure we aren't blocking anyone who's sending us a message. 01575 * They can have idSwitcher and never release it because they are 01576 * waiting on us to process the sent message. And we're waiting on 01577 * idSwitcher, hence a deadlock. 01578 */ 01579 xxxSleepThread(0, 1, FALSE); 01580 } 01581 01582 /* 01583 * If there is a window, we want to check the state of the window. 01584 * For most calls, we want to ensure we are in windowed mode. 01585 * However, for Console, we want to make sure we are in fullscreen mode. 01586 * So differentiate between the two. We will check if the TEXTMODE 01587 * flag is passed in the DEVMODE. 01588 */ 01589 01590 if (bFullscreenSwitch) { 01591 01592 if (GetFullScreen(pwnd) != FULLSCREEN) { 01593 01594 xxxShowWindow(pwnd, SW_SHOWMINIMIZED | TEST_PUDF(PUDF_ANIMATE)); 01595 01596 xxxUpdateWindow(pwnd); 01597 } 01598 01599 if (!xxxMakeWindowForegroundWithState(pwnd, FULLSCREEN)) { 01600 goto FullscreenSwitchFailed; 01601 } 01602 01603 if ((idSwitcher != NOSWITCHER) || 01604 (gbFullScreen != FULLSCREEN)) { 01605 goto FullscreenSwitchFailed; 01606 } 01607 01608 } else { 01609 01610 /* 01611 * For the console windows, we want to call with WINDOWED 01612 */ 01613 01614 if (!xxxMakeWindowForegroundWithState(pwnd, WINDOWED)) { 01615 goto FullscreenSwitchFailed; 01616 } 01617 01618 if ((idSwitcher != NOSWITCHER) || 01619 (gbFullScreen != GDIFULLSCREEN)) { 01620 01621 FullscreenSwitchFailed: 01622 TRACE_INIT(("ChangeDisplaySettings: Can not switch out of fullscreen\n")); 01623 bStat = FALSE; 01624 } 01625 } 01626 01627 ThreadUnlock(&tlpwnd); 01628 01629 return bStat; 01630 } 01631 01632 01633 NTSTATUS 01634 RemoteRedrawRectangle( 01635 WORD Left, 01636 WORD Top, 01637 WORD Right, 01638 WORD Bottom) 01639 { 01640 TL tlpwnd; 01641 RECT rcl; 01642 01643 CheckCritIn(); 01644 01645 TRACE_HYDAPI(("RemoteRedrawRectangle\n")); 01646 01647 UserAssert(ISCSRSS()); 01648 /* 01649 * If xxxRemoteStopScreenUpdates has not been called, 01650 * then just repaint the current foreground window. 01651 */ 01652 if (gspdeskShouldBeForeground == NULL) { 01653 if (gspwndFullScreen) { 01654 01655 ThreadLock(gspwndFullScreen, &tlpwnd); 01656 01657 rcl.left = Left; 01658 rcl.top = Top; 01659 rcl.right = Right; 01660 rcl.bottom = Bottom; 01661 01662 vDrvInvalidateRect(gpDispInfo->hDev, &rcl); 01663 01664 xxxRedrawWindow(gspwndFullScreen, &rcl, NULL, 01665 RDW_INVALIDATE | RDW_ALLCHILDREN | 01666 RDW_ERASE | RDW_ERASENOW); 01667 ThreadUnlock(&tlpwnd); 01668 } 01669 } 01670 01671 return STATUS_SUCCESS; 01672 } 01673 01674 NTSTATUS 01675 RemoteRedrawScreen( 01676 VOID) 01677 { 01678 TL tlpdesk; 01679 PWINDOWSTATION pwinsta; 01680 DWORD dwFlagsPrev; 01681 PTHREADINFO ptiCurrent; 01682 01683 TRACE_HYDAPI(("RemoteRedrawScreen\n")); 01684 01685 CheckCritIn(); 01686 01687 if (!gbFreezeScreenUpdates) 01688 return STATUS_SUCCESS; 01689 01690 ptiCurrent = PtiCurrentShared(); 01691 01692 gbFreezeScreenUpdates = FALSE; 01693 01694 /* 01695 * Switch back to the previous desktop 01696 */ 01697 if (gspdeskShouldBeForeground == NULL) { 01698 RIPMSG0(RIP_WARNING, "RemoteRedrawScreen called with no gspdeskShouldBeForeground"); 01699 return STATUS_SUCCESS; 01700 } 01701 01702 /* 01703 * Clear desktop switch lock 01704 * (WSF_SWITCHLOCK must be clear for xxxSwitchDesktop to succeed) 01705 */ 01706 gbDesktopLocked = FALSE; 01707 01708 pwinsta = gspdeskShouldBeForeground->rpwinstaParent; 01709 01710 dwFlagsPrev = pwinsta->dwWSF_Flags; 01711 pwinsta->dwWSF_Flags &= ~WSF_SWITCHLOCK; 01712 01713 /* 01714 * Switch back to previous desktop 01715 */ 01716 if (!(gspdeskShouldBeForeground->dwDTFlags & DF_DESTROYED)) { 01717 ThreadLockDesktop(ptiCurrent, gspdeskShouldBeForeground, &tlpdesk, LDLT_FN_CTXREDRAWSCREEN); 01718 xxxSwitchDesktop(pwinsta, gspdeskShouldBeForeground, FALSE); 01719 ThreadUnlockDesktop(ptiCurrent, &tlpdesk, LDUT_FN_CTXREDRAWSCREEN); 01720 01721 /* 01722 * Enable screen updates 01723 */ 01724 DrvEnableMDEV(gpDispInfo->pmdev, TRUE); 01725 } 01726 pwinsta->dwWSF_Flags = dwFlagsPrev; 01727 LockDesktop(&gspdeskShouldBeForeground, NULL, LDL_DESKSHOULDBEFOREGROUND2, 0 ); 01728 01729 return STATUS_SUCCESS; 01730 } 01731 01732 NTSTATUS 01733 RemoteDisableScreen( 01734 VOID) 01735 { 01736 TL tlpdesk; 01737 DWORD dwFlagsPrev; 01738 PTHREADINFO ptiCurrent; 01739 PWINDOWSTATION pwinsta; 01740 NTSTATUS Status = STATUS_SUCCESS; 01741 01742 CheckCritIn(); 01743 01744 TRACE_HYDAPI(("RemoteDisableScreen\n")); 01745 01746 01747 ptiCurrent = PtiCurrentShared(); 01748 01749 if (grpdeskRitInput != gspdeskDisconnect && 01750 gspdeskDisconnect != NULL) { 01751 01752 pwinsta = gspdeskDisconnect->rpwinstaParent; 01753 01754 /* 01755 * Save current desktop 01756 */ 01757 UserAssert(grpdeskRitInput == pwinsta->pdeskCurrent); 01758 01759 LockDesktop(&gspdeskShouldBeForeground, 01760 grpdeskRitInput, 01761 LDL_DESKSHOULDBEFOREGROUND3, 0); 01762 01763 /* 01764 * Set desktop switch lock 01765 * (WSF_SWITCHLOCK must be clear for xxxSwitchDesktop to succeed) 01766 */ 01767 dwFlagsPrev = pwinsta->dwWSF_Flags; 01768 pwinsta->dwWSF_Flags &= ~WSF_SWITCHLOCK; 01769 gbDesktopLocked = TRUE; 01770 01771 /* 01772 * Switch to Disconnected desktop 01773 */ 01774 ThreadLockDesktop(ptiCurrent, gspdeskDisconnect, &tlpdesk, LDLT_FN_CTXDISABLESCREEN); 01775 xxxSwitchDesktop(pwinsta, gspdeskDisconnect, FALSE); 01776 ThreadUnlockDesktop(ptiCurrent, &tlpdesk, LDUT_FN_CTXDISABLESCREEN); 01777 01778 pwinsta->dwWSF_Flags = dwFlagsPrev; 01779 01780 /* 01781 * Disable screen updates 01782 */ 01783 DrvDisableMDEV(gpDispInfo->pmdev, TRUE); 01784 01785 } else if (gspdeskDisconnect != NULL) { 01786 /* 01787 * For some reason the disconnected desktop was the current desktop. 01788 * Now prevent switching from it. 01789 */ 01790 gbDesktopLocked = TRUE; 01791 } 01792 01793 return Status; 01794 } 01795 01796 VOID 01797 xxxBroadcastDisplaySettingsChange( 01798 PDESKTOP pdesk, 01799 BOOL bBroadcastColorChange) 01800 { 01801 01802 /* 01803 * Broadcast that the display has changed resolution. We are going 01804 * to specify the desktop for the changing-desktop. That way we 01805 * don't get confused as to what desktop to broadcast to. 01806 */ 01807 xxxBroadcastMessage(pdesk->pDeskInfo->spwnd, 01808 WM_DISPLAYCHANGE, 01809 gpsi->BitCount, 01810 MAKELONG(SYSMET(CXSCREEN), SYSMET(CYSCREEN)), 01811 BMSG_SENDNOTIFYMSG, 01812 NULL); 01813 01814 /* 01815 * Broadcast a color-change if requested to do so. 01816 */ 01817 01818 if (bBroadcastColorChange){ 01819 #if 1 // We might want to remove this call, since color-change seems 01820 // to provide apps the notification. Need to review 01821 // chriswil - 06/11/96 01822 01823 xxxBroadcastMessage(pdesk->pDeskInfo->spwnd, 01824 WM_SETTINGCHANGE, 01825 0, 01826 0, 01827 BMSG_SENDNOTIFYMSG, 01828 NULL); 01829 #endif 01830 01831 xxxBroadcastMessage(pdesk->pDeskInfo->spwnd, 01832 WM_SYSCOLORCHANGE, 01833 0, 01834 0, 01835 BMSG_SENDNOTIFYMSG, 01836 NULL); 01837 } 01838 01839 }

Generated on Sat May 15 19:40:05 2004 for test by doxygen 1.3.7