Tk Source Code

Check-in [a8d82409]
Login

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

Overview
Comment:Fix for shimmering of buttons embedded when scrolled in text and canvas widgets; improvements in scrolling smoothness in text widget. Thanks to Marc Culler for patches.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: a8d82409cd315302189fd747f5e9b6f62a285f3a
User & Date: kevin_walzer 2014-08-16 00:52:12
Context
2014-08-18
20:21
merge mark check-in: d9afbc28 user: dgp tags: trunk
2014-08-16
00:52
Fix for shimmering of buttons embedded when scrolled in text and canvas widgets; improvements in scrolling smoothness in text widget. Thanks to Marc Culler for patches. check-in: a8d82409 user: kevin_walzer tags: trunk
2014-08-14
02:41
Allow Tk to post popup menus when Tk app is not frontmost check-in: 51268e7b user: kevin_walzer tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tkTextDisp.c.

3966
3967
3968
3969
3970
3971
3972









3973
3974
3975
3976
3977
3978
3979
    /*
     * First recompute what's supposed to be displayed.
     */

    UpdateDisplayInfo(textPtr);
    dInfoPtr->dLinesInvalidated = 0;










    /*
     * See if it's possible to bring some parts of the screen up-to-date by
     * scrolling (copying from other parts of the screen). We have to be
     * particularly careful with the top and bottom lines of the display,
     * since these may only be partially visible and therefore not helpful for
     * some scrolling purposes.
     */







>
>
>
>
>
>
>
>
>







3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
    /*
     * First recompute what's supposed to be displayed.
     */

    UpdateDisplayInfo(textPtr);
    dInfoPtr->dLinesInvalidated = 0;

#ifdef MAC_OSX_TK
    /*
     * Make sure that unmapped subwindows really have been unmapped.
     * If the unmap request is pending as an idle request, the window
     * can get redrawn on top of the widget.
     */
    while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
#endif

    /*
     * See if it's possible to bring some parts of the screen up-to-date by
     * scrolling (copying from other parts of the screen). We have to be
     * particularly careful with the top and bottom lines of the display,
     * since these may only be partially visible and therefore not helpful for
     * some scrolling purposes.
     */
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045

	/*
	 * Reduce the height of the area being copied if necessary to avoid
	 * overwriting the border area.
	 */

	if ((y + height) > dInfoPtr->maxY) {
	    height = dInfoPtr->maxY -y;
	}
	oldY = dlPtr->oldY;
	if (y < dInfoPtr->y) {
	    /*
	     * Adjust if the area being copied is going to overwrite the top
	     * border of the window (so the top line is only half onscreen).
	     */







|







4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054

	/*
	 * Reduce the height of the area being copied if necessary to avoid
	 * overwriting the border area.
	 */

	if ((y + height) > dInfoPtr->maxY) {
	    height = dInfoPtr->maxY - y;
	}
	oldY = dlPtr->oldY;
	if (y < dInfoPtr->y) {
	    /*
	     * Adjust if the area being copied is going to overwrite the top
	     * border of the window (so the top line is only half onscreen).
	     */

Changes to macosx/tkMacOSXButton.c.

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25


















































26
27
28
29
30
31
32
33
34
35
/*
 * tkMacOSXButton.c --
 *
 *	This file implements the Macintosh specific portion of the
 *	button widgets.
 *
 * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
 * Copyright 2001-2009, Apple Inc.
 * Copyright (c) 2006-2009 Daniel A. Steffen <[email protected]>

 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkButton.h"
#include "tkMacOSXFont.h"
#include "tkMacOSXDebug.h"

/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_BUTTON
#endif
*/



















































typedef struct MacButton {
    TkButton info;
    NSButton *button;
    NSImage *image, *selectImage, *tristateImage;
#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
    int fix;
#endif
} MacButton;

#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS









>
















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/*
 * tkMacOSXButton.c --
 *
 *	This file implements the Macintosh specific portion of the
 *	button widgets.
 *
 * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
 * Copyright 2001-2009, Apple Inc.
 * Copyright (c) 2006-2009 Daniel A. Steffen <[email protected]>
 * Copyright 2014 Marc Culler.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkButton.h"
#include "tkMacOSXFont.h"
#include "tkMacOSXDebug.h"

/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_BUTTON
#endif
*/

static NSRect TkMacOSXGetButtonFrame(TkButton *butPtr);

/*
 * A subclass of NSButton with sanity checking:
 * NSButtons created by Tk will have their tag set to a pointer to the TkButton
 * which manages the NSButton.  This allows a TkNSButton to be aware of the
 * state of its Tk parent.  This subclass overrides the drawRect method
 * so that it will not draw itself unless the NSButton frame matches
 * the frame which was installed by DisplayButton, and the TkButton is
 * mapped.  Also, it will not draw anything if the widget is completely
 * outside of its container.
 */

@interface TkNSButton: NSButton

@end

@implementation TkNSButton

    - (void)drawRect:(NSRect)dirtyRect
    {
	NSInteger tag = [self tag];
	if ( tag != -1) {
	    TkButton *butPtr = (TkButton *)tag;
	    MacDrawable* macWin = (MacDrawable *)butPtr;
	    NSRect Tkframe = TkMacOSXGetButtonFrame(butPtr);
	    Tk_Window tkwin = butPtr->tkwin;
	    /* Do not draw if the widget is misplaced or unmapped. */
	    if ( NSIsEmptyRect(Tkframe) || 
		 ! macWin->winPtr->flags & TK_MAPPED ||
		 ! NSEqualRects(Tkframe, [self frame]) 
		 ) {
		return;
	    }
	     /* Do not draw if the widget is completely outside of its parent, or within 20 pixels of the lower border; this prevents buttons from being drawn on peer widgets as scrolling occurs. */
	    if (tkwin) {
		int parent_height = Tk_Height(Tk_Parent(tkwin));
		int widget_height = Tk_Height(tkwin);
		int y = Tk_Y(tkwin);
		if ( y > parent_height - 20 || y + widget_height < 0 ) {
		    return;
		}
	    }
	[super drawRect:dirtyRect];
    }
 }

@end


typedef struct MacButton {
    TkButton info;
    TkNSButton *button;
    NSImage *image, *selectImage, *tristateImage;
#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
    int fix;
#endif
} MacButton;

#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
182
183
184
185
186
187
188







































189
190
191
192
193
194
195
	break;
    }
}

