summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;