- Timestamp:
- Sep 16, 2009, 5:47:31 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/gui/kernel/qwidget_pm.cpp
r182 r183 777 777 778 778 /*! 779 \internal 780 781 Helper function to extract regions of all windows that overlap the given 782 hwnd subject to their z-order (excluding children of hwnd) from the given 783 hrgn. hps is the presentation space of hrgn. 784 */ 785 void qt_WinExcludeOverlappingWindows(HWND hwnd, HPS hps, HRGN hrgn) 786 { 787 HRGN vr = GpiCreateRegion(hps, 0, NULL); 788 RECTL r; 789 790 // enumerate all windows that are on top of this hwnd 791 HWND id = hwnd, deskId = QApplication::desktop()->winId(); 792 do { 793 HWND i = id; 794 while((i = WinQueryWindow( i, QW_PREV ))) { 795 if (WinIsWindowVisible(i)) { 796 WinQueryWindowRect(i, &r); 797 WinMapWindowPoints(i, hwnd, (PPOINTL) &r, 2); 798 GpiSetRegion(hps, vr, 1, &r); 799 GpiCombineRegion(hps, hrgn, hrgn, vr, CRGN_DIFF); 800 } 801 } 802 id = WinQueryWindow(id, QW_PARENT); 803 } while(id != deskId); 804 805 GpiDestroyRegion(hps, vr); 806 } 807 808 /*! 809 \internal 810 811 Helper function to scroll window contents. WinScrollWindow() is a bit 812 buggy and corrupts update regions sometimes (which leaves some outdated 813 areas unpainted after scrolling), so we reimplement its functionality in 814 this function. dy and clip->yBottom/yTop should be GPI coordinates, not Qt. 815 all clip coordinates are inclusive. 816 */ 817 void qt_WinScrollWindowWell(HWND hwnd, LONG dx, LONG dy, const PRECTL clip = NULL) 818 { 819 WinLockVisRegions(HWND_DESKTOP, TRUE); 820 821 HPS lhps = WinGetClipPS(hwnd, HWND_TOP, 822 PSF_LOCKWINDOWUPDATE | PSF_CLIPSIBLINGS); 823 if (clip) 824 GpiIntersectClipRectangle(lhps, clip); 825 826 // remember the update region and validate it. it will be shifted and 827 // invalidated again later 828 HRGN update = GpiCreateRegion(lhps, 0, NULL); 829 WinQueryUpdateRegion(hwnd, update); 830 WinValidateRegion(hwnd, update, TRUE); 831 832 POINTL ptls[4]; 833 RECTL &sr = *(PRECTL) &ptls[2]; 834 RECTL &tr = *(PRECTL) &ptls[0]; 835 836 // get the source rect for scrolling 837 GpiQueryClipBox(lhps, &sr); 838 sr.xRight++; sr.yTop++; // inclusive -> exclusive 839 840 // get the visible region ignoring areas covered by children 841 HRGN visible = GpiCreateRegion(lhps, 1, &sr); 842 qt_WinExcludeOverlappingWindows(hwnd, lhps, visible); 843 844 // scroll visible region rectangles separately to avoid the flicker 845 // that could be produced by scrolling parts of overlapping windows 846 RGNRECT ctl; 847 ctl.ircStart = 1; 848 ctl.crc = 0; 849 ctl.crcReturned = 0; 850 if (dx >= 0) { 851 if (dy >= 0) ctl.ulDirection = RECTDIR_RTLF_TOPBOT; 852 else ctl.ulDirection = RECTDIR_RTLF_BOTTOP; 853 } else { 854 if (dy >= 0) ctl.ulDirection = RECTDIR_LFRT_TOPBOT; 855 else ctl.ulDirection = RECTDIR_LFRT_BOTTOP; 856 } 857 GpiQueryRegionRects(lhps, visible, NULL, &ctl, NULL); 858 ctl.crc = ctl.crcReturned; 859 int rclcnt = ctl.crcReturned; 860 PRECTL rcls = new RECTL[rclcnt]; 861 GpiQueryRegionRects(lhps, visible, NULL, &ctl, rcls); 862 PRECTL r = rcls; 863 for (int i = 0; i < rclcnt; i++, r++) { 864 // source rect 865 sr = *r; 866 // target rect 867 tr.xLeft = sr.xLeft + dx; 868 tr.xRight = sr.xRight + dx; 869 tr.yBottom = sr.yBottom + dy; 870 tr.yTop = sr.yTop + dy; 871 GpiBitBlt(lhps, lhps, 3, ptls, ROP_SRCCOPY, BBO_IGNORE); 872 } 873 delete [] rcls; 874 875 // make the scrolled version of the visible region 876 HRGN scrolled = GpiCreateRegion(lhps, 0, NULL); 877 GpiCombineRegion(lhps, scrolled, visible, 0, CRGN_COPY); 878 // invalidate the initial update region 879 GpiCombineRegion(lhps, scrolled, scrolled, update, CRGN_DIFF); 880 // shift the region 881 POINTL dp = { dx, dy }; 882 GpiOffsetRegion(lhps, scrolled, &dp); 883 // substract scrolled from visible to get invalid areas 884 GpiCombineRegion(lhps, scrolled, visible, scrolled, CRGN_DIFF); 885 886 WinInvalidateRegion(hwnd, scrolled, TRUE); 887 888 GpiDestroyRegion(lhps, scrolled); 889 GpiDestroyRegion(lhps, visible); 890 GpiDestroyRegion(lhps, update); 891 892 WinReleasePS(lhps); 893 894 WinLockVisRegions(HWND_DESKTOP, FALSE); 895 896 WinUpdateWindow(hwnd); 897 } 898 899 /*! 779 900 * \internal 780 901 * For some unknown reason, PM sends WM_SAVEAPPLICATION to every window … … 2084 2205 void QWidgetPrivate::scroll_sys(int dx, int dy) 2085 2206 { 2086 // @todo implement 2207 Q_Q(QWidget); 2208 scrollChildren(dx, dy); 2209 2210 if (!paintOnScreen()) { 2211 scrollRect(q->rect(), dx, dy); 2212 } else { 2213 // @todo ask qt_WinScrollWindowWell() to erase background if 2214 // WA_OpaquePaintEvent is reset? 2215 //if (!q->testAttribute(Qt::WA_OpaquePaintEvent)) 2216 // ; 2217 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); 2218 qt_WinScrollWindowWell(q->internalWinId(), dx, -dy, NULL); 2219 } 2087 2220 } 2088 2221 2089 2222 void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r) 2090 2223 { 2091 // @todo implement 2224 Q_Q(QWidget); 2225 2226 if (!paintOnScreen()) { 2227 scrollRect(r, dx, dy); 2228 } else { 2229 int h = data.crect.height(); 2230 // flip y coordinate (all coordinates are inclusive) 2231 RECTL rcl = { r.left(), h - (r.bottom() + 1), r.right(), h - (r.top() + 1) }; 2232 2233 // @todo ask qt_WinScrollWindowWell() to erase background if 2234 // WA_OpaquePaintEvent is reset? 2235 //if (!q->testAttribute(Qt::WA_OpaquePaintEvent)) 2236 // ; 2237 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); 2238 qt_WinScrollWindowWell(q->internalWinId(), dx, -dy, &rcl); 2239 } 2092 2240 } 2093 2241
Note:
See TracChangeset
for help on using the changeset viewer.