summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpatthoyts <patthoyts@users.sourceforge.net>2009-01-07 00:25:43 (GMT)
committerpatthoyts <patthoyts@users.sourceforge.net>2009-01-07 00:25:43 (GMT)
commit114517ca2014f21586487d79a7362b44af6b3540 (patch)
tree17c88a341322430e47b0ae50b50423cfe52580e7
parent201429e710c7c59022b3773a0368171bf3475eb6 (diff)
downloadtk-114517ca2014f21586487d79a7362b44af6b3540.zip
tk-114517ca2014f21586487d79a7362b44af6b3540.tar.gz
tk-114517ca2014f21586487d79a7362b44af6b3540.tar.bz2
[Bug 1847002] On Windows a grab can be bypassed using the taskbar. This prevents that by handling the keyboard activation message and the system menu commands when grabs are present.
-rw-r--r--ChangeLog4
-rw-r--r--win/tkWinWm.c99
2 files changed, 84 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index 270d415..342dbd6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2009-01-07 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tkWinWm.c: prevent grabs being bypassed on Windows [Bug 1847002]
+
2009-01-06 Jan Nijtmans <nijtmans@users.sf.net>
* generic/tk.h: A few const -> CONST86 modifications, improving
diff --git a/win/tkWinWm.c b/win/tkWinWm.c
index 89fe23e..9267049 100644
--- a/win/tkWinWm.c
+++ b/win/tkWinWm.c
@@ -12,7 +12,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkWinWm.c,v 1.134 2008/12/09 21:22:56 dgp Exp $
+ * RCS: @(#) $Id: tkWinWm.c,v 1.135 2009/01/07 00:25:43 patthoyts Exp $
*/
#include "tkWinInt.h"
@@ -34,12 +34,16 @@
/*
* Event structure for synthetic activation events. These events are placed on
- * the event queue whenever a toplevel gets a WM_MOUSEACTIVATE message.
+ * the event queue whenever a toplevel gets a WM_MOUSEACTIVATE message or
+ * a WM_ACTIVATE. If the window is being moved (*flagPtr will be true)
+ * then the handling of this event must be delayed until the operation
+ * has completed to avoid a premature WM_EXITSIZEMOVE event.
*/
typedef struct ActivateEvent {
Tcl_Event ev;
TkWindow *winPtr;
+ int *flagPtr;
} ActivateEvent;
/*
@@ -418,6 +422,7 @@ TCL_DECLARE_MUTEX(winWmMutex)
static int ActivateWindow(Tcl_Event *evPtr, int flags);
static void ConfigureTopLevel(WINDOWPOS *pos);
static void GenerateConfigureNotify(TkWindow *winPtr);
+static void GenerateActivateEvent(TkWindow *winPtr, int *flagPtr);
static void GetMaxSize(WmInfo *wmPtr,
int *maxWidthPtr, int *maxHeightPtr);
static void GetMinSize(WmInfo *wmPtr,
@@ -7755,7 +7760,7 @@ WmProc(
* after leaving move/size mode. Note that
* this mechanism assumes move/size is only
* one level deep. */
- LRESULT result;
+ LRESULT result = 0;
TkWindow *winPtr = NULL;
switch (message) {
@@ -7779,6 +7784,20 @@ WmProc(
break;
case WM_ACTIVATE:
+ if ( WA_ACTIVE == LOWORD(wParam) ) {
+ winPtr = GetTopLevel(hwnd);
+ if (winPtr && (TkGrabState(winPtr) == TK_GRAB_EXCLUDED)) {
+ /*
+ * There is a grab in progress so queue an Activate event
+ */
+
+ GenerateActivateEvent(winPtr, &inMoveSize);
+ result = 0;
+ goto done;
+ }
+ }
+ /* fall through */
+
case WM_EXITSIZEMOVE:
if (inMoveSize) {
inMoveSize = 0;
@@ -7881,8 +7900,6 @@ WmProc(
}
case WM_MOUSEACTIVATE: {
- ActivateEvent *eventPtr;
-
winPtr = GetTopLevel((HWND) wParam);
if (winPtr && (TkGrabState(winPtr) != TK_GRAB_EXCLUDED)) {
/*
@@ -7902,10 +7919,7 @@ WmProc(
*/
if (winPtr) {
- eventPtr = (ActivateEvent *) ckalloc(sizeof(ActivateEvent));
- eventPtr->ev.proc = ActivateWindow;
- eventPtr->winPtr = winPtr;
- Tcl_QueueEvent((Tcl_Event *) eventPtr, TCL_QUEUE_TAIL);
+ GenerateActivateEvent(winPtr, &inMoveSize);
}
result = MA_NOACTIVATE;
goto done;
@@ -7934,6 +7948,24 @@ WmProc(
winPtr = GetTopLevel(hwnd);
switch(message) {
case WM_SYSCOMMAND:
+ /*
+ * If there is a grab in effect then ignore the minimize command
+ * If there is a grab in effect and this window is outside the
+ * grab tree then ignore all system commands. [Bug 1847002]
+ */
+
+ if (winPtr) {
+ int cmd = wParam & 0xfff0;
+ int grab = TkGrabState(winPtr);
+ if (grab != TK_GRAB_NONE && SC_MINIMIZE == cmd)
+ goto done;
+ if (grab == TK_GRAB_EXCLUDED
+ && !(SC_MOVE == cmd || SC_SIZE == cmd)) {
+ goto done;
+ }
+ }
+ /* fall through */
+
case WM_INITMENU:
case WM_COMMAND:
case WM_MENUCHAR:
@@ -7941,20 +7973,21 @@ WmProc(
case WM_DRAWITEM:
case WM_MENUSELECT:
case WM_ENTERIDLE:
- case WM_INITMENUPOPUP: {
- HWND hMenuHWnd = Tk_GetEmbeddedMenuHWND((Tk_Window) winPtr);
+ case WM_INITMENUPOPUP:
+ if (winPtr) {
+ HWND hMenuHWnd = Tk_GetEmbeddedMenuHWND((Tk_Window) winPtr);
- if (hMenuHWnd) {
- if (SendMessage(hMenuHWnd, message, wParam, lParam)) {
+ if (hMenuHWnd) {
+ if (SendMessage(hMenuHWnd, message, wParam, lParam)) {
+ goto done;
+ }
+ } else if (TkWinHandleMenuEvent(&hwnd, &message, &wParam, &lParam,
+ &result)) {
goto done;
}
- } else if (TkWinHandleMenuEvent(&hwnd, &message, &wParam, &lParam,
- &result)) {
- goto done;
}
break;
}
- }
if (winPtr && winPtr->window) {
HWND child = Tk_GetHWND(winPtr->window);
@@ -8109,6 +8142,25 @@ TkpGetWrapperWindow(
/*
*----------------------------------------------------------------------
*
+ * GenerateActivateEvent --
+ *
+ * This function is called to activate a Tk window.
+ */
+
+static void
+GenerateActivateEvent(TkWindow * winPtr, int *flagPtr)
+{
+ ActivateEvent *eventPtr;
+ eventPtr = (ActivateEvent *)ckalloc(sizeof(ActivateEvent));
+ eventPtr->ev.proc = ActivateWindow;
+ eventPtr->winPtr = winPtr;
+ eventPtr->flagPtr = flagPtr;
+ Tcl_QueueEvent((Tcl_Event *)eventPtr, TCL_QUEUE_TAIL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* ActivateWindow --
*
* This function is called when an ActivateEvent is processed.
@@ -8127,13 +8179,22 @@ ActivateWindow(
Tcl_Event *evPtr, /* Pointer to ActivateEvent. */
int flags) /* Notifier event mask. */
{
- TkWindow *winPtr;
+ ActivateEvent *eventPtr = (ActivateEvent *)evPtr;
+ TkWindow *winPtr = eventPtr->winPtr;
if (! (flags & TCL_WINDOW_EVENTS)) {
return 0;
}
- winPtr = ((ActivateEvent *) evPtr)->winPtr;
+ /*
+ * If the toplevel is in the middle of a move or size operation then
+ * we must delay handling of this event to avoid stealing the focus
+ * while the window manage is in control.
+ */
+
+ if (eventPtr->flagPtr && *eventPtr->flagPtr) {
+ return 0;
+ }
/*
* If the window is excluded by a grab, call SetFocus on the grabbed