From e732ca1eeb37060c866b1e0f32bb45eb0c27db5d Mon Sep 17 00:00:00 2001 From: patthoyts Date: Sun, 3 Jan 2010 20:03:55 +0000 Subject: Patch 2848897: Support the system keyboard cues setting on Windows Backported this patch from HEAD (kovalenko, thoyts) --- ChangeLog | 7 ++++ generic/tkMenu.h | 17 ++++++++-- win/tkWinMenu.c | 97 ++++++++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 99 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index 721d5ad..38f812e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2010-01-03 Pat Thoyts + * generic/tkMenu.h: [Patch 2848897] Support the system keyboard + * win/tkWinMenu.c: cues option on Windows. This system parameter + hides the underlines on menu items unless the keyboard is used to + open the menu. (kovalenko, thoyts) + +2010-01-03 Pat Thoyts + * library/tearoff.tcl: tearoff menus should be transient and use the toolwindow style on Windows. * tests/menu.test: menu tests using 'tkwait visibility' are unix only diff --git a/generic/tkMenu.h b/generic/tkMenu.h index 642958a..c304ee0 100644 --- a/generic/tkMenu.h +++ b/generic/tkMenu.h @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMenu.h,v 1.14 2007/12/13 15:24:16 dgp Exp $ + * RCS: @(#) $Id: tkMenu.h,v 1.14.2.1 2010/01/03 20:03:55 patthoyts Exp $ */ #ifndef _TKMENU @@ -50,6 +50,19 @@ enum compound { }; /* + * Additional menu entry drawing parameters for Windows platform. + * DRAW_MENU_ENTRY_ARROW makes TkpDrawMenuEntry draw the arrow + * itself when cascade entry is disabled. + * DRAW_MENU_ENTRY_NOUNDERLINE forbids underline when ODS_NOACCEL + * is set, thus obeying the system-wide Windows UI setting. + */ + +enum drawingParameters { + DRAW_MENU_ENTRY_ARROW = (1<<0), + DRAW_MENU_ENTRY_NOUNDERLINE = (1<<1) +}; + +/* * One of the following data structures is kept for each entry of each menu * managed by this file: */ @@ -548,7 +561,7 @@ MODULE_SCOPE void TkpDrawMenuEntry(TkMenuEntry *mePtr, Drawable d, Tk_Font tkfont, const Tk_FontMetrics *menuMetricsPtr, int x, int y, int width, int height, int strictMotif, - int drawArrow); + int drawingParameters); MODULE_SCOPE void TkpMenuInit(void); MODULE_SCOPE int TkpMenuNewEntry(TkMenuEntry *mePtr); MODULE_SCOPE int TkpNewMenu(TkMenu *menuPtr); diff --git a/win/tkWinMenu.c b/win/tkWinMenu.c index 8e19e0a..44f144e 100644 --- a/win/tkWinMenu.c +++ b/win/tkWinMenu.c @@ -10,9 +10,11 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinMenu.c,v 1.59.2.4 2009/12/27 23:42:45 patthoyts Exp $ + * RCS: @(#) $Id: tkWinMenu.c,v 1.59.2.5 2010/01/03 20:03:55 patthoyts Exp $ */ +#define WINVER 0x0500 /* Requires Windows 2K definitions */ +#define _WIN32_WINNT 0x0500 #define OEMRESOURCE #include "tkWinInt.h" #include "tkMenu.h" @@ -50,6 +52,34 @@ #define MENU_SYSTEM_MENU MENU_PLATFORM_FLAG1 #define MENU_RECONFIGURE_PENDING MENU_PLATFORM_FLAG2 +/* + * ODS_NOACCEL flag forbids drawing accelerator cues (i.e. underlining labels) + * on Windows 2000 and above. The ODS_NOACCEL define is missing from mingw32 + * headers and undefined for _WIN32_WINNT < 0x0500 in Microsoft SDK. We might + * check for _WIN32_WINNT here, but I think it's not needed, as checking for + * this flag does no harm on even on NT: reserved bits should be zero, and in + * fact they are. + */ + +#ifndef ODS_NOACCEL +#define ODS_NOACCEL 0x100 +#endif +#ifndef SPI_GETKEYBOARDCUES +#define SPI_GETKEYBOARDCUES 0x100A +#endif +#ifndef WM_UPDATEUISTATE +#define WM_UPDATEUISTATE 0x0128 +#endif +#ifndef UIS_SET +#define UIS_SET 1 +#endif +#ifndef UIS_CLEAR +#define UIS_CLEAR 2 +#endif +#ifndef UISF_HIDEACCEL +#define UISF_HIDEACCEL 2 +#endif + #ifndef WM_UNINITMENUPOPUP #define WM_UNINITMENUPOPUP 0x0125 #endif @@ -59,6 +89,8 @@ static int indicatorDimensions[2]; * menu entry. Calculated at init time to save * time. */ +static BOOL showMenuAccelerators; + typedef struct ThreadSpecificData { int inPostMenu; /* We cannot be re-entrant like X Windows. */ WORD lastCommandID; /* The last command ID we allocated. */ @@ -112,7 +144,7 @@ static void DrawMenuEntryIndicator(TkMenu *menuPtr, static void DrawMenuEntryLabel(TkMenu *menuPtr, TkMenuEntry *mePtr, Drawable d, GC gc, Tk_Font tkfont, const Tk_FontMetrics *fmPtr, int x, int y, - int width, int height); + int width, int height, int underline); static void DrawMenuSeparator(TkMenu *menuPtr, TkMenuEntry *mePtr, Drawable d, GC gc, Tk_Font tkfont, const Tk_FontMetrics *fmPtr, @@ -940,6 +972,13 @@ TkWinEmbeddedMenuProc( nIdles = 0; break; + case WM_SETTINGCHANGE: + if (wParam == SPI_SETNONCLIENTMETRICS + || wParam == SPI_SETKEYBOARDCUES) { + SetDefaults(0); + } + break; + case WM_INITMENU: case WM_SYSCOMMAND: case WM_COMMAND: @@ -1165,11 +1204,14 @@ TkWinHandleMenuEvent( TkWinDrawable *twdPtr; LPDRAWITEMSTRUCT itemPtr = (LPDRAWITEMSTRUCT) *plParam; Tk_FontMetrics fontMetrics; - int drawArrow = 0; + int drawingParameters = 0; if (itemPtr != NULL && tsdPtr->modalMenuPtr != NULL) { Tk_Font tkfont; + if (itemPtr->itemState & ODS_NOACCEL && !showMenuAccelerators) { + drawingParameters |= DRAW_MENU_ENTRY_NOUNDERLINE; + } mePtr = (TkMenuEntry *) itemPtr->itemData; menuPtr = mePtr->menuPtr; twdPtr = (TkWinDrawable *) ckalloc(sizeof(TkWinDrawable)); @@ -1198,12 +1240,12 @@ TkWinHandleMenuEvent( } /* - * Also, set the drawArrow flag for a disabled cascade menu - * since we need to draw the arrow ourselves. + * Also, set the DRAW_MENU_ENTRY_ARROW flag for a disabled + * cascade menu since we need to draw the arrow ourselves. */ if (mePtr->type == CASCADE_ENTRY) { - drawArrow = 1; + drawingParameters |= DRAW_MENU_ENTRY_ARROW; } } @@ -1212,7 +1254,8 @@ TkWinHandleMenuEvent( TkpDrawMenuEntry(mePtr, (Drawable) twdPtr, tkfont, &fontMetrics, itemPtr->rcItem.left, itemPtr->rcItem.top, itemPtr->rcItem.right - itemPtr->rcItem.left, - itemPtr->rcItem.bottom - itemPtr->rcItem.top, 0,drawArrow); + itemPtr->rcItem.bottom - itemPtr->rcItem.top, + 0, drawingParameters); ckfree((char *) twdPtr); } @@ -2140,7 +2183,8 @@ DrawMenuEntryLabel( int x, /* left edge */ int y, /* right edge */ int width, /* width of entry */ - int height) /* height of entry */ + int height, /* height of entry */ + int underline) /* accelerator cue should be drawn */ { int indicatorSpace = mePtr->indicatorSpace; int activeBorderWidth; @@ -2285,8 +2329,10 @@ DrawMenuEntryLabel( Tk_DrawChars(menuPtr->display, d, gc, tkfont, label, mePtr->labelLength, leftEdge + textXOffset, baseline + textYOffset); - DrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr, - x + textXOffset, y + textYOffset, width, height); + if (underline) { + DrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr, + x + textXOffset, y + textYOffset, width, height); + } } } @@ -2443,9 +2489,9 @@ TkpDrawMenuEntry( int width, /* Width of the entry rectangle */ int height, /* Height of the current rectangle */ int strictMotif, /* Boolean flag */ - int drawArrow) /* Whether or not to draw the cascade arrow - * for cascade items. Only applies to - * Windows. */ + int drawingParameters) /* Whether or not to draw the cascade arrow + * for cascade items and accelerator + * cues. Only applies to Windows. */ { GC gc, indicatorGC; TkMenu *menuPtr = mePtr->menuPtr; @@ -2566,12 +2612,13 @@ TkpDrawMenuEntry( adjustedX, adjustedY, width, adjustedHeight); } else { DrawMenuEntryLabel(menuPtr, mePtr, d, gc, tkfont, fmPtr, - adjustedX, adjustedY, width, adjustedHeight); + adjustedX, adjustedY, width, adjustedHeight, + (drawingParameters & DRAW_MENU_ENTRY_NOUNDERLINE)?0:1); DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr, activeBorder, adjustedX, adjustedY, width, adjustedHeight); DrawMenuEntryArrow(menuPtr, mePtr, d, gc, activeBorder, adjustedX, adjustedY, width, adjustedHeight, - drawArrow); + (drawingParameters & DRAW_MENU_ENTRY_ARROW)?1:0); if (!mePtr->hideMargin) { DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont, fmPtr, adjustedX, adjustedY, width, adjustedHeight); @@ -3122,21 +3169,21 @@ TkWinGetMenuSystemDefault( /* *---------------------------------------------------------------------- * - * TkWinMenuSetDefaults -- + * SetDefaults -- * - * Sets up the hash tables and the variables used by the menu package. + * Read system menu settings (font, sizes of items, use of accelerators) + * This is called if the UI theme or settings are changed. * * Results: * None. * * Side effects: - * lastMenuID gets initialized, and the parent hash and the command hash - * are allocated. + * May result in menu items being redrawn with different appearance. * *---------------------------------------------------------------------- */ -void +static void SetDefaults( int firstTime) /* Is this the first time this has been * called? */ @@ -3227,6 +3274,16 @@ SetDefaults( indicatorDimensions[0] = HIWORD(dimensions); indicatorDimensions[1] = LOWORD(dimensions); } + + /* + * Accelerators used to be always underlines until Win2K when a system + * parameter was introduced to hide them unless Alt is pressed. + */ + + showMenuAccelerators = TRUE; + if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) { + SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &showMenuAccelerators, 0); + } } /* -- cgit v0.12