BOOL xxxAddFullScreen(PWND pwnd) { BOOL fYielded; PDESKTOP pdesk = pwnd->head.rpdesk; CheckLock(pwnd); fYielded = FALSE; if (pdesk == NULL) return fYielded; if (!TestWF(pwnd, WFFULLSCREEN) && FCallTray(pdesk)) { SetWF(pwnd, WFFULLSCREEN); if (!(pdesk->cFullScreen)++) { xxxSetTrayWindow(pdesk, STW_SAME); fYielded = TRUE; } if ((pwnd = pwnd->spwndOwner) && !TestWF(pwnd, WFCHILD) && !pwnd->rcWindow.right && !pwnd->rcWindow.left && !TestWF(pwnd, WFVISIBLE)) { TL tlpwnd; ThreadLock(pwnd, &tlpwnd); if (xxxAddFullScreen(pwnd)) fYielded = TRUE; ThreadUnlock(&tlpwnd); } } return(fYielded); }
VOID xxxSendNCPaint( PWND pwnd, HRGN hrgnUpdate) { CheckLock(pwnd); /* * Clear the WFSENDNCPAINT bit... */ ClrWF(pwnd, WFSENDNCPAINT); /* * If the window is active, but its FRAMEON bit hasn't * been set yet, set it and make sure that the entire frame * gets redrawn when we send the NCPAINT. */ if ((pwnd == PtiCurrent()->pq->spwndActive) && !TestWF(pwnd, WFFRAMEON)) { SetWF(pwnd, WFFRAMEON); hrgnUpdate = HRGN_FULL; ClrWF(pwnd, WFNONCPAINT); } /* * If PixieHack() has set the WM_NCPAINT bit, we must be sure * to send with hrgnClip == HRGN_FULL. (see PixieHack() in wmupdate.c) */ if (TestWF(pwnd, WFPIXIEHACK)) { ClrWF(pwnd, WFPIXIEHACK); hrgnUpdate = HRGN_FULL; } if (hrgnUpdate) xxxSendMessage(pwnd, WM_NCPAINT, (WPARAM)hrgnUpdate, 0L); }
VOID SetDialogPointer(PWND pwnd, LONG_PTR lPtr) { if ((pwnd->cbwndExtra < DLGWINDOWEXTRA) || TestWF(pwnd, WFSERVERSIDEPROC) || (PpiCurrent() != GETPTI(pwnd)->ppi)) { RIPMSG1(RIP_WARNING, "SetDialogPointer: Unexpected pwnd:%#p", pwnd); return; } ((PDIALOG)pwnd)->pdlg = (PDLG)lPtr; if (lPtr == 0) { pwnd->fnid |= FNID_CLEANEDUP_BIT; ClrWF(pwnd, WFDIALOGWINDOW); } else { if (pwnd->fnid == 0) { pwnd->fnid = FNID_DIALOG; } SetWF(pwnd, WFDIALOGWINDOW); } }
static int DriverPrivateEvents(XEvent *report) { UINT wstate; HWND hWnd,hWndFrame; WINDOWPOS wp; int count; int msgposted = 0; DWORD dwClientWin; RECT rcWnd; PRIVATEDISPLAY *dp; static Window win; Window win_focus; DWORD dwStyle; int revert_return; char *msgstr = 0; dp = GETDP(); switch (report->type) { case SelectionNotify: msgstr = "SelectionNotify"; dp->ServerTime = report->xselection.time; break; case SelectionClear: msgstr = "SelectionClear"; dp->ServerTime = report->xselectionclear.time; break; case SelectionRequest: msgstr = "SelectionRequest"; dp->ServerTime = report->xselectionrequest.time; break; case PropertyNotify: msgstr = "PropertyNotify"; dp->ServerTime = report->xproperty.time; /* * fall through to common code, handle X ICCCM * PropertyNotify will be related to clipboard and DDE * ClientMessage will be either * wm_protocol for user/window manager interactions * ipc_protocol for DDE and low-level interactions */ case ClientMessage: msgstr = "ClientMessage"; if(InternalICCCM(report->type,dp,report)) msgposted--; break; case Expose: { XRectangle rcexpose; Region RgnExpose = 0; RECT rcExpose; HWND hWndFrame = 0; msgstr = "Expose"; count = 0; do { if (count == 0) { if (XFindContext(dp->display,report->xexpose.window, dp->client_hwnd,(caddr_t *)&dwClientWin)) continue; hWndFrame = (HWND)HIWORD(dwClientWin); count = report->xexpose.count; if (count == 0) { rcExpose.left = report->xexpose.x; rcExpose.top = report->xexpose.y; rcExpose.right = report->xexpose.x+ report->xexpose.width; rcExpose.bottom = report->xexpose.y+ report->xexpose.height; lpLibCallback(TWINLIBCALLBACK_EXPOSE,(LPARAM)hWndFrame, SIMPLEREGION, (LPVOID)&rcExpose); msgposted--; continue; } else RgnExpose = XCreateRegion(); } rcexpose.x = report->xexpose.x; rcexpose.y = report->xexpose.y; rcexpose.width = report->xexpose.width; rcexpose.height = report->xexpose.height; XUnionRectWithRegion(&rcexpose,RgnExpose,RgnExpose); if (report->xexpose.count == 0) { lpLibCallback(TWINLIBCALLBACK_EXPOSE,(LPARAM)hWndFrame, COMPLEXREGION,(LPVOID)RgnExpose); msgposted--; XDestroyRegion(RgnExpose); count = 0; } } while (XCheckTypedEvent(dp->display,Expose,report)); break; } case ReparentNotify: msgstr = "ReparentNotify"; if (XFindContext(dp->display,report->xreparent.window, dp->client_hwnd,(caddr_t *)&dwClientWin)) break; /* We have to repeat XResizeWindow for the sake of */ /* OpenWindows, which loses resizing requests */ hWnd = LOWORD(dwClientWin); GetPhysicalRect(hWnd,&rcWnd); XResizeWindow(dp->display, report->xreparent.window, rcWnd.right-rcWnd.left, rcWnd.bottom-rcWnd.top); break; case ConfigureNotify: msgstr = "ConfigureNotify"; if (XFindContext(dp->display,report->xconfigure.window, dp->client_hwnd,(caddr_t *)&dwClientWin)) break; /* Window managers send synthetic ConfigureNotify events */ /* if the window was moved but not resized (July 27, 1988 */ /* ICCCM draft). Some window managers (OpenWin) offset the */ /* origin by some fixed value, so take size portion and go */ /* get origin from Xlib */ wstate = SWP_NOACTIVATE|SWP_DRIVER|SWP_NOZORDER; { int xRoot,yRoot; Window child_return; XTranslateCoordinates(dp->display, report->xconfigure.window, RootWindow(dp->display,dp->screen), 0,0, &xRoot,&yRoot, &child_return); report->xconfigure.x = xRoot; report->xconfigure.y = yRoot; } if (!report->xconfigure.width || !report->xconfigure.height) wstate |= SWP_NOSIZE; wp.hwnd = (HWND)HIWORD(dwClientWin); wp.hwndInsertAfter = (HWND)0; wp.x = report->xconfigure.x; wp.y = report->xconfigure.y; wp.cx = report->xconfigure.width; wp.cy = report->xconfigure.height; wp.flags = wstate; lpLibCallback(TWINLIBCALLBACK_CONFIGURE,(LPARAM)wp.hwnd, 0, (LPVOID)&wp); break; case ButtonPress: msgstr = "ButtonPress"; msgposted = DrvWindowsEvents(0L,0L,(LPVOID)report); break; case ButtonRelease: msgstr = "ButtonRelease"; msgposted = DrvWindowsEvents(0L,0L,(LPVOID)report); break; case MotionNotify: msgstr = "MotionNotify"; msgposted = DrvWindowsEvents(0L,0L,(LPVOID)report); break; case KeyPress: msgstr = "KeyPress"; msgposted = DrvHandleKeyboardEvents(0L,0L,(LPVOID)report); break; case KeyRelease: msgstr = "KeyRelease"; msgposted = DrvHandleKeyboardEvents(0L,0L,(LPVOID)report); break; case EnterNotify: msgstr = "EnterNotify"; if (XFindContext(dp->display,report->xcrossing.window, dp->client_hwnd,(caddr_t *)&dwClientWin)) break; XFindContext(dp->display,report->xcrossing.window, dp->window_style,(caddr_t *)&dwStyle); if ((dwStyle & WS_CAPTION) != WS_CAPTION) { XGetInputFocus(dp->display,&win,&revert_return); if (win != report->xcrossing.window) { XSetInputFocus(dp->display,report->xcrossing.window, revert_return,CurrentTime); } } break; case LeaveNotify: msgstr = "LeaveNotify"; if (XFindContext(dp->display,report->xcrossing.window, dp->client_hwnd,(caddr_t *)&dwClientWin)) break; XFindContext(dp->display,report->xcrossing.window, dp->window_style,(caddr_t *)&dwStyle); if ((dwStyle & WS_CAPTION) != WS_CAPTION) { XGetInputFocus(dp->display,&win_focus,&revert_return); if (win && (win != report->xcrossing.window)) { if (win != RootWindow(dp->display,dp->screen)) { XSetInputFocus(dp->display,win, revert_return,CurrentTime); } else { XSetInputFocus(dp->display,PointerRoot, 0,CurrentTime); } } win = 0; } break; case FocusIn: msgstr = "FocusIn"; case FocusOut: if(msgstr == 0) msgstr = "FocusOut"; if (XFindContext(dp->display,report->xfocus.window, dp->client_hwnd,(caddr_t *)&dwClientWin)) break; hWndFrame = HIWORD(dwClientWin); lpLibCallback(TWINLIBCALLBACK_FOCUS,(LPARAM)hWndFrame, IFC_DRIVERFOCUS, (LPVOID)(report->type == FocusIn)); msgposted--; break; case KeymapNotify: msgstr = "KeymapNotify"; /* this could/should be used to update us on the current * state of the keyboard. Can it be different from what * we know about it? Yes, we could have keydown somewhere * and keyup in our space... */ break; case VisibilityNotify: msgstr = "VisibilityNotify"; /* * The following function call prints the entire tree of * windows known to X11. It is commented out because it * is far too wordy in most debugging situations. */ DrvPrintTree(dp, XRootWindow(dp->display, dp->screen)); if (XFindContext(dp->display, report->xvisibility.window, dp->client_hwnd, (caddr_t *)&dwClientWin)) break; hWnd = (HWND)LOWORD(dwClientWin); switch (report->xvisibility.state) { case VisibilityUnobscured: case VisibilityPartiallyObscured: SetWF(hWnd,WFVISIBILITY); break; case VisibilityFullyObscured: ClearWF(hWnd,WFVISIBILITY); break; } msgposted--; break; case CreateNotify: msgstr = "CreateNotify"; break; case DestroyNotify: msgstr = "DestroyNotify"; break; case MappingNotify: msgstr = "MappingNotify"; XRefreshKeyboardMapping((XMappingEvent *)report); break; case MapNotify: msgstr = "MapNotify"; #ifdef DEBUG if (XFindContext(dp->display,report->xmap.window, dp->client_hwnd,(caddr_t *)&dwClientWin)) break; hWnd = HIWORD(dwClientWin); #endif break; case UnmapNotify: msgstr = "UnmapNotify"; if (XFindContext(dp->display,report->xunmap.window, dp->client_hwnd,(caddr_t *)&dwClientWin)) break; hWnd = HIWORD(dwClientWin); ClearWF(hWnd, WFMAPPED); break; case CirculateNotify: msgstr = "CirculateNotify"; break; case CirculateRequest: msgstr = "CirculateRequest"; break; case NoExpose: msgstr = "NoExpose"; break; default: msgstr = "UNKNOWN"; break; } /* end switch */ return msgposted; }
BOOL xxxShowWindow( PWND pwnd, DWORD cmdShowAnimate) { BOOL fVisOld, fVisNew; UINT swpFlags = SWP_NOMOVE | SWP_NOSIZE; PTHREADINFO pti; BOOL bFirstMain = FALSE; int cmdShow = LOWORD(cmdShowAnimate); CheckLock(pwnd); fVisOld = TestWF(pwnd, WFVISIBLE); pti = PtiCurrent(); /* * See if this is the first "main" top level * window being created by this application - if show, assume it * is showing with the SW_SHOWDEFAULT command. * * Checks for: * - cmdShow is a "default" show command * - we haven't done startupinfo yet (we only use it once) * - this is not a child (it is a top level window) * - this has a titlebar (indicator of the main window) * - it isn't owned (indicator of the main window) */ if ((pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW) && !TestwndChild(pwnd) && (TestWF(pwnd, WFBORDERMASK) == (BYTE)LOBYTE(WFCAPTION)) && (pwnd->spwndOwner == NULL)) { bFirstMain = TRUE; switch (cmdShow) { case SW_SHOWNORMAL: case SW_SHOW: /* * Then assume default! */ cmdShow = SW_SHOWDEFAULT; break; } } /* * If this application specified SW_SHOWDEFAULT, then we get the * real SW_* command from the application's STARTUPINFO structure * (STARTUPINFO is passed to CreateProcess() when this application * was launched). */ if (cmdShow == SW_SHOWDEFAULT) { /* * Call the client to get the SW_* command from the STARTUPINFO * for this process. */ if (pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW) { bFirstMain = TRUE; cmdShow = pti->ppi->usi.wShowWindow; #if 0 switch (cmdShow) { case SW_SHOWMINIMIZED: case SW_MINIMIZE: /* * If the default show was "minimized", then make sure it doesn't * become active. Minimized is effectively "background". */ cmdShow = SW_SHOWMINNOACTIVE; break; } #endif } } // // This is in case someone said SW_SHOWDEFAULT but has no startupinfo. // Or in case cmdShow inside of STARTUPINFO is SW_SHOWDEFAULT. // if (cmdShow == SW_SHOWDEFAULT) cmdShow = SW_SHOWNORMAL; /* * Turn off startup info. We turn this off after the first call to * ShowWindow. If we don't apps can be started by progman with * the start info being minimized and then be restored and then * call ShowWindow(SW_SHOW) and the app would minimize again. * Notepad had that problem 2985. */ if (bFirstMain) { pti->ppi->usi.dwFlags &= ~(STARTF_USESHOWWINDOW|STARTF_USESIZE \ | STARTF_USEPOSITION); } /* * Take care of all the OLD show commands with columns & iconslot. */ if (cmdShow & 0xFF00) { if ((cmdShow & 0xFF80) == (int)0xFF80) cmdShow = SW_SHOWMINNOACTIVE; else cmdShow = SW_SHOW; } /* * Change to new fullscreen if needed and in same desktop */ if ((pwnd->bFullScreen != WINDOWED) && (pwnd->head.rpdesk == grpdeskRitInput)) { if ((cmdShow == SW_SHOWNORMAL) || (cmdShow == SW_RESTORE) || (cmdShow == SW_MAXIMIZE) || (cmdShow == SW_SHOWMAXIMIZED)) { cmdShow = SW_SHOWMINIMIZED; if (pwnd->bFullScreen == FULLSCREENMIN) { pwnd->bFullScreen = FULLSCREEN; } if (gpqForeground != NULL && gpqForeground->spwndActive == pwnd) { xxxMakeWindowForegroundWithState(NULL, 0); } } } switch (cmdShow) { case SW_SHOWNOACTIVATE: case SW_SHOWNORMAL: case SW_RESTORE: /* * If min/max, let xxxMinMaximize() do all the work. */ if (TestWF(pwnd, WFMINIMIZED) || TestWF(pwnd, WFMAXIMIZED)) { xxxMinMaximize(pwnd, (UINT)cmdShow, cmdShowAnimate & MINMAX_ANIMATE); return fVisOld; } else { /* * Ignore if the window is already visible. */ if (fVisOld) { return fVisOld; } swpFlags |= SWP_SHOWWINDOW; if ( cmdShow == SW_SHOWNOACTIVATE) { swpFlags |= SWP_NOZORDER; #ifdef NEVER /* * This is what win3.1 does. On NT, since each "queue" has * its own active window, there is often no active window. * In this case, win3.1 turns a SHOWNOACTIVATE into a "SHOW * with activate". Since win3.1 almost always has an active * window, this almost never happens. So on NT, we're not * going to do this check - that way we'll be more compatible * with win3.1 because we'll usally not activate (like win3.1). * With this check, this causes FoxPro 2.5 for Windows to not * properly activate its command window when first coming up. */ if (pti->pq->spwndActive != NULL) swpFlags |= SWP_NOACTIVATE; #else swpFlags |= SWP_NOACTIVATE; #endif } } break; case SW_SHOWMINNOACTIVE: case SW_SHOWMINIMIZED: case SW_SHOWMAXIMIZED: case SW_MINIMIZE: xxxMinMaximize(pwnd, (UINT)cmdShow, cmdShowAnimate & MINMAX_ANIMATE); return fVisOld; case SW_SHOWNA: swpFlags |= SWP_SHOWWINDOW | SWP_NOACTIVATE; // LATER removed this to be compatible with SHOWNOACTIVATE //if (pti->pq->spwndActive != NULL) // swpFlags |= SWP_NOACTIVATE; break; case SW_SHOW: /* * Don't bother if it is already visible. */ if (fVisOld) return fVisOld; swpFlags |= SWP_SHOWWINDOW; if (cmdShow == SW_SHOWNOACTIVATE) { swpFlags |= SWP_NOZORDER | SWP_NOACTIVATE; } break; case SW_HIDE: /* * Don't bother if it is already hidden. */ if (!fVisOld) return fVisOld; swpFlags |= SWP_HIDEWINDOW; if (pwnd != pti->pq->spwndActive) swpFlags |= (SWP_NOACTIVATE | SWP_NOZORDER); break; default: RIPERR0(ERROR_INVALID_SHOWWIN_COMMAND, RIP_VERBOSE, ""); return fVisOld; } /* * If we're changing from visible to hidden or vise-versa, send * WM_SHOWWINDOW. */ fVisNew = !(cmdShow == SW_HIDE); if (fVisNew != fVisOld) { xxxSendMessage(pwnd, WM_SHOWWINDOW, fVisNew, 0L); if (!TestWF(pwnd, WFWIN31COMPAT)) { xxxSendMessage(pwnd, WM_SETVISIBLE, fVisNew, 0L); } } if (!TestwndChild(pwnd)) { if (TestCF(pwnd, CFSAVEBITS)) { /* * Activate to prevent discarding saved bits??? */ if (cmdShow == SW_SHOW || cmdShow == SW_SHOWNORMAL) { xxxActivateWindow(pwnd, AW_USE); swpFlags |= SWP_NOZORDER | SWP_NOACTIVATE; } } } else { /* * Children can't get activation... */ swpFlags |= (SWP_NOACTIVATE | SWP_NOZORDER); } /* * If our parent is hidden, don't bother to call xxxSetWindowPos. */ if (_FChildVisible(pwnd)) { xxxSetWindowPos(pwnd, (PWND)NULL, 0, 0, 0, 0, swpFlags); } else { if (cmdShow == SW_HIDE) ClrWF(pwnd, WFVISIBLE); else SetWF(pwnd, WFVISIBLE); } /* * Send size and move messages AFTER repainting */ if (TestWF(pwnd, WFSENDSIZEMOVE)) { ClrWF(pwnd, WFSENDSIZEMOVE); if (TestWF(pwnd, WFMINIMIZED)) { xxxSendSizeMessage(pwnd, SIZEICONIC); } else if (TestWF(pwnd, WFMAXIMIZED)) { xxxSendSizeMessage(pwnd, SIZEFULLSCREEN); } else { xxxSendSizeMessage(pwnd, SIZENORMAL); } if (pwnd->spwndParent) { xxxSendMessage(pwnd, WM_MOVE, 0, MAKELONG( pwnd->rcClient.left - pwnd->spwndParent->rcClient.left, pwnd->rcClient.top - pwnd->spwndParent->rcClient. top)); } else { /* * NULL parent implies this window is a zombie */ xxxSendMessage(pwnd, WM_MOVE, 0, MAKELONG( pwnd->rcClient.left, pwnd->rcClient.top)); } } /* * If hiding and is active-foreground window, activate someone else. * If hiding a active window make someone active. */ if (cmdShow == SW_HIDE) { if ((pwnd == pti->pq->spwndActive) && (pti->pq == gpqForeground)) { xxxActivateWindow(pwnd, AW_SKIP); } else { xxxCheckFocus(pwnd); } } return fVisOld; }
VOID DoQueuedSyncPaint( PWND pwnd, DWORD flags, PTHREADINFO pti) { PTHREADINFO ptiPwnd = GETPTI(pwnd); if ((ptiPwnd != pti) && TestWF(pwnd, WFSENDNCPAINT) && TestWF(pwnd, WFSENDERASEBKGND) && TestWF(pwnd, WFVISIBLE)) { PSMS psms = ptiPwnd->psmsReceiveList; /* * If this window already has a WM_SYNCPAINT queue'd up, then there's * no need to send another one. Also protects our heap from getting * chewed up. */ while (psms != NULL) { if ((psms->message == WM_SYNCPAINT) && (psms->spwnd == pwnd)) { break; } psms = psms->psmsReceiveNext; } if (psms == NULL) { /* * This will give this message the semantics of a notify * message (sendmessage no wait), without calling back * the WH_CALLWNDPROC hook. We don't want to do that * because that'll let all these processes with invalid * windows to process paint messages before they process * "synchronous" erasing or framing needs. * * Hi word of wParam must be zero or wow will drop it * * LATER mikeke * Do we need to send down the flags with DWP_ERASE and DSP_FRAME * in it? */ UserAssert(HIWORD(flags) == 0); QueueNotifyMessage(pwnd, WM_SYNCPAINT, flags, 0); /* * Set our syncpaint-pending flag, since we queued one up. This * will be used to check when we validate-parents for windows * without clipchildren. */ SetWF(pwnd, WFSYNCPAINTPENDING); } /* * If we posted a WM_SYNCPAINT for a top-level window that is not * of the current thread we're done; we'll pick up the children * when we process the message for real. If we're the desktop * however make sure we get all it children. */ if (pwnd != PWNDDESKTOP(pwnd)) return; } /* * Normally we like to enumerate all of this window's children and have * them erase their backgrounds synchronously. However, this is a bad * thing to do if the window is NOT CLIPCHLIDREN. Here's the scenario * we want to to avoid: * * 1. Window 'A' is invalidated * 2. 'A' erases itself (or not, doesn't matter) * 3. 'A's children are enumerated and they erase themselves. * 4. 'A' paints over its children (remember, 'A' isn't CLIPCHILDREN) * 5. 'A's children paint but their backgrounds aren't their ERASEBKND * color (because 'A' painted over them) and everything looks like * dirt. */ if ((flags & DSP_ALLCHILDREN) || ((flags & DSP_ENUMCLIPPEDCHILDREN) && TestWF(pwnd, WFCLIPCHILDREN))) { PWND pwndT; for (pwndT = pwnd->spwndChild; pwndT; pwndT = pwndT->spwndNext) { /* * Don't cause any more intertask sendmessages cause it does * bad things to cbt's windowproc hooks. (Due to SetParent * allowing child windows in the topwindow hierarchy. * The child bit also catches the desktop window; we want to */ if (TestWF(pwndT, WFCHILD) && (pti != GETPTI(pwndT))) continue; /* * Note that we pass only certain bits down as we recurse: * the other bits pertain to the current window only. */ DoQueuedSyncPaint(pwndT, flags, pti); } } }
BOOL DoPaint( PWND pwndFilter, LPMSG lpMsg) { PWND pwnd; PWND pwndT; PTHREADINFO ptiCurrent = PtiCurrent(); #if 0 // CHRISWIL: WIN95 SPECIFIC /* * If there is a system modal up and it is attached to another task, * DON'T do paints. We don't want to return a message for a window in * another task! */ if (hwndSysModal && (hwndSysModal->hq != hqCurrent)) { /* * Poke this guy so he wakes up at some point in the future, * otherwise he may never wake up to realize he should paint. * Causes hangs - e.g. Photoshop installation program * PostThreadMessage32(Lpq(hqCurrent)->idThread, WM_NULL, 0, 0, 0); */ return FALSE; } #endif /* * If this is a system thread, then walk the windowstation desktop-list * to find the window which needs painting. For other threads, we * reference off the thread-desktop. */ if (ptiCurrent->TIF_flags & TIF_SYSTEMTHREAD) { PWINDOWSTATION pwinsta; PDESKTOP pdesk; if ((pwinsta = ptiCurrent->pwinsta) == NULL) { RIPMSG0(RIP_ERROR, "DoPaint: SYSTEMTHREAD does not have (pwinsta)"); return FALSE; } pwnd = NULL; for(pdesk = pwinsta->rpdeskList; pdesk; pdesk = pdesk->rpdeskNext) { if (pwnd = InternalDoPaint(pdesk->pDeskInfo->spwnd, ptiCurrent)) break; } } else { pwnd = InternalDoPaint(ptiCurrent->rpdesk->pDeskInfo->spwnd, ptiCurrent); } if (pwnd != NULL) { if (!CheckPwndFilter(pwnd, pwndFilter)) return FALSE; /* * We're returning a WM_PAINT message, so clear WFINTERNALPAINT so * it won't get sent again later. */ if (TestWF(pwnd, WFINTERNALPAINT)) { ClrWF(pwnd, WFINTERNALPAINT); /* * If there is no update region, then no more paint for this * window. */ if (pwnd->hrgnUpdate == NULL) DecPaintCount(pwnd); } /* * Set the STARTPAINT so that any other calls to BeginPaint while * painting is begin performed, will prevent painting on those * windows. * * Clear the UPDATEDIRTY since some apps (DBFast) don't call * GetUpdateRect, BeginPaint/EndPaint. */ ClrWF(pwnd, WFSTARTPAINT); ClrWF(pwnd, WFUPDATEDIRTY); /* * If we get an invalidate between now and the time the app calls * BeginPaint() and the windows parent is not CLIPCHILDREN, then * the parent will paint in the wrong order. So we are going to * cause the child to paint again. Look in beginpaint and internal * invalidate for other parts of this fix. * * Set a flag to signify that we are in the bad zone. * * Must go up the parent links to make sure all parents have * WFCLIPCHILDREN set otherwise set the WFWMPAINTSENT flag. * This is to fix Excel spreadsheet and fulldrag. The speadsheet * parent window (class XLDESK) has WFCLIPCHILDREN set but it's * parent (class XLMAIN) doesn't. So the main window erases the * background after the child window paints. * * JOHANNEC : 27-Jul-1994 */ /* * NT Bug 400167: As we walk up the tree, we need to stop short of * desktop windows and mother desktop windows. We can't do a test * for WFCLIPCHILDREN on the mother desktop window's parent because * it doesn't exist. This means that no desktop window will get * WFWMPAINTSENT set, but the message window will be able to get * WFWMPAINTSENT set. */ pwndT = pwnd; while (pwndT && (GETFNID(pwndT) != FNID_DESKTOP)) { if (!TestWF(pwndT->spwndParent, WFCLIPCHILDREN)) { SetWF(pwnd, WFWMPAINTSENT); break; } pwndT = pwndT->spwndParent; } /* * If the top level "tiled" owner/parent of this window is iconed, * send a WM_PAINTICON rather than a WM_PAINT. The wParam * is TRUE if this is the tiled window and FALSE if it is a * child/owned popup of the minimized window. * * BACKWARD COMPATIBILITY HACK * * 3.0 sent WM_PAINTICON with wParam == TRUE for no apparent * reason. Lotus Notes 2.1 depends on this for some reason * to properly change its icon when new mail arrives. */ if (!TestWF(pwnd, WFWIN40COMPAT) && TestWF(pwnd, WFMINIMIZED) && (pwnd->pcls->spicn != NULL)) { StoreMessage(lpMsg, pwnd, WM_PAINTICON, (DWORD)TRUE, 0L, 0L); } else { StoreMessage(lpMsg, pwnd, WM_PAINT, 0, 0L, 0L); } return TRUE; } return FALSE; }
HDC xxxBeginPaint( PWND pwnd, LPPAINTSTRUCT lpps) { HRGN hrgnUpdate; HDC hdc; BOOL fSendEraseBkgnd; CheckLock(pwnd); UserAssert(IsWinEventNotifyDeferredOK()); if (TEST_PUDF(PUDF_DRAGGINGFULLWINDOW)) SetWF(pwnd, WFSTARTPAINT); /* * We're processing a WM_PAINT message: clear this flag. */ ClrWF(pwnd, WFPAINTNOTPROCESSED); /* * If this bit gets set while we are drawing the frame we will need * to redraw it. * * If necessary, send our WM_NCPAINT message now. * * please heed these notes * * We have to send this message BEFORE we diddle hwnd->hrgnUpdate, * because an app may call ValidateRect or InvalidateRect in its * handler, and it expects what it does to affect what gets drawn * in the later WM_PAINT. * * It is possible to get an invalidate when we leave the critical * section below, therefore we loop until UPDATEDIRTY is clear * meaning there were no additional invalidates. */ if (TestWF(pwnd, WFSENDNCPAINT)) { do { ClrWF(pwnd, WFUPDATEDIRTY); hrgnUpdate = GetNCUpdateRgn(pwnd, FALSE); xxxSendNCPaint(pwnd, hrgnUpdate); DeleteMaybeSpecialRgn(hrgnUpdate); } while (TestWF(pwnd, WFUPDATEDIRTY)); } else { ClrWF(pwnd, WFUPDATEDIRTY); } /* * Hide the caret if needed. Do this before we get the DC so * that if HideCaret() gets and releases a DC we will be able * to reuse it later here. * No need to DeferWinEventNotify() since pwnd is locked. */ if (pwnd == PtiCurrent()->pq->caret.spwnd) zzzInternalHideCaret(); /* * Send the check for sending an WM_ERASEBKGND to the * window. */ if (fSendEraseBkgnd = TestWF(pwnd, WFSENDERASEBKGND)) { ClrWF(pwnd, WFERASEBKGND); ClrWF(pwnd, WFSENDERASEBKGND); } /* * Validate the entire window. */ if (NEEDSPAINT(pwnd)) DecPaintCount(pwnd); ClrWF(pwnd, WFINTERNALPAINT); hrgnUpdate = pwnd->hrgnUpdate; pwnd->hrgnUpdate = NULL; if (TestWF(pwnd, WFDONTVALIDATE)) { if (ghrgnUpdateSave == NULL) { ghrgnUpdateSave = CreateEmptyRgn(); } if (ghrgnUpdateSave != NULL) { UnionRgn(ghrgnUpdateSave, ghrgnUpdateSave, hrgnUpdate); gnUpdateSave++; } } /* * Clear these flags for backward compatibility */ lpps->fIncUpdate = lpps->fRestore = FALSE; lpps->hdc = hdc = _GetDCEx(pwnd, hrgnUpdate, DCX_USESTYLE | DCX_INTERSECTRGN); if (UT_GetParentDCClipBox(pwnd, hdc, &lpps->rcPaint)) { /* * If necessary, erase our background, and possibly deal with * our children's frames and backgrounds. */ if (fSendEraseBkgnd) xxxSendEraseBkgnd(pwnd, hdc, hrgnUpdate); } /* * Now that we're completely erased, see if there are any children * that couldn't draw their own frames because their update regions * got deleted. */ xxxSendChildNCPaint(pwnd); /* * The erase and frame operation has occured. Clear the WFREDRAWIFHUNG * bit here. We don't want to clear it until we know the erase and * frame has occured, so we know we always have a consistent looking * window. */ ClearHungFlag(pwnd, WFREDRAWIFHUNG); lpps->fErase = (TestWF(pwnd, WFERASEBKGND) != 0); return hdc; }
BOOL xxxSendEraseBkgnd( PWND pwnd, HDC hdcBeginPaint, HRGN hrgnUpdate) { PTHREADINFO ptiCurrent; BOOL fErased; HDC hdc; CheckLock(pwnd); /* * For minimized dudes in win3.1, we would've sent an * WM_ICONERASEBKGND and cleared the erase bit. Now that min * windows in 4.0 are all nonclient, don't bother erasing at * all. Pretend like we did. * * NOTE: * For < 4.0 windows, we may have to send a fake WM_ICONERASEKBGND * to keep 'em happy. Saves time not to though. Getting a DC and * sending the message ain't speedy. */ if ((hrgnUpdate == NULL) || TestWF(pwnd, WFMINIMIZED)) return FALSE; /* * If a DC to use was not passed in, get one. * We want one clipped to this window's update region. */ if (hdcBeginPaint == NULL) { hdc = _GetDCEx(pwnd, hrgnUpdate, DCX_USESTYLE | DCX_INTERSECTRGN | DCX_NODELETERGN); } else { hdc = hdcBeginPaint; } /* * If we're send the WM_ERASEBKGND to another process * we need to change the DC owner. * * We'd like to change the owner to pwnd->pti->idProcess, but * GDI won't let us assign ownership back to ourselves later. */ ptiCurrent = PtiCurrent(); if (GETPTI(pwnd)->ppi != ptiCurrent->ppi) GreSetDCOwner(hdc, OBJECT_OWNER_PUBLIC); /* * Send the event to the window. This contains the DC clipped to * the update-region. */ fErased = (BOOL)xxxSendMessage(pwnd, WM_ERASEBKGND, (WPARAM)hdc, 0L); /* * If we've changed the DC owner, change it back to * the current process. */ if (GETPTI(pwnd)->ppi != ptiCurrent->ppi) GreSetDCOwner(hdc, OBJECT_OWNER_CURRENT); /* * If the WM_ERASEBKGND message did not erase the * background, then set this flag to let BeginPaint() * know to ask the caller to do it via the fErase * flag in the PAINTSTRUCT. */ if (!fErased) { SetWF(pwnd, WFERASEBKGND); if (!TestWF(pwnd, WFWIN31COMPAT)) SetWF(pwnd, WFSENDERASEBKGND); } /* * If we got a cache DC in this routine, release it. */ if (hdcBeginPaint == NULL) { ReleaseCacheDC(hdc, TRUE); } return fErased; }
/***************************************************************************\ * * SetShellWindow() * * Returns true if shell window is successfully set. Note that we return * FALSE if a shell window already exists. I.E., this works on a first * come, first serve basis. * * We also do NOT allow child windows to be shell windows. Other than that, * it's up to the caller to size her window appropriately. * * The pwndBkGnd is provided for the explorer shell. Since the shellwnd * and the window which does the drawing of background wallpapers are * different, we need to provide means by which we can draw directly on * the background window during hung-app drawing. The pwnd and pwndBkGnd * will be identical if called through the SetShellWindow() api. * * \***************************************************************************/ BOOL xxxSetShellWindow(PWND pwnd, PWND pwndBkGnd) { PTHREADINFO ptiCurrent = PtiCurrent(); PDESKTOPINFO pdeskinfo = GETDESKINFO(ptiCurrent); PPROCESSINFO ppiShellProcess; UserAssert(pwnd); /* * Fail the call if another shell window exists */ if (pdeskinfo->spwndShell != NULL) return(FALSE); /* * The shell window must be * (1) Top-level * (2) Unowned * (3) Not topmost */ if (TestwndChild(pwnd) || (pwnd->spwndOwner != NULL) || TestWF(pwnd, WEFTOPMOST)) { RIPMSG0(RIP_WARNING, "xxxSetShellWindow: Invalid type of window"); return(FALSE); } /* * Chicago has a totally different input model which has special code * that checks for Ctrl-Esc and sends it to the shell. We can get * the same functionality, without totally re-writing our input model * by just automatically installing the Ctrl-Esc as a hotkey for the * shell window. The hotkey delivery code has a special case which * turns this into a WM_SYSCOMMAND message instead of a WM_HOTKEY * message. * * We don't both checking for failure. Somebody could already have * a Ctrl-Esc handler installed. */ _RegisterHotKey(pwnd,SC_TASKLIST,MOD_CONTROL,VK_ESCAPE); /* * This is the shell window wright. * So get the process id for the shell. */ ppiShellProcess = GETPTI(pwnd)->ppi; /* * Set the shell process id to the desktop only if it's the first instance */ if ((ppiShellProcess != NULL) && (pdeskinfo->ppiShellProcess == NULL)) { pdeskinfo->ppiShellProcess = ppiShellProcess; } Lock(&pdeskinfo->spwndShell, pwnd); Lock(&pdeskinfo->spwndBkGnd, pwndBkGnd); /* * Push window to bottom of stack. */ SetWF(pdeskinfo->spwndShell, WFBOTTOMMOST); xxxSetWindowPos(pdeskinfo->spwndShell, PWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); return(TRUE); }
void xxxCalcClientRect( PWND pwnd, LPRECT lprc, BOOL fHungRedraw) { int cxFrame, yTopOld; RECT rcTemp; PMENU pMenu; TL tlpmenu; int cBorders; BOOL fEmptyClient; CheckLock(pwnd); /* * Clear all the frame bits. NOTE: The HIBYTE of all these #defines * must stay the same for this line to work. */ ClrWF(pwnd, (WFHPRESENT | WFVPRESENT | WFCPRESENT | WFMPRESENT)); // // We need to clear the client border bits also. Otherwise, when the // window gets really small, the client border will draw over the menu // and caption. // ClrWF(pwnd, WFCEPRESENT); /* * If the window is iconic, the client area is empty. */ if (TestWF(pwnd, WFMINIMIZED)) { // SetRectEmpty(lprc); // We must make it an empty rectangle. // But, that empty rectangle should be at the top left corner of the // window rect. Else, ScreenToClient() will return bad values. lprc->right = lprc->left; lprc->bottom = lprc->top; return; } // Save rect into rcTemp for easy local calculations. CopyRect(&rcTemp, lprc); // Save the top so we'll know how tall the caption was yTopOld = rcTemp.top; // Adjustment for the caption if (TestWF(pwnd, WFBORDERMASK) == LOBYTE(WFCAPTION)) { SetWF(pwnd, WFCPRESENT); rcTemp.top += TestWF(pwnd, WEFTOOLWINDOW) ? SYSMET(CYSMCAPTION) : SYSMET(CYCAPTION); } // Subtract out window borders cBorders = GetWindowBorders(pwnd->style, pwnd->ExStyle, TRUE, FALSE); cxFrame = cBorders * SYSMET(CXBORDER); InflateRect(&rcTemp, -cxFrame, -cBorders*SYSMET(CYBORDER)); if (!TestwndChild(pwnd) && (pMenu = pwnd->spmenu)) { SetWF(pwnd, WFMPRESENT); if (!fHungRedraw) { ThreadLockAlways(pMenu, &tlpmenu); rcTemp.top += xxxMenuBarCompute(pMenu, pwnd, rcTemp.top - yTopOld, cxFrame, rcTemp.right - rcTemp.left); ThreadUnlock(&tlpmenu); } } // // Fix for B#1425 -- Sizing window really small used to move children's // rects because the client calculations were wrong. So we make the // bottom of the client match up with the top (the bottom of the menu // bar). // fEmptyClient = FALSE; if (rcTemp.top >= rcTemp.bottom) { rcTemp.bottom = rcTemp.top; fEmptyClient = TRUE; } // // BOGUS BOGUS BOGUS // Hack for Central Point PC Tools. // Possibly for M5 only. // B#8445 // // They check for div-by-zero all over, but they jump to the wrong place // if a zero divisor is encountered, and end up faulting anyway. So this // code path was never tested basically. There's a period when starting // up where the window rect of their drives ribbon is empty. In Win3.x, // the client would be shrunk to account for the border it had, and it // would look like it wasn't empty because the width would be negative, // signed! So we version-switch this code, since other apps have // reported the non-emptiness as an annoying bug. // if (TestWF(pwnd, WFWIN40COMPAT) && (rcTemp.left >= rcTemp.right)) { rcTemp.right = rcTemp.left; fEmptyClient = TRUE; } if (fEmptyClient) goto ClientCalcEnd; // // Subtract client edge if we have space // if (TestWF(pwnd, WEFCLIENTEDGE) && (rcTemp.right - rcTemp.left >= (2 * SYSMET(CXEDGE))) && (rcTemp.bottom - rcTemp.top >= (2 * SYSMET(CYEDGE))) ) { SetWF(pwnd, WFCEPRESENT); InflateRect(&rcTemp, -SYSMET(CXEDGE), -SYSMET(CYEDGE)); } // // Subtract scrollbars // Note compatibility with 3.1: // * You don't get a horizontal scrollbar unless you have MORE // space (> ) in your client than you need for one. // * You get a vertical scrollbar if you have AT LEAST ENOUGH // space (>=) in your client for one. // if (TestWF(pwnd, WFHSCROLL) && (rcTemp.bottom - rcTemp.top > SYSMET(CYHSCROLL))) { SetWF(pwnd, WFHPRESENT); if (!fHungRedraw) rcTemp.bottom -= SYSMET(CYHSCROLL); } if (TestWF(pwnd, WFVSCROLL) && (rcTemp.right - rcTemp.left >= SYSMET(CXVSCROLL))) { SetWF(pwnd, WFVPRESENT); if (!fHungRedraw) rcTemp.right -= SYSMET(CXVSCROLL); } ClientCalcEnd: CopyRect(lprc, &rcTemp); }
HWND InternalCreateDialog(HINSTANCE hInst, LPSTR lpDlg, HWND hWnd, DLGPROC lpFunc, LPARAM lParam) { DIALOGDATA *dp = (DIALOGDATA *) lpDlg; CONTROLDATA *cp; HWND hDlg; int i; HWND hCtl; HWND hFirst = 0,hFirstButton; int X,Y; HFONT hFont = (HFONT)0; HFONT ctlFont; DWORD dwBaseUnits; DWORD dwRet; WORD wDialogWidth, wDialogHeight; WORD wDlgCode; int nWidth, nHeight; int nXBorder = 0, nYBorder = 0; int cyCaption; LOGFONT LogFont; BOOL bVisible; DWORD dwStyle; #if 0 HDC hDC; HCURSOR hCursOld, hCursHourGlass; #endif dwBaseUnits = GetDialogFontUnits(hFont); wDialogWidth = LOWORD(dwBaseUnits); wDialogHeight = HIWORD(dwBaseUnits); dwStyle = dp->lStyle; /* force WS_POPUP style for top-level dialogs */ if (!(dwStyle & WS_CHILD)) dwStyle |= WS_POPUP; if (dwStyle & DS_SETFONT && dp->szFaceName != NULL && strlen(dp->szFaceName)) { memset((LPVOID)&LogFont,0,sizeof(LOGFONT)); /* dp->wPointSize is defined as the typographical point size,*/ /* it must be converted to the logical font size. */ #if 0 LogFont.lfHeight = -1 * MulDiv(dp->wPointSize, GetDeviceCaps (hDC, LOGPIXELSY), 72); #else /* dp->wPointSize is NOT a typographical point size. It is * the font height in dialog base units. It was misnamed. */ LogFont.lfHeight = (dp->wPointSize * wDialogHeight / 8); #endif LogFont.lfWeight = 700; strcpy(LogFont.lfFaceName,dp->szFaceName); hFont = CreateFontIndirect(&LogFont); } /* NOTE: * the coordinates here are from the resource file * we should not change them here, but in Windows.c. * this was converted from a straight muliply then * divide, to MulDiv, this will round up both the x,y * and the width. */ X = MulDiv(dp->x,wDialogWidth,4); Y = MulDiv(dp->y,wDialogHeight,8); nWidth = MulDiv(dp->cx,wDialogWidth,4); nHeight = MulDiv(dp->cy,wDialogHeight,8); /* final window size and coordinates should be adjusted by */ /* border and caption size depending on the style */ if (dwStyle & WS_DLGFRAME) { nXBorder = GetSystemMetrics(SM_CXDLGFRAME); nYBorder = GetSystemMetrics(SM_CYDLGFRAME); } else if (dwStyle & WS_BORDER) { nXBorder = GetSystemMetrics(SM_CXBORDER); nYBorder = GetSystemMetrics(SM_CYBORDER); } if (dwStyle & WS_THICKFRAME) { nXBorder = GetSystemMetrics(SM_CXFRAME); nYBorder = GetSystemMetrics(SM_CYFRAME); } X -= nXBorder; Y -= nYBorder; nWidth += 2*nXBorder; nHeight += 2*nYBorder; if ((dwStyle & WS_CAPTION) == WS_CAPTION) { cyCaption = GetSystemMetrics(SM_CYCAPTION); Y -= cyCaption; nHeight += cyCaption; } if (dwStyle & WS_VISIBLE) { bVisible = TRUE; dwStyle &= ~WS_VISIBLE; } else bVisible = FALSE; hDlg = CreateWindow( (!HIWORD(dp->szClassName) || !strlen(dp->szClassName))? TWIN_DIALOGCLASS:dp->szClassName, (HIWORD(dp->szCaption) && strlen(dp->szCaption))? dp->szCaption:" ", dwStyle, X,Y,nWidth,nHeight, hWnd, (HMENU)0, (hInst)?hInst: (hWnd?GetWindowInstance(hWnd):0), NULL ); if(hDlg == 0) { return 0; } /* * The following code was removed because it needlessly leaves * an hour glass on all of the applications windows while the dialog * box is up. Another call to SetCursor() was also commented out * at the end of this function. */ #if 0 hCursHourGlass = LoadCursor((HINSTANCE)0, IDC_WAIT); hCursOld = SetCursor(hCursHourGlass); #endif SetWF(hDlg,WFDIALOGWINDOW); SetWindowWord(hDlg,DWW_STATUS,0); SetWindowWord(hDlg,DWW_PARENT,hWnd); SetWindowLong(hDlg,DWL_DLGPROC,(LONG)lpFunc); SetWindowLong(hDlg,DWL_LPARAM,lParam); SetWindowWord(hDlg,DWW_DEFID,(WORD)0L); if (hFont) SendMessage(hDlg, WM_SETFONT, (WPARAM)hFont, (LPARAM)MAKELONG(FALSE,0)); for(i=0,cp=dp->controlinfo; i<(int)(dp->bNumberOfItems); i++,cp++) { hCtl = CreateWindow( cp->szClass?cp->szClass:"STATIC", ((!cp->szClass || !lstrcmpi(cp->szClass,"STATIC")) && ((cp->lStyle & 0xf) == SS_ICON))? NULL:cp->szText, cp->lStyle, (int)(cp->x*wDialogWidth)/4, (int)(cp->y*wDialogHeight)/8, (int)(cp->cx*wDialogWidth)/4, (int)(cp->cy*wDialogHeight)/8, hDlg, cp->wID, hWnd?GetWindowInstance(hWnd):hInst, NULL ); if(!hFirst && (cp->lStyle & WS_TABSTOP)) hFirst = hCtl; if ((!cp->szClass || !lstrcmpi(cp->szClass,"STATIC")) && ((cp->lStyle & 0xf) == SS_ICON)) { /* icon for the SS_ICON control comes from the same place, as dialog template, note, only send message if we actually have one */ if(cp->szText) SendMessage(hCtl, STM_SETICON, (WPARAM)LoadIcon(hInst,cp->szText), (LPARAM)0); } /* if a dialog class font was specified, and the control */ /* has not done a WM_SETFONT, then set this font. */ if(hFont) { ctlFont = (HFONT)SendMessage(hCtl, WM_GETFONT, 0, 0); if(ctlFont == 0) SendMessage( hCtl, WM_SETFONT, (WPARAM)hFont, (LPARAM)MAKELONG(FALSE,0) ); } } dwRet = SendMessage(hDlg,WM_INITDIALOG,(WPARAM)hFirst,lParam); for (hCtl = GetWindow(hDlg,GW_CHILD),hFirstButton = 0; hCtl; hCtl = GetWindow(hCtl,GW_HWNDNEXTSIB)) { wDlgCode = (WORD)SendMessage(hCtl,WM_GETDLGCODE,0,0L); if (wDlgCode & DLGC_DEFPUSHBUTTON) break; if ((wDlgCode & DLGC_UNDEFPUSHBUTTON) && (hFirstButton == 0)) hFirstButton = hCtl; } if (hCtl != 0) SetWindowWord(hDlg,DWW_DEFID,GetWindowID(hCtl)); else if (hFirstButton != 0) SetWindowWord(hDlg,DWW_DEFID,GetWindowID(hFirstButton)); else SetWindowWord(hDlg,DWW_DEFID,0); if (dwRet) { DlgSetFocus(hFirst); if ((WORD)SendMessage(hFirst,WM_GETDLGCODE,0,0L) & DLGC_HASSETSEL) Edit_SetSel(hFirst, 0, -1); } hCtl = GetFocus(); if(hCtl == 0) { hCtl = GetFirstDlgTabItem(hDlg); if(hCtl) { DlgSetFocus(hCtl); if ((WORD)SendMessage(hCtl,WM_GETDLGCODE,0,0L) & DLGC_HASSETSEL) Edit_SetSel(hCtl, 0, -1); } } if (bVisible) { ShowWindow(hDlg,SW_SHOWNORMAL); } if (bVisible) { UpdateWindow(hDlg); } #ifdef CURSORWARPING /* this will warp the cursor to the default button */ /* it only should be activated by a user preference */ /* and not automatically */ { HWND hWnd; int width ,height; RECT rcDlg; hWnd = hCtl; GetWindowRect(hWnd,&rcDlg); width = (rcDlg.left + rcDlg.right)/2; height = (rcDlg.bottom + rcDlg.top)/2; SetCursorPos(width,height); } #endif /* SetCursor(hCursOld); */ return hDlg; }