/*
 *----------------------------------------------------------------------
 *







































 * TkpComputeButtonGeometry --
 *
 *	After changes in a button's text or bitmap, this procedure
 *	recomputes the button's geometry and passes this information
 *	along to the geometry manager for the window.
 *
 * Results:







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
	break;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkpShiftButton --
 *
 *	Moves the frame of an NSButton (or TkNSButton) and in case the tag is
 *     set, also adjusts the xOff and yOff of the controlling TkButton's
 *     MacDrawable.  This is used to avoid jitter when scrolling.
 *
 * Results:
 *	None
 *
 * Side effects:
 *	Moves the NSbutton after adjusting the associated MacDrawable.
 *
 *----------------------------------------------------------------------
 */
void
TkpShiftButton(
    NSButton *button,
    NSPoint delta )
    {
	NSPoint origin = [button frame].origin;
	NSInteger tag = [button tag];
	if ( tag != -1) {
	    TkButton* butPtr = (TkButton *)tag;
	    TkWindow *winPtr = (TkWindow *) (butPtr->tkwin);
	    if (winPtr) {
		MacDrawable *macWin =  (MacDrawable *) winPtr->window;
		macWin->xOff += delta.x;
		macWin->yOff += delta.y;
	    }
	}
        origin.x += delta.x;
	origin.y -= delta.y;
	[button setFrameOrigin:origin];
    }


/*
 *----------------------------------------------------------------------
 *
 * TkpComputeButtonGeometry --
 *
 *	After changes in a button's text or bitmap, this procedure
 *	recomputes the button's geometry and passes this information
 *	along to the geometry manager for the window.
 *
 * Results:
214
215
216
217
218
219
220
221

222
223
224
225
226
227
228
	}
	ComputeUnixButtonGeometry(butPtr);
	break;
    case TYPE_BUTTON:
    case TYPE_CHECK_BUTTON:
    case TYPE_RADIO_BUTTON:
	if (!macButtonPtr->button) {
	    NSButton *button = [[NSButton alloc] initWithFrame:NSZeroRect];

	    macButtonPtr->button = TkMacOSXMakeUncollectable(button);
	}
	ComputeNativeButtonGeometry(butPtr);
	break;
    }
}








|
>







304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
	}
	ComputeUnixButtonGeometry(butPtr);
	break;
    case TYPE_BUTTON:
    case TYPE_CHECK_BUTTON:
    case TYPE_RADIO_BUTTON:
	if (!macButtonPtr->button) {
	    TkNSButton *button = [[TkNSButton alloc] initWithFrame:NSZeroRect];
	    [button setTag:(NSInteger)butPtr];
	    macButtonPtr->button = TkMacOSXMakeUncollectable(button);
	}
	ComputeNativeButtonGeometry(butPtr);
	break;
    }
}

262
263
264
265
266
267
268














































269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
#pragma mark -
#pragma mark Native Buttons:


/*
 *----------------------------------------------------------------------
 *














































 * DisplayNativeButton --
 *
 *	This procedure is invoked to display a button widget. It is
 *	normally invoked as an idle handler.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Commands are output to X to display the button in its
 *	current mode. The REDRAW_PENDING flag is cleared.
 *
 *----------------------------------------------------------------------
 */

