mirror of
https://github.com/python/cpython.git
synced 2025-10-03 21:55:41 +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
|
#define HAVE_CREATEFILEHANDLER
|
||||||
#endif
|
#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();
|
extern int Tk_GetNumMainWindows();
|
||||||
|
|
||||||
#ifdef macintosh
|
#ifdef macintosh
|
||||||
|
@ -342,6 +360,10 @@ Tcl_AppInit(interp)
|
||||||
/* Initialize the Tk application; see the `main' function in
|
/* Initialize the Tk application; see the `main' function in
|
||||||
* `tkMain.c'.
|
* `tkMain.c'.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static void EnableEventHook(); /* Forward */
|
||||||
|
static void DisableEventHook(); /* Forward */
|
||||||
|
|
||||||
static TkappObject *
|
static TkappObject *
|
||||||
Tkapp_New(screenName, baseName, className, interactive)
|
Tkapp_New(screenName, baseName, className, interactive)
|
||||||
char *screenName;
|
char *screenName;
|
||||||
|
@ -392,6 +414,8 @@ Tkapp_New(screenName, baseName, className, interactive)
|
||||||
if (Tcl_AppInit(v->interp) != TCL_OK)
|
if (Tcl_AppInit(v->interp) != TCL_OK)
|
||||||
return (TkappObject *)Tkinter_Error(v);
|
return (TkappObject *)Tkinter_Error(v);
|
||||||
|
|
||||||
|
EnableEventHook();
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1128,9 +1152,7 @@ Tkapp_CreateFileHandler(self, args)
|
||||||
PyObject *file, *func, *data;
|
PyObject *file, *func, *data;
|
||||||
PyObject *idkey;
|
PyObject *idkey;
|
||||||
int mask, id;
|
int mask, id;
|
||||||
#if TKMAJORMINOR < 8000
|
FHANDLE tfile;
|
||||||
Tcl_File tfile;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!Tkapp_ClientDataDict) {
|
if (!Tkapp_ClientDataDict) {
|
||||||
if (!(Tkapp_ClientDataDict = PyDict_New()))
|
if (!(Tkapp_ClientDataDict = PyDict_New()))
|
||||||
|
@ -1159,18 +1181,9 @@ Tkapp_CreateFileHandler(self, args)
|
||||||
}
|
}
|
||||||
Py_DECREF(idkey);
|
Py_DECREF(idkey);
|
||||||
|
|
||||||
#if TKMAJORMINOR < 8000
|
tfile = MAKEFHANDLE(id);
|
||||||
#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 */
|
|
||||||
/* Ought to check for null Tcl_File object... */
|
/* Ought to check for null Tcl_File object... */
|
||||||
Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
|
Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
|
||||||
#else /* >= 8000 */
|
|
||||||
Tcl_CreateFileHandler(id, mask, FileHandler, (ClientData) data);
|
|
||||||
#endif /* >= 8000 */
|
|
||||||
/* XXX fileHandlerDict */
|
/* XXX fileHandlerDict */
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
return Py_None;
|
return Py_None;
|
||||||
|
@ -1186,9 +1199,7 @@ Tkapp_DeleteFileHandler(self, args)
|
||||||
PyObject *idkey;
|
PyObject *idkey;
|
||||||
PyObject *data;
|
PyObject *data;
|
||||||
int id;
|
int id;
|
||||||
#if TKMAJORMINOR < 8000
|
FHANDLE tfile;
|
||||||
Tcl_File tfile;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O", &file))
|
if (!PyArg_ParseTuple(args, "O", &file))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1207,18 +1218,9 @@ Tkapp_DeleteFileHandler(self, args)
|
||||||
PyDict_DelItem(Tkapp_ClientDataDict, idkey);
|
PyDict_DelItem(Tkapp_ClientDataDict, idkey);
|
||||||
Py_DECREF(idkey);
|
Py_DECREF(idkey);
|
||||||
|
|
||||||
#if TKMAJORMINOR < 8000
|
tfile = MAKEFHANDLE(id);
|
||||||
#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
|
|
||||||
/* Ought to check for null Tcl_File object... */
|
/* Ought to check for null Tcl_File object... */
|
||||||
Tcl_DeleteFileHandler(tfile);
|
Tcl_DeleteFileHandler(tfile);
|
||||||
#else /* >= 8000 */
|
|
||||||
Tcl_DeleteFileHandler(id);
|
|
||||||
#endif /* >= 8000 */
|
|
||||||
/* XXX fileHandlerDict */
|
/* XXX fileHandlerDict */
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
return Py_None;
|
return Py_None;
|
||||||
|
@ -1511,6 +1513,7 @@ Tkapp_Dealloc(self)
|
||||||
{
|
{
|
||||||
Tcl_DeleteInterp(Tkapp_Interp(self));
|
Tcl_DeleteInterp(Tkapp_Interp(self));
|
||||||
PyMem_DEL(self);
|
PyMem_DEL(self);
|
||||||
|
DisableEventHook();
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -1584,22 +1587,41 @@ static PyMethodDef moduleMethods[] =
|
||||||
{NULL, NULL}
|
{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 PyInterpreterState *event_interp = NULL;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
EventHook()
|
EventHook()
|
||||||
{
|
{
|
||||||
PyThreadState *tstate, *save_tstate;
|
PyThreadState *tstate, *save_tstate;
|
||||||
|
#ifdef WAIT_FOR_STDIN
|
||||||
|
FHANDLE tfile = MAKEFHANDLE(((int)fileno(stdin)));
|
||||||
|
|
||||||
if (Tk_GetNumMainWindows() == 0)
|
stdin_ready = 0;
|
||||||
return 0;
|
Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
|
||||||
if (event_interp == NULL)
|
#endif
|
||||||
return 0;
|
|
||||||
tstate = PyThreadState_New(event_interp);
|
tstate = PyThreadState_New(event_interp);
|
||||||
save_tstate = PyThreadState_Swap(NULL);
|
save_tstate = PyThreadState_Swap(NULL);
|
||||||
PyEval_RestoreThread(tstate);
|
PyEval_RestoreThread(tstate);
|
||||||
if (!errorInCmd)
|
#ifdef WAIT_FOR_STDIN
|
||||||
Tcl_DoOneEvent(TCL_DONT_WAIT);
|
while (!errorInCmd && !stdin_ready)
|
||||||
|
#endif
|
||||||
|
Tcl_DoOneEvent(WAITFLAG);
|
||||||
if (errorInCmd) {
|
if (errorInCmd) {
|
||||||
errorInCmd = 0;
|
errorInCmd = 0;
|
||||||
PyErr_Restore(excInCmd, valInCmd, trbInCmd);
|
PyErr_Restore(excInCmd, valInCmd, trbInCmd);
|
||||||
|
@ -1610,9 +1632,29 @@ EventHook()
|
||||||
PyEval_SaveThread();
|
PyEval_SaveThread();
|
||||||
PyThreadState_Swap(save_tstate);
|
PyThreadState_Swap(save_tstate);
|
||||||
PyThreadState_Delete(tstate);
|
PyThreadState_Delete(tstate);
|
||||||
|
#ifdef WAIT_FOR_STDIN
|
||||||
|
Tcl_DeleteFileHandler(tfile);
|
||||||
|
#endif
|
||||||
return 0;
|
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() */
|
/* all errors will be checked in one fell swoop in init_tkinter() */
|
||||||
static void
|
static void
|
||||||
|
@ -1670,11 +1712,6 @@ init_tkinter()
|
||||||
PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
|
PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
|
||||||
PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
|
PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
|
||||||
|
|
||||||
if (PyOS_InputHook == NULL) {
|
|
||||||
event_interp = PyThreadState_Get()->interp;
|
|
||||||
PyOS_InputHook = EventHook;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PyErr_Occurred())
|
if (PyErr_Occurred())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue