summaryrefslogtreecommitdiffstats
path: root/macosx/tkMacOSXWindowEvent.c
diff options
context:
space:
mode:
authorKevin Walzer <kw@codebykevin.com>2015-04-09 02:00:59 (GMT)
committerKevin Walzer <kw@codebykevin.com>2015-04-09 02:00:59 (GMT)
commitd10216afc1dcddd76f93bcdbb6e87bdca8dc7453 (patch)
tree3d2c1b4ec2054fbe9fd8a6a5cd948ad5cc6d8c71 /macosx/tkMacOSXWindowEvent.c
parentf801eafc556ad7c6648d5da223a6563c99b998ca (diff)
downloadtk-d10216afc1dcddd76f93bcdbb6e87bdca8dc7453.zip
tk-d10216afc1dcddd76f93bcdbb6e87bdca8dc7453.tar.gz
tk-d10216afc1dcddd76f93bcdbb6e87bdca8dc7453.tar.bz2
Re-working of internal Cocoa widget drawing routines, especially when resizing; fix rendering of scrollbar when resized or clipped; cleanup of button metrics; thanks to Marc Culler for extensive patches
Diffstat (limited to 'macosx/tkMacOSXWindowEvent.c')
-rw-r--r--macosx/tkMacOSXWindowEvent.c101
1 files changed, 60 insertions, 41 deletions
diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c
index d68a933..ef3c86b 100644
--- a/macosx/tkMacOSXWindowEvent.c
+++ b/macosx/tkMacOSXWindowEvent.c
@@ -29,7 +29,7 @@
* Declaration of functions used only in this file
*/
-static int GenerateUpdates(HIMutableShapeRef updateRgn,
+static int GenerateUpdates(HIShapeRef updateRgn,
CGRect *updateBounds, TkWindow *winPtr);
static int GenerateActivateEvents(TkWindow *winPtr,
int activeFlag);
@@ -316,7 +316,7 @@ extern BOOL opaqueTag;
static int
GenerateUpdates(
- HIMutableShapeRef updateRgn,
+ HIShapeRef updateRgn,
CGRect *updateBounds,
TkWindow *winPtr)
{
@@ -784,7 +784,8 @@ Tk_MacOSXIsAppInFront(void)
@interface TKContentView(TKWindowEvent)
- (void) drawRect: (NSRect) rect;
-- (void) generateExposeEvents: (HIMutableShapeRef) shape;
+- (void) generateExposeEvents: (HIShapeRef) shape;
+- (void) generateExposeEvents: (HIShapeRef) shape childrenOnly: (int) childrenOnly;
- (void) viewDidEndLiveResize;
- (void) tkToolbarButton: (id) sender;
- (BOOL) isOpaque;
@@ -806,6 +807,15 @@ ExposeRestrictProc(
? TK_PROCESS_EVENT : TK_DEFER_EVENT);
}
+/*Restrict event processing to ConfigureNotify events.*/
+static Tk_RestrictAction
+ConfigureRestrictProc(
+ ClientData arg,
+ XEvent *eventPtr)
+{
+ return (eventPtr->type==ConfigureNotify ? TK_PROCESS_EVENT : TK_DEFER_EVENT);
+}
+
@implementation TKContentView(TKWindowEvent)
- (void) drawRect: (NSRect) rect
@@ -832,11 +842,12 @@ ExposeRestrictProc(
HIShapeUnionWithRect(drawShape, &r);
}
if (CFRunLoopGetMain() == CFRunLoopGetCurrent()) {
- [self generateExposeEvents:drawShape];
+ [self generateExposeEvents:(HIShapeRef)drawShape];
} else {
[self performSelectorOnMainThread:@selector(generateExposeEvents:)
withObject:(id)drawShape waitUntilDone:NO
modes:[NSArray arrayWithObjects:NSRunLoopCommonModes,
+
NSEventTrackingRunLoopMode, NSModalPanelRunLoopMode,
nil]];
}
@@ -848,25 +859,37 @@ ExposeRestrictProc(
-(void) setFrameSize: (NSSize)newsize
{
if ( [self inLiveResize] ) {
- NSWindow *window = [self window];
- TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
+ NSWindow *w = [self window];
+ TkWindow *winPtr = TkMacOSXGetTkWindow(w);
Tk_Window tkwin = (Tk_Window) winPtr;
unsigned int width = (unsigned int)newsize.width;
unsigned int height=(unsigned int)newsize.height;
+ ClientData oldArg;
+ Tk_RestrictProc *oldProc;
+
+ /* Resize the NSView */
+ [super setFrameSize: newsize];
- /* Resize the Tk Window to the requested size.*/
+ /* Disable drawing until the window has been completely configured.*/
+ TkMacOSXSetDrawingEnabled(winPtr, 0);
+
+ /* Generate and handle a ConfigureNotify event for the new size.*/
TkGenWMConfigureEvent(tkwin, Tk_X(tkwin), Tk_Y(tkwin), width, height,
TK_SIZE_CHANGED | TK_MACOSX_HANDLE_EVENT_IMMEDIATELY);
+ oldProc = Tk_RestrictEvents(ConfigureRestrictProc, NULL, &oldArg);
+ while ( Tk_DoOneEvent(TK_X_EVENTS|TK_DONT_WAIT) ) {}
+ Tk_RestrictEvents(oldProc, oldArg, &oldArg);
- /* Then resize the NSView to the actual window size*/
- newsize.width = (CGFloat)Tk_Width(tkwin);
- newsize.height = (CGFloat)Tk_Height(tkwin);
- [super setFrameSize: newsize];
-
- /* Process all pending events to update the window. */
- while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {}
- while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
+ /* Now that Tk has configured all subwindows we can create the clip regions. */
+ TkMacOSXSetDrawingEnabled(winPtr, 1);
+ TkMacOSXInvalClipRgns(tkwin);
+ TkMacOSXUpdateClipRgn(winPtr);
+ /* Finally, generate and process expose events to redraw the window. */
+ HIRect bounds = NSRectToCGRect([self bounds]);
+ HIShapeRef shape = HIShapeCreateWithRect(&bounds);
+ [self generateExposeEvents: shape];
+ while ( Tk_DoOneEvent(TK_ALL_EVENTS|TK_DONT_WAIT) ) {}
} else {
[super setFrameSize: newsize];
}
@@ -882,52 +905,49 @@ ExposeRestrictProc(
{
HIRect bounds = NSRectToCGRect([self bounds]);
HIShapeRef shape = HIShapeCreateWithRect(&bounds);
+ [super viewDidEndLiveResize];
[self generateExposeEvents: shape];
}
-
-/*Core function of this class, generates expose events for redrawing.*/
-- (void) generateExposeEvents: (HIMutableShapeRef) shape
+/* Core method of this class: generates expose events for redrawing.
+ * Whereas drawRect is intended to be called only from the Appkit event
+ * loop, this can be called from Tk. If the Tcl_ServiceMode is set to
+ * TCL_SERVICE_ALL then the expose events will be immediately removed
+ * from the Tcl event loop and processed. Typically, they should be queued,
+ * however.
+ */
+- (void) generateExposeEvents: (HIShapeRef) shape
{
+ [self generateExposeEvents:shape childrenOnly:0];
+}
+- (void) generateExposeEvents: (HIShapeRef) shape
+ childrenOnly: (int) childrenOnly
+{
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
unsigned long serial;
CGRect updateBounds;
+ int updatesNeeded;
if (!winPtr) {
return;
}
+ /* Generate Tk Expose events. */
HIShapeGetBounds(shape, &updateBounds);
+ /* All of these events will share the same serial number. */
serial = LastKnownRequestProcessed(Tk_Display(winPtr));
- if (GenerateUpdates(shape, &updateBounds, winPtr) &&
- ![[NSRunLoop currentRunLoop] currentMode] &&
- Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
- /*
- * Ensure there are no pending idle-time redraws that could
- * prevent the just posted Expose events from generating
- * new redraws.
- */
-
- while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
-
- /*
- * For smoother drawing, process Expose events and resulting
- * redraws immediately instead of at idle time.
- */
-
- ClientData oldArg;
+ updatesNeeded = GenerateUpdates(shape, &updateBounds, winPtr);
+
+ /* Process the Expose events if the service mode is TCL_SERVICE_ALL */
+ if (updatesNeeded && Tcl_GetServiceMode() == TCL_SERVICE_ALL) {
+ ClientData oldArg;
Tk_RestrictProc *oldProc = Tk_RestrictEvents(ExposeRestrictProc,
UINT2PTR(serial), &oldArg);
-
while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {}
-
Tk_RestrictEvents(oldProc, oldArg, &oldArg);
-
- while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
}
-
}
/*
@@ -943,7 +963,6 @@ ExposeRestrictProc(
int x, y;
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
Tk_Window tkwin = (Tk_Window) winPtr;
-
bzero(&event, sizeof(XVirtualEvent));
event.type = VirtualEvent;
event.serial = LastKnownRequestProcessed(Tk_Display(tkwin));