Tk Source Code

Check-in [d741ac0a]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to tclconference@googlegroups.com
or submit via the online form by Sep 9.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Possibly fix bug [06f3922f8b]: Aqua generates more expose events than necessary.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | bug-06f3922f8b
Files: files | file ages | folders
SHA3-256:d741ac0ae2886bfe7b2ea81b501f4aef161c997eca6f34655e6b5663ba33ca3e
User & Date: culler 2019-04-16 20:43:14
Context
2019-04-16
20:43
Possibly fix bug [06f3922f8b]: Aqua generates more expose events than necessary. Leaf check-in: d741ac0a user: culler tags: bug-06f3922f8b
2019-04-15
20:48
Adjust conditional code to fix compiler warnings on macOS 10.9. check-in: e3a0be7d user: culler tags: core-8-6-branch
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to macosx/tkMacOSXDraw.c.

1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540

1541
1542
1543











1544
1545
1546
1547

1548
1549
1550
1551
1552
1553

1554
1555
1556
1557
1558
1559
1560
	dc.portBounds = clipBounds = CGContextGetClipBoundingBox(dc.context);
    } else if (win) {
	NSView *view = TkMacOSXDrawableView(macDraw);
	if (view) {

	    /*
	     * We can only draw into the view when the current CGContext is
	     * valid and belongs to the view.  Validity can only be guaranteed
	     * inside of a view's drawRect or setFrame methods.  The isDrawing
	     * attribute tells us whether we are being called from one of those
	     * methods.
	     *
	     * If the CGContext is not valid, or belongs to a different View,
	     * then we mark our view as needing display and return failure.
	     * It should get drawn in a later call to drawRect.

	     */

           if (view != [NSView focusView]) {











	       [view setNeedsDisplay:YES];
	       canDraw = false;
	       goto end;
	   }

	    dc.view = view;
	    dc.context = GET_CGCONTEXT;
	    dc.portBounds = NSRectToCGRect([view bounds]);
	    if (dc.clipRgn) {
		clipBounds = CGContextGetClipBoundingBox(dc.context);
	    }

	} else {
	    Tcl_Panic("TkMacOSXSetupDrawingContext(): "
		    "no NSView to draw into !");
	}
    } else {
	Tcl_Panic("TkMacOSXSetupDrawingContext(): "
		"no context to draw into !");







|




|
|
|
>


<
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
>






>







1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543

1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
	dc.portBounds = clipBounds = CGContextGetClipBoundingBox(dc.context);
    } else if (win) {
	NSView *view = TkMacOSXDrawableView(macDraw);
	if (view) {

	    /*
	     * We can only draw into the view when the current CGContext is
	     * valid.  Starting with OSX 10.14, validity can only be guaranteed
	     * inside of a view's drawRect or setFrame methods.  The isDrawing
	     * attribute tells us whether we are being called from one of those
	     * methods.
	     *
	     * If the CGContext is not valid then we mark our view as needing
	     * display in the bounding rectangle of the clipping region and
	     * return failure.  That rectangle should get drawn in a later call
	     * to drawRect.
	     */


	    if (![NSApp isDrawing]) {
		NSRect bounds = [view bounds];
		NSRect dirtyNS = bounds;
		CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,
					.ty = dirtyNS.size.height};
		if (dc.clipRgn) {
		    CGRect dirtyCG = NSRectToCGRect(dirtyNS);
		    HIShapeGetBounds(dc.clipRgn, &dirtyCG);
		    dirtyNS = NSRectToCGRect(CGRectApplyAffineTransform(dirtyCG, t));
		}

		[view setNeedsDisplayInRect:dirtyNS];
		canDraw = false;
		goto end;
	    }

	    dc.view = view;
	    dc.context = GET_CGCONTEXT;
	    dc.portBounds = NSRectToCGRect([view bounds]);
	    if (dc.clipRgn) {
		clipBounds = CGContextGetClipBoundingBox(dc.context);
	    }

	} else {
	    Tcl_Panic("TkMacOSXSetupDrawingContext(): "
		    "no NSView to draw into !");
	}
    } else {
	Tcl_Panic("TkMacOSXSetupDrawingContext(): "
		"no context to draw into !");

Changes to macosx/tkMacOSXWindowEvent.c.

406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
...
430
431
432
433
434
435
436







437
438
439
440
441
442
443
...
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
GenerateUpdates(
    HIShapeRef updateRgn,
    CGRect *updateBounds,
    TkWindow *winPtr)
{
    TkWindow *childPtr;
    XEvent event;
    CGRect bounds, damageBounds;
    HIShapeRef boundsRgn, damageRgn;

    TkMacOSXWinCGBounds(winPtr, &bounds);
    if (!CGRectIntersectsRect(bounds, *updateBounds)) {
	return 0;
    }
    if (!HIShapeIntersectsRect(updateRgn, &bounds)) {
	return 0;
    }
................................................................................
    if (HIShapeIsEmpty(damageRgn)) {
	CFRelease(damageRgn);
	CFRelease(boundsRgn);
	return 0;
    }
    HIShapeGetBounds(damageRgn, &damageBounds);








    CFRelease(damageRgn);
    CFRelease(boundsRgn);

    event.xany.serial = LastKnownRequestProcessed(Tk_Display(winPtr));
    event.xany.send_event = false;
    event.xany.window = Tk_WindowId(winPtr);
    event.xany.display = Tk_Display(winPtr);
................................................................................
#endif

    /*
     * Generate updates for the children of this window
     */

    for (childPtr = winPtr->childList; childPtr != NULL;
	    childPtr = childPtr->nextPtr) {
	if (!Tk_IsMapped(childPtr) || Tk_IsTopLevel(childPtr)) {
	    continue;
	}
	GenerateUpdates(updateRgn, updateBounds, childPtr);
    }

    /*
     * Generate updates for any contained windows
     */

    if (Tk_IsContainer(winPtr)) {
	childPtr = TkpGetOtherWindow(winPtr);
	if (childPtr != NULL && Tk_IsMapped(childPtr)) {
	    GenerateUpdates(updateRgn, updateBounds, childPtr);
	}

	/*
	 * TODO: Here we should handle out of process embedding.
	 */
    }

    return 1;







|

|







 







>
>
>
>
>
>
>







 







|
|
|
|
|







|
|
|
|







406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
...
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
...
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
GenerateUpdates(
    HIShapeRef updateRgn,
    CGRect *updateBounds,
    TkWindow *winPtr)
{
    TkWindow *childPtr;
    XEvent event;
    CGRect bounds, damageBounds, insetBounds;
    HIShapeRef boundsRgn, damageRgn;
    
    TkMacOSXWinCGBounds(winPtr, &bounds);
    if (!CGRectIntersectsRect(bounds, *updateBounds)) {
	return 0;
    }
    if (!HIShapeIntersectsRect(updateRgn, &bounds)) {
	return 0;
    }
................................................................................
    if (HIShapeIsEmpty(damageRgn)) {
	CFRelease(damageRgn);
	CFRelease(boundsRgn);
	return 0;
    }
    HIShapeGetBounds(damageRgn, &damageBounds);

    /*
     * Expand the damage rectangle a bit to avoid artifacts when
     * moving canvas items very quickly.
     */
    
    damageBounds = CGRectInset(damageBounds, -10, -10);
    
    CFRelease(damageRgn);
    CFRelease(boundsRgn);

    event.xany.serial = LastKnownRequestProcessed(Tk_Display(winPtr));
    event.xany.send_event = false;
    event.xany.window = Tk_WindowId(winPtr);
    event.xany.display = Tk_Display(winPtr);
................................................................................
#endif

    /*
     * Generate updates for the children of this window
     */

    for (childPtr = winPtr->childList; childPtr != NULL;
    	    childPtr = childPtr->nextPtr) {
    	if (!Tk_IsMapped(childPtr) || Tk_IsTopLevel(childPtr)) {
    	    continue;
    	}
    	GenerateUpdates(updateRgn, updateBounds, childPtr);
    }

    /*
     * Generate updates for any contained windows
     */

    if (Tk_IsContainer(winPtr)) {
        childPtr = TkpGetOtherWindow(winPtr);
        if (childPtr != NULL && Tk_IsMapped(childPtr)) {
            GenerateUpdates(updateRgn, updateBounds, childPtr);
        }

	/*
	 * TODO: Here we should handle out of process embedding.
	 */
    }

    return 1;