tkgoodstuff/libs/tkXAccess.c

1662 lines
55 KiB
C
Raw Normal View History

/*
* tkXAccess.c --
*
* This module implements functionality required for sending
* X events to windows and do other Xlib stuff.
*
* Copyright (c) 1995 by Sven Delmas
* All rights reserved.
* See the file COPYRIGHT for the copyright notes.
*
*/
#ifndef lint
static char *AtFSid = "$Header: /usr1/master/RCS/TclTk/ccode/TkSteal/tkXAccess.c,v 2.0.0.1 1995/10/27 16:12:17 sachin Exp $";
#endif /* not lint */
#include "tkPort.h"
#include "tk.h"
#include "tkXAccess.h"
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
/*
I do not know why, but several window managers require multiple
reparent events. Right now a value of 25 should be enough.
*/
#define REPARENT_LOOPS 25
/* If this variable is 1, X errors will not stop the */
/* continuation of the xaccess command. Otherwise a */
/* standard X error is created. */
static int continueXAccess;
/* This variable contains the cursor that is used */
/* when interactively picking a color from the screen. */
static Cursor tksteal_cursor = (Cursor) NULL;
/* This struct contains the list of predefined */
/* (supported) window properties for the property */
/* manipulation. */
typedef struct {
char *name;
Atom type;
} AtomList;
static AtomList propertyTable[] = {
{"ARC", XA_ARC},
{"ATOM", XA_ATOM},
{"BITMAP", XA_BITMAP},
{"CARDINAL", XA_CARDINAL},
{"COLORMAP", XA_COLORMAP},
{"CURSOR", XA_CURSOR},
{"DRAWABLE", XA_DRAWABLE},
{"FONT", XA_FONT},
{"INTEGER", XA_INTEGER},
{"PIXMAP", XA_PIXMAP},
{"POINT", XA_POINT},
{"RECTANGLE", XA_RECTANGLE},
{"RGB_COLOR_MAP", XA_RGB_COLOR_MAP},
{"STRING", XA_STRING},
{"WINDOW", XA_WINDOW},
{"VISUALID", XA_VISUALID},
{"WM_COMMAND", XA_WM_COMMAND},
{"WM_HINTS", XA_WM_HINTS},
{"WM_ICON_SIZE", XA_WM_ICON_SIZE},
{"WM_SIZE_HINTS", XA_WM_SIZE_HINTS},
{"", 0},
};
/*
* external functions used by TkSteal.
*/
/*
*----------------------------------------------------------------------
*
* LocalXErrorHandler --
*
* This procedure prevents X errors, by replacing the
* standard X error handler.
*
* Results:
* 0
*
* Side effects:
* X errors are ignored.
*
*----------------------------------------------------------------------
*/
static int
LocalXErrorHandler(clientData, errorPtr)
ClientData clientData;
XErrorEvent *errorPtr;
{
continueXAccess = 0;
/*
fprintf(stderr, "X error: errcode %d request %d minor %d<\n",
errorPtr->error_code, errorPtr->request_code,
errorPtr->minor_code);
*/
return 0;
}
/*
*----------------------------------------------------------------------
*
* TkXAccessMatchModifierState --
*
* This procedure matches a string to the corresponding
* modifier state.
*
* Results:
* The state of the modifier.
*
* Side effects:
* None
*
*----------------------------------------------------------------------
*/
static int
TkXAccessMatchModifierState(name)
char *name;
{
size_t length = 0;
length = strlen(name);
if ((strncmp(name, "Any", length) == 0) &&
(length >= 2)) {
return(0);
} else if ((strncmp(name, "Shift", length) == 0) &&
(length >= 2)) {
return(ShiftMask);
} else if ((strncmp(name, "Lock", length) == 0) &&
(length >= 2)) {
return(LockMask);
} else if ((strncmp(name, "Control", length) == 0) &&
(length >= 2)) {
return(ControlMask);
} else if ((strncmp(name, "Meta", length) == 0) &&
(length == 4)) {
return(Mod1Mask);
} else if ((strncmp(name, "Mod1", length) == 0) &&
(length >= 4)) {
return(Mod1Mask);
} else if ((strncmp(name, "Mod2", length) == 0) &&
(length >= 4)) {
return(Mod2Mask);
} else if ((strncmp(name, "Mod3", length) == 0) &&
(length >= 4)) {
return(Mod3Mask);
} else if ((strncmp(name, "Mod4", length) == 0) &&
(length >= 4)) {
return(Mod4Mask);
} else if ((strncmp(name, "Mod5", length) == 0) &&
(length >= 4)) {
return(Mod5Mask);
} else if ((strncmp(name, "Mod2", length) == 0) &&
(length >= 4)) {
return(Mod2Mask);
} else if ((strncmp(name, "Button1", length) == 0) &&
(length >= 7)) {
return(Button1Mask);
} else if ((strncmp(name, "Button2", length) == 0) &&
(length >= 7)) {
return(Button2Mask);
} else if ((strncmp(name, "Button3", length) == 0) &&
(length >= 7)) {
return(Button3Mask);
} else if ((strncmp(name, "Button4", length) == 0) &&
(length >= 7)) {
return(Button4Mask);
} else if ((strncmp(name, "Button5", length) == 0) &&
(length >= 7)) {
return(Button5Mask);
}
return -1;
}
/*
*----------------------------------------------------------------------
*
* TkXAccessCmd --
*
* This procedure gives access to various X-lib calls.
*
* Results:
* Returns a standard Tcl completion code, and leaves an error
* message in interp->result if an error occurs.
*
* Side effects:
* Depends on the performed action.
*
*----------------------------------------------------------------------
*/
int
TkXAccessCmd(clientData, interp, argc, argv)
ClientData clientData; /* Main window associated with
* interpreter. */
Tcl_Interp *interp; /* Current interpreter. */
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
char c;
char *interval = (char *) NULL;
char *property_return = (char *) NULL;
char *win_name = (char *) NULL;
char *windowname = (char *) NULL;
char buf[30];
char error_buf[80];
int actual_format = 0;
int border_width = 0;
int counter1 = 0;
int counter2 = 0;
int counter3 = 0;
int counter4 = 0;
int dataindex = 0;
int datalen = 0;
int delete = 0;
int format = 8;
int grabResult = 0;
int height = 0;
int keysymsPerKeyCode = 0;
int maxKeyCode = 0;
int minKeyCode = 0;
int mode = PropModeReplace;
int num_elements = 0;
int override_redirect = True;
int relative = 0;
int width = 0;
int x = -1002;
int x_ret = -1002;
int x_root = -1002;
int x_root_ret = -1002;
int y = -1002;
int y_ret = -1002;
int y_root = -1002;
int y_root_ret = -1002;
unsigned int button = 0;
unsigned int keycode = 0;
unsigned int mask_ret = 0;
unsigned int modeModifierMask = 0;
unsigned int num_child1 = 0;
unsigned int num_child2 = 0;
unsigned int num_child3 = 0;
unsigned int permanentState = 0;
unsigned int state = 0;
unsigned int tmpKeycode = 0;
long interval_value = 0L;
long long_length = 100000L;
long long_offset = 0L;
long retries = 10000L;
unsigned long bytes_after = 0L;
unsigned long lcounter1 = 0L;
unsigned long lcounter2 = 0L;
unsigned long long_num_elements = 0L;
double interval_steps = 0;
double x_tmp = 0;
double y_tmp = 0;
size_t length = 0;
size_t paramLength = 0;
struct timeval time;
struct timeval startTime;
Window above = (Window) None;
Window child_ret = (Window) None;
Window parent = (Window) None;
Window parent_ret = (Window) None;
Window root_ret = (Window) None;
Window root_window = (Window) None;
Window window = (Window) None;
Window stop_window = (Window) None;
Window *child_list1 = (Window *) None;
Window *child_list2 = (Window *) None;
Window *child_list3 = (Window *) None;
Atom actual_type = (Atom) NULL;
Atom message_type = (Atom) NULL;
Atom property = (Atom) NULL;
Atom req_type = (Atom) XA_STRING;
Atom type = (Atom) XA_STRING;
Atom *atomList = (Atom *) NULL;
KeySym *mainKeyMap;
KeySym keySym;
KeyCode *keyCode;
XColor color;
XWindowAttributes winAttributes;
XImage *image;
XModifierKeymap *modifierMap;
XEvent xevent;
XButtonEvent *xbutton;
XClientMessageEvent *xclient;
XConfigureEvent *xconfig;
XExposeEvent *xexpose;
XKeyEvent *xkey;
XFocusInEvent *xfocusin;
XFocusOutEvent *xfocusout;
Tk_Window abovetkwin = (Tk_Window) NULL;
Tk_Window parenttkwin = (Tk_Window) NULL;
Tk_Window tkrootwin = (Tk_Window) clientData;
Tk_Window tkwin = (Tk_Window) NULL;
Tk_ErrorHandler handler1;
Tk_ErrorHandler handler2;
Tk_ErrorHandler handler3;
if (argc < 2) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, "wrong # args: should be \"",
argv[0], " command ?arg arg....?\"",
(char *) NULL);
return TCL_ERROR;
}
continueXAccess = 1;
/* Parse the arguments. */
while (counter1 < argc) {
length = strlen(argv[counter1]);
if ((strncmp(argv[counter1], "-abovewidget", length) == 0) &&
(counter1 < argc) && (length >= 9)) {
counter1++;
if ((abovetkwin = Tk_NameToWindow(interp, argv[counter1],
tkrootwin)) != (Tk_Window) NULL) {
above = Tk_WindowId(abovetkwin);
}
} else if ((strncmp(argv[counter1], "-abovewindowid", length) == 0) &&
(counter1 < argc) && (length >= 9)) {
counter1++;
above = strtoul(argv[counter1], (char **) NULL, 0);
} else if ((strncmp(argv[counter1], "-borderwidth", length) == 0) &&
(counter1 < argc) && (length >= 3)) {
counter1++;
border_width = atoi(argv[counter1]);
} else if ((strncmp(argv[counter1], "-button", length) == 0) &&
(counter1 < argc) && (length >= 4)) {
counter1++;
paramLength = strlen(argv[counter1]);
if ((strncmp(argv[counter1], "1", paramLength) == 0) &&
(paramLength == 1)) {
button = Button1;
} else if ((strncmp(argv[counter1], "2", paramLength) == 0) &&
(paramLength == 1)) {
button = Button2;
} else if ((strncmp(argv[counter1], "3", paramLength) == 0) &&
(paramLength == 1)) {
button = Button3;
} else if ((strncmp(argv[counter1], "4", paramLength) == 0) &&
(paramLength == 1)) {
button = Button4;
} else if ((strncmp(argv[counter1], "5", paramLength) == 0) &&
(paramLength == 1)) {
button = Button5;
}
} else if ((strncmp(argv[counter1], "-data", length) == 0) &&
(counter1 < argc) && (length >= 3)) {
counter1++;
dataindex = counter1;
datalen = strlen(argv[dataindex]);
} else if ((strncmp(argv[counter1], "-delete", length) == 0) &&
(counter1 < argc) && (length >= 3)) {
counter1++;
delete = atoi(argv[counter1]);
} else if ((strncmp(argv[counter1], "-format", length) == 0) &&
(counter1 < argc) && (length >= 3)) {
counter1++;
format = atoi(argv[counter1]);
} else if ((strncmp(argv[counter1], "-height", length) == 0) &&
(counter1 < argc) && (length >= 3)) {
counter1++;
height = atoi(argv[counter1]);
} else if ((strncmp(argv[counter1], "-interval", length) == 0) &&
(counter1 < argc) && (length >= 3)) {
counter1++;
interval = argv[counter1];
} else if ((strncmp(argv[counter1], "-keycode", length) == 0) &&
(counter1 < argc) && (length >= 4)) {
counter1++;
keycode = XKeysymToKeycode(Tk_Display(tkrootwin),
XStringToKeysym(argv[counter1]));
} else if ((strncmp(argv[counter1], "-longlength", length) == 0) &&
(counter1 < argc) && (length >= 6)) {
counter1++;
long_length = strtoul(argv[counter1], (char **) NULL, 0);
} else if ((strncmp(argv[counter1], "-longoffset", length) == 0) &&
(counter1 < argc) && (length >= 6)) {
counter1++;
long_offset = strtoul(argv[counter1], (char **) NULL, 0);
} else if ((strncmp(argv[counter1], "-messagetype", length) == 0) &&
(counter1 < argc) && (length >= 12)) {
counter1++;
message_type = strtoul(argv[counter1], (char **) NULL, 0);
} else if ((strncmp(argv[counter1], "-messagetypename", length) == 0) &&
(counter1 < argc) && (length >= 13)) {
counter1++;
message_type = Tk_InternAtom(tkrootwin, argv[counter1]);
} else if ((strncmp(argv[counter1], "-numelements", length) == 0) &&
(counter1 < argc) && (length >= 3)) {
counter1++;
num_elements = atoi(argv[counter1]);
} else if ((strncmp(argv[counter1], "-overrideredirect", length) == 0) &&
(counter1 < argc) && (length >= 3)) {
counter1++;
override_redirect = atoi(argv[counter1]);
} else if ((strncmp(argv[counter1], "-parentwidget", length) == 0) &&
(counter1 < argc) && (length >= 10)) {
counter1++;
if ((parenttkwin = Tk_NameToWindow(interp, argv[counter1],
tkrootwin)) != (Tk_Window) NULL) {
parent = Tk_WindowId(parenttkwin);
}
} else if ((strncmp(argv[counter1], "-parentwindowid", length) == 0) &&
(counter1 < argc) && (length >= 10)) {
counter1++;
parent = strtoul(argv[counter1], (char **) NULL, 0);
} else if ((strncmp(argv[counter1], "-property", length) == 0) &&
(counter1 < argc) && (length >= 9)) {
counter1++;
property = strtoul(argv[counter1], (char **) NULL, 0);
} else if ((strncmp(argv[counter1], "-propertyname", length) == 0) &&
(counter1 < argc) && (length >= 10)) {
counter1++;
property = Tk_InternAtom(tkrootwin, argv[counter1]);
} else if ((strncmp(argv[counter1], "-propmode", length) == 0) &&
(counter1 < argc) && (length >= 6)) {
counter1++;
if (strcmp(argv[counter1], "replace") == 0) {
mode = PropModeReplace;
} else if (strcmp(argv[counter1], "prepend") == 0) {
mode = PropModePrepend;
} else if (strcmp(argv[counter1], "append") == 0) {
mode = PropModeAppend;
}
} else if ((strncmp(argv[counter1], "-proptype", length) == 0) &&
(counter1 < argc) && (length >= 6)) {
counter1++;
lcounter1 = 0;
while (1) {
if (strcmp(propertyTable[lcounter1].name, "") == 0) {
break;
}
if (strcmp(propertyTable[lcounter1].name, argv[counter1]) == 0) {
type = propertyTable[lcounter1].type;
req_type = propertyTable[lcounter1].type;
break;
}
lcounter1++;
}
} else if ((strncmp(argv[counter1], "-relative", length) == 0) &&
(counter1 < argc) && (length >= 3)) {
counter1++;
relative = atoi(argv[counter1]);
} else if ((strncmp(argv[counter1], "-retries", length) == 0) &&
(counter1 < argc) && (length >= 3)) {
counter1++;
retries = strtoul(argv[counter1], (char **) NULL, 0);
} else if ((strncmp(argv[counter1], "-state", length) == 0) &&
(counter1 < argc) && (length >= 4)) {
counter1++;
if (TkXAccessMatchModifierState(argv[counter1]) != -1) {
state |= TkXAccessMatchModifierState(argv[counter1]);
}
} else if ((strncmp(argv[counter1], "-widget", length) == 0) &&
(counter1 < argc) && (length >= 4)) {
counter1++;
if ((tkwin = Tk_NameToWindow(interp, argv[counter1],
tkrootwin)) != (Tk_Window) NULL) {
window = Tk_WindowId(tkwin);
}
} else if ((strncmp(argv[counter1], "-width", length) == 0) &&
(counter1 < argc) && (length >= 3)) {
counter1++;
width = atoi(argv[counter1]);
} else if ((strncmp(argv[counter1], "-windowid", length) == 0) &&
(counter1 < argc) && (length >= 4)) {
counter1++;
window = strtoul(argv[counter1], (char **) NULL, 0);
} else if ((strncmp(argv[counter1], "-windowname", length) == 0) &&
(counter1 < argc) && (length >= 4)) {
counter1++;
windowname = argv[counter1];
} else if ((strncmp(argv[counter1], "-x", length) == 0) &&
(counter1 < argc) && (length == 2)) {
counter1++;
x = atoi(argv[counter1]);
} else if ((strncmp(argv[counter1], "-xroot", length) == 0) &&
(counter1 < argc) && (length >= 3)) {
counter1++;
x_root = atoi(argv[counter1]);
} else if ((strncmp(argv[counter1], "-y", length) == 0) &&
(counter1 < argc) && (length == 2)) {
counter1++;
y = atoi(argv[counter1]);
} else if ((strncmp(argv[counter1], "-yroot", length) == 0) &&
(counter1 < argc) && (length >= 3)) {
counter1++;
y_root = atoi(argv[counter1]);
}
counter1++;
}
/* Make sure that the possible X errors are */
/* ignored. At least we don't care about. */
handler1 = Tk_CreateErrorHandler(Tk_Display(tkrootwin), BadWindow,
-1, -1, LocalXErrorHandler,
(ClientData) NULL);
handler2 = Tk_CreateErrorHandler(Tk_Display(tkrootwin), BadAccess,
X_GetProperty, -1,
LocalXErrorHandler, (ClientData)
NULL);
handler3 = Tk_CreateErrorHandler(Tk_Display(tkrootwin), BadAtom,
X_GetProperty, -1,
LocalXErrorHandler, (ClientData)
NULL);
/* Validate the parameters. */
length = strlen(argv[1]);
if (window == (Window) None &&
!(((strncmp(argv[1], "eventmotion", length) == 0) && length >= 7) ||
((strncmp(argv[1], "eventreparent", length) == 0) && length >= 6))) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, argv[0], ": no target window specified",
(char *) NULL);
goto error;
}
if (format != 8 && format != 16 && format != 32) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, argv[0],
": wrong format value (must be 8, 16 or 32)",
(char *) NULL);
goto error;
}
/* Retrieve global (often used) informations. */
if (window != (Window) None) {
XQueryTree(Tk_Display(tkrootwin), window, &root_ret, &parent_ret,
&child_list1, &num_child1);
if (!continueXAccess) {
sprintf(error_buf, "querying the widget tree for the root window!");
goto Xerror;
}
XQueryPointer(Tk_Display(tkrootwin), window, &root_ret,
&child_ret, &x_root_ret, &y_root_ret, &x_ret,
&y_ret, &mask_ret);
if (!continueXAccess) {
sprintf(error_buf, "querying the current pointer position!");
goto Xerror;
}
} else {
XQueryTree(Tk_Display(tkrootwin), Tk_WindowId(tkrootwin),
&root_ret, &parent_ret, &child_list1, &num_child1);
if (!continueXAccess) {
sprintf(error_buf, "querying the widget tree for the root window!");
goto Xerror;
}
XQueryPointer(Tk_Display(tkrootwin), Tk_WindowId(tkrootwin),
&root_ret, &child_ret, &x_root_ret, &y_root_ret,
&x_ret, &y_ret, &mask_ret);
if (!continueXAccess) {
sprintf(error_buf, "querying the current pointer position!");
goto Xerror;
}
}
(void) gettimeofday(&time, (struct timezone *) NULL);
if (num_elements == 0) {
num_elements = datalen;
}
if (width == 0 && tkwin != (Tk_Window) NULL) {
width = Tk_Width(tkwin);
}
if (height == 0 && tkwin != (Tk_Window) NULL) {
height = Tk_Height(tkwin);
}
if (x == -1002) {
x = x_ret;
}
if (x_root == -1002) {
x_root = x_root_ret;
}
if (y == -1002) {
y = y_ret;
}
if (y_root == -1002) {
y_root = y_root_ret;
}
c = argv[1][0];
if ((c == 'e') &&
(strncmp(argv[1], "eventbuttonpress", length) == 0) &&
(length >= 12)) {
xevent.type = ButtonPress;
xbutton = (XButtonPressedEvent*) &xevent;
xbutton->display = Tk_Display(tkrootwin);
xbutton->window = window;
xbutton->root = root_ret;
xbutton->subwindow = child_ret;
xbutton->time = (time.tv_sec * 1000) + time.tv_usec;
xbutton->x = x;
xbutton->y = y;
xbutton->x_root = x_root;
xbutton->y_root = y_root;
xbutton->state = state;
xbutton->button = button;
xbutton->same_screen = True;
XSendEvent(Tk_Display(tkrootwin), window, True, 0xffffL, &xevent);
if (!continueXAccess) {
sprintf(error_buf, "event button press %d", button);
goto Xerror;
}
} else if ((c == 'e') &&
(strncmp(argv[1], "eventbuttonrelease", length) == 0) &&
(length >= 12)) {
xevent.type = ButtonRelease;
xbutton = (XButtonReleasedEvent*) &xevent;
xbutton->display = Tk_Display(tkrootwin);
xbutton->window = window;
xbutton->root = root_ret;
xbutton->subwindow = child_ret;
xbutton->time = (time.tv_sec * 1000) + time.tv_usec;
xbutton->x = x;
xbutton->y = y;
xbutton->x_root = x_root;
xbutton->y_root = y_root;
xbutton->state = state;
xbutton->button = button;
xbutton->same_screen = True;
XSendEvent(Tk_Display(tkrootwin), window, True, 0xffffL, &xevent);
if (!continueXAccess) {
sprintf(error_buf, "event button release %d", button);
goto Xerror;
}
} else if ((c == 'e') &&
(strncmp(argv[1], "eventclientmessage", length) == 0) &&
(length >= 7)) {
xevent.type = ClientMessage;
xclient = (XClientMessageEvent*) &xevent;
xclient->display = Tk_Display(tkrootwin);
xclient->window = window;
xclient->message_type = message_type;
xclient->format = format;
XSendEvent(Tk_Display(tkrootwin), window, True, 0xffffL, &xevent);
if (!continueXAccess) {
sprintf(error_buf, "event client message");
goto Xerror;
}
} else if ((c == 'e') &&
(strncmp(argv[1], "eventconfigure", length) == 0) &&
(length >= 7)) {
xevent.type = ConfigureNotify;
xconfig = (XConfigureEvent*) &xevent;
xconfig->display = Tk_Display(tkrootwin);
xconfig->event = window;
xconfig->window = window;
xconfig->x = x;
xconfig->y = y;
xconfig->width = width;
xconfig->height = height;
xconfig->border_width = border_width;
xconfig->above = above;
xconfig->override_redirect = override_redirect;
XSendEvent(Tk_Display(tkrootwin), window, True, 0xffffL, &xevent);
if (!continueXAccess) {
sprintf(error_buf, "event configure notifiy");
goto Xerror;
}
} else if ((c == 'e') &&
(strncmp(argv[1], "eventexpose", length) == 0) &&
(length >= 6)) {
xevent.type = Expose;
xexpose = (XExposeEvent*) &xevent;
xexpose->count = 0;
xexpose->display = Tk_Display(tkrootwin);
xexpose->window = window;
xexpose->x = x;
xexpose->y = y;
xexpose->width = width;
xexpose->height = height;
XSendEvent(Tk_Display(tkrootwin), window, True, 0xffffL, &xevent);
if (!continueXAccess) {
sprintf(error_buf, "event window expose");
goto Xerror;
}
} else if ((c == 'e') &&
(strncmp(argv[1], "eventfocusin", length) == 0) &&
(length >= 11)) {
xevent.type = FocusIn;
xfocusin = (XFocusInEvent*) &xevent;
xfocusin->display = Tk_Display(tkrootwin);
xfocusin->window = window;
xfocusin->mode = NotifyNormal;
xfocusin->detail = NotifyPointer;
XSendEvent(Tk_Display(tkrootwin), window, True, 0xffffL, &xevent);
if (!continueXAccess) {
sprintf(error_buf, "event window focusin");
goto Xerror;
}
} else if ((c == 'e') &&
(strncmp(argv[1], "eventfocusout", length) == 0) &&
(length >= 11)) {
xevent.type = FocusOut;
xfocusout = (XFocusOutEvent*) &xevent;
xfocusout->display = Tk_Display(tkrootwin);
xfocusout->window = window;
xfocusout->mode = NotifyNormal;
xfocusout->detail = NotifyPointer;
XSendEvent(Tk_Display(tkrootwin), window, True, 0xffffL, &xevent);
if (!continueXAccess) {
sprintf(error_buf, "event window focusout");
goto Xerror;
}
} else if ((c == 'e') &&
(strncmp(argv[1], "eventkeypress", length) == 0) &&
(length >= 9)) {
xevent.type = KeyPress;
xkey = (XKeyPressedEvent*) &xevent;
xkey->display = Tk_Display(tkrootwin);
xkey->window = window;
xkey->root = root_ret;
xkey->subwindow = child_ret;
xkey->time = (time.tv_sec * 1000) + time.tv_usec;
xkey->x = x;
xkey->y = y;
xkey->x_root = x_root;
xkey->y_root = y_root;
xkey->state = state;
xkey->keycode = keycode;
xkey->same_screen = True;
XSendEvent(Tk_Display(tkrootwin), window, True, 0xffffL, &xevent);
if (!continueXAccess) {
sprintf(error_buf, "event key press %d", keycode);
goto Xerror;
}
} else if ((c == 'e') &&
(strncmp(argv[1], "eventkeyrelease", length) == 0) &&
(length >= 9)) {
xevent.type = KeyRelease;
xkey = (XKeyReleasedEvent*) &xevent;
xkey->display = Tk_Display(tkrootwin);
xkey->window = window;
xkey->root = root_ret;
xkey->subwindow = child_ret;
xkey->time = (time.tv_sec * 1000) + time.tv_usec;
xkey->x = x;
xkey->y = y;
xkey->x_root = x_root;
xkey->y_root = y_root;
xkey->state = state;
xkey->keycode = keycode;
xkey->same_screen = True;
XSendEvent(Tk_Display(tkrootwin), window, True, 0xffffL, &xevent);
if (!continueXAccess) {
sprintf(error_buf, "event key release %d", keycode);
goto Xerror;
}
} else if ((c == 'e') && (strncmp(argv[1], "eventmap", length) == 0) &&
(length >= 7)) {
XMapWindow(Tk_Display(tkrootwin), window);
if (!continueXAccess) {
sprintf(error_buf, "event window map");
goto Xerror;
}
} else if ((c == 'e') &&
(strncmp(argv[1], "eventmotion", length) == 0) &&
(length >= 7)) {
if (interval != (char *) NULL) {
interval_steps = atof(interval);
}
XQueryPointer(Tk_Display(tkrootwin), Tk_WindowId(tkrootwin),
&root_ret, &child_ret, &x_root_ret, &y_root_ret,
&x_ret, &y_ret, &mask_ret);
if (!continueXAccess) {
sprintf(error_buf, "querying the current pointer position!");
goto Xerror;
}
if (window == (Window) None) {
if (!relative) {
x -= x_root_ret;
y -= y_root_ret;
}
}
if (interval_steps > 0) {
x_tmp = x_ret;
y_tmp = y_ret;
while (x_tmp != x || y_tmp != y) {
if (x_tmp < x) {
x_tmp += interval_steps;
if (x_tmp > x) {
x_tmp = x;
}
} else {
x_tmp -= interval_steps;
if (x_tmp < x) {
x_tmp = x;
}
}
if (y_tmp < y) {
y_tmp += interval_steps;
if (y_tmp > y) {
y_tmp = y;
}
} else {
y_tmp -= interval_steps;
if (y_tmp < y) {
y_tmp = y;
}
}
XWarpPointer(Tk_Display(tkrootwin), (Window) None, (Window) window,
0, 0, 0, 0, (int) x_tmp, (int) y_tmp);
if (!continueXAccess) {
sprintf(error_buf,
"setting the pointer position to x:%d y:%d",
(int) x_tmp, (int) y_tmp);
goto Xerror;
}
XSync(Tk_Display(tkrootwin), False);
}
} else {
XWarpPointer(Tk_Display(tkrootwin), (Window) None, (Window) window,
0, 0, 0, 0, x, y);
if (!continueXAccess) {
sprintf(error_buf,
"setting the pointer position to x:%d y:%d", x, y);
goto Xerror;
}
}
} else if ((c == 'e') &&
(strncmp(argv[1], "eventreparent", length) == 0) &&
(length >= 6)) {
if (parent == (Window) None) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, argv[0], ": no parent window specified",
(char *) NULL);
goto error;
}
/* Get the first level of X windows. */
#if defined(XlibSpecificationRelease)
XFree((Window *) child_list1);
#else
XFree((char *) child_list1);
#endif
child_list1 = (Window *) None;
XSync(Tk_Display(tkrootwin), False);
XQueryTree(Tk_Display(tkrootwin), Tk_WindowId(tkrootwin),
&root_window, &parent_ret, &child_list1, &num_child1);
if (!continueXAccess) {
sprintf(error_buf, "querying the widget tree for the root window!");
goto Xerror;
}
if (windowname != (char *) NULL && strcmp(windowname, "") != 0) {
/* Get the second, third and fourth level of X */
/* windows. Check their names against the name to */
/* reparent. Do this several times, as it may take */
/* some time for the embedded application to create */
/* the window. */
#if defined(XlibSpecificationRelease)
XFree((Window *) child_list1);
#else
XFree((char *) child_list1);
#endif
child_list1 = (Window *) None;
for (counter4 = 0; counter4 < retries; counter4++) {
XSync(Tk_Display(tkrootwin), False);
XQueryTree(Tk_Display(tkrootwin), root_window,
&root_ret, &parent_ret, &child_list1, &num_child1);
if (!continueXAccess) {
sprintf(error_buf, "querying the widget tree for the root window!");
goto Xerror;
}
for (counter1 = 0; counter1 < num_child1; counter1++) {
XSync(Tk_Display(tkrootwin), False);
XFetchName(Tk_Display(tkrootwin), child_list1[counter1],
&win_name);
if (!continueXAccess) {
sprintf(error_buf, "retrieving window name!");
goto Xerror;
}
if (win_name != (char *) NULL && strcmp(win_name, "") != 0) {
if (Tcl_StringMatch(win_name, windowname)) {
window = child_list1[counter1];
XFree(win_name);
goto doreparent;
}
XFree(win_name);
}
XSync(Tk_Display(tkrootwin), False);
XQueryTree(Tk_Display(tkrootwin), child_list1[counter1],
&root_ret, &parent_ret, &child_list2, &num_child2);
if (!continueXAccess) {
sprintf(error_buf, "querying the widget tree for the root window!");
goto Xerror;
}
for (counter2 = 0; counter2 < num_child2; counter2++) {
XSync(Tk_Display(tkrootwin), False);
XFetchName(Tk_Display(tkrootwin), child_list2[counter2],
&win_name);
if (!continueXAccess) {
sprintf(error_buf, "retrieving window name!");
goto Xerror;
}
if (win_name != (char *) NULL && strcmp(win_name, "") != 0) {
if (Tcl_StringMatch(win_name, windowname)) {
window = child_list2[counter2];
XFree(win_name);
goto doreparent;
}
XFree(win_name);
}
XSync(Tk_Display(tkrootwin), False);
XQueryTree(Tk_Display(tkrootwin), child_list2[counter2],
&root_ret, &parent_ret, &child_list3, &num_child3);
if (!continueXAccess) {
sprintf(error_buf, "querying the widget tree for the root window!");
goto Xerror;
}
for (counter3 = 0; counter3 < num_child3; counter3++) {
XSync(Tk_Display(tkrootwin), False);
XFetchName(Tk_Display(tkrootwin), child_list3[counter3],
&win_name);
if (!continueXAccess) {
sprintf(error_buf, "retrieving window name!");
goto Xerror;
}
if (win_name != (char *) NULL && strcmp(win_name, "") != 0) {
if (Tcl_StringMatch(win_name, windowname)) {
window = child_list3[counter3];
XFree(win_name);
goto doreparent;
}
XFree(win_name);
}
}
#if defined(XlibSpecificationRelease)
XFree((Window *) child_list3);
#else
XFree((char *) child_list3);
#endif
child_list3 = (Window *) None;
}
#if defined(XlibSpecificationRelease)
XFree((Window *) child_list2);
#else
XFree((char *) child_list2);
#endif
child_list2 = (Window *) None;
}
#if defined(XlibSpecificationRelease)
XFree((Window *) child_list1);
#else
XFree((char *) child_list1);
#endif
child_list1 = (Window *) None;
}
}
doreparent:
if (window != (Window) None) {
/* We found the window to reparent... now reparent it */
XSync(Tk_Display(tkrootwin), False);
XWithdrawWindow(Tk_Display(tkrootwin), window,
Tk_ScreenNumber(tkrootwin));
for (counter1 = 0; counter1 < REPARENT_LOOPS; counter1++) {
XReparentWindow(Tk_Display(tkrootwin), window, parent, 0, 0);
XSync(Tk_Display(tkrootwin), False);
}
XMapWindow(Tk_Display(tkrootwin), window);
if (!continueXAccess) {
XSync(Tk_Display(tkrootwin), False);
sprintf(error_buf, "event window reparent %ld to %ld", window, parent);
goto Xerror;
}
Tcl_ResetResult(interp);
sprintf(buf, "%ld", window);
Tcl_AppendResult(interp, buf, (char *) NULL);
}
XSync(Tk_Display(tkrootwin), False);
} else if ((c == 'e') &&
(strncmp(argv[1], "eventunmap", length) == 0) &&
(length >= 6)) {
XUnmapWindow(Tk_Display(tkrootwin), window);
if (!continueXAccess) {
sprintf(error_buf, "event window unmap");
goto Xerror;
}
} else if ((c == 'p') && (strncmp(argv[1], "pickcolor", length) == 0) &&
(length >= 3)) {
#if defined(XlibSpecificationRelease)
XFree((Window *) child_list1);
#else
XFree((char *) child_list1);
#endif
child_list1 = (Window *) None;
if (tksteal_cursor == (Cursor) NULL) {
tksteal_cursor = XCreateFontCursor(Tk_Display(tkrootwin), XC_target);
}
Tcl_ResetResult(interp);
XQueryTree(Tk_Display(tkrootwin), Tk_WindowId(tkrootwin),
&root_window, &parent_ret, &child_list1, &num_child1);
XUngrabPointer(Tk_Display(tkrootwin), CurrentTime);
grabResult = XGrabPointer(Tk_Display(tkrootwin), window,
False, ButtonReleaseMask,
GrabModeAsync, GrabModeAsync, None,
tksteal_cursor, CurrentTime);
if (grabResult == GrabSuccess) {
counter1 = 1;
while (counter1) {
XNextEvent(Tk_Display(tkrootwin), &xevent);
switch (xevent.type) {
case ButtonRelease:
window = root_window;
x = xevent.xbutton.x_root;
y = xevent.xbutton.y_root;
XTranslateCoordinates(Tk_Display(tkrootwin), window, window,
x, y, &x, &y, &stop_window);
if (!stop_window)
stop_window = window;
XGetWindowAttributes(Tk_Display(tkrootwin), stop_window,
&winAttributes);
if (winAttributes.depth ==
DefaultDepth(Tk_Display(tkrootwin),
Tk_ScreenNumber(tkrootwin))) {
image = XGetImage(Tk_Display(tkrootwin), root_window,
xevent.xbutton.x_root,
xevent.xbutton.y_root,
1, 1, AllPlanes, ZPixmap);
} else {
XTranslateCoordinates(Tk_Display(tkrootwin), root_window,
window, xevent.xbutton.x_root,
xevent.xbutton.y_root,
&x_ret, &y_ret, &stop_window);
image = XGetImage(Tk_Display(tkrootwin), root_window,
x_ret, y_ret, 1, 1, AllPlanes, ZPixmap);
}
color.pixel = XGetPixel(image, 0, 0);
XQueryColor(Tk_Display(tkrootwin), winAttributes.colormap, &color);
sprintf(buf, "#%04x%04x%04x", color.red, color.green, color.blue);
Tcl_AppendResult(interp, buf, (char *) NULL);
XDestroyImage(image);
counter1 = 0;
break;
}
}
} else {
Tcl_ResetResult(interp);
sprintf(buf, "%d", grabResult);
Tcl_AppendResult(interp, argv[0], ": unable to grab server (",
buf, ")", (char *) NULL);
goto error;
}
XUngrabPointer(Tk_Display(tkrootwin), CurrentTime);
} else if ((c == 'p') && (strncmp(argv[1], "propchange", length) == 0) &&
(length >= 5)) {
if (dataindex == 0) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, argv[0], ": no data defined",
(char *) NULL);
goto error;
}
if (property == (Atom) NULL) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, argv[0], ": no property specified",
(char *) NULL);
goto error;
}
XChangeProperty(Tk_Display(tkrootwin), window, property, type,
format, mode, (unsigned char *) argv[dataindex],
num_elements);
if (!continueXAccess) {
sprintf(error_buf, "event change property");
goto Xerror;
}
} else if ((c == 'p') && (strncmp(argv[1], "propdelete", length) == 0) &&
(length >= 5)) {
XDeleteProperty(Tk_Display(tkrootwin), window, property);
} else if ((c == 'p') && (strncmp(argv[1], "propget", length) == 0) &&
(length >= 5)) {
if (property == (Atom) NULL) {
atomList = XListProperties(Tk_Display(tkrootwin), window,
&num_elements);
if (!continueXAccess) {
sprintf(error_buf, "event list properties");
goto Xerror;
}
if (atomList != (Atom *) NULL) {
Tcl_ResetResult(interp);
for (counter1 = 0; counter1 < num_elements; counter1++) {
sprintf(buf, "%ld ", atomList[counter1]);
Tcl_AppendResult(interp, buf, (char *) NULL);
}
#if defined(XlibSpecificationRelease)
XFree((Atom *) atomList);
#else
XFree((char *) atomList);
#endif
}
} else {
if (XGetWindowProperty(Tk_Display(tkrootwin), window, property,
long_offset, long_length, delete, req_type,
&actual_type, &actual_format,
&long_num_elements, &bytes_after,
(unsigned char **) &property_return) != Success) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, argv[0], ": could not read property",
(char *) NULL);
goto error;
}
if (actual_type == None) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, argv[0], ": could not read property",
(char *) NULL);
goto error;
}
if (actual_type != XA_STRING) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, argv[0], ": can only retrieve XA_STRING type",
(char *) NULL);
goto error;
}
if (!continueXAccess) {
sprintf(error_buf, "event get window property");
goto Xerror;
}
lcounter1 = 0;
Tcl_ResetResult(interp);
Tcl_AppendResult(interp,
XGetAtomName(Tk_Display(tkrootwin), property),
(char *) NULL);
Tcl_AppendResult(interp, " ", (char *) NULL);
while (1) {
if (strcmp(propertyTable[lcounter1].name, "") == 0) {
Tcl_AppendResult(interp, "UNDEFINED", (char *) NULL);
break;
}
if (propertyTable[lcounter1].type == actual_type) {
Tcl_AppendResult(interp,
propertyTable[lcounter1].name,
(char *) NULL);
break;
}
lcounter1++;
}
Tcl_AppendResult(interp, " {", (char *) NULL);
for (lcounter2 = 0; lcounter2 < long_num_elements; lcounter2++) {
sprintf(buf, "%c", property_return[lcounter2]);
Tcl_AppendResult(interp, buf, (char *) NULL);
if (property_return[lcounter2] == '\0' &&
lcounter2 < long_num_elements-1) {
Tcl_AppendResult(interp, "} {", (char *) NULL);
}
}
Tcl_AppendResult(interp, "}", (char *) NULL);
XFree((char *) property_return);
}
} else if ((c == 's') && (strncmp(argv[1], "sendstring", length) == 0) &&
(length >= 2)) {
if (dataindex == 0) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, argv[0], ": no data defined",
(char *) NULL);
goto error;
}
if (interval != (char *) NULL) {
interval_value = atol(interval);
}
if ((modifierMap = XGetModifierMapping(Tk_Display(tkrootwin))) == NULL) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, argv[0], ": unable to get ",
"modifier mapping", (char *) NULL);
goto error;
}
/* Thanks go to John Ousterhout who implemented this in */
/* tkBind.c... so I took it from there instead of reimplementing. */
keyCode = modifierMap->modifiermap;
for (counter2 = 0; counter2 < 8 * modifierMap->max_keypermod;
counter2++, keyCode++) {
if (*keyCode == 0) {
continue;
}
if (XKeycodeToKeysym(Tk_Display(tkrootwin), *keyCode, 0)
== XK_Mode_switch) {
modeModifierMask |= ShiftMask << (counter2/modifierMap->max_keypermod);
}
}
XFreeModifiermap(modifierMap);
XDisplayKeycodes(Tk_Display(tkrootwin), &minKeyCode, &maxKeyCode);
if ((mainKeyMap = XGetKeyboardMapping(Tk_Display(tkrootwin),
(KeyCode) minKeyCode,
(maxKeyCode - minKeyCode + 1),
&keysymsPerKeyCode)) == NULL) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, argv[0], ": unable to get ",
"keyboard mapping", (char *) NULL);
goto error;
}
for (counter1 = 0; counter1 < datalen; counter1++) {
if (argv[dataindex][counter1] == '<') {
counter1++;
if (counter1 == datalen) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, argv[0], ": malformed data defined: \"",
argv[dataindex], "\"", (char *) NULL);
goto error;
}
if (argv[dataindex][counter1] != '<') {
if (argv[dataindex][counter1] == 'P' &&
argv[dataindex][counter1+1] == 'r' &&
argv[dataindex][counter1+2] == 'e' &&
argv[dataindex][counter1+3] == 's' &&
argv[dataindex][counter1+4] == 's' &&
argv[dataindex][counter1+5] == '-') {
counter1 += 6;
if (counter1 == datalen) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, argv[0], ": malformed data defined: \"",
argv[dataindex], "\"", (char *) NULL);
goto error;
}
lcounter1 = 0;
while (counter1 < datalen && argv[dataindex][counter1] != '>') {
buf[lcounter1++] = argv[dataindex][counter1++];
}
buf[lcounter1] = '\0';
if (TkXAccessMatchModifierState(buf) != -1) {
permanentState |= TkXAccessMatchModifierState(buf);
}
continue;
} else {
if (argv[dataindex][counter1] == 'R' &&
argv[dataindex][counter1+1] == 'e' &&
argv[dataindex][counter1+2] == 'l' &&
argv[dataindex][counter1+3] == 'e' &&
argv[dataindex][counter1+4] == 'a' &&
argv[dataindex][counter1+5] == 's' &&
argv[dataindex][counter1+6] == 'e' &&
argv[dataindex][counter1+7] == '-') {
counter1 += 8;
if (counter1 == datalen) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, argv[0],
": malformed data defined: \"",
argv[dataindex], "\"", (char *) NULL);
goto error;
}
lcounter1 = 0;
while (counter1 < datalen && argv[dataindex][counter1] != '>') {
buf[lcounter1++] = argv[dataindex][counter1++];
}
buf[lcounter1] = '\0';
if (TkXAccessMatchModifierState(buf) != -1) {
permanentState &= ~TkXAccessMatchModifierState(buf);
}
continue;
} else {
lcounter1 = 0;
while (counter1 < datalen && argv[dataindex][counter1] != '>') {
buf[lcounter1++] = argv[dataindex][counter1++];
}
buf[lcounter1] = '\0';
if (TkXAccessMatchModifierState(buf) != -1) {
state |= TkXAccessMatchModifierState(buf);
continue;
}
}
}
} else {
buf[0] = argv[dataindex][counter1];
buf[1] = '\0';
}
} else {
buf[0] = argv[dataindex][counter1];
buf[1] = '\0';
}
/* now we map certain special character. Is there another way */
/* to do this (ok besides using a ascii indexed table) ??? */
if (strlen(buf) == 1) {
switch (buf[0]) {
case '^':
strcpy(buf, "asciicircum");
break;
case '~':
strcpy(buf, "asciitilde");
break;
case ' ':
strcpy(buf, "space");
break;
case '!':
strcpy(buf, "exclam");
break;
case '"':
strcpy(buf, "quotedbl");
break;
case '@':
strcpy(buf, "at");
break;
case '$':
strcpy(buf, "dollar");
break;
case '%':
strcpy(buf, "percent");
break;
case '&':
strcpy(buf, "ampersand");
break;
case '/':
strcpy(buf, "slash");
break;
case '(':
strcpy(buf, "parenleft");
break;
case ')':
strcpy(buf, "parenright");
break;
case '{':
strcpy(buf, "braceleft");
break;
case '}':
strcpy(buf, "braceright");
break;
case '[':
strcpy(buf, "bracketleft");
break;
case ']':
strcpy(buf, "bracketright");
break;
case '=':
strcpy(buf, "equal");
break;
case '?':
strcpy(buf, "question");
break;
case '\\':
strcpy(buf, "backslash");
break;
case '\'':
strcpy(buf, "apostrophe");
break;
case '`':
strcpy(buf, "grave");
break;
case '+':
strcpy(buf, "plus");
break;
case '*':
strcpy(buf, "asterisk");
break;
case '#':
strcpy(buf, "numbersign");
break;
case '|':
strcpy(buf, "bar");
break;
case ',':
strcpy(buf, "comma");
break;
case ';':
strcpy(buf, "semicolon");
break;
case '.':
strcpy(buf, "period");
break;
case ':':
strcpy(buf, "colon");
break;
case '-':
strcpy(buf, "minus");
break;
case '_':
strcpy(buf, "underscore");
break;
case '<':
strcpy(buf, "less");
break;
case '>':
strcpy(buf, "greater");
break;
case '\t':
strcpy(buf, "Tab");
break;
case '\r':
strcpy(buf, "Return");
break;
case '\n':
strcpy(buf, "Return");
break;
case '\b':
strcpy(buf, "BackSpace");
break;
}
}
keycode = 0;
tmpKeycode = XKeysymToKeycode(Tk_Display(tkrootwin),
XStringToKeysym(buf));
keySym = XKeycodeToKeysym(Tk_Display(tkrootwin), tmpKeycode, 0);
if (XKeysymToString(keySym) != NULL &&
strcmp(buf, XKeysymToString(keySym)) == 0) {
keycode = tmpKeycode;
}
if (keycode == 0 && keysymsPerKeyCode > 0) {
keySym = XKeycodeToKeysym(Tk_Display(tkrootwin), tmpKeycode, 1);
if (XKeysymToString(keySym) != NULL &&
strcmp(buf, XKeysymToString(keySym)) == 0) {
keycode = tmpKeycode;
state |= ShiftMask;
}
}
if (keycode == 0 && keysymsPerKeyCode > 1) {
keySym = XKeycodeToKeysym(Tk_Display(tkrootwin), tmpKeycode, 2);
if (XKeysymToString(keySym) != NULL &&
strcmp(buf, XKeysymToString(keySym)) == 0) {
keycode = tmpKeycode;
state |= modeModifierMask;
}
}
if (keycode == 0 && keysymsPerKeyCode > 2) {
keySym = XKeycodeToKeysym(Tk_Display(tkrootwin), tmpKeycode, 3);
if (XKeysymToString(keySym) != NULL &&
strcmp(buf, XKeysymToString(keySym)) == 0) {
keycode = tmpKeycode;
state |= ShiftMask;
state |= modeModifierMask;
}
}
if (keycode != 0) {
(void) gettimeofday(&time, (struct timezone *) NULL);
xevent.type = KeyPress;
xkey = (XKeyPressedEvent*) &xevent;
xkey->display = Tk_Display(tkrootwin);
xkey->window = window;
xkey->root = root_ret;
xkey->subwindow = child_ret;
xkey->time = (time.tv_sec * 1000) + time.tv_usec;
xkey->x = x;
xkey->y = y;
xkey->x_root = x_root;
xkey->y_root = y_root;
xkey->state = state | permanentState;
xkey->keycode = keycode;
xkey->same_screen = True;
XSendEvent(Tk_Display(tkrootwin), window, True, 0xffffL, &xevent);
if (!continueXAccess) {
sprintf(error_buf, "event key press %d", keycode);
goto Xerror;
}
XSync(Tk_Display(tkrootwin), False);
(void) gettimeofday(&time, (struct timezone *) NULL);
xevent.type = KeyRelease;
xkey = (XKeyReleasedEvent*) &xevent;
xkey->display = Tk_Display(tkrootwin);
xkey->window = window;
xkey->root = root_ret;
xkey->subwindow = child_ret;
xkey->time = (time.tv_sec * 1000) + time.tv_usec;
xkey->x = x;
xkey->y = y;
xkey->x_root = x_root;
xkey->y_root = y_root;
xkey->state = state | permanentState;
xkey->keycode = keycode;
xkey->same_screen = True;
XSendEvent(Tk_Display(tkrootwin), window, True, 0xffffL, &xevent);
if (!continueXAccess) {
sprintf(error_buf, "event key release %d", keycode);
goto Xerror;
}
XSync(Tk_Display(tkrootwin), False);
if (interval_value > 0) {
(void) gettimeofday(&startTime, (struct timezone *) NULL);
startTime.tv_sec += interval_value;
while (1) {
(void) gettimeofday(&time, (struct timezone *) NULL);
if ((startTime.tv_sec < time.tv_sec) ||
((startTime.tv_sec == time.tv_sec) &&
(startTime.tv_usec < time.tv_usec))) {
break;
}
}
}
}
state = 0;
}
XFree ((char *) mainKeyMap);
} else if ((c == 'x') && (strncmp(argv[1], "xwinchilds", length) == 0) &&
(length >= 5)) {
Tcl_ResetResult(interp);
for (counter1 = 0; counter1 < num_child1; counter1++) {
if (counter1 == num_child1 - 1) {
sprintf(buf, "%ld", child_list1[counter1]);
} else {
sprintf(buf, "%ld ", child_list1[counter1]);
}
Tcl_AppendResult(interp, buf, (char *) NULL);
}
} else if ((c == 'x') && (strncmp(argv[1], "xwinname", length) == 0) &&
(length >= 5)) {
Tcl_ResetResult(interp);
if (!XFetchName(Tk_Display(tkrootwin), window, &win_name)) {
if (!continueXAccess) {
sprintf(error_buf, "retrieving window name!");
goto Xerror;
}
Tcl_AppendResult(interp, "", (char *) NULL);
} else {
if (!continueXAccess) {
sprintf(error_buf, "retrieving window name!");
goto Xerror;
}
if (win_name != (char *) NULL && strcmp(win_name, "") != 0) {
Tcl_AppendResult(interp, win_name, (char *) NULL);
XFree(win_name);
}
}
} else if ((c == 'x') && (strncmp(argv[1], "xwinparent", length) == 0) &&
(length >= 5)) {
Tcl_ResetResult(interp);
sprintf(buf, "%ld", parent_ret);
Tcl_AppendResult(interp, buf, (char *) NULL);
} else if ((c == 'x') && (strncmp(argv[1], "xwinroot", length) == 0) &&
(length >= 5)) {
Tcl_ResetResult(interp);
sprintf(buf, "%ld", root_ret);
Tcl_AppendResult(interp, buf, (char *) NULL);
} else {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, argv[0], ": unknown command \"", argv[1], "\"",
(char *) NULL);
goto error;
}
XFlush(Tk_Display(tkrootwin));
if (child_list3 != (Window *) None) {
#if defined(XlibSpecificationRelease)
XFree((Window *) child_list3);
#else
XFree((char *) child_list3);
#endif
}
if (child_list2 != (Window *) None) {
#if defined(XlibSpecificationRelease)
XFree((Window *) child_list2);
#else
XFree((char *) child_list2);
#endif
}
if (child_list1 != (Window *) None) {
#if defined(XlibSpecificationRelease)
XFree((Window *) child_list1);
#else
XFree((char *) child_list1);
#endif
}
Tk_DeleteErrorHandler(handler1);
Tk_DeleteErrorHandler(handler2);
Tk_DeleteErrorHandler(handler3);
return TCL_OK;
Xerror:
XFlush(Tk_Display(tkrootwin));
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, argv[0], " X protocol error: ",
error_buf, (char *) NULL);
error:
if (property_return != (char *) NULL) {
XFree((char *) property_return);
}
if (atomList != (Atom *) NULL) {
#if defined(XlibSpecificationRelease)
XFree((Atom *) atomList);
#else
XFree((char *) atomList);
#endif
}
if (child_list3 != (Window *) None) {
#if defined(XlibSpecificationRelease)
XFree((Window *) child_list3);
#else
XFree((char *) child_list3);
#endif
}
if (child_list2 != (Window *) None) {
#if defined(XlibSpecificationRelease)
XFree((Window *) child_list2);
#else
XFree((char *) child_list2);
#endif
}
if (child_list1 != (Window *) None) {
#if defined(XlibSpecificationRelease)
XFree((Window *) child_list1);
#else
XFree((char *) child_list1);
#endif
}
Tk_DeleteErrorHandler(handler1);
Tk_DeleteErrorHandler(handler2);
Tk_DeleteErrorHandler(handler3);
return TCL_ERROR;
}
/*
*----------------------------------------------------------------------
*
* TkSteal_Init --
*
* This procedure initializes the TkSteal package, and
* should be called in Tcl_AppInit, or by the load feature.
*
* Results:
* Always TCL_OK.
*
* Side effects:
* Adds the new commands to the interpreter.
*
*----------------------------------------------------------------------
*/
int
Tksteal_Init(interp)
Tcl_Interp *interp; /* Interpreter for application. */
{
int code;
/*
* Call Tcl_CreateCommand for application-specific commands.
*/
Tcl_CreateCommand(interp, "xaccess", TkXAccessCmd,
(ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
code = Tcl_PkgProvide(interp, "Tksteal", "4.1");
if (code != TCL_OK) {
return code;
}
return TCL_OK;
}
/* eof */