static void
DisplayNativeButton(
    TkButton *butPtr)
{
    MacButton *macButtonPtr = (MacButton *) butPtr;
    NSButton *button = macButtonPtr->button;
    Tk_Window tkwin = butPtr->tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;
    MacDrawable *macWin =  (MacDrawable *) winPtr->window;
    TkMacOSXDrawingContext dc;
    NSView *view = TkMacOSXDrawableView(macWin);
    CGFloat viewHeight = [view bounds].size.height;
    CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




















|







353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
#pragma mark -
#pragma mark Native Buttons:


/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXGetButtonFrame --
 *
 *	Computes a frame for an NSButton that will correspond to where
 *	Tk thinks the button is located.
 *
 * Results:
 *	Returns an NSRect describing a frame for an NSButton.
 *
 * Side effects:
 *	None
 *
 *----------------------------------------------------------------------
 */
NSRect TkMacOSXGetButtonFrame(
     TkButton *butPtr)
{
    MacButton *macButtonPtr = (MacButton *) butPtr;
    Tk_Window tkwin = butPtr->tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;
    if (tkwin) {
	MacDrawable *macWin =  (MacDrawable *) winPtr->window;
	NSView *view = TkMacOSXDrawableView(macWin);
	CGFloat viewHeight = [view bounds].size.height;
	NSRect frame = NSMakeRect(macWin->xOff, macWin->yOff,
				  Tk_Width(tkwin), Tk_Height(tkwin));

#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
	if (tkMacOSXUseCompatibilityMetrics) {
	    BoundsFix boundsFix = boundsFixes[macButtonPtr->fix];
	    frame = NSOffsetRect(frame, boundsFix.offsetX, boundsFix.offsetY);
	    frame.size.height -= boundsFix.shrinkH + NATIVE_BUTTON_EXTRA_H;
	    frame = NSInsetRect(frame, boundsFix.inset + NATIVE_BUTTON_INSET,
		boundsFix.inset + NATIVE_BUTTON_INSET);
	}
#endif

	frame.origin.y = viewHeight - (frame.origin.y + frame.size.height);
	return frame;
    } else {
	return NSZeroRect;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * DisplayNativeButton --
 *
 *	This procedure is invoked to display a button widget. It is
 *	normally invoked as an idle handler.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Commands are output to X to display the button in its
 *	current mode. The REDRAW_PENDING flag is cleared.
 *
 *----------------------------------------------------------------------
 */

static void
DisplayNativeButton(
    TkButton *butPtr)
{
    MacButton *macButtonPtr = (MacButton *) butPtr;
    TkNSButton *button = macButtonPtr->button;
    Tk_Window tkwin = butPtr->tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;
    MacDrawable *macWin =  (MacDrawable *) winPtr->window;
    TkMacOSXDrawingContext dc;
    NSView *view = TkMacOSXDrawableView(macWin);
    CGFloat viewHeight = [view bounds].size.height;
    CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
    }
    if (butPtr->type == TYPE_BUTTON && butPtr->defaultState == STATE_ACTIVE) {
	//[[view window] setDefaultButtonCell:cell];
	[button setKeyEquivalent:@"\r"];
    } else {
	[button setKeyEquivalent:@""];
    }
    frame = NSMakeRect(macWin->xOff, macWin->yOff, Tk_Width(tkwin),
	    Tk_Height(tkwin));
#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
    if (tkMacOSXUseCompatibilityMetrics) {
	BoundsFix boundsFix = boundsFixes[macButtonPtr->fix];
	frame = NSOffsetRect(frame, boundsFix.offsetX, boundsFix.offsetY);
	frame.size.height -= boundsFix.shrinkH + NATIVE_BUTTON_EXTRA_H;
	frame = NSInsetRect(frame, boundsFix.inset + NATIVE_BUTTON_INSET,
		boundsFix.inset + NATIVE_BUTTON_INSET);
    }
#endif
    frame.origin.y = viewHeight - (frame.origin.y + frame.size.height);
    if (!NSEqualRects(frame, [button frame])) {
	[button setFrame:frame];
    }
    [button displayRectIgnoringOpacity:[button bounds]];
    TkMacOSXRestoreDrawingContext(&dc);
#ifdef TK_MAC_DEBUG_BUTTON
    TKLog(@"button %s frame %@ width %d height %d",
	    ((TkWindow *)butPtr->tkwin)->pathName, NSStringFromRect(frame),
	    Tk_Width(tkwin), Tk_Height(tkwin));
#endif







<
<
<
|
<
<
<
<
<
<
<
<
<
|
<







482
483
484
485
486
487
488



489









490

491
492
493
494
495
496
497
    }
    if (butPtr->type == TYPE_BUTTON && butPtr->defaultState == STATE_ACTIVE) {
	//[[view window] setDefaultButtonCell:cell];
	[button setKeyEquivalent:@"\r"];
    } else {
	[button setKeyEquivalent:@""];
    }



    frame = TkMacOSXGetButtonFrame(butPtr);









    [button setFrame:frame];

    [button displayRectIgnoringOpacity:[button bounds]];
    TkMacOSXRestoreDrawingContext(&dc);
#ifdef TK_MAC_DEBUG_BUTTON
    TKLog(@"button %s frame %@ width %d height %d",
	    ((TkWindow *)butPtr->tkwin)->pathName, NSStringFromRect(frame),
	    Tk_Width(tkwin), Tk_Height(tkwin));
#endif
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
 */

static void
ComputeNativeButtonGeometry(
    TkButton *butPtr)		/* Button whose geometry may have changed. */
{
    MacButton *macButtonPtr = (MacButton *) butPtr;
    NSButton *button = macButtonPtr->button;
    NSButtonCell *cell = [button cell];
    NSButtonType type = -1;
    NSBezelStyle style = 0;
    NSInteger highlightsBy = 0, showsStateBy = 0;
    NSFont *font;
    NSRect bounds = NSZeroRect, titleRect = NSZeroRect;
    int haveImage = (butPtr->image || butPtr->bitmap != None), haveText = 0;







|







516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
 */

static void
ComputeNativeButtonGeometry(
    TkButton *butPtr)		/* Button whose geometry may have changed. */
{
    MacButton *macButtonPtr = (MacButton *) butPtr;
    TkNSButton *button = macButtonPtr->button;
    NSButtonCell *cell = [button cell];
    NSButtonType type = -1;
    NSBezelStyle style = 0;
    NSInteger highlightsBy = 0, showsStateBy = 0;
    NSFont *font;
    NSRect bounds = NSZeroRect, titleRect = NSZeroRect;
    int haveImage = (butPtr->image || butPtr->bitmap != None), haveText = 0;
1165
1166
1167
1168
1169
1170
1171

1172
1173
1174
1175
1176
1177
1178
1179
	height += 2*butPtr->padY;
    }
    Tk_GeometryRequest(butPtr->tkwin, (int) (width
	    + 2*butPtr->inset), (int) (height + 2*butPtr->inset));
    Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);
}


/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */







>








1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
	height += 2*butPtr->padY;
    }
    Tk_GeometryRequest(butPtr->tkwin, (int) (width
	    + 2*butPtr->inset), (int) (height + 2*butPtr->inset));
    Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);
}


