- Timestamp:
- Mar 12, 2006, 2:26:37 PM (19 years ago)
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/qwidget.h
r63 r64 599 599 friend class QDragManager; 600 600 #elif defined (Q_WS_PM) 601 enum ClipMode { ClipDefault, Unclipped, ClipAll, ClipSiblings }; 601 #if !defined (QT_PM_NO_WIDGETMASK) 602 void validateObstacles(); 603 LONG combineObstacles( HRGN hrgn, LONG op ); 604 #endif 605 enum ClipMode { ClipDefault, Unclipped, ClipAll }; 602 606 HPS getTargetPS( ClipMode m = ClipDefault ); 603 607 friend Q_EXPORT void bitBlt( QPaintDevice *, int, int, -
trunk/src/kernel/qapplication_pm.cpp
r61 r64 958 958 //@@TODO (dmik): are they all available in Warp3? 959 959 enum { 960 // sent to hwnd that has been entered by mouse.960 // sent to hwnd that has been entered to by a mouse pointer. 961 961 // FID_CLIENT also receives enter messages of its WC_FRAME. 962 962 // mp1 = hwnd that is entered, mp2 = hwnd that is left 963 963 WM_U_MOUSEENTER = 0x41E, 964 // sent to hwnd that has been left by mouse.964 // sent to hwnd that has been left by a mouse pointer. 965 965 // FID_CLIENT also receives leave messages of its WC_FRAME. 966 966 // mp1 = hwnd that is left, mp2 = hwnd that is entered … … 1437 1437 break; 1438 1438 case WM_ERASEBACKGROUND: // erase window background 1439 #if defined (QT_PM_NO_WIDGETMASK) 1439 1440 // flush WM_PAINT messages here to update window contents 1440 1441 // instantly while tracking the resize frame (normally these … … 1447 1448 // clients only, so we would have to do all calculations ourselves). 1448 1449 WinUpdateWindow( widget->winId() ); 1450 #else 1451 // We flush WM_PAINT messages in QETWidget::translateConfigEvent(). 1452 #endif 1449 1453 RETURN( FALSE ); 1450 1454 break; … … 1729 1733 QPoint cpos = QCursor::pos(); 1730 1734 dispatch = !geom.contains( cpos ); 1731 //@@TODO (dmik): later, window regions (WinQueryClipRegion())1732 // if ( !dispatch ) {1733 // HRGN hrgn = CreateRectRgn(0,0,0,0);1734 // if ( GetWindowRgn( curWin, hrgn ) != ERROR ) {1735 // QPoint lcpos = widget->mapFromGlobal( cpos );1736 // dispatch = !PtInRegion( hrgn, lcpos.x(), lcpos.y() );1737 // }1738 // DeleteObject(hrgn);1739 // }1740 1735 } 1741 1736 if ( dispatch ) { … … 3211 3206 bool QETWidget::translatePaintEvent( const QMSG & ) 3212 3207 { 3213 HRGN hrgn; 3214 hrgn = GpiCreateRegion( qt_display_ps(), 0, NULL ); 3208 HPS displayPS = qt_display_ps(); 3209 3210 #if !defined (QT_PM_NO_WIDGETMASK) 3211 // Since we don't use WS_CLIPSIBLINGS and WS_CLIPCHILDREN bits (see 3212 // qwidget_pm.cpp), we have to validate areas that intersect with our 3213 // children and siblings, taking their clip regions into account. 3214 validateObstacles(); 3215 #endif 3216 3217 HRGN hrgn = GpiCreateRegion( displayPS, 0, NULL ); 3215 3218 LONG rc = WinQueryUpdateRegion( winId(), hrgn ); 3216 if ( rc == RGN_ERROR || rc == RGN_NULL) {3217 GpiDestroyRegion( qt_display_ps(), hrgn );3219 if ( rc == RGN_ERROR ) { 3220 GpiDestroyRegion( displayPS, hrgn ); 3218 3221 hps = 0; 3219 3222 clearWState( WState_InPaintEvent ); … … 3232 3235 if ( !rcl.xRight || !rcl.yTop ) { 3233 3236 WinEndPaint( hps ); 3234 GpiDestroyRegion( qt_display_ps(), hrgn );3237 GpiDestroyRegion( displayPS, hrgn ); 3235 3238 hps = 0; 3236 3239 clearWState( WState_InPaintEvent ); … … 3238 3241 } 3239 3242 3243 #if !defined (QT_PM_NO_WIDGETMASK) 3244 if ( WinQueryClipRegion( winId(), 0 ) != QCRGN_NO_CLIP_REGION ) { 3245 // Correct the update region by intersecting it with the clip 3246 // region (PM doesn't do that itself). It is necessary 3247 // to have a correct QRegion in QPaintEvent. 3248 HRGN hcrgn = GpiCreateRegion( displayPS, 0, NULL ); 3249 WinQueryClipRegion( winId(), hcrgn ); 3250 GpiCombineRegion( displayPS, hrgn, hrgn, hcrgn, CRGN_AND ); 3251 GpiDestroyRegion( displayPS, hcrgn ); 3252 } 3253 #endif 3254 3240 3255 // flip y coordinate 3241 3256 rcl.yBottom = height() - (rcl.yBottom + rcl.yTop); … … 3291 3306 // that sends WM_SIZE). 3292 3307 QSize newSize( SHORT1FROMMP(qmsg.mp2), SHORT2FROMMP(qmsg.mp2) ); 3293 if ( qmsg.msg == WM_SIZE && size() != newSize ) 3308 if ( qmsg.msg == WM_SIZE && size() != newSize ) { 3294 3309 if ( !(fStyle & WS_MINIMIZED) ) 3295 3310 crect.setSize( newSize ); 3311 } 3296 3312 return TRUE; 3297 3313 } … … 3318 3334 } 3319 3335 if ( !(fStyle & WS_MINIMIZED) && oldSize != newSize) { 3336 #if !defined (QT_PM_NO_WIDGETMASK) 3337 // Spontaneous (external to Qt) WM_SIZE messages should occur only 3338 // on top-level widgets. If we get them for a non top-level widget, 3339 // the result will most likely be incorrect because widget masks will 3340 // not be properly processed (i.e. in the way it is done in 3341 // QWidget::internalSetGeometry() when the geometry is changed from 3342 // within Qt). So far, I see no need to support this (who will ever 3343 // need to move a non top-level window of a foreign process?). 3344 Q_ASSERT( isTopLevel() ); 3345 #endif 3320 3346 if ( isVisible() ) { 3321 3347 QResizeEvent e( newSize, oldSize ); … … 3323 3349 if ( !testWFlags( WStaticContents ) ) 3324 3350 repaint( !testWFlags(WResizeNoErase) ); 3351 #if !defined (QT_PM_NO_WIDGETMASK) 3352 // Flush WM_PAINT messages here to update window contents 3353 // instantly while tracking the resize frame (normally these 3354 // messages are delivered after resizing is stopped for some 3355 // time). It makes resizing a bit slower but gives a better look 3356 // (no invalid window contents can be seen during resize). 3357 // The alternative could be to erase the background only 3358 // (similarly to Win32), but we need to do it for every 3359 // non-toplevel window, which can be also time-consuming 3360 WinUpdateWindow( winId() ); 3361 #endif 3325 3362 } else { 3326 3363 QResizeEvent *e = new QResizeEvent( newSize, oldSize ); -
trunk/src/kernel/qwidget_pm.cpp
r63 r64 51 51 #include "qcursor.h" 52 52 #include <private/qapplication_p.h> 53 // @@TODO (dmik):remove?53 /// @todo (dmik) remove? 54 54 //#include <private/qinputcontext_p.h> 55 55 56 56 const QString qt_reg_winclass( int ); // defined in qapplication_pm.cpp 57 // @@TODO (dmik):later?57 /// @todo (dmik) later? 58 58 //void qt_olednd_unregister( QWidget* widget, QOleDropTarget *dst ); // dnd_win 59 59 //QOleDropTarget* qt_olednd_register( QWidget* widget ); … … 61 61 62 62 extern bool qt_nograb(); 63 //@@TODO (dmik): later (qregion_pm.cpp)64 //extern HRGN qt_win_bitmapToRegion(const QBitmap& bitmap);65 63 66 64 // defined in qapplication_pm.cpp … … 84 82 return QtOldSysMenuProc( hwnd, msg, mp1, mp2 ); 85 83 } 84 85 #if !defined (QT_PM_NO_WIDGETMASK) 86 87 //#define DEBUG_WIDGETMASK 88 89 /** 90 * \internal 91 * Extended version of WinQueryClipRegion(). If the given window has a 92 * clip region, the given region will receive a copy of the clip region 93 * clipped to the current window rectangle. If there is no clip region, 94 * the given region will contain only the window rectangle on return. 95 */ 96 static void qt_WinQueryClipRegionOrRect( HWND hwnd, HRGN hrgn ) 97 { 98 RECTL rcl; 99 WinQueryWindowRect( hwnd, &rcl ); 100 101 HPS hps = qt_display_ps(); 102 GpiSetRegion( hps, hrgn, 1, &rcl ); 103 if ( WinQueryClipRegion( hwnd, 0 ) != QCRGN_NO_CLIP_REGION ) { 104 HRGN hrgnTemp = GpiCreateRegion( hps, 0, NULL ); 105 WinQueryClipRegion( hwnd, hrgnTemp ); 106 GpiCombineRegion( hps, hrgn, hrgnTemp, hrgn, CRGN_AND ); 107 GpiDestroyRegion( hps, hrgnTemp ); 108 } 109 } 110 111 enum { 112 PWO_Children = 0x01, 113 PWO_Sibings = 0x02, 114 PWO_Ancestors = 0x04, 115 PWO_All = PWO_Children | PWO_Sibings | PWO_Ancestors, 116 }; 117 118 /** 119 * \internal 120 * Extended version of WinInvalidateRegion(): invalidates the specified region 121 * of the given window and regions of children from \a hwndFrom to \a hwndTo 122 * if they intersect with the invalid region. If either of child window 123 * handles is NULLHANDLE, children are not invalidated at all. Also, HWND_TOP 124 * can be used as \a hwndFrom, HWND_BOTTOM \a can be used as \a hwndTo. 125 */ 126 static BOOL qt_WinInvalidateRegionEx( HWND hwnd, HRGN hrgn, 127 HWND hwndFrom, HWND hwndTo ) 128 { 129 #if defined (DEBUG_WIDGETMASK) 130 QWidget *w = QWidget::find( hwnd ); 131 qDebug( "qt_WinInvalidateRegionEx: hwnd=%08lX (%s/%s) " 132 "hwndFrom=%08lX hwndTo=%08lX", 133 hwnd, w ? w->name() : 0, w ? w->className() : 0, hwndFrom, hwndTo ); 134 #endif 135 136 if ( hwndFrom == HWND_TOP ) 137 hwndFrom = WinQueryWindow( hwnd, QW_TOP ); 138 if ( hwndTo == HWND_BOTTOM ) 139 hwndTo = WinQueryWindow( hwnd, QW_BOTTOM ); 140 141 if ( hwndFrom == 0 || hwndTo == 0 ) 142 return WinInvalidateRegion( hwnd, hrgn, FALSE ); 143 144 if ( WinQueryWindow( hwndFrom, QW_PARENT ) != hwnd || 145 WinQueryWindow( hwndTo, QW_PARENT ) != hwnd ) 146 return FALSE; 147 148 HPS hps = qt_display_ps(); 149 150 SWP swp; 151 HWND child = hwndFrom; 152 HRGN hrgnChild = GpiCreateRegion( hps, 0, NULL ); 153 HRGN hrgnInv = GpiCreateRegion( hps, 0, NULL ); 154 GpiCombineRegion( hps, hrgnInv, hrgn, 0, CRGN_COPY ); 155 156 LONG cmplx = RGN_RECT; 157 158 while ( child ) { 159 WinQueryWindowPos( child, &swp ); 160 #if defined (DEBUG_WIDGETMASK) 161 w = QWidget::find( child ); 162 qDebug( " child=%08lX [fl=%08lX] (%s/%s)", child, swp.fl, 163 w ? w->name() : 0, w ? w->className() : 0 ); 164 #endif 165 // proceed only if not hidden 166 if ( swp.fl & SWP_SHOW ) { 167 // get sibling's bounds (clip region or rect) 168 qt_WinQueryClipRegionOrRect( child, hrgnChild ); 169 // translate the region to the parent's coordinate system 170 POINTL ptl = { swp.x, swp.y }; 171 GpiOffsetRegion( hps, hrgnChild, &ptl ); 172 // intersect the child's region with the invalid one 173 // and invalidate if not NULL 174 cmplx = GpiCombineRegion( hps, hrgnChild, hrgnChild, hrgnInv, 175 CRGN_AND ); 176 if ( cmplx != RGN_NULL ) { 177 POINTL ptl2 = { -swp.x, -swp.y }; 178 GpiOffsetRegion( hps, hrgnChild, &ptl2 ); 179 WinInvalidateRegion( child, hrgnChild, TRUE ); 180 GpiOffsetRegion( hps, hrgnChild, &ptl ); 181 // substract the invalidated area from the widget's region 182 // (no need to invalidate it any more) 183 cmplx = GpiCombineRegion( hps, hrgnInv, hrgnInv, hrgnChild, 184 CRGN_DIFF ); 185 #if defined (DEBUG_WIDGETMASK) 186 qDebug( " processed" ); 187 #endif 188 // finish if nothing left 189 if ( cmplx == RGN_NULL ) 190 break; 191 } 192 } 193 // iterate to the next window (below) 194 if ( child == hwndTo ) 195 break; 196 child = WinQueryWindow( child, QW_NEXT ); 197 } 198 199 BOOL ok = (cmplx == RGN_NULL) || (child == hwndTo); 200 201 if ( ok ) { 202 // invalidate what's left invalid after substracting children 203 WinInvalidateRegion( hwnd, hrgnInv, FALSE ); 204 } 205 206 GpiDestroyRegion( hps, hrgnInv ); 207 GpiDestroyRegion( hps, hrgnChild ); 208 209 return ok; 210 } 211 212 /** 213 * \internal 214 * Helper function to collect all relative windows intersecting with the 215 * given window and placed above it in z-order. 216 * 217 * \param hwnd window in question 218 * \param prcl rectangle (in window coordinates) to limit processing to 219 * (if null, the whole window rectange is used) 220 * \param hrgn region where to combine all obstacles 221 * (if 0, obstacles are directly validated instead of collecting) 222 * \param op region operation perfomed when combining obstacles (CRGN_*) 223 * \param flags flags defining the scope (PWO_* ORed together) 224 * 225 * \return complexity of the combined region (only when \a hrgn is not 0) 226 */ 227 static LONG qt_WinProcessWindowObstacles( HWND hwnd, PRECTL prcl, HRGN hrgn, 228 LONG op, LONG flags = PWO_All ) 229 { 230 Q_ASSERT( hwnd ); 231 232 HPS displayPS = qt_display_ps(); 233 234 #if defined (DEBUG_WIDGETMASK) 235 QWidget *w = QWidget::find( hwnd ); 236 qDebug( "qt_WinProcessWindowObstacles: hwnd=%08lX (%s/%s), prcl=%p " 237 "hrgn=%08lX, op=%ld flags=%08lX", 238 hwnd, w->name(), w->className(), prcl, hrgn, op, flags ); 239 #endif 240 241 SWP swpSelf; 242 WinQueryWindowPos( hwnd, &swpSelf ); 243 244 RECTL rclSelf = { 0, 0, swpSelf.cx, swpSelf.cy }; 245 if ( prcl ) 246 rclSelf = *prcl; 247 248 HRGN whrgn = GpiCreateRegion( displayPS, 0, NULL ); 249 250 LONG cmplx = RGN_NULL; 251 HWND relative; 252 SWP swp; 253 254 // first, go through all children (in z-order) 255 if ( flags & PWO_Children ) { 256 relative = WinQueryWindow( hwnd, QW_BOTTOM ); 257 if ( relative != NULLHANDLE ) { 258 for ( ; relative != HWND_TOP; relative = swp.hwndInsertBehind ) { 259 WinQueryWindowPos( relative, &swp ); 260 #if defined (DEBUG_WIDGETMASK) 261 w = QWidget::find( relative ); 262 qDebug( " child=%08lX [fl=%08lX] (%s/%s)", relative, swp.fl, 263 w ? w->name() : 0, w ? w->className() : 0 ); 264 #endif 265 // skip if hidden 266 if ( !(swp.fl & SWP_SHOW) ) 267 continue; 268 // rough check for intersection 269 if ( swp.x >= rclSelf.xRight || swp.y >= rclSelf.yTop || 270 swp.x + swp.cx <= rclSelf.xLeft || 271 swp.y + swp.cy <= rclSelf.yBottom ) 272 continue; 273 // get the bounds (clip region or rect) 274 qt_WinQueryClipRegionOrRect( relative, whrgn ); 275 // translate the region to this window's coordinate system 276 POINTL ptl = { swp.x, swp.y }; 277 GpiOffsetRegion( displayPS, whrgn, &ptl ); 278 // process the region 279 if ( hrgn != NULLHANDLE ) { 280 cmplx = GpiCombineRegion( displayPS, hrgn, hrgn, whrgn, op ); 281 } else { 282 WinValidateRegion( hwnd, whrgn, FALSE ); 283 } 284 #if defined (DEBUG_WIDGETMASK) 285 qDebug( " extracted" ); 286 #endif 287 } 288 } 289 } 290 291 HWND desktop = WinQueryDesktopWindow( 0, 0 ); 292 HWND parent = WinQueryWindow( hwnd, QW_PARENT ); 293 294 // next, go through all siblings placed above (in z-order), 295 // but only if they are not top-level windows (that cannot be 296 // non-rectangular and thus are always correctly clipped by the system) 297 if ( (flags & PWO_Sibings) && parent != desktop ) { 298 for ( relative = swpSelf.hwndInsertBehind; 299 relative != HWND_TOP; relative = swp.hwndInsertBehind ) { 300 WinQueryWindowPos( relative, &swp ); 301 #if defined (DEBUG_WIDGETMASK) 302 w = QWidget::find( relative ); 303 qDebug( " sibling=%08lX [fl=%08lX] (%s/%s)", relative, swp.fl, 304 w ? w->name() : 0, w ? w->className() : 0 ); 305 #endif 306 // skip if hidden 307 if ( !(swp.fl & SWP_SHOW) ) 308 continue; 309 // rough check for intersection 310 if ( swp.x >= swpSelf.x + rclSelf.xRight || 311 swp.y >= swpSelf.y + rclSelf.yTop || 312 swp.x + swp.cx <= swpSelf.x + rclSelf.xLeft || 313 swp.y + swp.cy <= swpSelf.y + rclSelf.yBottom ) 314 continue; 315 // get the bounds (clip region or rect) 316 qt_WinQueryClipRegionOrRect( relative, whrgn ); 317 // translate the region to this window's coordinate system 318 POINTL ptl = { swp.x - swpSelf.x, swp.y - swpSelf.y }; 319 GpiOffsetRegion( displayPS, whrgn, &ptl ); 320 // process the region 321 if ( hrgn != NULLHANDLE ) { 322 cmplx = GpiCombineRegion( displayPS, hrgn, hrgn, whrgn, op ); 323 } else { 324 WinValidateRegion( hwnd, whrgn, FALSE ); 325 } 326 #if defined (DEBUG_WIDGETMASK) 327 qDebug( " extracted" ); 328 #endif 329 } 330 } 331 332 // last, go through all siblings of our parent and its ancestors 333 // placed above (in z-order) 334 if ( flags & PWO_Ancestors ) { 335 POINTL delta = { swpSelf.x, swpSelf.y }; 336 while ( parent != desktop ) { 337 HWND grandParent = WinQueryWindow( parent, QW_PARENT ); 338 // no need to clip top-level windows (that cannot be non-rectangular 339 // and thus are always correctly clipped by the system) 340 if ( grandParent == desktop ) 341 break; 342 343 WinQueryWindowPos( parent, &swp ); 344 #if defined (DEBUG_WIDGETMASK) 345 w = QWidget::find( parent ); 346 qDebug( " parent=%08lX [fl=%08lX] (%s/%s)", parent, swp.fl, 347 w ? w->name() : 0, w ? w->className() : 0 ); 348 #endif 349 delta.x += swp.x; 350 delta.y += swp.y; 351 for ( relative = swp.hwndInsertBehind; 352 relative != HWND_TOP; relative = swp.hwndInsertBehind ) { 353 WinQueryWindowPos( relative, &swp ); 354 #if defined (DEBUG_WIDGETMASK) 355 w = QWidget::find( relative ); 356 qDebug( " ancestor=%08lX [fl=%08lX] (%s/%s)", relative, swp.fl, 357 w ? w->name() : 0, w ? w->className() : 0 ); 358 #endif 359 // skip if hidden 360 if ( !(swp.fl & SWP_SHOW) ) 361 continue; 362 // rough check for intersection 363 if ( swp.x - delta.x >= rclSelf.xRight || 364 swp.y - delta.y >= rclSelf.yTop || 365 swp.x - delta.x + swp.cx <= rclSelf.xLeft || 366 swp.y - delta.y + swp.cy <= rclSelf.yBottom ) 367 continue; 368 // get the bounds (clip region or rect) 369 qt_WinQueryClipRegionOrRect( relative, whrgn ); 370 // translate the region to this window's coordinate system 371 POINTL ptl = { swp.x - delta.x, swp.y - delta.y }; 372 GpiOffsetRegion( displayPS, whrgn, &ptl ); 373 // process the region 374 if ( hrgn != NULLHANDLE ) { 375 cmplx = GpiCombineRegion( displayPS, hrgn, hrgn, whrgn, op ); 376 } else { 377 WinValidateRegion( hwnd, whrgn, FALSE ); 378 } 379 #if defined (DEBUG_WIDGETMASK) 380 qDebug( " extracted" ); 381 #endif 382 } 383 parent = grandParent; 384 } 385 } 386 387 GpiDestroyRegion( displayPS, whrgn ); 388 389 return cmplx; 390 } 391 392 /** 393 * \internal 394 * Partial reimplementation of the WinSetWindowPos() API that obeys window clip 395 * regions. Currently supported flags are SWP_ZORDER, SWP_SHOW and SWP_HIDE. 396 * Other flags should not be used. Note that if any other flag is specified 397 * (alone or in addition to the supported ones), or if the given window is a 398 * top-level window, this function acts exactly like the original 399 * WinSetWindowPos() function. 400 */ 401 static BOOL qt_WinSetWindowPos( HWND hwnd, HWND hwndInsertBehind, 402 LONG x, LONG y, LONG cx, LONG cy, 403 ULONG fl ) 404 { 405 #if defined (DEBUG_WIDGETMASK) 406 QWidget *w = QWidget::find( hwnd ); 407 qDebug( "qt_WinSetWindowPos: hwnd=%08lX (%s/%s) fl=%08lX", 408 hwnd, w ? w->name() : 0, w ? w->className() : 0, fl ); 409 #endif 410 411 Q_ASSERT( (fl & ~(SWP_ZORDER | SWP_SHOW | SWP_HIDE)) == 0 ); 412 413 HWND desktop = WinQueryDesktopWindow( 0, 0 ); 414 if ( (fl & ~(SWP_ZORDER | SWP_SHOW | SWP_HIDE)) != 0 || 415 hwnd == desktop || WinQueryWindow( hwnd, QW_PARENT ) == desktop ) { 416 return WinSetWindowPos( hwnd, hwndInsertBehind, x, y, cx, cy, fl ); 417 } 418 419 SWP swpOld; 420 WinQueryWindowPos( hwnd, &swpOld ); 421 422 // do some checks 423 if ( (fl & SWP_ZORDER) && swpOld.hwndInsertBehind == hwndInsertBehind ) 424 fl &= ~SWP_ZORDER; 425 if ( (fl & SWP_SHOW) && (swpOld.fl & SWP_SHOW) ) 426 fl &= ~SWP_SHOW; 427 if ( (fl & SWP_HIDE) && (swpOld.fl & SWP_HIDE) ) 428 fl &= ~SWP_HIDE; 429 if ( (fl & (SWP_SHOW | SWP_HIDE)) == (SWP_SHOW | SWP_HIDE) ) 430 fl &= ~SWP_HIDE; 431 432 BOOL rc = WinSetWindowPos( hwnd, hwndInsertBehind, x, y, cx, cy, 433 fl | SWP_NOREDRAW ); 434 if ( rc == FALSE || (fl & SWP_NOREDRAW) ) 435 return rc; 436 437 SWP swpNew; 438 WinQueryWindowPos( hwnd, &swpNew ); 439 440 if ( swpOld.hwndInsertBehind == swpNew.hwndInsertBehind ) 441 fl &= ~SWP_ZORDER; 442 443 if ( (fl & (SWP_ZORDER | SWP_SHOW | SWP_HIDE)) == 0 ) 444 return rc; 445 446 HPS hps = qt_display_ps(); 447 HWND hwndParent = WinQueryWindow( hwnd, QW_PARENT ); 448 449 // get window bounds 450 HRGN hrgnSelf = GpiCreateRegion( hps, 0, NULL ); 451 qt_WinQueryClipRegionOrRect( hwnd, hrgnSelf ); 452 453 if ( fl & SWP_SHOW ) { 454 WinInvalidateRegion( hwnd, hrgnSelf, TRUE ); 455 } else if ( fl & SWP_HIDE ) { 456 // translate the region to the parent coordinate system 457 POINTL ptl = { swpNew.x, swpNew.y }; 458 GpiOffsetRegion( hps, hrgnSelf, &ptl ); 459 // invalidate the parent and children below this window 460 qt_WinInvalidateRegionEx( hwndParent, hrgnSelf, 461 WinQueryWindow( hwnd, QW_NEXT ), HWND_BOTTOM ); 462 } else { // fl & SWP_ZORDER 463 // below we assume that WinSetWindowPos() returns FALSE if 464 // an incorrect (unrelated) hwndInsertBehind is passed when SWP_ZORDER 465 // is set 466 467 // first, detect whether we are moving up or down 468 BOOL up; 469 HWND hwndFrom, hwndTo; 470 if ( swpOld.hwndInsertBehind == HWND_TOP ) { 471 up = FALSE; 472 hwndFrom = WinQueryWindow( hwndParent, QW_TOP ); 473 hwndTo = swpNew.hwndInsertBehind; 474 } else { 475 up = TRUE; 476 for ( HWND hwndAbove = hwnd; 477 (hwndAbove = WinQueryWindow( hwndAbove, QW_PREV )) != 0; ) { 478 if ( hwndAbove == swpOld.hwndInsertBehind ) { 479 up = FALSE; 480 break; 481 } 482 } 483 if ( up ) { 484 hwndFrom = swpOld.hwndInsertBehind; 485 hwndTo = WinQueryWindow( hwnd, QW_NEXT ); 486 } else { 487 hwndFrom = WinQueryWindow( swpOld.hwndInsertBehind, QW_NEXT ); 488 hwndTo = swpNew.hwndInsertBehind; 489 } 490 } 491 #if defined (DEBUG_WIDGETMASK) 492 qDebug( " moving up? %ld", up ); 493 w = QWidget::find( hwndFrom ); 494 qDebug( " hwndFrom=%08lX (%s/%s)", hwndFrom, 495 w ? w->name() : 0, w ? w->className() : 0 ); 496 w = QWidget::find( hwndTo ); 497 qDebug( " hwndTo=%08lX (%s/%s)", hwndTo, 498 w ? w->name() : 0, w ? w->className() : 0 ); 499 #endif 500 501 SWP swp; 502 HWND sibling = hwndFrom; 503 HRGN hrgn = GpiCreateRegion( hps, 0, NULL ); 504 HRGN hrgnUpd = GpiCreateRegion( hps, 0, NULL ); 505 506 if ( up ) { 507 // go upwards in z-order 508 while ( 1 ) { 509 WinQueryWindowPos( sibling, &swp ); 510 #if defined (DEBUG_WIDGETMASK) 511 w = QWidget::find( sibling ); 512 qDebug( " sibling=%08lX [fl=%08lX] (%s/%s)", sibling, swp.fl, 513 w ? w->name() : 0, w ? w->className() : 0 ); 514 #endif 515 // proceed only if not hidden 516 if ( swp.fl & SWP_SHOW ) { 517 // get sibling's bounds (clip region or rect) 518 qt_WinQueryClipRegionOrRect( sibling, hrgn ); 519 // translate the region to this window's coordinate system 520 POINTL ptl = { swp.x - swpNew.x, swp.y - swpNew.y }; 521 GpiOffsetRegion( hps, hrgn, &ptl ); 522 // add to the region of siblings we're moving on top of 523 GpiCombineRegion( hps, hrgnUpd, hrgnUpd, hrgn, CRGN_OR ); 524 #if defined (DEBUG_WIDGETMASK) 525 qDebug( " processed" ); 526 #endif 527 } 528 // iterate to the prev window (above) 529 if ( sibling == hwndTo ) 530 break; 531 sibling = swp.hwndInsertBehind; 532 } 533 // intersect the resulting region with the widget region and 534 // invalidate 535 GpiCombineRegion( hps, hrgnUpd, hrgnSelf, hrgnUpd, CRGN_AND ); 536 WinInvalidateRegion( hwnd, hrgnUpd, TRUE ); 537 } else { 538 // go downwards in reverse z-order 539 POINTL ptl = { 0, 0 }; 540 while ( 1 ) { 541 WinQueryWindowPos( sibling, &swp ); 542 #if defined (DEBUG_WIDGETMASK) 543 w = QWidget::find( sibling ); 544 qDebug( " sibling=%08lX [fl=%08lX] (%s/%s)", sibling, swp.fl, 545 w ? w->name() : 0, w ? w->className() : 0 ); 546 #endif 547 // proceed only if not hidden 548 if ( swp.fl & SWP_SHOW ) { 549 // get sibling's bounds (clip region or rect) 550 qt_WinQueryClipRegionOrRect( sibling, hrgn ); 551 // undo the previous translation and translate this window's 552 // region to the siblings's coordinate system 553 ptl.x += swpNew.x - swp.x; 554 ptl.y += swpNew.y - swp.y; 555 GpiOffsetRegion( hps, hrgnSelf, &ptl ); 556 // intersect the sibling's region with the translated one 557 // and invalidate the sibling 558 GpiCombineRegion( hps, hrgnUpd, hrgnSelf, hrgn, CRGN_AND ); 559 WinInvalidateRegion( sibling, hrgnUpd, TRUE ); 560 // substract the invalidated area from the widget's region 561 // (no need to invalidate it any more) 562 GpiCombineRegion( hps, hrgnSelf, hrgnSelf, hrgnUpd, CRGN_DIFF ); 563 // prepare the translation from the sibling's 564 // coordinates back to this window's coordinates 565 ptl.x = swp.x - swpNew.x; 566 ptl.y = swp.y - swpNew.y; 567 #if defined (DEBUG_WIDGETMASK) 568 qDebug( " processed" ); 569 #endif 570 } 571 // iterate to the next window (below) 572 if ( sibling == hwndTo ) 573 break; 574 sibling = WinQueryWindow( sibling, QW_NEXT ); 575 } 576 } 577 578 GpiDestroyRegion( hps, hrgnUpd ); 579 GpiDestroyRegion( hps, hrgn ); 580 } 581 582 GpiDestroyRegion( hps, hrgnSelf ); 583 584 return TRUE; 585 } 586 587 #endif 86 588 87 589 static void removeSysMenuAccels( HWND frame ) … … 216 718 } 217 719 if ( !desktop ) { 720 #if !defined (QT_PM_NO_WIDGETMASK) 721 // We don't use WS_CLIPSIBLINGS and WS_CLIPCHILDREN, because when these 722 // styles are set and a child/sibling window has a non-NULL clip region, 723 // PM still continues to exclude the entire child's rectangle from the 724 // parent window's update region, ignoring its clip region. As a result, 725 // areas outside the clip region are left unpainted. Instead, we correct 726 // the update region of the window ourselves, on every WM_PAINT event. 727 #else 218 728 /// @todo (dmik) 219 729 // this is temporarily commented out because QSplitter sets … … 223 733 /* if ( !testWFlags( WPaintUnclipped ) ) */ 224 734 style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN; 735 #endif 225 736 // for all top-level windows except popups we create a WC_FRAME 226 737 // as a parent and owner. … … 325 836 ); 326 837 #endif 838 // note that we place the client on top (HWND_TOP) to exclude other 839 // frame controls from being analysed in qt_WinProcessWindowObstacles 327 840 id = WinCreateWindow( 328 841 fId, pszClassName, title, style, 0, 0, 0, 0, 329 fId, HWND_ BOTTOM, FID_CLIENT, NULL, NULL842 fId, HWND_TOP, FID_CLIENT, NULL, NULL 330 843 ); 331 844 } else { … … 905 1418 RECTL rcl = { x, y, x + w, y + h }; 906 1419 1420 #if !defined (QT_PM_NO_WIDGETMASK) 1421 WinInvalidateRect( winId(), &rcl, FALSE ); 1422 #else 907 1423 // WinInvalidateRect() has such a "feature" that children are not 908 1424 // actually extracted from the window's update region when it has … … 931 1447 w = (QWidget*)object; 932 1448 if ( !w->isTopLevel() && w->isShown() ) { 933 //@@TODO (dmik): later: substract the region of the child window934 // (WinQueryClipRegion()) instead of the window rectangle.935 1449 const QRect &r = w->crect; 936 1450 rcl.xLeft = r.left(); … … 949 1463 WinInvalidateRect( winId(), &rcl, FALSE ); 950 1464 } 1465 #endif 951 1466 } 952 1467 } … … 1116 1631 deactivateWidgetCleanup(); 1117 1632 HWND id = winFId(); 1633 1634 #if defined (QT_PM_NO_WIDGETMASK) 1118 1635 WinShowWindow( id, FALSE ); 1636 #else 1637 qt_WinSetWindowPos( id, 0, 0, 0, 0, 0, SWP_HIDE ); 1638 #endif 1639 1119 1640 if ( isTopLevel() ) 1120 1641 WinSetWindowPos( id, 0, 0, 0, 0, 0, SWP_DEACTIVATE ); … … 1137 1658 void QWidget::showWindow() 1138 1659 { 1660 #if defined (QT_PM_NO_WIDGETMASK) 1139 1661 WinShowWindow( winFId(), TRUE ); 1662 #else 1663 qt_WinSetWindowPos( winFId(), 0, 0, 0, 0, 0, SWP_SHOW ); 1664 #endif 1665 1140 1666 ULONG fl = 0; 1141 1667 if ( isTopLevel() ) { … … 1178 1704 if ( fl ) 1179 1705 WinSetWindowPos( winFId(), 0, 0, 0, 0, 0, fl ); 1180 1181 //@@TODO (dmik): remove? in OS/2 WinShowWindow() does not influence1182 // any other state flags of the window (such as maximized/minimized, active),1183 // so, the window is always shown at its current state (i.e. if its state was1184 // not changed while it was hidden it will be restored to that state upon1185 // unhiding; if the state was changed, it will be restored to that new state).1186 // int sm = SW_SHOWNORMAL;1187 // if ( isTopLevel() ) {1188 // if (testWState(WState_Minimized))1189 // sm = SW_SHOWMINIMIZED;1190 // else if (testWState(WState_Maximized))1191 // sm = SW_SHOWMAXIMIZED;1192 // }1193 // if (testWFlags(WStyle_Tool) || isPopup())1194 // sm = SW_SHOWNOACTIVATE;1195 //1196 // ShowWindow( winId(), sm );1197 // UpdateWindow( winId() );1198 1706 } 1199 1707 … … 1205 1713 //@@TODO (dmik): remove? SWP_ZORDER doesn't cause activation in OS/2... 1206 1714 // uint f = ( isPopup() || testWFlags(WStyle_Tool) ) ? SWP_NOACTIVATE : 0; 1715 1716 #if defined (QT_PM_NO_WIDGETMASK) 1207 1717 WinSetWindowPos( winFId(), HWND_TOP, 0, 0, 0, 0, SWP_ZORDER ); 1718 #else 1719 qt_WinSetWindowPos( winFId(), HWND_TOP, 0, 0, 0, 0, SWP_ZORDER ); 1720 #endif 1208 1721 } 1209 1722 … … 1215 1728 //@@TODO (dmik): remove? SWP_ZORDER doesn't cause activation in OS/2... 1216 1729 // uint f = ( isPopup() || testWFlags(WStyle_Tool) ) ? SWP_NOACTIVATE : 0; 1730 1731 #if defined (QT_PM_NO_WIDGETMASK) 1217 1732 WinSetWindowPos( winFId(), HWND_BOTTOM, 0, 0, 0, 0, SWP_ZORDER ); 1733 #else 1734 qt_WinSetWindowPos( winFId(), HWND_BOTTOM, 0, 0, 0, 0, SWP_ZORDER ); 1735 #endif 1218 1736 } 1219 1737 … … 1227 1745 p->childObjects->insert( p->childObjects->findRef(w), this ); 1228 1746 } 1747 #if defined (QT_PM_NO_WIDGETMASK) 1229 1748 WinSetWindowPos( winId(), w->winId(), 0, 0, 0, 0, SWP_ZORDER ); 1749 #else 1750 qt_WinSetWindowPos( winId(), w->winId(), 0, 0, 0, 0, SWP_ZORDER ); 1751 #endif 1230 1752 } 1231 1753 … … 1253 1775 if ( !isTopLevel() ) 1254 1776 isMove = (crect.topLeft() != QPoint( x, y )); 1255 if ( isMove == FALSE && oldSize.width()==w && oldSize.height()==h ) 1777 bool isResize = w != oldSize.width() || h != oldSize.height(); 1778 if ( isMove == FALSE && isResize == FALSE ) 1256 1779 return; 1257 1780 clearWState(WState_Maximized); … … 1264 1787 setWState( WState_ConfigPending ); 1265 1788 if ( isTopLevel() ) { 1266 //@@TODO (dmik): remove, no need to check for extra... 1267 // QRect fr( frameGeometry() ); 1268 // if ( extra ) { 1269 // fr.setLeft( fr.left() + x - crect.left() ); 1270 // fr.setTop( fr.top() + y - crect.top() ); 1271 // fr.setRight( fr.right() + ( x + w - 1 ) - crect.right() ); 1272 // fr.setBottom( fr.bottom() + ( y + h - 1 ) - crect.bottom() ); 1273 // } 1274 // MoveWindow( winId(), fr.x(), fr.y(), fr.width(), fr.height(), TRUE ); 1275 // crect.setRect( x, y, w, h ); 1276 1277 //@@TODO (dmik): optimize: use extra->topextra directly (after updating fstrut 1789 /// @todo (dmik) optimize: use extra->topextra directly (after updating fstrut 1278 1790 // if necessary) instead of calling frameGeometry() 1279 1791 QRect fr( frameGeometry() ); … … 1287 1799 WinSetWindowPos( winFId(), 0, fx, fy, fw, fh, SWP_MOVE | SWP_SIZE ); 1288 1800 } else { 1801 #if defined (QT_PM_NO_WIDGETMASK) 1289 1802 // flip y coordinate 1290 1803 int fy = parentWidget()->height() - (y + h); 1291 1804 crect.setRect( x, y, w, h ); 1292 1805 WinSetWindowPos( winId(), 0, x, fy, w, h, SWP_MOVE | SWP_SIZE ); 1806 #else 1807 // When WS_CLIPCHILDREN and WS_CLIPSIBLINGS are not used, 1808 // WinSetWindowPos() does not correctly update involved windows. 1809 // The fix is to do it ourselves, taking clip regions into account. 1810 1811 QWidget *parent = parentWidget(); 1812 const int ph = parent->height(); 1813 // flip y coordinate 1814 int fy = ph - (y + h); 1815 // set new and old rectangles 1816 const RECTL rcls [2] = { 1817 // new (y flipped, relative to parent) 1818 { x, fy, x + w, fy + h }, 1819 // old (y flipped, relative to parent) 1820 { crect.left(), ph - (crect.bottom() + 1), 1821 crect.right() + 1, ph - crect.top() } 1822 }; 1823 const RECTL &rclNew = rcls [0]; 1824 const RECTL &rclOld = rcls [1]; 1825 // delta to shift coordinate space from parent to this widget 1826 POINTL ptlToSelf = { -x, -fy }; 1827 // update crect and move the widget w/o redrawing 1828 crect.setRect( x, y, w, h ); 1829 WinSetWindowPos( winId(), 0, x, fy, w, h, 1830 SWP_MOVE | SWP_SIZE | SWP_NOREDRAW ); 1831 // use parent PS for blitting 1832 HPS hps = WinGetPS( parent->winId() ); 1833 // get old and new clip regions (relative to parent) 1834 HRGN hrgnOld = GpiCreateRegion( hps, 1, &rclOld ); 1835 HRGN hrgnNew = GpiCreateRegion( hps, 1, &rclNew ); 1836 if ( WinQueryClipRegion( winId(), 0 ) != QCRGN_NO_CLIP_REGION ) { 1837 HRGN hrgnTemp = GpiCreateRegion( hps, 0, NULL ); 1838 // old (clipped to the old rect) 1839 WinQueryClipRegion( winId(), hrgnTemp ); 1840 GpiOffsetRegion( hps, hrgnTemp, (PPOINTL) &rclOld ); 1841 GpiCombineRegion( hps, hrgnOld, hrgnTemp, hrgnOld, CRGN_AND ); 1842 // new (clipped to the new rect) 1843 WinQueryClipRegion( winId(), hrgnTemp ); 1844 if ( oldSize.height() != h ) { 1845 // keep the clip region top-left aligned by adding the 1846 // height delta (new size - old size) 1847 POINTL ptl = { 0, h - oldSize.height() }; 1848 GpiOffsetRegion( hps, hrgnTemp, &ptl ); 1849 WinSetClipRegion( winId(), hrgnTemp ); 1850 } 1851 GpiOffsetRegion( hps, hrgnTemp, (PPOINTL) &rclNew ); 1852 GpiCombineRegion( hps, hrgnNew, hrgnTemp, hrgnNew, CRGN_AND ); 1853 GpiDestroyRegion( hps, hrgnTemp ); 1854 } 1855 // the rest is useful only when the widget is visible 1856 if ( isVisible() ) { 1857 // create affected region (old + new, relative to widget) 1858 HRGN hrgnAff = GpiCreateRegion( hps, 0, NULL ); 1859 GpiCombineRegion( hps, hrgnAff, hrgnOld, hrgnNew, CRGN_OR ); 1860 GpiOffsetRegion( hps, hrgnAff, &ptlToSelf ); 1861 // get bounding rectangle of affected region 1862 RECTL rclAff; 1863 GpiQueryRegionBox( hps, hrgnAff, &rclAff ); 1864 // get region of obstacles limited to affected rectangle 1865 HRGN hrgnObst = GpiCreateRegion( hps, 0, NULL ); 1866 qt_WinProcessWindowObstacles( winId(), &rclAff, hrgnObst, CRGN_OR, 1867 PWO_Sibings | PWO_Ancestors ); 1868 // shift region of obstacles and affected region back to 1869 // parent coords 1870 GpiOffsetRegion( hps, hrgnObst, (PPOINTL) &rclNew ); 1871 GpiOffsetRegion( hps, hrgnAff, (PPOINTL) &rclNew ); 1872 // get parent bounds (clip region or rect) 1873 HRGN hrgnUpd = GpiCreateRegion( hps, 0, NULL ); 1874 qt_WinQueryClipRegionOrRect( parent->winId(), hrgnUpd ); 1875 // add parts of old region beyond parent bounds to 1876 // region of obstacles 1877 GpiCombineRegion( hps, hrgnOld, hrgnOld, hrgnUpd, CRGN_DIFF ); 1878 GpiCombineRegion( hps, hrgnObst, hrgnObst, hrgnOld, CRGN_OR ); 1879 // substract region of obstacles from affected region 1880 GpiCombineRegion( hps, hrgnAff, hrgnAff, hrgnObst, CRGN_DIFF ); 1881 // remember it as parent update region (need later) 1882 GpiCombineRegion( hps, hrgnUpd, hrgnAff, 0, CRGN_COPY ); 1883 // copy region of obstacles to delta region and shift it by 1884 // delta (note: movement is considered to be top-left aligned) 1885 HRGN hrgnDelta = GpiCreateRegion( hps, 0, NULL ); 1886 GpiCombineRegion( hps, hrgnDelta, hrgnObst, 0, CRGN_COPY ); 1887 POINTL ptlDelta = { rclNew.xLeft - rclOld.xLeft, 1888 rclNew.yTop - rclOld.yTop }; 1889 GpiOffsetRegion( hps, hrgnDelta, &ptlDelta ); 1890 // substract region of obstacles from delta region to get 1891 // pure delta 1892 GpiCombineRegion( hps, hrgnDelta, hrgnDelta, hrgnObst, CRGN_DIFF ); 1893 // calculate minimal rectangle to blit (top-left aligned) 1894 int minw = QMIN( oldSize.width(), w ); 1895 int minh = QMIN( oldSize.height(), h ); 1896 POINTL blitPtls [4] = { 1897 // target (new) 1898 { rclNew.xLeft, rclNew.yTop - minh }, 1899 { rclNew.xLeft + minw, rclNew.yTop }, 1900 // source (old) 1901 { rclOld.xLeft, rclOld.yTop - minh }, 1902 }; 1903 // proceed with blitting only if target and source rects differ 1904 if ( blitPtls[0].x != blitPtls[2].x || 1905 blitPtls[0].y != blitPtls[2].y ) 1906 { 1907 // Substract delta region from affected region (to minimize 1908 // flicker) 1909 GpiCombineRegion( hps, hrgnAff, hrgnAff, hrgnDelta, CRGN_DIFF ); 1910 // set affected region to parent PS 1911 GpiSetClipRegion( hps, hrgnAff, NULL ); 1912 // blit minimal rectangle 1913 GpiBitBlt( hps, hps, 3, blitPtls, ROP_SRCCOPY, BBO_IGNORE ); 1914 GpiSetClipRegion( hps, 0, NULL ); 1915 } 1916 // substract new widget region from the parent update region 1917 // and invalidate it (with underlying children) 1918 GpiCombineRegion( hps, hrgnUpd, hrgnUpd, hrgnNew, CRGN_DIFF ); 1919 qt_WinInvalidateRegionEx( parent->winId(), hrgnUpd, 1920 WinQueryWindow( winId(), QW_NEXT ), 1921 HWND_BOTTOM ); 1922 // intersect pure delta region with new region 1923 // (to detect areas clipped off to minimize flicker when blitting) 1924 GpiCombineRegion( hps, hrgnDelta, hrgnDelta, hrgnNew, CRGN_AND ); 1925 // substract blitted rectangle from new region 1926 GpiSetRegion( hps, hrgnAff, 1, (PRECTL) &blitPtls ); 1927 GpiCombineRegion( hps, hrgnNew, hrgnNew, hrgnAff, CRGN_DIFF ); 1928 // combine the rest with intersected delta region 1929 GpiCombineRegion( hps, hrgnNew, hrgnNew, hrgnDelta, CRGN_OR ); 1930 // shift the result back to widget coords and invalidate 1931 GpiOffsetRegion( hps, hrgnNew, &ptlToSelf ); 1932 WinInvalidateRegion( winId(), hrgnNew, TRUE ); 1933 // free resources 1934 GpiDestroyRegion( hps, hrgnDelta ); 1935 GpiDestroyRegion( hps, hrgnUpd ); 1936 GpiDestroyRegion( hps, hrgnObst ); 1937 GpiDestroyRegion( hps, hrgnAff ); 1938 } 1939 // free resources 1940 GpiDestroyRegion( hps, hrgnOld ); 1941 GpiDestroyRegion( hps, hrgnNew ); 1942 WinReleasePS( hps ); 1943 #endif 1293 1944 } 1294 1945 clearWState( WState_ConfigPending ); 1295 1946 } 1296 1947 1297 bool isResize = w != oldSize.width() || h != oldSize.height();1298 1948 if ( isVisible() ) { 1299 1949 if ( isMove && pos() != oldPos ) { … … 1456 2106 newRegion = rgn.handle( height() ); 1457 2107 } 1458 GpiSetClipRegion( lhps, newRegion, &oldRegion);2108 GpiSetClipRegion( lhps, newRegion, NULL ); 1459 2109 1460 2110 QPoint offset = backgroundOffset(); … … 1475 2125 } 1476 2126 2127 #if defined (QT_PM_NO_WIDGETMASK) 1477 2128 1478 2129 // helper function to extract regions of all windows that overlap the given … … 1490 2141 while( (i = WinQueryWindow( i, QW_PREV )) ) { 1491 2142 if ( WinIsWindowShowing( i ) ) { 1492 //@@TODO (dmik): probably we should use WinQueryClipRegion() here to1493 // handle non-rectangular windows properly1494 2143 WinQueryWindowRect( i, &r ); 1495 2144 WinMapWindowPoints( i, hwnd, (PPOINTL) &r, 2 ); … … 1593 2242 } 1594 2243 2244 #else 2245 2246 /** 2247 * \internal 2248 * Helper to scroll window contents. 2249 * All coordinates are GPI, not Qt. 2250 */ 2251 static void scrollWindow( HWND hwnd, int w, int h, 2252 int dx, int dy, const PRECTL clip = NULL ) 2253 { 2254 POINTL ptlDelta = { dx, dy }; 2255 2256 POINTL ptls[4]; 2257 RECTL &rclSrc = *(PRECTL) &ptls[2]; 2258 RECTL &rclDst = *(PRECTL) &ptls[0]; 2259 2260 if ( clip ) { 2261 rclSrc = *clip; 2262 } else { 2263 rclSrc.xLeft = rclSrc.yBottom = 0; 2264 rclSrc.xRight = w; 2265 rclSrc.yTop = h; 2266 } 2267 rclDst = rclSrc; 2268 rclDst.xLeft += dx; 2269 rclDst.xRight += dx; 2270 rclDst.yBottom += dy; 2271 rclDst.yTop += dy; 2272 2273 if ( !clip ) { 2274 // move all child widgets silently 2275 SWP swp; 2276 HWND child = WinQueryWindow( hwnd, QW_BOTTOM ); 2277 if ( child != NULLHANDLE ) { 2278 for ( ; child != HWND_TOP; child = swp.hwndInsertBehind ) { 2279 WinQueryWindowPos( child, &swp ); 2280 swp.x += dx; 2281 swp.y += dy; 2282 WinSetWindowPos( child, 0, swp.x, swp.y, 0, 0, 2283 SWP_MOVE | SWP_NOADJUST | SWP_NOREDRAW ); 2284 // WinSetWindowPos() doesn't send WM_MOVE to windows w/o 2285 // CS_MOVENOTIFY, but having this style for non-toplevel 2286 // widgets is unwanted, so we send them WM_MOVE manually 2287 // to let their geometry to be properly updated by 2288 // QETWidget::translateConfigEvent(). 2289 WinSendMsg( child, WM_MOVE, 0, 0 ); 2290 } 2291 } 2292 } 2293 2294 WinLockVisRegions( HWND_DESKTOP, TRUE ); 2295 2296 HPS hps = WinGetPS( hwnd ); 2297 2298 // get widget bounds (clip region or rect) 2299 HRGN hrgnClip = GpiCreateRegion( hps, 0, NULL ); 2300 qt_WinQueryClipRegionOrRect( hwnd, hrgnClip ); 2301 // compose a region uncovered after scrolling 2302 HRGN hrgnUpd = GpiCreateRegion( hps, 0, NULL ); 2303 GpiCombineRegion( hps, hrgnUpd, hrgnClip, 0, CRGN_COPY ); 2304 GpiOffsetRegion( hps, hrgnUpd, &ptlDelta ); 2305 GpiCombineRegion( hps, hrgnUpd, hrgnClip, hrgnUpd, CRGN_DIFF ); 2306 2307 if ( clip ) { 2308 // intersect it with the given clip rect 2309 HRGN hrgn = GpiCreateRegion( hps, 1, clip ); 2310 GpiCombineRegion( hps, hrgnUpd, hrgnClip, hrgnUpd, CRGN_AND ); 2311 GpiDestroyRegion( hps, hrgn ); 2312 } 2313 2314 int pwoFlags = PWO_Ancestors | PWO_Sibings; 2315 if ( clip ) 2316 pwoFlags |= PWO_Children; 2317 2318 // get the region of obstacles 2319 HRGN hrgnObst = GpiCreateRegion( hps, 0, NULL ); 2320 qt_WinProcessWindowObstacles( hwnd, &rclSrc, hrgnObst, CRGN_OR, pwoFlags ); 2321 // create the delta region of obstacles 2322 HRGN hrgnDelta = GpiCreateRegion( hps, 0, NULL ); 2323 GpiCombineRegion( hps, hrgnDelta, hrgnObst, 0, CRGN_COPY ); 2324 GpiOffsetRegion( hps, hrgnDelta, &ptlDelta ); 2325 // substract the region of obstaces fro the delta region to get pure delta 2326 GpiCombineRegion( hps, hrgnDelta, hrgnDelta, hrgnObst, CRGN_DIFF ); 2327 // substract obstacles the clip region 2328 GpiCombineRegion( hps, hrgnClip, hrgnClip, hrgnObst, CRGN_DIFF ); 2329 // substract pure delta from the clip region (to reduce flicker) 2330 GpiCombineRegion( hps, hrgnClip, hrgnClip, hrgnDelta, CRGN_DIFF ); 2331 2332 // scroll the area 2333 GpiSetClipRegion( hps, hrgnClip, NULL ); 2334 GpiBitBlt( hps, hps, 3, ptls, ROP_SRCCOPY, BBO_IGNORE ); 2335 GpiSetClipRegion( hps, 0, NULL ); 2336 2337 // invalidate the delta region (clipped off when blitting) 2338 WinInvalidateRegion( hwnd, hrgnDelta, clip == NULL ); 2339 2340 // invalidate the region uncovered after scrolling 2341 WinInvalidateRegion( hwnd, hrgnUpd, clip == NULL ); 2342 2343 GpiDestroyRegion( hps, hrgnDelta ); 2344 GpiDestroyRegion( hps, hrgnObst ); 2345 GpiDestroyRegion( hps, hrgnUpd ); 2346 GpiDestroyRegion( hps, hrgnClip ); 2347 WinReleasePS( hps ); 2348 2349 WinLockVisRegions( HWND_DESKTOP, FALSE ); 2350 2351 WinUpdateWindow( hwnd ); 2352 } 2353 2354 #endif 2355 1595 2356 void QWidget::scroll( int dx, int dy ) 1596 2357 { 1597 2358 if ( testWState( WState_BlockUpdates ) && !children() ) 1598 2359 return; 2360 2361 #if defined (QT_PM_NO_WIDGETMASK) 1599 2362 1600 2363 // move non-toplevel children … … 1628 2391 1629 2392 qt_WinScrollWindowWell( winId(), dx, -dy, NULL ); 2393 2394 #else 2395 2396 scrollWindow( winId(), width(), height(), dx, -dy, NULL ); 2397 2398 #endif 1630 2399 } 1631 2400 … … 1635 2404 return; 1636 2405 2406 #if defined (QT_PM_NO_WIDGETMASK) 2407 1637 2408 int h = crect.height(); 1638 2409 // flip y coordinate (all coordinates are inclusive) 1639 2410 RECTL rcl = { r.left(), h - (r.bottom() + 1), r.right(), h - (r.top() + 1) }; 1640 2411 qt_WinScrollWindowWell( winId(), dx, -dy, &rcl ); 2412 2413 #else 2414 2415 int h = crect.height(); 2416 // flip y coordinate 2417 RECTL rcl = { r.left(), h - (r.bottom() + 1), 2418 r.right() + 1, h - r.top() }; 2419 scrollWindow( winId(), width(), height(), dx, -dy, &rcl ); 2420 2421 #endif 1641 2422 } 1642 2423 … … 1727 2508 { 1728 2509 return 0; 1729 // @@TODO (dmik):later2510 /// @todo (dmik) later 1730 2511 // return ( extra && extra->dropTarget ); 1731 2512 } … … 1733 2514 void QWidget::setAcceptDrops( bool on ) 1734 2515 { 1735 // @@TODO (dmik):later2516 /// @todo (dmik) later 1736 2517 // // Enablement is defined by extra->dropTarget != 0. 1737 2518 // … … 1752 2533 } 1753 2534 2535 #if !defined (QT_PM_NO_WIDGETMASK) 2536 2537 // helper for QWidget::setMask() 2538 static void setClipRegion( HWND hwnd, int x, int y, int w, int h, HRGN hrgn, 2539 HWND parent ) 2540 { 2541 if ( !WinIsWindowVisible( hwnd ) ) { 2542 // if the window is hidden, no need to invalidate anything 2543 WinSetClipRegion( hwnd, hrgn ); 2544 return; 2545 } 2546 2547 HPS hps = qt_display_ps(); 2548 const RECTL rcl = { 0, 0, w, h }; 2549 2550 // get the old bounds (clip region or rect) 2551 HRGN hrgnOld = GpiCreateRegion( hps, 0, NULL ); 2552 qt_WinQueryClipRegionOrRect( hwnd, hrgnOld ); 2553 // set the new clip region 2554 WinSetClipRegion( hwnd, hrgn ); 2555 2556 HRGN hrgnUpd; 2557 if ( hrgn != 0 ) { 2558 hrgnUpd = GpiCreateRegion( hps, 0, NULL ); 2559 // substract the new clip region from the old one 2560 GpiCombineRegion( hps, hrgnUpd, hrgnOld, hrgn, CRGN_DIFF ); 2561 // move the result to the parent coordinate space 2562 POINTL ptl = { x, y }; 2563 GpiOffsetRegion( hps, hrgnUpd, &ptl ); 2564 // invalidate areas in parent uncovered by the new clip region 2565 qt_WinInvalidateRegionEx( parent, hrgnUpd, 2566 WinQueryWindow( hwnd, QW_NEXT ), HWND_BOTTOM ); 2567 } else { 2568 // the new region is being set to NULL, which means to widget bounds 2569 // (no need to substract new from old, because it will produce RGN_NULL) 2570 hrgnUpd = GpiCreateRegion( hps, 1, &rcl ); 2571 hrgn = hrgnUpd; 2572 } 2573 // substract the old clip region from the new one 2574 GpiCombineRegion( hps, hrgnUpd, hrgn, hrgnOld, CRGN_DIFF ); 2575 // invalidate areas in hwnd uncovered by the new clip region 2576 WinInvalidateRegion( hwnd, hrgnUpd, TRUE ); 2577 2578 GpiDestroyRegion( hps, hrgnUpd ); 2579 GpiDestroyRegion( hps, hrgnOld ); 2580 } 2581 2582 #endif 2583 2584 /*! 2585 \overload 2586 2587 Causes only the parts of the widget which overlap \a region to be 2588 visible. If the region includes pixels outside the rect() of the 2589 widget, window system controls in that area may or may not be 2590 visible, depending on the platform. 2591 2592 Note that this effect can be slow if the region is particularly 2593 complex. 2594 2595 Note that on OS/2, masks for top-level widgets are not currently 2596 supported, so setting a mask on such a widget has no effect. 2597 2598 \sa setMask(), clearMask() 2599 */ 2600 1754 2601 void QWidget::setMask( const QRegion ®ion ) 1755 2602 { 1756 qWarning( "QWidget::setMask() is not yet implemented on OS/2" ); 1757 //@@TODO (dmik): later (don't forget to offset region, see qregion_pm.cpp) 1758 // // Since SetWindowRegion takes ownership, and we need to translate, 1759 // // we take a copy. 1760 // HRGN wr = CreateRectRgn(0,0,1,1); 1761 // CombineRgn(wr, region.handle(), 0, RGN_COPY); 1762 // 1763 // int fleft = 0, ftop = 0; 1764 // if (isTopLevel()) { 1765 // ftop = topData()->ftop; 1766 // fleft = topData()->fleft; 1767 // } 1768 // OffsetRgn(wr, fleft, ftop ); 1769 // SetWindowRgn( winId(), wr, TRUE ); 1770 } 2603 #if !defined (QT_PM_NO_WIDGETMASK) 2604 if (isTopLevel()) { 2605 #if defined (QT_CHECK_STATE) 2606 qWarning( "QWidget::setMask() for top-level widgets " 2607 "is not implemented on OS/2" ); 2608 #endif 2609 return; 2610 } 2611 setClipRegion( winId(), x(), parentWidget()->height() - (y() + height()), 2612 width(), height(), region.handle( height() ), 2613 parentWidget()->winId() ); 2614 #else 2615 Q_UNUSED( region ); 2616 #endif 2617 } 2618 2619 /*! 2620 Causes only the pixels of the widget for which \a bitmap has a 2621 corresponding 1 bit to be visible. If the region includes pixels 2622 outside the rect() of the widget, window system controls in that 2623 area may or may not be visible, depending on the platform. 2624 2625 Note that this effect can be slow if the region is particularly 2626 complex. 2627 2628 Note that on OS/2, masks for top-level widgets are not currently 2629 supported, so setting a mask on such a widget has no effect. 2630 2631 See \c examples/tux for an example of masking for transparency. 2632 2633 \sa setMask(), clearMask() 2634 */ 1771 2635 1772 2636 void QWidget::setMask( const QBitmap &bitmap ) 1773 2637 { 1774 qWarning( "QWidget::setMask() is not yet implemented on OS/2" ); 1775 //@@TODO (dmik): later 1776 // HRGN wr = qt_win_bitmapToRegion(bitmap); 1777 // 1778 // int fleft = 0, ftop = 0; 1779 // if (isTopLevel()) { 1780 // ftop = topData()->ftop; 1781 // fleft = topData()->fleft; 1782 // } 1783 // OffsetRgn(wr, fleft, ftop ); 1784 // SetWindowRgn( winId(), wr, TRUE ); 2638 #if !defined (QT_PM_NO_WIDGETMASK) 2639 if (isTopLevel()) { 2640 #if defined (QT_CHECK_STATE) 2641 qWarning( "QWidget::setMask() for top-level widgets " 2642 "is not implemented on OS/2" ); 2643 #endif 2644 return; 2645 } 2646 QRegion rgn = QRegion( bitmap ); 2647 setClipRegion( winId(), x(), parentWidget()->height() - (y() + height()), 2648 width(), height(), rgn.handle( height() ), 2649 parentWidget()->winId() ); 2650 #else 2651 Q_UNUSED( bitmap ); 2652 #endif 1785 2653 } 1786 2654 1787 2655 void QWidget::clearMask() 1788 2656 { 1789 qWarning( "QWidget::clearMask() is not yet implemented on OS/2" ); 1790 //@@TODO (dmik): later 1791 // SetWindowRgn( winId(), 0, TRUE ); 2657 #if !defined (QT_PM_NO_WIDGETMASK) 2658 if (isTopLevel()) 2659 return; 2660 setClipRegion( winId(), x(), parentWidget()->height() - (y() + height()), 2661 width(), height(), 0, 2662 parentWidget()->winId() ); 2663 #endif 1792 2664 } 1793 2665 … … 1846 2718 } 1847 2719 1848 /* 1849 \internal1850 Returns the frame wihdow handle if this widget is a top-level widget and1851 has the standard WC_FRAME as its parent/owner (where it is FID_CLIENT).1852 If the widget does not have the standard frame or it is not top-level, this1853 function simply retuns the winId() value.1854 */2720 /** 2721 * \internal 2722 * Returns the frame wihdow handle if this widget is a top-level widget and 2723 * has the standard WC_FRAME as its parent/owner (where it is FID_CLIENT). 2724 * If the widget does not have the standard frame or it is not top-level, this 2725 * function simply retuns the winId() value. 2726 */ 1855 2727 WId QWidget::winFId() 1856 2728 { … … 1863 2735 } 1864 2736 2737 #if !defined (QT_PM_NO_WIDGETMASK) 2738 2739 /*! 2740 * \internal 2741 * 2742 * Validates areas of this widget covered by (intersected with) its children 2743 * and sibling widgets. 2744 * 2745 * Clip regions of all relative widgets (set by WinSetClipRegion()) are taken 2746 * into account. 2747 */ 2748 void QWidget::validateObstacles() 2749 { 2750 RECTL updateRcl; 2751 if ( WinQueryUpdateRect( winId(), &updateRcl ) ) { 2752 // the update rectangle may be empty 2753 if ( updateRcl.xLeft != updateRcl.xRight && 2754 updateRcl.yBottom != updateRcl.yTop ) { 2755 qt_WinProcessWindowObstacles( winId(), &updateRcl, 0, 0 ); 2756 } 2757 } 2758 } 2759 2760 /*! 2761 * \internal 2762 * 2763 * Combines areas of this widget covered by (intersected with) its children 2764 * and sibling widgets to a region \a hrgn using an operation \a op 2765 * (see GpiCombineRegion()). Returns the complexity of the combined region. 2766 * 2767 * Clip regions of all relative widgets (set by WinSetClipRegion()) are taken 2768 * into account. 2769 */ 2770 /// @todo (dmik) is it really necessary somewhere? 2771 LONG QWidget::combineObstacles( HRGN hrgn, LONG op ) 2772 { 2773 return qt_WinProcessWindowObstacles( winId(), NULL, hrgn, op ); 2774 } 2775 2776 #endif // !defined (QT_PM_NO_WIDGETMASK) 2777 1865 2778 /*! 1866 2779 * \internal 1867 2780 * 1868 2781 * Obtains a presentaiton space to draw on this widget, set up according 1869 * to widget flags. If \a m != Unclipped and WPaintUnclipped flag is not 1870 * set, a clip region is set on the returned PS according to \a m. 2782 * mode \a m and to widget flags. 1871 2783 * 1872 2784 * The returned handle must be freed using WinReleasePS() after usage. … … 1878 2790 if ( isDesktop() ) { 1879 2791 widgetPS = WinGetScreenPS( HWND_DESKTOP ); 2792 return widgetPS; 1880 2793 } else { 1881 2794 if ( m == Unclipped || (m == ClipDefault && 1882 2795 testWFlags( WPaintUnclipped )) ) { 1883 2796 widgetPS = WinGetClipPS( winId(), 0, PSF_PARENTCLIP ); 2797 return widgetPS; 1884 2798 } else { 1885 2799 widgetPS = WinGetPS( winId() ); … … 1887 2801 } 1888 2802 2803 #if !defined (QT_PM_NO_WIDGETMASK) 2804 RECTL rcl = { 0, 0, crect.width(), crect.height() }; 2805 HRGN hrgn = GpiCreateRegion( widgetPS, 1, &rcl ); 2806 qt_WinProcessWindowObstacles( winId(), NULL, hrgn, CRGN_DIFF ); 2807 HRGN hrgnOld = 0; 2808 GpiSetClipRegion( widgetPS, hrgn, &hrgnOld ); 2809 Q_ASSERT( !hrgnOld ); 2810 if ( hrgnOld ) 2811 GpiDestroyRegion( widgetPS, hrgnOld ); 2812 #endif 2813 1889 2814 return widgetPS; 1890 2815 }
Note:
See TracChangeset
for help on using the changeset viewer.