diff options
author | das <das> | 2007-11-08 14:25:59 (GMT) |
---|---|---|
committer | das <das> | 2007-11-08 14:25:59 (GMT) |
commit | 79be45fe605260d8587e9c3124a73e9b690f8f37 (patch) | |
tree | 21bc4a65eca3729665c885b0c72b9e654245a83e /macosx/tkMacOSXMenubutton.c | |
parent | 9617eeb79cbc00a24c526a8bd4a897bfa323b175 (diff) | |
download | tk-79be45fe605260d8587e9c3124a73e9b690f8f37.zip tk-79be45fe605260d8587e9c3124a73e9b690f8f37.tar.gz tk-79be45fe605260d8587e9c3124a73e9b690f8f37.tar.bz2 |
* macosx/tkMacOSXButton.c: replace HiliteControl() by modern API
* macosx/tkMacOSXMenubutton.c: for activation and enabling;
distinguish inactive and disabled
look&feel; correct activation handling
to match that of container toplevel.
* macosx/tkMacOSXMenubutton.c: correct size computation of bevelbutton
variant to match that of buttons;
fix crash with bitmap due to NULL GC;
delay picParams setup until needed;
formatting cleanup. [Bug 1824521]
Diffstat (limited to 'macosx/tkMacOSXMenubutton.c')
-rw-r--r-- | macosx/tkMacOSXMenubutton.c | 247 |
1 files changed, 164 insertions, 83 deletions
diff --git a/macosx/tkMacOSXMenubutton.c b/macosx/tkMacOSXMenubutton.c index fb18b2e..d728fe5 100644 --- a/macosx/tkMacOSXMenubutton.c +++ b/macosx/tkMacOSXMenubutton.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXMenubutton.c,v 1.16 2007/10/15 20:52:47 hobbs Exp $ + * RCS: @(#) $Id: tkMacOSXMenubutton.c,v 1.17 2007/11/08 14:25:59 das Exp $ */ #include "tkMacOSXPrivate.h" @@ -27,6 +27,9 @@ #define TK_POPUP_OFFSET 32 /* size of popup marker */ +#define FIRST_DRAW 2 +#define ACTIVE 4 + MODULE_SCOPE int TkMacOSXGetNewMenuID(Tcl_Interp *interp, TkMenu *menuInstPtr, int cascade, short *menuIDPtr); MODULE_SCOPE void TkMacOSXFreeMenuID(short menuID); @@ -76,6 +79,7 @@ static void UserPaneBackgroundProc(ControlHandle, ControlBackgroundPtr info); static int MenuButtonInitControl (MacMenuButton *mbPtr, Rect *paneRect, Rect *cntrRect ); +static void MenuButtonEventProc(ClientData clientData, XEvent *eventPtr); static int UpdateControlColors(MacMenuButton *mbPtr); static void ComputeMenuButtonControlParams(TkMenuButton *mbPtr, MenuButtonControlParams * paramsPtr); @@ -116,22 +120,17 @@ TkpCreateMenuButton( Tk_Window tkwin) { MacMenuButton *mbPtr = (MacMenuButton *) ckalloc(sizeof(MacMenuButton)); - mbPtr->userPaneBackground = PIXEL_MAGIC << 24; + + Tk_CreateEventHandler(tkwin, ActivateMask, + MenuButtonEventProc, (ClientData) mbPtr); mbPtr->flags = 0; + mbPtr->userPaneBackground = PIXEL_MAGIC << 24; mbPtr->userPane = NULL; mbPtr->control = NULL; - mbPtr->picParams.version = -2; - mbPtr->picParams.hRes = 0x00480000; - mbPtr->picParams.vRes = 0x00480000; - mbPtr->picParams.srcRect.top = 0; - mbPtr->picParams.srcRect.left = 0; - mbPtr->picParams.reserved1 = 0; - mbPtr->picParams.reserved2 = 0; - mbPtr->bevelButtonContent.contentType = kControlContentPictHandle; mbPtr->menuRef = NULL; - bzero(&mbPtr->params, sizeof(mbPtr->params)); - bzero(&mbPtr->titleParams,sizeof(mbPtr->titleParams)); + bzero(&mbPtr->titleParams, sizeof(mbPtr->titleParams)); + return (TkMenuButton *) mbPtr; } @@ -162,26 +161,25 @@ TkpDisplayMenuButton( Pixmap pixmap; MacMenuButton *mbPtr = (MacMenuButton *) butPtr; CGrafPtr destPort, savePort; - Boolean portChanged; + Boolean portChanged = false; int hasImageOrBitmap = 0, width, height; OSStatus err; ControlButtonGraphicAlignment theAlignment; Rect paneRect, cntrRect; + int active, enabled; butPtr->flags &= ~REDRAW_PENDING; if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { return; } pixmap = (Pixmap) Tk_WindowId(tkwin); - destPort = TkMacOSXGetDrawablePort(Tk_WindowId(tkwin)); - portChanged = QDSwapPort(destPort, &savePort); TkMacOSXSetUpClippingRgn(Tk_WindowId(tkwin)); winPtr = (TkWindow *)butPtr->tkwin; paneRect.left = winPtr->privatePtr->xOff; paneRect.top = winPtr->privatePtr->yOff; - paneRect.right = paneRect.left+Tk_Width(butPtr->tkwin)-1; - paneRect.bottom = paneRect.top+Tk_Height(butPtr->tkwin)-1; + paneRect.right = paneRect.left+Tk_Width(butPtr->tkwin); + paneRect.bottom = paneRect.top+Tk_Height(butPtr->tkwin); cntrRect = paneRect; @@ -212,21 +210,29 @@ TkpDisplayMenuButton( return; } } - SetControlBounds(mbPtr->userPane,&paneRect); - SetControlBounds(mbPtr->control,&cntrRect); + SetControlBounds(mbPtr->userPane, &paneRect); + SetControlBounds(mbPtr->control, &cntrRect); + + if (butPtr->image != None) { + Tk_SizeOfImage(butPtr->image, &width, &height); + hasImageOrBitmap = 1; + } else if (butPtr->bitmap != None) { + Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height); + hasImageOrBitmap = 1; + } /* * We need to cache the title and its style */ - if (!(mbPtr->flags & 2)) { + if (!(mbPtr->flags & FIRST_DRAW)) { ControlTitleParams titleParams; int titleChanged; int styleChanged; - ComputeControlTitleParams(butPtr,&titleParams); - CompareControlTitleParams(&titleParams,&mbPtr->titleParams, - &titleChanged,&styleChanged); + ComputeControlTitleParams(butPtr, &titleParams); + CompareControlTitleParams(&titleParams, &mbPtr->titleParams, + &titleChanged, &styleChanged); if (titleChanged) { CFStringRef cf = CFStringCreateWithCString(NULL, (char*) titleParams.title, kCFStringEncodingUTF8); @@ -253,43 +259,54 @@ TkpDisplayMenuButton( sizeof(titleParams.style)); } } - if (butPtr->image != None) { - Tk_SizeOfImage(butPtr->image, &width, &height); - hasImageOrBitmap = 1; - } else if (butPtr->bitmap != None) { - Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height); - hasImageOrBitmap = 1; - } if (hasImageOrBitmap) { - mbPtr->picParams.srcRect.right = width; - mbPtr->picParams.srcRect.bottom = height; - - /* - * Set the flag to circumvent clipping and bounds problems with OS - * 10.0.4 - */ - - tkPictureIsOpen = 1; - mbPtr->bevelButtonContent.u.picture = OpenCPicture(&mbPtr->picParams); - if (!mbPtr->bevelButtonContent.u.picture) { - TkMacOSXDbgMsg("OpenCPicture failed"); - } - - /* - * TO DO - There is one case where XCopyPlane calls CopyDeepMask, - * which does not get recorded in the picture. So the bitmap code - * will fail in that case. - */ + { + destPort = TkMacOSXGetDrawablePort(Tk_WindowId(tkwin)); + portChanged = QDSwapPort(destPort, &savePort); + mbPtr->picParams.version = -2; + mbPtr->picParams.hRes = 0x00480000; + mbPtr->picParams.vRes = 0x00480000; + mbPtr->picParams.srcRect.top = 0; + mbPtr->picParams.srcRect.left = 0; + mbPtr->picParams.srcRect.bottom = height; + mbPtr->picParams.srcRect.right = width; + mbPtr->picParams.reserved1 = 0; + mbPtr->picParams.reserved2 = 0; + mbPtr->bevelButtonContent.contentType = kControlContentPictHandle; + mbPtr->bevelButtonContent.u.picture = OpenCPicture(&mbPtr->picParams); + if (!mbPtr->bevelButtonContent.u.picture) { + TkMacOSXDbgMsg("OpenCPicture failed"); + } + tkPictureIsOpen = 1; + /* + * TO DO - There is one case where XCopyPlane calls CopyDeepMask, + * which does not get recorded in the picture. So the bitmap code + * will fail in that case. + */ + } if (butPtr->image != NULL) { Tk_RedrawImage(butPtr->image, 0, 0, width, height, pixmap, 0, 0); } else { - XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, NULL, 0, 0, + GC gc; + + if (butPtr->state == STATE_DISABLED) { + gc = butPtr->disabledGC; + } else if (butPtr->state == STATE_ACTIVE) { + gc = butPtr->activeTextGC; + } else { + gc = butPtr->normalTextGC; + } + XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, gc, 0, 0, width, height, 0, 0, 1); } - ClosePicture(); - - tkPictureIsOpen = 0; + { + ClosePicture(); + tkPictureIsOpen = 0; + if (portChanged) { + QDSwapPort(savePort, NULL); + } + } ChkErr(SetControlData, mbPtr->control, kControlButtonPart, kControlBevelButtonContentTag, sizeof(ControlButtonContentInfo), @@ -328,25 +345,47 @@ TkpDisplayMenuButton( kControlBevelButtonGraphicAlignTag, sizeof(ControlButtonGraphicAlignment), (char *) &theAlignment); } - if (butPtr->flags & GOT_FOCUS) { - HiliteControl(mbPtr->control,kControlButtonPart); - } else { - HiliteControl(mbPtr->control,kControlNoPart); + active = ((mbPtr->flags & ACTIVE) != 0); + if (active != IsControlActive(mbPtr->control)) { + if (active) { + ChkErr(ActivateControl, mbPtr->control); + } else { + ChkErr(DeactivateControl, mbPtr->control); + } + } + enabled = !(butPtr->state == STATE_DISABLED); + if (enabled != IsControlEnabled(mbPtr->control)) { + if (enabled) { + ChkErr(EnableControl, mbPtr->control); + } else { + ChkErr(DisableControl, mbPtr->control); + } + } + if (active && enabled) { + if (butPtr->state == STATE_ACTIVE) { + if (hasImageOrBitmap) { + HiliteControl(mbPtr->control, kControlButtonPart); + } else { + HiliteControl(mbPtr->control, kControlLabelPart); + } + } else { + HiliteControl(mbPtr->control, kControlNoPart); + } } UpdateControlColors(mbPtr); - if (mbPtr->flags&2) { + if (mbPtr->flags & FIRST_DRAW) { ShowControl(mbPtr->control); ShowControl(mbPtr->userPane); - mbPtr->flags ^= 2; + mbPtr->flags ^= FIRST_DRAW; } else { - Draw1Control(mbPtr->userPane); SetControlVisibility(mbPtr->control, true, true); + Draw1Control(mbPtr->userPane); } if (hasImageOrBitmap) { - KillPicture(mbPtr->bevelButtonContent.u.picture); - } - if (portChanged) { - QDSwapPort(savePort, NULL); + if (mbPtr->bevelButtonContent.contentType == + kControlContentPictHandle) { + KillPicture(mbPtr->bevelButtonContent.u.picture); + } } } @@ -413,21 +452,9 @@ TkpComputeMenuButtonGeometry(mbPtr) mbPtr->inset = mbPtr->highlightWidth + mbPtr->borderWidth; if (mbPtr->image != None) { Tk_SizeOfImage(mbPtr->image, &width, &height); - if (mbPtr->width > 0) { - width = mbPtr->width; - } - if (mbPtr->height > 0) { - height = mbPtr->height; - } hasImageOrBitmap = 1; } else if (mbPtr->bitmap != None) { Tk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height); - if (mbPtr->width > 0) { - width = mbPtr->width; - } - if (mbPtr->height > 0) { - height = mbPtr->height; - } hasImageOrBitmap = 1; } else { hasImageOrBitmap = 0; @@ -449,7 +476,19 @@ TkpComputeMenuButtonGeometry(mbPtr) width += 2*mbPtr->padX; height += 2*mbPtr->padY; } - + if (hasImageOrBitmap) { + if (mbPtr->width > 0) { + width = mbPtr->width; + } + if (mbPtr->height > 0) { + height = mbPtr->height; + } + mbPtr->inset = mbPtr->highlightWidth + 2; + width += (2 * mbPtr->borderWidth + 4); + height += (2 * mbPtr->borderWidth + 4); + } else { + width += TK_POPUP_OFFSET; + } if (mbPtr->indicatorOn) { mm = WidthMMOfScreen(Tk_Screen(mbPtr->tkwin)); pixels = WidthOfScreen(Tk_Screen(mbPtr->tkwin)); @@ -460,9 +499,6 @@ TkpComputeMenuButtonGeometry(mbPtr) mbPtr->indicatorHeight = 0; mbPtr->indicatorWidth = 0; } - if (!hasImageOrBitmap) { - width += TK_POPUP_OFFSET; - } Tk_GeometryRequest(mbPtr->tkwin, (int) (width + 2*mbPtr->inset), (int) (height + 2*mbPtr->inset)); @@ -640,7 +676,7 @@ MenuButtonInitControl( * Do this only if we are using bevel buttons. */ - ComputeControlTitleParams(butPtr,&mbPtr->titleParams); + ComputeControlTitleParams(butPtr, &mbPtr->titleParams); mbPtr->control = NewControl(mbPtr->windowRef, cntrRect, "\p" /* mbPtr->titleParams.title */, initiallyVisible, mbPtr->params.initialValue, @@ -706,7 +742,10 @@ MenuButtonInitControl( SetControlMaximum(mbPtr->control, 1); SetControlValue(mbPtr->control, 1); } - mbPtr->flags |= 2; + mbPtr->flags |= FIRST_DRAW; + if (IsWindowActive(mbPtr->windowRef)) { + mbPtr->flags |= ACTIVE; + } return 0; } @@ -863,7 +902,7 @@ UpdateControlColors( MacMenuButton *mbPtr) { XColor *xcolor; - TkMenuButton * butPtr = ( TkMenuButton * )mbPtr; + TkMenuButton * butPtr = (TkMenuButton *) mbPtr; /* * Under Appearance we cannot change the background of the @@ -881,3 +920,45 @@ UpdateControlColors( return false; } + +/* + *-------------------------------------------------------------- + * + * MenuButtonEventProc -- + * + * This procedure is invoked by the Tk dispatcher for various + * events on buttons. + * + * Results: + * None. + * + * Side effects: + * When it gets exposed, it is redisplayed. + * + *-------------------------------------------------------------- + */ + +static void +MenuButtonEventProc( + ClientData clientData, /* Information about window. */ + XEvent *eventPtr) /* Information about event. */ +{ + TkMenuButton *buttonPtr = (TkMenuButton *) clientData; + MacMenuButton *mbPtr = (MacMenuButton *) clientData; + + if (eventPtr->type == ActivateNotify + || eventPtr->type == DeactivateNotify) { + if ((buttonPtr->tkwin == NULL) || (!Tk_IsMapped(buttonPtr->tkwin))) { + return; + } + if (eventPtr->type == ActivateNotify) { + mbPtr->flags |= ACTIVE; + } else { + mbPtr->flags &= ~ACTIVE; + } + if ((buttonPtr->flags & REDRAW_PENDING) == 0) { + Tcl_DoWhenIdle(TkpDisplayMenuButton, (ClientData) buttonPtr); + buttonPtr->flags |= REDRAW_PENDING; + } + } +} |