/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */

Changes to macosx/tkMacOSXDraw.c.

13
14
15
16
17
18
19

20
21
22
23
24
25
26
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXDebug.h"
#include "xbytes.h"


/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_DRAWING
#define TK_MAC_DEBUG_IMAGE_DRAWING
#endif
*/







>







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXDebug.h"
#include "xbytes.h"
#include "tkButton.h"

/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_DRAWING
#define TK_MAC_DEBUG_IMAGE_DRAWING
#endif
*/
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486

1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
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
    GC gc,			/* GC for window to be scrolled. */
    int x, int y,		/* Position rectangle to be scrolled. */
    int width, int height,
    int dx, int dy,		/* Distance rectangle should be moved. */
    TkRegion damageRgn)		/* Region to accumulate damage in. */
{
    Drawable drawable = Tk_WindowId(tkwin);
    MacDrawable *macDraw = (MacDrawable *) drawable;
    NSView *view = TkMacOSXDrawableView(macDraw);
    CGRect visRect, srcRect, dstRect, scroll_src, scroll_dst;
    HIShapeRef dmgRgn = NULL;
    NSRect bounds;

    int result;

    if ( view ) {
	/*  Get the scroll area in NSView coordinates (origin at bottom left). */
	bounds = [view bounds];
	scroll_src = CGRectMake(
				macDraw->xOff + x,
				bounds.size.height - height - (macDraw->yOff + y),
				width, height);
	scroll_dst = CGRectOffset(scroll_src, dx, -dy);
	/* Limit scrolling to the window content area. */
	visRect = NSRectToCGRect([view visibleRect]);
	scroll_src = CGRectIntersection(scroll_src, visRect);
	scroll_dst = CGRectIntersection(scroll_dst, visRect);

	if ( !CGRectIsEmpty(scroll_src) && !CGRectIsEmpty(scroll_dst) ) {

	    /*
	     * Mark the difference between source and destination as damaged.
	     * This region is described in the Tk coordinate system, after shifting by dy.
	     */

	    srcRect = CGRectMake(x - macDraw->xOff, y - macDraw->yOff,
				 width, height);
	    dstRect = CGRectOffset(srcRect, dx, dy);
	    dmgRgn = HIShapeCreateMutableWithRect(&srcRect);
	    HIShapeRef dstRgn = HIShapeCreateWithRect(&dstRect);
	    ChkErr(HIShapeDifference, dmgRgn, dstRgn, (HIMutableShapeRef) dmgRgn);
	    CFRelease(dstRgn);

	    /* Scroll the rectangle. */
	    [view scrollRect:NSRectFromCGRect(scroll_src) by:NSMakeSize(dx, -dy)];
	    [view displayRect:NSRectFromCGRect(scroll_dst)];

	    /*
	     * When a Text widget contains embedded images, scrolling generates
	     * lots of artifacts involving multiple copies of the images
	     * displayed on top of each other.  Extensive experimentation, with
	     * very little help from the Apple documentation, indicates that
	     * whenever an image is displayed it gets added as a subview, which
	     * then gets automatically redisplayed in its original location.
	     *
	     * We do two things to combat this.  First, each subview that meets
	     * the scroll area is added as a damage rectangle.  Second, we
	     * redisplay the subviews after the scroll.
	     */

	    /*
	     * Step 1: Find any subviews that meet the scroll area and mark
	     * them as damaged.  Use Tk coordinates, shifted to account for the
	     * future scrolling.
	     */

	    for (NSView *subview in [view subviews] ) {

		NSRect frame = [subview frame];
		CGRect subviewRect = CGRectMake(
			frame.origin.x - macDraw->xOff + dx,
			(bounds.size.height - frame.origin.y - frame.size.height) - macDraw->yOff + dy,
			frame.size.width, frame.size.height);
		/* Rectangles with negative coordinates seem to cause trouble. */
		if (subviewRect.origin.y < 0 && subviewRect.origin.y + subviewRect.size.height > 0) {
		    subviewRect.origin.y = 0;
		}
		CGRect intersection = CGRectIntersection(srcRect, subviewRect);
		if (! CGRectIsEmpty(intersection) ){
		    dstRgn = HIShapeCreateWithRect(&subviewRect);
		    ChkErr(HIShapeUnion, dmgRgn, dstRgn, (HIMutableShapeRef) dmgRgn);
		    CFRelease(dstRgn);
		}
	    }
	}


    }



    if ( dmgRgn == NULL ) {
	dmgRgn = HIShapeCreateEmpty();
    }
    TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn);
    result = HIShapeIsEmpty(dmgRgn) ? 0 : 1;
    CFRelease(dmgRgn);
    return result;
}








