mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
Use a different implementation of EventHook(). The new version
registers an input file handler for stdin with Tcl and handles Tcl events until something is available on stdin; it then deletes the handler and returns from EventHook(). This works with or without GNU readline, and doesn't busy-wait. It still doesn't work for Mac or Windows :-(
This commit is contained in:
parent
6a50ba82ce
commit
7bf15648a4
1 changed files with 74 additions and 37 deletions
|
@ -83,6 +83,24 @@ PERFORMANCE OF THIS SOFTWARE.
|
|||
#define HAVE_CREATEFILEHANDLER
|
||||
#endif
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
#define FHANDLETYPE TCL_WIN_SOCKET
|
||||
#else
|
||||
#define FHANDLETYPE TCL_UNIX_FD
|
||||
#endif
|
||||
|
||||
#if TKMAJORMINOR < 8000
|
||||
#define FHANDLE Tcl_File
|
||||
#define MAKEFHANDLE(fd) Tcl_GetFile((ClientData)(fd), FHANDLETYPE)
|
||||
#else
|
||||
#define FHANDLE int
|
||||
#define MAKEFHANDLE(fd) (fd)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CREATEFILEHANDLER) && !defined(MS_WINDOWS)
|
||||
#define WAIT_FOR_STDIN
|
||||
#endif
|
||||
|
||||
extern int Tk_GetNumMainWindows();
|
||||
|
||||
#ifdef macintosh
|
||||
|
@ -342,6 +360,10 @@ Tcl_AppInit(interp)
|
|||
/* Initialize the Tk application; see the `main' function in
|
||||
* `tkMain.c'.
|
||||
*/
|
||||
|
||||
static void EnableEventHook(); /* Forward */
|
||||
static void DisableEventHook(); /* Forward */
|
||||
|
||||
static TkappObject *
|
||||
Tkapp_New(screenName, baseName, className, interactive)
|
||||
char *screenName;
|
||||
|
@ -392,6 +414,8 @@ Tkapp_New(screenName, baseName, className, interactive)
|
|||
if (Tcl_AppInit(v->interp) != TCL_OK)
|
||||
return (TkappObject *)Tkinter_Error(v);
|
||||
|
||||
EnableEventHook();
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
@ -1128,9 +1152,7 @@ Tkapp_CreateFileHandler(self, args)
|
|||
PyObject *file, *func, *data;
|
||||
PyObject *idkey;
|
||||
int mask, id;
|
||||
#if TKMAJORMINOR < 8000
|
||||
Tcl_File tfile;
|
||||
#endif
|
||||
FHANDLE tfile;
|
||||
|
||||
if (!Tkapp_ClientDataDict) {
|
||||
if (!(Tkapp_ClientDataDict = PyDict_New()))
|
||||
|
@ -1159,18 +1181,9 @@ Tkapp_CreateFileHandler(self, args)
|
|||
}
|
||||
Py_DECREF(idkey);
|
||||
|
||||
#if TKMAJORMINOR < 8000
|
||||
#ifdef MS_WINDOWS
|
||||
/* We assume this is a socket... */
|
||||
tfile = Tcl_GetFile((ClientData)id, TCL_WIN_SOCKET);
|
||||
#else /* !MS_WINDOWS */
|
||||
tfile = Tcl_GetFile((ClientData)id, TCL_UNIX_FD);
|
||||
#endif /* !MS_WINDOWS */
|
||||
tfile = MAKEFHANDLE(id);
|
||||
/* Ought to check for null Tcl_File object... */
|
||||
Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
|
||||
#else /* >= 8000 */
|
||||
Tcl_CreateFileHandler(id, mask, FileHandler, (ClientData) data);
|
||||
#endif /* >= 8000 */
|
||||
/* XXX fileHandlerDict */
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
@ -1186,9 +1199,7 @@ Tkapp_DeleteFileHandler(self, args)
|
|||
PyObject *idkey;
|
||||
PyObject *data;
|
||||
int id;
|
||||
#if TKMAJORMINOR < 8000
|
||||
Tcl_File tfile;
|
||||
#endif
|
||||
FHANDLE tfile;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O", &file))
|
||||
return NULL;
|
||||
|
@ -1207,18 +1218,9 @@ Tkapp_DeleteFileHandler(self, args)
|
|||
PyDict_DelItem(Tkapp_ClientDataDict, idkey);
|
||||
Py_DECREF(idkey);
|
||||
|
||||
#if TKMAJORMINOR < 8000
|
||||
#ifdef MS_WINDOWS
|
||||
/* We assume this is a socket... */
|
||||
tfile = Tcl_GetFile((ClientData)id, TCL_WIN_SOCKET);
|
||||
#else
|
||||
tfile = Tcl_GetFile((ClientData)id, TCL_UNIX_FD);
|
||||
#endif
|
||||
tfile = MAKEFHANDLE(id);
|
||||
/* Ought to check for null Tcl_File object... */
|
||||
Tcl_DeleteFileHandler(tfile);
|
||||
#else /* >= 8000 */
|
||||
Tcl_DeleteFileHandler(id);
|
||||
#endif /* >= 8000 */
|
||||
/* XXX fileHandlerDict */
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
@ -1511,6 +1513,7 @@ Tkapp_Dealloc(self)
|
|||
{
|
||||
Tcl_DeleteInterp(Tkapp_Interp(self));
|
||||
PyMem_DEL(self);
|
||||
DisableEventHook();
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
|
@ -1584,22 +1587,41 @@ static PyMethodDef moduleMethods[] =
|
|||
{NULL, NULL}
|
||||
};
|
||||
|
||||
#ifdef WAIT_FOR_STDIN
|
||||
#define WAITFLAG 0
|
||||
|
||||
static int stdin_ready = 0;
|
||||
|
||||
static void
|
||||
MyFileProc(clientData, mask)
|
||||
void *clientData;
|
||||
int mask;
|
||||
{
|
||||
stdin_ready = 1;
|
||||
}
|
||||
#else
|
||||
#define WAITFLAG TCL_DONT_WAIT
|
||||
#endif
|
||||
|
||||
static PyInterpreterState *event_interp = NULL;
|
||||
|
||||
static int
|
||||
EventHook()
|
||||
{
|
||||
PyThreadState *tstate, *save_tstate;
|
||||
#ifdef WAIT_FOR_STDIN
|
||||
FHANDLE tfile = MAKEFHANDLE(((int)fileno(stdin)));
|
||||
|
||||
if (Tk_GetNumMainWindows() == 0)
|
||||
return 0;
|
||||
if (event_interp == NULL)
|
||||
return 0;
|
||||
stdin_ready = 0;
|
||||
Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
|
||||
#endif
|
||||
tstate = PyThreadState_New(event_interp);
|
||||
save_tstate = PyThreadState_Swap(NULL);
|
||||
PyEval_RestoreThread(tstate);
|
||||
if (!errorInCmd)
|
||||
Tcl_DoOneEvent(TCL_DONT_WAIT);
|
||||
#ifdef WAIT_FOR_STDIN
|
||||
while (!errorInCmd && !stdin_ready)
|
||||
#endif
|
||||
Tcl_DoOneEvent(WAITFLAG);
|
||||
if (errorInCmd) {
|
||||
errorInCmd = 0;
|
||||
PyErr_Restore(excInCmd, valInCmd, trbInCmd);
|
||||
|
@ -1610,9 +1632,29 @@ EventHook()
|
|||
PyEval_SaveThread();
|
||||
PyThreadState_Swap(save_tstate);
|
||||
PyThreadState_Delete(tstate);
|
||||
#ifdef WAIT_FOR_STDIN
|
||||
Tcl_DeleteFileHandler(tfile);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
EnableEventHook()
|
||||
{
|
||||
if (PyOS_InputHook == NULL) {
|
||||
event_interp = PyThreadState_Get()->interp;
|
||||
PyOS_InputHook = EventHook;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DisableEventHook()
|
||||
{
|
||||
if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
|
||||
PyOS_InputHook = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* all errors will be checked in one fell swoop in init_tkinter() */
|
||||
static void
|
||||
|
@ -1670,11 +1712,6 @@ init_tkinter()
|
|||
PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
|
||||
PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
|
||||
|
||||
if (PyOS_InputHook == NULL) {
|
||||
event_interp = PyThreadState_Get()->interp;
|
||||
PyOS_InputHook = EventHook;
|
||||
}
|
||||
|
||||
if (PyErr_Occurred())
|
||||
return;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue