summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhobbs <hobbs>2002-09-09 23:52:02 (GMT)
committerhobbs <hobbs>2002-09-09 23:52:02 (GMT)
commit958042034bbbe215fbb0915cf6c07b9914923724 (patch)
tree804bf93151524b4ec43b4495c97883b3f0b0d9d8
parentec6a4daee7df6a5652185b52f34a9e48d28a652e (diff)
downloadtk-958042034bbbe215fbb0915cf6c07b9914923724.zip
tk-958042034bbbe215fbb0915cf6c07b9914923724.tar.gz
tk-958042034bbbe215fbb0915cf6c07b9914923724.tar.bz2
* library/tk.tcl: use command instead of control on Aqua bindings.
Force dialogs to appear below fixed native Mac menubar. * macosx/tkMacOSXKeyEvent.c: * macosx/tkMacOSXKeyboard.c: Keypress/release events for pure modifier keys were not being passed to Tk. Deadkey presses were inserting null characters into text windows. Now they do nothing. (Still not ideal, but better than before!) * macosx/tkMacOSXMenu.c: Allow more than 200 menus to exist - increased to 2000. * macosx/tkMacOSXMouseEvent.c: Bad interactions between floating windows and ordinary ones. Ensure that local<->global coordinate transformations are wrt to the correct window. * macosx/tkMacOSXWm.c: Better error msg for 'wm attributes'. Remove crash in 'wm transient'. Add 'noActivates' and 'noUpdates' flags to unsupported command. [Patch #606658] (darley)
-rw-r--r--library/tk.tcl17
-rw-r--r--macosx/tkMacOSXKeyEvent.c89
-rw-r--r--macosx/tkMacOSXKeyboard.c36
-rw-r--r--macosx/tkMacOSXMenu.c15
-rw-r--r--macosx/tkMacOSXMouseEvent.c44
-rw-r--r--macosx/tkMacOSXWm.c14
6 files changed, 192 insertions, 23 deletions
diff --git a/library/tk.tcl b/library/tk.tcl
index e695924..cb6e662 100644
--- a/library/tk.tcl
+++ b/library/tk.tcl
@@ -3,7 +3,7 @@
# Initialization script normally executed in the interpreter for each
# Tk-based application. Arranges class bindings for widgets.
#
-# RCS: @(#) $Id: tk.tcl,v 1.43 2002/08/31 06:12:28 das Exp $
+# RCS: @(#) $Id: tk.tcl,v 1.44 2002/09/09 23:52:02 hobbs Exp $
#
# Copyright (c) 1992-1994 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
@@ -111,6 +111,11 @@ proc ::tk::PlaceWindow {w {place ""} {anchor ""}} {
} elseif {$y > ([winfo screenheight $w]-[winfo reqheight $w])} {
set y [expr {[winfo screenheight $w]-[winfo reqheight $w]}]
}
+ if {[tk windowingsystem] eq "macintosh" \
+ || [tk windowingsystem] eq "aqua"} {
+ # Avoid the native menu bar which sits on top of everything.
+ if {$y < 20} { set y 20 }
+ }
}
wm geometry $w +$x+$y
wm deiconify $w
@@ -369,13 +374,13 @@ switch [tk windowingsystem] {
event add <<Redo>> <Control-Key-y>
}
"aqua" {
- event add <<Cut>> <Control-Key-x> <Key-F2>
- event add <<Copy>> <Control-Key-c> <Key-F3>
- event add <<Paste>> <Control-Key-v> <Key-F4>
+ event add <<Cut>> <Command-Key-x> <Key-F2>
+ event add <<Copy>> <Command-Key-c> <Key-F3>
+ event add <<Paste>> <Command-Key-v> <Key-F4>
event add <<PasteSelection>> <ButtonRelease-2>
event add <<Clear>> <Clear>
- event add <<Undo>> <Control-Key-z>
- event add <<Redo>> <Control-Key-y>
+ event add <<Undo>> <Command-Key-z>
+ event add <<Redo>> <Command-Key-y>
}
"classic" {
event add <<Cut>> <Control-Key-x> <Key-F2>
diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c
index 7c3474c..a8d2711 100644
--- a/macosx/tkMacOSXKeyEvent.c
+++ b/macosx/tkMacOSXKeyEvent.c
@@ -76,7 +76,8 @@ static Tk_Window gKeyboardWinPtr = NULL; /* Current keyboard grab window. */
static int GenerateKeyEvent _ANSI_ARGS_(( EventKind eKind,
KeyEventData * e,
Window window,
- UInt32 savedKeyCode));
+ UInt32 savedKeyCode,
+ UInt32 savedModifiers));
/*
*----------------------------------------------------------------------
*
@@ -99,6 +100,7 @@ int TkMacOSXProcessKeyboardEvent(
MacEventStatus * statusPtr)
{
static UInt32 savedKeyCode = 0;
+ static UInt32 savedModifiers = 0;
OSStatus status;
KeyEventData keyEventData;
Window window;
@@ -115,6 +117,26 @@ int TkMacOSXProcessKeyboardEvent(
keyEventData.global = keyEventData.local;
LocalToGlobal(&keyEventData.global);
keyEventData.state = TkMacOSXButtonKeyState();
+#if 0
+ /*
+ * This block of code seems like a good idea, to trap
+ * key-bindings which point directly to menus, but it
+ * has a number of problems:
+ * (1) when grabs are present we definitely don't want
+ * to do this.
+ * (2) Tk's semantics define accelerator keystrings in
+ * menus as a purely visual adornment, and require that
+ * the developer create separate bindings to trigger
+ * them. This breaks those semantics. (i.e. Tk will
+ * behave differently on Aqua to the behaviour on Unix/Win).
+ * (3) Tk's bindings depend on the current window's bindtags,
+ * which may be completely different to what happens to be
+ * in some global menu (agreed, it shouldn't be that different,
+ * but it often is).
+ *
+ * While a better middleground might be possible, the best, most
+ * compatible, approach at present is to disable this block.
+ */
if (IsMenuKeyEvent(NULL, eventPtr->eventRef,
kNilOptions, &menuRef, &menuItemIndex)) {
int oldMode;
@@ -138,6 +160,7 @@ int TkMacOSXProcessKeyboardEvent(
Tcl_SetServiceMode(oldMode);
return 0; /* TODO: may not be on event on queue. */
}
+#endif
status = GetEventParameter(eventPtr->eventRef,
kEventParamKeyMacCharCodes,
@@ -174,7 +197,8 @@ int TkMacOSXProcessKeyboardEvent(
window = TkMacOSXGetXWindow(keyEventData.whichWindow);
eventGenerated = GenerateKeyEvent(eventPtr->eKind, &keyEventData,
- window, savedKeyCode);
+ window, savedKeyCode, savedModifiers);
+ savedModifiers = keyEventData.keyModifiers;
if (eventGenerated == 0) {
savedKeyCode = keyEventData.message;
@@ -212,7 +236,8 @@ int
GenerateKeyEvent( EventKind eKind,
KeyEventData * e,
Window window,
- UInt32 savedKeyCode )
+ UInt32 savedKeyCode,
+ UInt32 savedModifiers )
{
Tk_Window tkwin;
XEvent event;
@@ -240,7 +265,23 @@ GenerateKeyEvent( EventKind eKind,
return -1;
}
byte = (e->message&charCodeMask);
- if ((savedKeyCode == 0) &&
+ if (byte == 0) {
+ /*
+ * Either we have a pure-modifier change, or perhaps
+ * a dead-key (e.g. opt-e) was pressed. In the former case we do
+ * want to generate an event, in the latter I'm not sure
+ * what to do.
+ */
+ if (eKind == kEventRawKeyModifiersChanged) {
+ /* Drop through to the event code below */
+ } else {
+ /*
+ * What shall we do here? We certainly aren't dealing
+ * with deadkeys at present. Is this where they come?
+ */
+ return 0;
+ }
+ } else if ((savedKeyCode == 0) &&
(Tcl_ExternalToUtf(NULL, TkMacOSXCarbonEncoding,
(char *) &byte, 1, 0, NULL,
buf, sizeof(buf), NULL, NULL, NULL) != TCL_OK)) {
@@ -262,6 +303,30 @@ GenerateKeyEvent( EventKind eKind,
Tk_TopCoordsToWindow(tkwin, e->local.h, e->local.v,
&event.xkey.x, &event.xkey.y);
+ /*
+ * Now, we may have a problem here. How do we handle 'Option-char'
+ * keypresses? The problem is that we might want to bind to some of
+ * these (e.g. Cmd-Opt-d is 'uncomment' in Alpha), but Option-d
+ * generates a 'delta' symbol with some keycode unrelated to 'd', and so
+ * the binding never triggers. In any case, the delta that is produced
+ * is never mapped to an 'XK_Greek_DELTA' keysym so bindings on that
+ * won't work either (a general KeyPress binding will of course trigger,
+ * but a specific binding on XK_Greek_DELTA will not).
+ *
+ * I think what we want is for the event to contain information on
+ * both the 'Opt-d' side of things and the 'delta'. Then a binding
+ * on Opt-d will trigger, but the ascii/string representation of the
+ * event will be a delta.
+ *
+ * A different way to look at this is that 'Opt-d' is delta, but that
+ * Command-Opt-d is nothing to do with delta, but I'm not sure that is
+ * helpful.
+ *
+ * Also some keypresses (Opt-e) are dead-keys to add accents to
+ * letters. We don't handle them yet.
+ *
+ * Help needed!
+ */
event.xkey.keycode = byte |
((savedKeyCode & charCodeMask) << 8) |
((e->message&keyCodeMask) << 8);
@@ -287,6 +352,22 @@ GenerateKeyEvent( EventKind eKind,
event.xany.type = KeyPress;
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
break;
+ case kEventRawKeyModifiersChanged:
+ if (savedModifiers > e->keyModifiers) {
+ event.xany.type = KeyRelease;
+ } else {
+ event.xany.type = KeyPress;
+ }
+ /*
+ * Use special '-1' to signify a special keycode to
+ * our platform specific code in tkMacOSXKeyboard.c.
+ * This is rather like what happens on Windows.
+ */
+ event.xany.send_event = -1;
+ /* Set keycode (which was zero) to the changed modifier */
+ event.xkey.keycode = (e->keyModifiers ^ savedModifiers);
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+ break;
default:
break;
}
diff --git a/macosx/tkMacOSXKeyboard.c b/macosx/tkMacOSXKeyboard.c
index db5d679..aff807e 100644
--- a/macosx/tkMacOSXKeyboard.c
+++ b/macosx/tkMacOSXKeyboard.c
@@ -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: tkMacOSXKeyboard.c,v 1.2 2002/08/31 06:12:30 das Exp $
+ * RCS: @(#) $Id: tkMacOSXKeyboard.c,v 1.3 2002/09/09 23:52:02 hobbs Exp $
*/
#include "tkInt.h"
@@ -148,6 +148,14 @@ XKeycodeToKeysym(
if (!initialized) {
InitKeyMaps();
}
+ if (keycode == 0) {
+ /*
+ * This means we had a pure modifier keypress or
+ * something similar which is a TO DO.
+ */
+ return NoSymbol;
+ }
+
virtualKey = (char) (keycode >> 16);
c = (keycode) & 0xffff;
if (c > 255) {
@@ -240,7 +248,7 @@ TkpGetString(
* Just return NULL if the character is a function key or another
* non-printing key.
*/
- if (c == 0x10) {
+ if (c == 0x10 || (eventPtr->xany.send_event == -1)) {
len = 0;
} else {
hPtr = Tcl_FindHashEntry(&keycodeTable, (char *) virtualKey);
@@ -487,6 +495,30 @@ TkpGetKeySym(dispPtr, eventPtr)
&& (eventPtr->xkey.state & LockMask))) {
index += 1;
}
+ if (eventPtr->xany.send_event == -1) {
+ /* We use -1 as a special signal for a pure modifier */
+ int modifier = eventPtr->xkey.keycode;
+ if (modifier == cmdKey) {
+ return XK_Alt_L;
+ } else if (modifier == shiftKey) {
+ return XK_Shift_L;
+ } else if (modifier == alphaLock) {
+ return XK_Caps_Lock;
+ } else if (modifier == optionKey) {
+ return XK_Meta_L;
+ } else if (modifier == controlKey) {
+ return XK_Control_L;
+ } else if (modifier == rightShiftKey) {
+ return XK_Shift_R;
+ } else if (modifier == rightOptionKey) {
+ return XK_Meta_R;
+ } else if (modifier == rightControlKey) {
+ return XK_Control_R;
+ } else {
+ /* If we get here, we probably need to implement something new */
+ return NoSymbol;
+ }
+ }
sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, index);
/*
diff --git a/macosx/tkMacOSXMenu.c b/macosx/tkMacOSXMenu.c
index 8578359..401bce5 100644
--- a/macosx/tkMacOSXMenu.c
+++ b/macosx/tkMacOSXMenu.c
@@ -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: tkMacOSXMenu.c,v 1.2 2002/08/31 06:12:30 das Exp $
+ * RCS: @(#) $Id: tkMacOSXMenu.c,v 1.3 2002/09/09 23:52:02 hobbs Exp $
*/
#include "tkMacOSXInt.h"
#include "tkMenuButton.h"
@@ -188,7 +188,7 @@ static int inPostMenu; /* We cannot be re-entrant like X
* windows. */
static short lastMenuID; /* To pass to NewMenu; need to figure out
* a good way to do this. */
-static unsigned char lastCascadeID;
+static short lastCascadeID;
/* Cascades have to have ids that are
* less than 256. */
static MacDrawable macMDEFDrawable;
@@ -390,6 +390,11 @@ TkMacOSXUseMenuID(
* the fly. We use the id as a key into a hash table; if there
* is no hash entry, we know that we can use the id.
*
+ * Carbon allows a much larger number of menus than the old APIs.
+ * I believe this is 32768, but am not sure. This code just uses
+ * 2000 as the upper limit. Unfortunately tk leaks menus when
+ * cloning, under some circumstances (see bug on sourceforge).
+ *
* Results:
* Returns TCL_OK if succesful; TCL_ERROR if there are no more
* ids of the appropriate type to allocate. menuIDPtr contains
@@ -448,8 +453,8 @@ int
* dealt with separately.
*/
- unsigned char curID = lastCascadeID + 1;
- if (curID == 236) {
+ short curID = lastCascadeID + 1;
+ if (curID == 2000) {
curID = 0;
}
@@ -463,7 +468,7 @@ int
break;
}
curID++;
- if (curID == 236) {
+ if (curID == 2000) {
curID = 0;
}
}
diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c
index 769472c..12bfc93 100644
--- a/macosx/tkMacOSXMouseEvent.c
+++ b/macosx/tkMacOSXMouseEvent.c
@@ -215,7 +215,17 @@ TkMacOSXProcessMouseEvent(TkMacOSXEvent *eventPtr, MacEventStatus * statusPtr)
medPtr->global = where;
medPtr->local = where;
- SetPortWindowPort(frontWindow);
+ /*
+ * We must set the port to the right window -- the one
+ * we are actually going to use -- before finding
+ * the local coordinates, otherwise we will have completely
+ * wrong local x,y!
+ *
+ * I'm pretty sure this window is medPtr->whichWin, unless
+ * perhaps there is a grab. Certainly 'frontWindow' or
+ * 'medPtr->activeNonFloating' are wrong.
+ */
+ SetPortWindowPort(medPtr->whichWin);
GlobalToLocal(&medPtr->local);
if (eventPtr->eKind == kEventMouseWheelMoved ) {
return GenerateMouseWheelEvent(medPtr);
@@ -389,7 +399,14 @@ GeneratePollingEvents(MouseEventData * medPtr)
int local_x, local_y;
TkDisplay *dispPtr;
-
+ /*
+ * I really do not understand this complicated logic. Surely the event
+ * should be to either: (1) medPtr->whichWin, the window under the mouse
+ * (from which we then obviously extract the correct Tk subwindow), or
+ * (2) the current grab window. I really don't see why anything else is
+ * relevant.
+ */
+#if 0
if ((!TkpIsWindowFloating(medPtr->whichWin)
&& (medPtr->activeNonFloating != medPtr->whichWin))) {
tkwin = NULL;
@@ -416,6 +433,23 @@ GeneratePollingEvents(MouseEventData * medPtr)
if ((tkwin == NULL) && (grabWin != NULL)) {
tkwin = grabWin;
}
+#else
+ grabWin = TkMacOSXGetCapture();
+ if (grabWin != NULL) {
+ tkwin = grabWin;
+ } else {
+ window = TkMacOSXGetXWindow(medPtr->whichWin);
+ dispPtr = TkGetDisplayList();
+ rootwin = Tk_IdToWindow(dispPtr->display, window);
+ if (rootwin == NULL) {
+ tkwin = NULL;
+ } else {
+ tkwin = Tk_TopCoordsToWindow(rootwin,
+ medPtr->local.h, medPtr->local.v,
+ &local_x, &local_y);
+ }
+ }
+#endif
Tk_UpdatePointer(tkwin, medPtr->global.h, medPtr->global.v,
medPtr->state);
@@ -683,15 +717,17 @@ TkGenerateButtonEvent(
FindWindow(where, &whichWin);
frontWin = FrontNonFloatingWindow();
- if ((frontWin == NULL) || ((!(TkpIsWindowFloating(whichWin))
+ if (0 && ((frontWin == NULL) || ((!(TkpIsWindowFloating(whichWin))
&& (frontWin != whichWin))
- && TkMacOSXGetCapture() == NULL)) {
+ && TkMacOSXGetCapture() == NULL))) {
return false;
}
dispPtr = TkGetDisplayList();
tkwin = Tk_IdToWindow(dispPtr->display, window);
+ /* SetPortWindowPort(ActiveNonFloatingWindow()); */
+ SetPortWindowPort(whichWin);
GlobalToLocal(&where);
if (tkwin != NULL) {
tkwin = Tk_TopCoordsToWindow(tkwin, where.h, where.v,
diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c
index 14f93fb..633e305 100644
--- a/macosx/tkMacOSXWm.c
+++ b/macosx/tkMacOSXWm.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: tkMacOSXWm.c,v 1.3 2002/09/03 11:48:56 vincentdarley Exp $
+ * RCS: @(#) $Id: tkMacOSXWm.c,v 1.4 2002/09/09 23:52:02 hobbs Exp $
*/
#include <Carbon/Carbon.h>
@@ -763,6 +763,7 @@ configArgs:
Tcl_AppendResult(interp, "wrong # arguments: must be \"",
Tcl_GetStringFromObj (objv[0], NULL), " attributes window",
" ?-modified ?bool??",
+ " ?-titlepath ?path??",
"\"", (char *) NULL);
return TCL_ERROR;
}
@@ -2544,7 +2545,8 @@ Tcl_Obj *CONST objv[]; /* Argument objects. */
wmPtr2 = ((TkWindow *) master)->wmInfoPtr;
- if (wmPtr2->iconFor != NULL) {
+ /* Under some circumstances, wmPtr2 is NULL here */
+ if (wmPtr2 != NULL && wmPtr2->iconFor != NULL) {
Tcl_AppendResult(interp, "can't make \"",
Tcl_GetString(objv[3]),
"\" a master: it is an icon for ",
@@ -4755,6 +4757,14 @@ TkUnsupported1Cmd(
} else if ((*attrArgv[i] == 's')
&& (strcmp(attrArgv[i], "sideTitlebar") == 0)) {
wmPtr->attributes |= kWindowSideTitlebarAttribute;
+ foundOne = 1;
+ } else if ((*attrArgv[i] == 'n')
+ && (strcmp(attrArgv[i], "noActivates") == 0)) {
+ wmPtr->attributes |= kWindowNoActivatesAttribute;
+ foundOne = 1;
+ } else if ((*attrArgv[i] == 'n')
+ && (strcmp(attrArgv[i], "noUpdates") == 0)) {
+ wmPtr->attributes |= kWindowNoUpdatesAttribute;
foundOne = 1;
} else {
foundOne = 0;