summaryrefslogtreecommitdiffstats
path: root/Mac
diff options
context:
space:
mode:
authorJust van Rossum <just@letterror.com>2001-12-14 23:16:04 (GMT)
committerJust van Rossum <just@letterror.com>2001-12-14 23:16:04 (GMT)
commit2c391152402d91d8f2109361858262c6aad9b79f (patch)
tree04087db7dee0ed31fe54582f0024670da506961d /Mac
parent9635f33e5b64495cc1ba18307f0b91a303e7e103 (diff)
downloadcpython-2c391152402d91d8f2109361858262c6aad9b79f.zip
cpython-2c391152402d91d8f2109361858262c6aad9b79f.tar.gz
cpython-2c391152402d91d8f2109361858262c6aad9b79f.tar.bz2
Made event callbacks more rubust: keep an actual reference to the
python callback, and do RemoveEventHandler() upon deallocation.
Diffstat (limited to 'Mac')
-rw-r--r--Mac/Modules/carbonevt/CarbonEvtscan.py12
-rw-r--r--Mac/Modules/carbonevt/CarbonEvtsupport.py69
-rwxr-xr-xMac/Modules/carbonevt/_CarbonEvtmodule.c62
3 files changed, 113 insertions, 30 deletions
diff --git a/Mac/Modules/carbonevt/CarbonEvtscan.py b/Mac/Modules/carbonevt/CarbonEvtscan.py
index 856f9b1..e93baf3 100644
--- a/Mac/Modules/carbonevt/CarbonEvtscan.py
+++ b/Mac/Modules/carbonevt/CarbonEvtscan.py
@@ -41,13 +41,14 @@ class CarbonEvents_Scanner(Scanner_OSX):
listname = "functions"
if arglist:
t, n, m = arglist[0]
- print "*********", t,
if t in RefObjectTypes and m == "InMode":
- print "method"
- classname = "CarbonEventsMethod"
+ if t == "EventHandlerRef":
+ classname = "EventHandlerRefMethod"
+ else:
+ classname = "CarbonEventsMethod"
listname = t + "methods"
- else:
- print "not method"
+ #else:
+ # print "not method"
return classname, listname
def writeinitialdefs(self):
@@ -82,6 +83,7 @@ class CarbonEvents_Scanner(Scanner_OSX):
# Wrote by hand
"InstallEventHandler",
+ "RemoveEventHandler",
"RunApplicationEventLoop",
# Write by hand?
diff --git a/Mac/Modules/carbonevt/CarbonEvtsupport.py b/Mac/Modules/carbonevt/CarbonEvtsupport.py
index a43d47c..ef862ee 100644
--- a/Mac/Modules/carbonevt/CarbonEvtsupport.py
+++ b/Mac/Modules/carbonevt/CarbonEvtsupport.py
@@ -11,6 +11,7 @@ for typ in RefObjectTypes:
execstr = "%(name)s = OpaqueByValueType('%(name)s')" % {"name": typ}
exec execstr
+
if 0:
# these types will have no methods and will merely be opaque blobs
# should write getattr and setattr for them?
@@ -53,6 +54,14 @@ EventHandlerProcPtr = FakeType("(EventHandlerProcPtr)0")
CarbonEventsFunction = OSErrFunctionGenerator
CarbonEventsMethod = OSErrMethodGenerator
+class EventHandlerRefMethod(OSErrMethodGenerator):
+ def precheck(self):
+ OutLbrace('if (_self->ob_itself == NULL)')
+ Output('PyErr_SetString(CarbonEvents_Error, "Handler has been removed");')
+ Output('return NULL;')
+ OutRbrace()
+
+
includestuff = r"""
#ifdef WITHOUT_FRAMEWORKS
#include <CarbonEvents.h>
@@ -188,15 +197,31 @@ myEventHandlerUPP = NewEventHandlerUPP(myEventHandler);
"""
module = MacModule('_CarbonEvt', 'CarbonEvents', includestuff, finalstuff, initstuff)
-#class CFReleaserObj(GlobalObjectDefinition):
-# def outputFreeIt(self, name):
-# Output("CFRelease(%s);" % name)
+
+
+
+class EventHandlerRefObjectDefinition(GlobalObjectDefinition):
+ def outputStructMembers(self):
+ Output("%s ob_itself;", self.itselftype)
+ Output("PyObject *ob_callback;")
+ def outputInitStructMembers(self):
+ Output("it->ob_itself = %sitself;", self.argref)
+ Output("it->ob_callback = NULL;")
+ def outputFreeIt(self, name):
+ OutLbrace("if (self->ob_itself != NULL)")
+ Output("RemoveEventHandler(self->ob_itself);")
+ Output("Py_DECREF(self->ob_callback);")
+ OutRbrace()
for typ in RefObjectTypes:
- execstr = typ + 'object = GlobalObjectDefinition(typ)'
- exec execstr
+ if typ == 'EventHandlerRef':
+ EventHandlerRefobject = EventHandlerRefObjectDefinition('EventHandlerRef')
+ else:
+ execstr = typ + 'object = GlobalObjectDefinition(typ)'
+ exec execstr
module.addobject(eval(typ + 'object'))
+
functions = []
for typ in RefObjectTypes: ## go thru all ObjectTypes as defined in CarbonEventsscan.py
# initialize the lists for carbongen to fill
@@ -205,6 +230,8 @@ for typ in RefObjectTypes: ## go thru all ObjectTypes as defined in CarbonEvents
execfile('CarbonEventsgen.py')
+
+
for f in functions: module.add(f) # add all the functions carboneventsgen put in the list
for typ in RefObjectTypes: ## go thru all ObjectTypes as defined in CarbonEventsscan.py
@@ -212,6 +239,29 @@ for typ in RefObjectTypes: ## go thru all ObjectTypes as defined in CarbonEv
obj = eval(typ + 'object') ## get a reference to the object
for m in methods: obj.add(m) ## add each method in the list to the object
+
+removeeventhandler = """
+OSStatus _err;
+if (_self->ob_itself == NULL) {
+ PyErr_SetString(CarbonEvents_Error, "Handler has been removed");
+ return NULL;
+}
+if (!PyArg_ParseTuple(_args, ""))
+ return NULL;
+_err = RemoveEventHandler(_self->ob_itself);
+if (_err != noErr) return PyMac_Error(_err);
+_self->ob_itself = NULL;
+Py_DECREF(_self->ob_callback);
+_self->ob_callback = NULL;
+Py_INCREF(Py_None);
+_res = Py_None;
+return _res;"""
+
+f = ManualGenerator("RemoveEventHandler", removeeventhandler);
+f.docstring = lambda: "() -> None"
+EventHandlerRefobject.add(f)
+
+
installeventhandler = """
EventTypeSpec inSpec;
PyObject *callback;
@@ -224,10 +274,15 @@ if (!PyArg_ParseTuple(_args, "O&O", EventTypeSpec_Convert, &inSpec, &callback))
_err = InstallEventHandler(_self->ob_itself, myEventHandlerUPP, 1, &inSpec, (void *)callback, &outRef);
if (_err != noErr) return PyMac_Error(_err);
-return Py_BuildValue("O&", EventHandlerRef_New, outRef);"""
+_res = EventHandlerRef_New(outRef);
+if (_res != NULL) {
+ ((EventHandlerRefObject*)_res)->ob_callback = callback;
+ Py_INCREF(callback);
+}
+return _res;"""
f = ManualGenerator("InstallEventHandler", installeventhandler);
-f.docstring = lambda: "(EventTargetRef inTarget, EventTypeSpec inSpec, Method callback) -> (EventHandlerRef outRef)"
+f.docstring = lambda: "(EventTypeSpec inSpec, Method callback) -> (EventHandlerRef outRef)"
EventTargetRefobject.add(f)
runappeventloop = """
diff --git a/Mac/Modules/carbonevt/_CarbonEvtmodule.c b/Mac/Modules/carbonevt/_CarbonEvtmodule.c
index 0aefcc6..f9f3886 100755
--- a/Mac/Modules/carbonevt/_CarbonEvtmodule.c
+++ b/Mac/Modules/carbonevt/_CarbonEvtmodule.c
@@ -799,6 +799,7 @@ PyTypeObject EventHandlerRef_Type;
typedef struct EventHandlerRefObject {
PyObject_HEAD
EventHandlerRef ob_itself;
+ PyObject *ob_callback;
} EventHandlerRefObject;
PyObject *EventHandlerRef_New(EventHandlerRef itself)
@@ -807,6 +808,7 @@ PyObject *EventHandlerRef_New(EventHandlerRef itself)
it = PyObject_NEW(EventHandlerRefObject, &EventHandlerRef_Type);
if (it == NULL) return NULL;
it->ob_itself = itself;
+ it->ob_callback = NULL;
return (PyObject *)it;
}
int EventHandlerRef_Convert(PyObject *v, EventHandlerRef *p_itself)
@@ -822,29 +824,23 @@ int EventHandlerRef_Convert(PyObject *v, EventHandlerRef *p_itself)
static void EventHandlerRef_dealloc(EventHandlerRefObject *self)
{
- /* Cleanup of self->ob_itself goes here */
+ if (self->ob_itself != NULL) {
+ RemoveEventHandler(self->ob_itself);
+ Py_DECREF(self->ob_callback);
+ }
PyMem_DEL(self);
}
-static PyObject *EventHandlerRef_RemoveEventHandler(EventHandlerRefObject *_self, PyObject *_args)
-{
- PyObject *_res = NULL;
- OSStatus _err;
- if (!PyArg_ParseTuple(_args, ""))
- return NULL;
- _err = RemoveEventHandler(_self->ob_itself);
- if (_err != noErr) return PyMac_Error(_err);
- Py_INCREF(Py_None);
- _res = Py_None;
- return _res;
-}
-
static PyObject *EventHandlerRef_AddEventTypesToHandler(EventHandlerRefObject *_self, PyObject *_args)
{
PyObject *_res = NULL;
OSStatus _err;
UInt32 inNumTypes;
EventTypeSpec inList;
+ if (_self->ob_itself == NULL) {
+ PyErr_SetString(CarbonEvents_Error, "Handler has been removed");
+ return NULL;
+ }
if (!PyArg_ParseTuple(_args, "lO&",
&inNumTypes,
EventTypeSpec_Convert, &inList))
@@ -864,6 +860,10 @@ static PyObject *EventHandlerRef_RemoveEventTypesFromHandler(EventHandlerRefObje
OSStatus _err;
UInt32 inNumTypes;
EventTypeSpec inList;
+ if (_self->ob_itself == NULL) {
+ PyErr_SetString(CarbonEvents_Error, "Handler has been removed");
+ return NULL;
+ }
if (!PyArg_ParseTuple(_args, "lO&",
&inNumTypes,
EventTypeSpec_Convert, &inList))
@@ -877,13 +877,34 @@ static PyObject *EventHandlerRef_RemoveEventTypesFromHandler(EventHandlerRefObje
return _res;
}
+static PyObject *EventHandlerRef_RemoveEventHandler(EventHandlerRefObject *_self, PyObject *_args)
+{
+ PyObject *_res = NULL;
+
+ OSStatus _err;
+ if (_self->ob_itself == NULL) {
+ PyErr_SetString(CarbonEvents_Error, "Handler has been removed");
+ return NULL;
+ }
+ if (!PyArg_ParseTuple(_args, ""))
+ return NULL;
+ _err = RemoveEventHandler(_self->ob_itself);
+ if (_err != noErr) return PyMac_Error(_err);
+ _self->ob_itself = NULL;
+ Py_DECREF(_self->ob_callback);
+ _self->ob_callback = NULL;
+ Py_INCREF(Py_None);
+ _res = Py_None;
+ return _res;
+}
+
static PyMethodDef EventHandlerRef_methods[] = {
- {"RemoveEventHandler", (PyCFunction)EventHandlerRef_RemoveEventHandler, 1,
- "() -> None"},
{"AddEventTypesToHandler", (PyCFunction)EventHandlerRef_AddEventTypesToHandler, 1,
"(UInt32 inNumTypes, EventTypeSpec inList) -> None"},
{"RemoveEventTypesFromHandler", (PyCFunction)EventHandlerRef_RemoveEventTypesFromHandler, 1,
"(UInt32 inNumTypes, EventTypeSpec inList) -> None"},
+ {"RemoveEventHandler", (PyCFunction)EventHandlerRef_RemoveEventHandler, 1,
+ "() -> None"},
{NULL, NULL, 0}
};
@@ -1083,14 +1104,19 @@ static PyObject *EventTargetRef_InstallEventHandler(EventTargetRefObject *_self,
_err = InstallEventHandler(_self->ob_itself, myEventHandlerUPP, 1, &inSpec, (void *)callback, &outRef);
if (_err != noErr) return PyMac_Error(_err);
- return Py_BuildValue("O&", EventHandlerRef_New, outRef);
+ _res = EventHandlerRef_New(outRef);
+ if (_res != NULL) {
+ ((EventHandlerRefObject*)_res)->ob_callback = callback;
+ Py_INCREF(callback);
+ }
+ return _res;
}
static PyMethodDef EventTargetRef_methods[] = {
{"InstallStandardEventHandler", (PyCFunction)EventTargetRef_InstallStandardEventHandler, 1,
"() -> None"},
{"InstallEventHandler", (PyCFunction)EventTargetRef_InstallEventHandler, 1,
- "(EventTargetRef inTarget, EventTypeSpec inSpec, Method callback) -> (EventHandlerRef outRef)"},
+ "(EventTypeSpec inSpec, Method callback) -> (EventHandlerRef outRef)"},
{NULL, NULL, 0}
};