summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--doc/SetCaret.340
-rw-r--r--doc/tk.n18
-rw-r--r--generic/tkCmds.c86
-rw-r--r--generic/tkInt.h19
-rw-r--r--mac/tkMacXStubs.c13
-rw-r--r--tests/tk.test25
-rw-r--r--unix/tkUnixKey.c33
-rw-r--r--win/tkWinX.c29
9 files changed, 237 insertions, 40 deletions
diff --git a/ChangeLog b/ChangeLog
index 8d4cc4f..2e68d8f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2002-06-17 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tkCmds.c (Tk_TkObjCmd):
+ * generic/tkInt.h (struct TkCaret):
+ * mac/tkMacXStubs.c (Tk_SetCaretPos):
+ * unix/tkUnixKey.c (TkpGetString, Tk_SetCaretPos):
+ * win/tkWinX.c (Tk_SetCaretPos):
+ * tests/tk.test: Added 'tk caret' implementation of TIP#96
+ * doc/SetCaret.3 (new): which adds a TkCaret structure element to
+ * doc/tk.n: TkDisplay for maintaining state.
+
+ * unix/tkUnixSend.c (TkSendCleanup): special cleanup of
+ inputContext to avoid bug in XCloseIM. (dejong)
+
2002-06-17 Don Porter <dgp@users.sf.net>
* library/msgs/en_gb.msg: Added catalog for UK English.
diff --git a/doc/SetCaret.3 b/doc/SetCaret.3
new file mode 100644
index 0000000..b5bd901
--- /dev/null
+++ b/doc/SetCaret.3
@@ -0,0 +1,40 @@
+'\"
+'\" Copyright (c) 2002 ActiveState Corporation.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+'\" RCS: @(#) $Id: SetCaret.3,v 1.1 2002/06/17 20:09:01 hobbs Exp $
+'\"
+.so man.macros
+.TH Tk_SetCaretPos 3 8.4 Tk "Tk Library Procedures"
+.BS
+.SH NAME
+Tk_SetCaretPos \- set the display caret location
+.SH SYNOPSIS
+.nf
+\fB#include <tk.h>\fR
+.sp
+int
+\fBTk_SetCaretPos\fR(\fItkwin, x, y, height\fR)
+.SH ARGUMENTS
+.AP Tk_Window tkwin in
+Token for window.
+.AP int x in
+Window-relative x coordinate.
+.AP int y in
+Window-relative y coordinate.
+.AP int h in
+Height of the caret in the window.
+.BE
+
+.SH DESCRIPTION
+.PP
+\fBTk_SetCaretPos\fR sets the caret location for the display of the
+specified Tk_Window \fItkwin\fR. The caret is the per-display cursor
+location used for indicating global focus (e.g. to comply with Microsoft
+Accessibility guidelines), as well as for location of the over-the-spot XIM
+(X Input Methods) or Windows IME windows.
+
+.SH KEYWORDS
+caret, cursor
diff --git a/doc/tk.n b/doc/tk.n
index ad82002..7cac1ae 100644
--- a/doc/tk.n
+++ b/doc/tk.n
@@ -5,10 +5,10 @@
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
-'\" RCS: @(#) $Id: tk.n,v 1.4 2000/10/31 00:52:11 hobbs Exp $
+'\" RCS: @(#) $Id: tk.n,v 1.5 2002/06/17 20:09:01 hobbs Exp $
'\"
.so man.macros
-.TH tk n 8.3 Tk "Tk Built-In Commands"
+.TH tk n 8.4 Tk "Tk Built-In Commands"
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
@@ -43,6 +43,20 @@ be able to find some options for the application.
If sends have been disabled by deleting the \fBsend\fR command,
this command will reenable them and recreate the \fBsend\fR
command.
+.VS 8.4
+.TP
+\fBtk caret window \fR?\fB\-x \fIx\fR? \fR?\fB\-y \fIy\fR? \fR?\fB\-height \fIheight\fR?
+.
+Sets and queries the caret location for the display of the specified
+Tk window \fIwindow\fR. The caret is the per-display cursor location
+used for indicating global focus (e.g. to comply with Microsoft
+Accessibility guidelines), as well as for location of the over-the-spot
+XIM (X Input Methods) or Windows IME windows. If no options are specified,
+the last values used for setting the caret are return in option-value pair
+format. \fI\-x\fR and \fI\-y\fR represent window-relative coordinates, and
+\fI\-height\fR is the height of the current cursor location, or the height
+of the specified \fIwindow\fR if none is given.
+.VE
.TP
\fBtk scaling \fR?\fB\-displayof \fIwindow\fR? ?\fInumber\fR?
.
diff --git a/generic/tkCmds.c b/generic/tkCmds.c
index 733ff2e..6b08149 100644
--- a/generic/tkCmds.c
+++ b/generic/tkCmds.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkCmds.c,v 1.27 2002/06/15 02:15:39 hobbs Exp $
+ * RCS: @(#) $Id: tkCmds.c,v 1.28 2002/06/17 20:09:01 hobbs Exp $
*/
#include "tkPort.h"
@@ -618,10 +618,11 @@ Tk_TkObjCmd(clientData, interp, objc, objv)
int index;
Tk_Window tkwin;
static CONST char *optionStrings[] = {
- "appname", "scaling", "useinputmethods", NULL
+ "appname", "caret", "scaling", "useinputmethods",
+ NULL
};
enum options {
- TK_APPNAME, TK_SCALING, TK_USE_IM
+ TK_APPNAME, TK_CARET, TK_SCALING, TK_USE_IM
};
tkwin = (Tk_Window) clientData;
@@ -653,6 +654,85 @@ Tk_TkObjCmd(clientData, interp, objc, objv)
Tcl_AppendResult(interp, winPtr->nameUid, NULL);
break;
}
+ case TK_CARET: {
+ Tcl_Obj *objPtr;
+ TkCaret *caretPtr;
+ Tk_Window window;
+ static CONST char *caretStrings[]
+ = { "-x", "-y", "-height", NULL };
+ enum caretOptions
+ { TK_CARET_X, TK_CARET_Y, TK_CARET_HEIGHT };
+
+ if ((objc < 3) || ((objc > 4) && !(objc & 1))) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "window ?-x x? ?-y y? ?-height height?");
+ return TCL_ERROR;
+ }
+ window = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin);
+ if (window == NULL) {
+ return TCL_ERROR;
+ }
+ caretPtr = &(((TkWindow *) window)->dispPtr->caret);
+ if (objc == 3) {
+ /*
+ * Return all the current values
+ */
+ objPtr = Tcl_NewObj();
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewStringObj("-height", 7));
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewIntObj(caretPtr->height));
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewStringObj("-x", 2));
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewIntObj(caretPtr->x));
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewStringObj("-y", 2));
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewIntObj(caretPtr->y));
+ Tcl_SetObjResult(interp, objPtr);
+ } else if (objc == 4) {
+ int value;
+ /*
+ * Return the current value of the selected option
+ */
+ if (Tcl_GetIndexFromObj(interp, objv[3], caretStrings,
+ "caret option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (index == TK_CARET_X) {
+ value = caretPtr->x;
+ } else if (index == TK_CARET_Y) {
+ value = caretPtr->y;
+ } else /* if (index == TK_CARET_HEIGHT) -- last case */ {
+ value = caretPtr->height;
+ }
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), value);
+ } else {
+ int i, value, x = 0, y = 0, height = -1;
+
+ for (i = 3; i < objc; i += 2) {
+ if ((Tcl_GetIndexFromObj(interp, objv[i], caretStrings,
+ "caret option", 0, &index) != TCL_OK) ||
+ (Tcl_GetIntFromObj(interp, objv[i+1], &value)
+ != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ if (index == TK_CARET_X) {
+ x = value;
+ } else if (index == TK_CARET_Y) {
+ y = value;
+ } else /* if (index == TK_CARET_HEIGHT) -- last case */ {
+ height = value;
+ }
+ }
+ if (height < 0) {
+ height = Tk_Height(window);
+ }
+ Tk_SetCaretPos(window, x, y, height);
+ }
+ break;
+ }
case TK_SCALING: {
Screen *screenPtr;
int skip, width, height;
diff --git a/generic/tkInt.h b/generic/tkInt.h
index e2a3eb6..f6576d8 100644
--- a/generic/tkInt.h
+++ b/generic/tkInt.h
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: $Id: tkInt.h,v 1.49 2002/06/15 02:15:51 hobbs Exp $
+ * RCS: $Id: tkInt.h,v 1.50 2002/06/17 20:09:01 hobbs Exp $
*/
#ifndef _TKINT
@@ -92,6 +92,21 @@ typedef struct TkCursor {
#endif
/*
+ * The following structure is kept one-per-TkDisplay to maintain information
+ * about the caret (cursor location) on this display. This is used to
+ * dictate global focus location (Windows Accessibility guidelines) and to
+ * position the IME or XIM over-the-spot window.
+ */
+
+typedef struct TkCaret {
+ struct TkWindow *winPtr; /* the window on which we requested caret
+ * placement */
+ int x; /* relative x coord of the caret */
+ int y; /* relative y coord of the caret */
+ int height; /* specified height of the window */
+} TkCaret;
+
+/*
* One of the following structures is maintained for each display
* containing a window managed by Tk. In part, the structure is
* used to store thread-specific data, since each thread will have
@@ -488,6 +503,8 @@ typedef struct TkDisplay {
long deletionEpoch; /* Incremented by window deletions */
unsigned int flags; /* Various flag values: these are all
* defined in below. */
+ TkCaret caret; /* information about the caret for this
+ * display. This is not a pointer. */
} TkDisplay;
/*
diff --git a/mac/tkMacXStubs.c b/mac/tkMacXStubs.c
index 2e6b90a..6525c1f 100644
--- a/mac/tkMacXStubs.c
+++ b/mac/tkMacXStubs.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkMacXStubs.c,v 1.13 2002/04/12 07:31:20 hobbs Exp $
+ * RCS: @(#) $Id: tkMacXStubs.c,v 1.14 2002/06/17 20:09:01 hobbs Exp $
*/
#include "tkInt.h"
@@ -811,8 +811,8 @@ TkGetDefaultScreenName(
*
* Tk_SetCaretPos --
*
- * This indicates the cursor position to Tk. This is not used
- * on the Mac currently.
+ * This indicates the cursor position to Tk.
+ * This is currently a noop stub for MacX.
*
*----------------------------------------------------------------------
*/
@@ -820,5 +820,10 @@ TkGetDefaultScreenName(
void
Tk_SetCaretPos(Tk_Window tkwin, int x, int y, int height)
{
- return;
+ TkCaret *caretPtr = &(((TkWindow *) tkwin)->dispPtr->caret);
+
+ caretPtr->winPtr = ((TkWindow *) tkwin);
+ caretPtr->x = x;
+ caretPtr->y = y;
+ caretPtr->height = height;
}
diff --git a/tests/tk.test b/tests/tk.test
index a48716a..d9e8baa 100644
--- a/tests/tk.test
+++ b/tests/tk.test
@@ -3,9 +3,9 @@
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
-# All rights reserved.
+# Copyright (c) 2002 ActiveState Corporation.
#
-# RCS: @(#) $Id: tk.test,v 1.5 2000/10/31 00:52:11 hobbs Exp $
+# RCS: @(#) $Id: tk.test,v 1.6 2002/06/17 20:09:01 hobbs Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
source [file join [pwd] [file dirname [info script]] defs.tcl]
@@ -16,7 +16,7 @@ test tk-1.1 {tk command: general} {
} {1 {wrong # args: should be "tk option ?arg?"}}
test tk-1.2 {tk command: general} {
list [catch {tk xyz} msg] $msg
-} {1 {bad option "xyz": must be appname, scaling, or useinputmethods}}
+} {1 {bad option "xyz": must be appname, caret, scaling, or useinputmethods}}
set appname [tk appname]
test tk-2.1 {tk command: appname} {
@@ -110,6 +110,25 @@ test tk-4.7 {tk command: useinputmethods: set new} {macOrPc} {
} 0
tk useinputmethods $useim
+test tk-5.1 {tk caret} {
+ list [catch {tk caret} msg] $msg
+} {1 {wrong # args: should be "tk caret window ?-x x? ?-y y? ?-height height?"}}
+test tk-5.2 {tk caret} {
+ list [catch {tk caret bogus} msg] $msg
+} {1 {bad window path name "bogus"}}
+test tk-5.3 {tk caret} {
+ list [catch {tk caret . -foo} msg] $msg
+} {1 {bad caret option "-foo": must be -x, -y, or -height}}
+test tk-5.4 {tk caret} {
+ list [catch {tk caret . -x 0 -y} msg] $msg
+} {1 {wrong # args: should be "tk caret window ?-x x? ?-y y? ?-height height?"}}
+test tk-5.5 {tk caret} {
+ list [catch {tk caret . -x 10 -y 11 -h 12; tk caret .} msg] $msg
+} {0 {-height 12 -x 10 -y 11}}
+test tk-5.6 {tk caret} {
+ list [catch {tk caret . -x 20 -y 25 -h 30; tk caret . -hei} msg] $msg
+} {0 30}
+
# cleanup
::tcltest::cleanupTests
return
diff --git a/unix/tkUnixKey.c b/unix/tkUnixKey.c
index ac18f9c..6be5584 100644
--- a/unix/tkUnixKey.c
+++ b/unix/tkUnixKey.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: tkUnixKey.c,v 1.9 2002/06/15 02:08:12 hobbs Exp $
+ * RCS: @(#) $Id: tkUnixKey.c,v 1.10 2002/06/17 20:09:01 hobbs Exp $
*/
#include "tkInt.h"
@@ -18,10 +18,6 @@
* Prototypes for local procedures defined in this file:
*/
-#ifdef TK_USE_INPUT_METHODS
-static int caretX = 0, caretY = 0;
-#endif
-
/*
*----------------------------------------------------------------------
@@ -31,6 +27,7 @@ static int caretX = 0, caretY = 0;
* This enables correct placement of the XIM caret. This is called
* by widgets to indicate their cursor placement, and the caret
* location is used by TkpGetString to place the XIM caret.
+ * This is currently only used for over-the-spot XIM.
*
* Results:
* None
@@ -48,13 +45,16 @@ Tk_SetCaretPos(tkwin, x, y, height)
int y;
int height;
{
-#ifdef TK_USE_INPUT_METHODS
+ TkCaret *caretPtr = &(((TkWindow *) tkwin)->dispPtr->caret);
+
/*
* Use height for best placement of the XIM over-the-spot box.
*/
- caretX = x;
- caretY = y + height;
-#endif
+
+ caretPtr->winPtr = ((TkWindow *) tkwin);
+ caretPtr->x = x;
+ caretPtr->y = y;
+ caretPtr->height = height;
}
/*
@@ -86,6 +86,9 @@ TkpGetString(winPtr, eventPtr, dsPtr)
int len;
Tcl_DString buf;
Status status;
+#ifdef TK_USE_INPUT_METHODS
+ TkDisplay *dispPtr = winPtr->dispPtr;
+#endif
/*
* Overallocate the dstring to the maximum stack amount.
@@ -95,7 +98,7 @@ TkpGetString(winPtr, eventPtr, dsPtr)
Tcl_DStringSetLength(&buf, TCL_DSTRING_STATIC_SIZE-1);
#ifdef TK_USE_INPUT_METHODS
- if ((winPtr->dispPtr->flags & TK_DISPLAY_USE_IM)
+ if ((dispPtr->flags & TK_DISPLAY_USE_IM)
&& (winPtr->inputContext != NULL)
&& (eventPtr->type == KeyPress)) {
#if TK_XIM_SPOT
@@ -121,10 +124,12 @@ TkpGetString(winPtr, eventPtr, dsPtr)
#if TK_XIM_SPOT
/*
- * Adjust the XIM caret position.
+ * Adjust the XIM caret position. We might want to check that
+ * this is the right caret.winPtr as well.
*/
- if (winPtr->dispPtr->flags & TK_DISPLAY_XIM_SPOT) {
- spot.x = caretX; spot.y = caretY;
+ if (dispPtr->flags & TK_DISPLAY_XIM_SPOT) {
+ spot.x = dispPtr->caret.x;
+ spot.y = dispPtr->caret.y + dispPtr->caret.height;
preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL);
XSetICValues(winPtr->inputContext,
XNPreeditAttributes, preedit_attr, NULL);
@@ -183,7 +188,7 @@ TkpSetKeycodeAndState(tkwin, keySym, eventPtr)
if (state & 2) {
TkDisplay *dispPtr;
- dispPtr = ((TkWindow *) tkwin)->dispPtr;
+ dispPtr = ((TkWindow *) tkwin)->dispPtr;
eventPtr->xkey.state |= dispPtr->modeModMask;
}
break;
diff --git a/win/tkWinX.c b/win/tkWinX.c
index 99b5783..85e9464 100644
--- a/win/tkWinX.c
+++ b/win/tkWinX.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkWinX.c,v 1.21 2002/04/12 07:19:13 hobbs Exp $
+ * RCS: @(#) $Id: tkWinX.c,v 1.22 2002/06/17 20:09:01 hobbs Exp $
*/
#include "tkWinInt.h"
@@ -1582,10 +1582,24 @@ void
Tk_SetCaretPos(Tk_Window tkwin, int x, int y, int height)
{
static HWND caretHWND = NULL;
- static int lastX = -1, lastY = -1;
+ TkCaret *caretPtr = &(((TkWindow *) tkwin)->dispPtr->caret);
Window win;
/*
+ * Prevent processing anything if the values haven't changed.
+ * Windows only has one display, so we can do this with statics.
+ */
+ if ((caretPtr->winPtr == ((TkWindow *) tkwin))
+ && (caretPtr->x == x) && (caretPtr->y == y)) {
+ return;
+ }
+
+ caretPtr->winPtr = ((TkWindow *) tkwin);
+ caretPtr->x = x;
+ caretPtr->y = y;
+ caretPtr->height = height;
+
+ /*
* We adjust to the toplevel to get the coords right, as setting
* the IME composition window is based on the toplevel hwnd, so
* ignore height.
@@ -1605,16 +1619,6 @@ Tk_SetCaretPos(Tk_Window tkwin, int x, int y, int height)
HIMC hIMC;
HWND hwnd = Tk_GetHWND(win);
- if ((hwnd == caretHWND) && (lastX == x) && (lastY == y)) {
- /*
- * Prevent processing anything if the values haven't changed.
- */
- return;
- }
-
- lastX = x;
- lastY = y;
-
if (hwnd != caretHWND) {
DestroyCaret();
if (CreateCaret(hwnd, NULL, 0, 0)) {
@@ -1642,6 +1646,5 @@ Tk_SetCaretPos(Tk_Window tkwin, int x, int y, int height)
ImmSetCompositionWindow(hIMC, &cform);
ImmReleaseContext(hwnd, hIMC);
}
-
}
}