summaryrefslogtreecommitdiffstats
path: root/win/tkWinMenu.c
diff options
context:
space:
mode:
authorpatthoyts <patthoyts@users.sourceforge.net>2010-01-03 19:50:59 (GMT)
committerpatthoyts <patthoyts@users.sourceforge.net>2010-01-03 19:50:59 (GMT)
commit1695610f2b000063acc70451fe91fae47c911150 (patch)
treecea8865039c68954654c0375c60472fd677f3ec1 /win/tkWinMenu.c
parent497b85748d56fb3aa77b7f62ea9eaf98d49f6e22 (diff)
downloadtk-1695610f2b000063acc70451fe91fae47c911150.zip
tk-1695610f2b000063acc70451fe91fae47c911150.tar.gz
tk-1695610f2b000063acc70451fe91fae47c911150.tar.bz2
Patch 2848897: Support the system keyboard cues setting on Windows
This patch by Anton Kovalenko adds support for the Windows system-wide UI setting that prevents accelerators being underlined unless the Alt key is pressed. Modified to support the system keyboard cues flag and to handle dynamic changes to the system parameters by the user.
Diffstat (limited to 'win/tkWinMenu.c')
-rw-r--r--win/tkWinMenu.c97
1 files changed, 77 insertions, 20 deletions
diff --git a/win/tkWinMenu.c b/win/tkWinMenu.c
index 6b85e6d..4426546 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.70 2009/12/27 23:36:25 patthoyts Exp $
+ * RCS: @(#) $Id: tkWinMenu.c,v 1.71 2010/01/03 19:50:59 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);
@@ -3120,21 +3167,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? */
@@ -3225,6 +3272,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);
+ }
}
/*