|
|
/**************************** Module Header ********************************\
* Module Name: syscmd.c * * Copyright (c) 1985 - 1999, Microsoft Corporation * * System Command Routines * * History: * 01-25-91 IanJa Added handle revalidation \***************************************************************************/
#include "precomp.h"
#pragma hdrstop
/***************************************************************************\
* xxxHandleNCMouseGuys * * History: * 11-09-90 DavidPe Ported. \***************************************************************************/
void xxxHandleNCMouseGuys( PWND pwnd, UINT message, int htArea, LPARAM lParam) { UINT syscmd; PWND pwndT; TL tlpwndT;
CheckLock(pwnd);
syscmd = 0xFFFF;
switch (htArea) {
case HTCAPTION: switch (message) {
case WM_NCLBUTTONDBLCLK: if (TestWF(pwnd, WFMINIMIZED) || TestWF(pwnd, WFMAXIMIZED)) { syscmd = SC_RESTORE; } else if (TestWF(pwnd, WFMAXBOX)) { syscmd = SC_MAXIMIZE; } break;
case WM_NCLBUTTONDOWN: pwndT = GetTopLevelWindow(pwnd); ThreadLock(pwndT, &tlpwndT); xxxActivateWindow(pwndT, AW_USE2); ThreadUnlock(&tlpwndT); syscmd = SC_MOVE; break; } break;
case HTSYSMENU: case HTMENU: case HTHSCROLL: case HTVSCROLL: if (message == WM_NCLBUTTONDOWN || message == WM_NCLBUTTONDBLCLK) { switch (htArea) { case HTSYSMENU: if (message == WM_NCLBUTTONDBLCLK) { syscmd = SC_CLOSE; break; }
/*
*** FALL THRU ** */
case HTMENU: syscmd = SC_MOUSEMENU; break;
case HTHSCROLL: syscmd = SC_HSCROLL; break;
case HTVSCROLL: syscmd = SC_VSCROLL; break; } } break; }
switch (syscmd) {
case SC_MINIMIZE: case SC_MAXIMIZE: case SC_CLOSE:
/*
* Only do double click commands on an upclick. * This code is very sensitive to changes from this state. * Eat any mouse messages. */
/*
* Bug #152: WM_NCLBUTTONUP message missing from double click. * This code was broken in Windows 3.x and the test for whether * the mouse button was down always failed, so no mouse messages * were ever eaten. We'll emulate this by not even doing the test. * * * { * PQ pqCurrent; * MSG msg; * * pqCurrent = PtiCurrent()->pq; * if (TestKeyStateDown(pqCurrent, VK_LBUTTON)) { * xxxCapture(PtiCurrent(), pwnd, WINDOW_CAPTURE); * * while (TestKeyStateDown(pqCurrent, VK_LBUTTON)) { * if (!xxxPeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, * PM_REMOVE)) { * if (!xxxSleepThread(QS_MOUSE, 0, TRUE)) * break; * } * } * * xxxReleaseCapture(); * * } * } * */
/*
** FALL THRU ** */ case SC_SIZE: case SC_MOVE: /*
* For SysCommands on system menu, don't do if menu item is * disabled. */ if (TestWF(pwnd, WFSYSMENU)) { xxxSetSysMenu(pwnd); if (_GetMenuState(xxxGetSysMenuHandle(pwnd), (syscmd & 0xFFF0), MF_BYCOMMAND) & MFS_GRAYED) { return; } } break; }
if (syscmd != 0xFFFF) { xxxSendMessage(pwnd, WM_SYSCOMMAND, syscmd | htArea, lParam); } }
/***************************************************************************\
* StartScreenSaver * * History: * 11-12-90 MikeHar ported. \***************************************************************************/
void StartScreenSaver( BOOL bOnlyIfSecure) { /*
* If a screen saver is already running or we're in the midst of powering * down the machine, ignore this request. */ if (gppiScreenSaver != NULL || gPowerState.fInProgress) return;
if (gspwndLogonNotify != NULL) {
if( glinp.dwFlags & LINP_POWEROFF ) {
/*
* If the monitor is turned off. Tell winlogon to handle the * screen saver in a special manner. */ _PostMessage(gspwndLogonNotify, WM_LOGONNOTIFY, LOGON_INPUT_TIMEOUT, 2); } else {
/*
* Let the logon process take care of the screen saver */ _PostMessage(gspwndLogonNotify, WM_LOGONNOTIFY, LOGON_INPUT_TIMEOUT, bOnlyIfSecure); } } }
/***************************************************************************\
* xxxSysCommand * * History: * 11-12-90 MikeHar ported. * 02-07-91 DavidPe Added Win 3.1 WH_CBT support. \***************************************************************************/
void xxxSysCommand( PWND pwnd, DWORD cmd, LPARAM lParam) { UINT htArea; PWND pwndSwitch; PMENUSTATE pMenuState; TL tlpwnd; POINT pt; DWORD dw; PWND pwndCapture; PTHREADINFO pti;
CheckLock(pwnd);
htArea = (UINT)(cmd & 0x0F); cmd -= htArea;
/*
* Intense hack o' death. */ if (lParam == 0x00010000L) lParam = 0L;
/*
* If the system doesn't have capture (ie CLENT_CAPTURE_INTERNAL) * do the sys command. Also, do the sys command for the special case * where the window receiving the sys command is a console window that * is in full screen mode. In this case we let the sys command through. * * Also if this a SC_SCREENSAVE then we handle it anyway and * switching desktops will do the cancel. SC_SCREENSAVER * is special so we can start the screen saver even if we are in * menu mode for security so NT bug 10975 Banker's Trust */ pti = GETPTI(pwnd);
/*
* For 32bit apps (and apps on seperate queues), we need to check * the capture in the queue. Otherwise, on MDI child-destruction * we would get the restore when they shouldn't. This broke MSGOLF * who during the restore, AV'd because they assumed this wouldn't * happen. On 16bit shared apps, we want to check the internal * capture. Otherwise, when doing 16bit drag-and-drop, we would * not restore the minimized window if we had a queue-capture-window. */
/*
* But... it is too broad a change to just check internal capture for all WoW apps. Some * apps depend on bailing out when they have capture set. (Adobe Persuasion, NT bug 68794, * for SC_MOVE). So, let's restrict the hack to SC_RESTORE to keep Ole drag-and-drop working. * See NT bug 6109. FritzS */
pwndCapture = ((pti->TIF_flags & TIF_16BIT) && (cmd == SC_RESTORE)) ? gspwndInternalCapture : pti->pq->spwndCapture;
if ((!pwndCapture && !TestWF(pwnd, WFDISABLED)) || (pwnd == gspwndFullScreen) || (cmd == SC_SCREENSAVE) || (cmd == SC_MONITORPOWER) || (cmd == SC_TASKLIST)) {
/*
* Perform the sys command */
#ifdef SYSMODALWINDOWS
if (gspwndSysModal != NULL) { switch (cmd) { case SC_SIZE: case SC_MOVE: case SC_MINIMIZE: case SC_MAXIMIZE: case SC_NEXTWINDOW: case SC_PREVWINDOW: case SC_SCREENSAVE: return; } } #endif
/*
* Call the CBT hook asking if it's okay to do this command. * If not, return from here. */ if (IsHooked(PtiCurrent(), WHF_CBT) && xxxCallHook(HCBT_SYSCOMMAND, (DWORD)cmd, (DWORD)lParam, WH_CBT)) { return; }
switch (cmd) { case SC_RESTORE: cmd = SW_RESTORE; if (TestWF(pwnd, WFMINIMIZED) || !TestWF(pwnd, WFMAXIMIZED)) PlayEventSound(USER_SOUND_RESTOREUP); else PlayEventSound(USER_SOUND_RESTOREDOWN); goto MinMax;
case SC_MINIMIZE: cmd = SW_MINIMIZE;
/*
* Are we already minimized? */ if (TestWF(pwnd, WFMINIMIZED)) break;
PlayEventSound(USER_SOUND_MINIMIZE);
goto MinMax; case SC_MAXIMIZE: cmd = SW_SHOWMAXIMIZED;
/*
* Are we already maximized? */ if (TestWF(pwnd, WFMAXIMIZED)) break;
PlayEventSound(USER_SOUND_MAXIMIZE); MinMax: xxxShowWindow(pwnd, cmd | TEST_PUDF(PUDF_ANIMATE)); return;
case SC_SIZE: { xxxMoveSize(pwnd, htArea, _GetMessagePos()); } return;
case SC_MOVE: //
// Don't enter movesize loop unless the user is actually
// dragging from the caption. Otherwise, put up the system
// menu on a minimized window.
//
//
// Are we dragging with the left mouse button?
//
dw = _GetMessagePos(); POINTSTOPOINT( pt, MAKEPOINTS(dw)); if ( !htArea || xxxIsDragging(pwnd, pt, WM_LBUTTONUP)) {
/*
* We are moving. Enter move/size loop. */ { xxxMoveSize(pwnd, (htArea == 0) ? WMSZ_KEYMOVE : WMSZ_MOVE, dw); } } else {
/*
* Activate our window, just like we would have in * MoveSize(). */ xxxSetWindowPos(pwnd, PWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); if (TestWF(pwnd, WFMINIMIZED)) {
/*
* Try to popup the system menu */ xxxSendMessage(pwnd, WM_SYSCOMMAND, SC_KEYMENU, (DWORD) (TestWF(pwnd, WFCHILD) ? '-' : MENUSYSMENU)); } } return;
case SC_CLOSE: xxxSendMessage(pwnd, WM_CLOSE, 0L, 0L); return;
case SC_NEXTWINDOW: case SC_PREVWINDOW: xxxOldNextWindow((UINT)lParam); break;
case SC_CONTEXTHELP: xxxHelpLoop(pwnd); break;
case SC_KEYMENU:
/*
* A menu was selected via keyboard */ pMenuState = xxxMNStartMenuState(pwnd, cmd, lParam); if (pMenuState != NULL) { UserAssert(PtiCurrent() == pMenuState->ptiMenuStateOwner);
/*
* Make sure we are not fullscreen */ if (gspwndFullScreen == pwnd) { PWND pwndT; TL tlpwndT;
pwndT = _GetDesktopWindow(); ThreadLock(pwndT, &tlpwndT); xxxMakeWindowForegroundWithState(pwndT, GDIFULLSCREEN); ThreadUnlock(&tlpwndT); }
pMenuState->fUnderline = TRUE; xxxMNKeyFilter(pMenuState->pGlobalPopupMenu, pMenuState, (UINT)lParam); if (!pMenuState->fModelessMenu) { xxxMNEndMenuState (TRUE); } } /*
* Capture must have been unlocked */ UserAssert(!(PtiCurrent()->pq->QF_flags & QF_CAPTURELOCKED)); return;
case SC_MOUSEMENU: case SC_DEFAULT:
/*
* If the window is not foreground, eat the command to avoid * wasting time flashing the system menu. * * We used to check if the top level window was WFFRAMEON (so a * child window's system menu works like Win 3.1) but Excel's * (SDM) dialogs allow you to access their menus even though * the child and parent appear to be inactive. */ if (!(GETPTI(pwnd)->pq == gpqForeground)) return;
/*
* A mouse click occurred on a toplevel menu. */ pMenuState = xxxMNStartMenuState(pwnd, cmd, lParam); if (pMenuState != NULL) { UserAssert(PtiCurrent() == pMenuState->ptiMenuStateOwner); xxxMNLoop(pMenuState->pGlobalPopupMenu, pMenuState, lParam, (cmd==SC_DEFAULT)); if (!pMenuState->fModelessMenu) { xxxMNEndMenuState (TRUE); } } /*
* Capture must have been unlocked */ UserAssert(!(PtiCurrent()->pq->QF_flags & QF_CAPTURELOCKED)); return;
case SC_VSCROLL: case SC_HSCROLL: xxxSBTrackInit(pwnd, lParam, htArea, (_GetKeyState(VK_SHIFT) < 0) ? SCROLL_DIRECT : SCROLL_NORMAL); return;
case SC_TASKLIST: // _PostThreadMessage(gptiTasklist, WM_SYSCOMMAND, SC_TASKLIST, 0);
// if (!FCallTray() ||
// !CallHook(HSHELL_TASKMAN, (WPARAM) HW16(hwnd), (LPARAM) 0, WH_SHELL))
/*
* Winlogon will set lParam to -1 to indicate that we really want a task list, * not just the start menu. We indicate this to the shell by passing a NULL * window ptr * This message is really intended for the SHELL, so give them the right * to set the foreground. */ if (FDoTray() && (FCallHookTray() || FPostTray(pwnd->head.rpdesk))) { PWND pwndTaskman = pwnd->head.rpdesk->pDeskInfo->spwndTaskman; if (FCallHookTray()) { xxxCallHook(HSHELL_TASKMAN, (WPARAM)HWq(pwnd), (LPARAM) 0, WH_SHELL); } if ((FPostTray(pwnd->head.rpdesk)) && (pwndTaskman != NULL)) { glinp.ptiLastWoken = GETPTI(pwndTaskman); _PostMessage(pwndTaskman, gpsi->uiShellMsg, HSHELL_TASKMAN, lParam == (ULONG)(-1) ? (LPARAM) -1 :(LPARAM)HWq(pwnd)); } } else if (gptiTasklist != NULL) { glinp.ptiLastWoken = gptiTasklist; _PostThreadMessage(gptiTasklist, WM_SYSCOMMAND, SC_TASKLIST, 0); // LATER -- FritzS
// HCURSOR hCursorLast;
// static char CODESEG szTask[] = " %d %d";
// ShowCursor(TRUE);
// hCursorLast = SetCursor32(hCursWait, TRUE);
// Try in the windows directory first.
// GetWindowsDirectory(szBuff, sizeof(szBuff));
// if (szBuff[lstrlen(szBuff) - 1] != '\\')
// lstrcatn(szBuff, "\\", sizeof(szBuff));
// lstrcatn(szBuff, (LPSTR)pTaskManName, sizeof(szBuff));
// wvsprintf(szBuff+lstrlen(szBuff), (LPSTR)szTask, (LPSTR)&lParam);
// if (WinExec((LPSTR)szBuff, SW_SHOWNORMAL) <= 32)
// {
// // If it wasn't in the windows directory then try
// // searching the full path.
// lstrcpyn(szBuff, pTaskManName, sizeof(szBuff));
// wvsprintf(szBuff+lstrlen(szBuff), (LPSTR)szTask, (LPSTR)&lParam);
// WinExec((LPSTR)szBuff, SW_SHOWNORMAL);
// }
//
// ShowCursor(FALSE);
// SetCursor32(hCursorLast, TRUE);
}
break;
case SC_MONITORPOWER: /*
* If we're powering down the machine, or if we are switching protocol,ignore this request. */
if (gPowerState.fInProgress || gfSwitchInProgress) { break; }
switch (lParam) { case POWERON_PHASE: if ( (glinp.dwFlags & LINP_POWERTIMEOUTS) || (glinp.dwFlags & LINP_POWEROFF) ) { glinp.dwFlags &= ~LINP_POWEROFF; glinp.dwFlags &= ~LINP_POWERTIMEOUTS; DrvSetMonitorPowerState(gpDispInfo->pmdev, PowerDeviceD0); } break; case LOWPOWER_PHASE: if ((glinp.dwFlags & LINP_LOWPOWER) == 0) { glinp.dwFlags |= LINP_LOWPOWER; DrvSetMonitorPowerState(gpDispInfo->pmdev, PowerDeviceD1); } break; case POWEROFF_PHASE: if ((glinp.dwFlags & LINP_POWEROFF) == 0) { glinp.dwFlags |= LINP_POWEROFF; DrvSetMonitorPowerState(gpDispInfo->pmdev, PowerDeviceD3); } break; default: break; } break;
case SC_SCREENSAVE: pwndSwitch = RevalidateHwnd(ghwndSwitch);
// Lock out screen save until we get another input message.
if (pwndSwitch != NULL && pwnd != pwndSwitch) { _PostMessage(pwndSwitch, WM_SYSCOMMAND, SC_SCREENSAVE, 0L); } else { StartScreenSaver(FALSE); } break;
case SC_HOTKEY:
/*
* Loword of the lparam is window to switch to */ pwnd = ValidateHwnd((HWND)lParam); if (pwnd != NULL) { pwndSwitch = _GetLastActivePopup(pwnd);
if (pwndSwitch != NULL) pwnd = pwndSwitch;
ThreadLockAlways(pwnd, &tlpwnd); xxxSetForegroundWindow(pwnd, FALSE); ThreadUnlock(&tlpwnd);
if (TestWF(pwnd, WFMINIMIZED)) _PostMessage(pwnd, WM_SYSCOMMAND, SC_RESTORE, 0); } break; } } }
/***************************************************************************\
* _RegisterTasklist (Private API) * * History: * 05-01-91 DavidPe Created. \***************************************************************************/
BOOL _RegisterTasklist( PWND pwndTasklist) { #ifdef LATER
//
// JimA - ??? Why do this?
//
PETHREAD Thread;
Thread = PsGetCurrentThread(); pRitCSRThread->ThreadHandle = Thread->ThreadHandle; #endif
gptiTasklist = GETPTI(pwndTasklist); ghwndSwitch = HWq(pwndTasklist);
/*
* Don't allow an app to call AttachThreadInput() on task man - * we want taskman to be unsynchronized at all times (so the user * can bring it up and kill other apps). */ GETPTI(pwndTasklist)->TIF_flags |= TIF_DONTATTACHQUEUE;
return TRUE; }
|