From 25f604e4d2e56721809b177202db73a38df2491e Mon Sep 17 00:00:00 2001 From: hobbs Date: Mon, 17 Jun 2002 20:09:01 +0000 Subject: * 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. --- ChangeLog | 14 +++++++++ doc/SetCaret.3 | 40 ++++++++++++++++++++++++++ doc/tk.n | 18 ++++++++++-- generic/tkCmds.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- generic/tkInt.h | 19 +++++++++++- mac/tkMacXStubs.c | 13 ++++++--- tests/tk.test | 25 ++++++++++++++-- unix/tkUnixKey.c | 33 ++++++++++++--------- win/tkWinX.c | 29 ++++++++++--------- 9 files changed, 237 insertions(+), 40 deletions(-) create mode 100644 doc/SetCaret.3 diff --git a/ChangeLog b/ChangeLog index 8d4cc4f..2e68d8f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2002-06-17 Jeff Hobbs + + * 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 * 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 \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); } - } } -- cgit v0.12