|

|
|
|
>

|

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

|







1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511

1512
1513
1514
1515
1516












1517

1518
1519

1520
1521
1522

1523
1524
1525
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
    GC gc,			/* GC for window to be scrolled. */
    int x, int y,		/* Position rectangle to be scrolled. */
    int width, int height,
    int dx, int dy,		/* Distance rectangle should be moved. */
    TkRegion damageRgn)		/* Region to accumulate damage in. */
{
    Drawable drawable = Tk_WindowId(tkwin);
    MacDrawable *macDraw = (MacDrawable *) drawable; 
    NSView *view = TkMacOSXDrawableView(macDraw);
    CGRect srcRect, dstRect;
    HIShapeRef dmgRgn = NULL, extraRgn;
    NSRect bounds, visRect, scrollSrc, scrollDst;
    NSPoint delta = NSMakePoint(dx, dy);
    int result;
  
    if ( view ) {
  	/*  Get the scroll area in NSView coordinates (origin at bottom left). */
  	bounds = [view bounds];
 	scrollSrc = NSMakeRect(
			       macDraw->xOff + x, 
			       bounds.size.height - height - (macDraw->yOff + y),
			       width, height);
 	scrollDst = NSOffsetRect(scrollSrc, dx, -dy);
  	/* Limit scrolling to the window content area. */
 	visRect = [view visibleRect];
 	scrollSrc = NSIntersectionRect(scrollSrc, visRect);
 	scrollDst = NSIntersectionRect(scrollDst, visRect);
  
 	if ( !NSIsEmptyRect(scrollSrc) && !NSIsEmptyRect(scrollDst) ) {
  
  	    /*
  	     * Mark the difference between source and destination as damaged.
 	     * This region is described in the Tk coordinate system.
  	     */
  
 	    srcRect = CGRectMake(x, y, width, height);

  	    dstRect = CGRectOffset(srcRect, dx, dy);
  	    dmgRgn = HIShapeCreateMutableWithRect(&srcRect);
 	    extraRgn = HIShapeCreateWithRect(&dstRect);
 	    ChkErr(HIShapeDifference, dmgRgn, extraRgn, (HIMutableShapeRef) dmgRgn);
 	    CFRelease(extraRgn);












  	    

 	    /* Scroll the rectangle. */
 	    [view scrollRect:scrollSrc by:NSMakeSize(dx, -dy)];

  
 	    /* 
 	     * Adjust the positions of the button subwindows that meet the scroll

 	     * area.
  	     */
 
  	    for (NSView *subview in [view subviews] ) {
 	    	if ( [subview isKindOfClass:[NSButton class]] == YES ) {
 		    NSRect subframe = [subview frame];

 		    if  ( NSIntersectsRect(scrollSrc, subframe) ||

 			  NSIntersectsRect(scrollDst, subframe) ) { 


 			TkpShiftButton((NSButton *)subview, delta );
 		    }





 	    	}
  	    }
 
 	    /* Redisplay the scrolled area. */
 	    [view displayRect:scrollDst];
 
  	}
    }
  
    if ( dmgRgn == NULL ) {
  	dmgRgn = HIShapeCreateEmpty();
    }
    TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn);
    result = HIShapeIsEmpty(dmgRgn) ? 0 : 1;
    CFRelease(dmgRgn);
    return result;
}


Changes to macosx/tkMacOSXInt.h.

20
21
22
23
24
25
26

27
28
29
30
31
32
33

/*
 * Include platform specific public interfaces.
 */

#ifndef _TKMAC
#include "tkMacOSX.h"

#endif

/*
 * Define compatibility platform types used in the structures below so that
 * this header can be included without pulling in the platform headers.
 */








>







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

/*
 * Include platform specific public interfaces.
 */

#ifndef _TKMAC
#include "tkMacOSX.h"
#import <Cocoa/Cocoa.h>
#endif

/*
 * Define compatibility platform types used in the structures below so that
 * this header can be included without pulling in the platform headers.
 */

192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
MODULE_SCOPE int XSetClipRectangles(Display *d, GC gc, int clip_x_origin,
	int clip_y_origin, XRectangle* rectangles, int n, int ordering);
#endif
MODULE_SCOPE void TkpClipDrawableToRect(Display *display, Drawable d, int x,
	int y, int width, int height);
MODULE_SCOPE void TkpRetainRegion(TkRegion r);
MODULE_SCOPE void TkpReleaseRegion(TkRegion r);

/*
 * Include the stubbed internal platform-specific API.
 */

#include "tkIntPlatDecls.h"

#endif /* _TKMACINT */







|







193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
MODULE_SCOPE int XSetClipRectangles(Display *d, GC gc, int clip_x_origin,
	int clip_y_origin, XRectangle* rectangles, int n, int ordering);
#endif
MODULE_SCOPE void TkpClipDrawableToRect(Display *display, Drawable d, int x,
	int y, int width, int height);
MODULE_SCOPE void TkpRetainRegion(TkRegion r);
MODULE_SCOPE void TkpReleaseRegion(TkRegion r);
MODULE_SCOPE void TkpShiftButton(NSButton *button, NSPoint delta);
/*
 * Include the stubbed internal platform-specific API.
 */

#include "tkIntPlatDecls.h"

#endif /* _TKMACINT */