@@ -1811,93 +1811,53 @@ - (void)flagsChanged:(NSEvent *)event
1811
1811
1812
1812
typedef struct {
1813
1813
PyObject_HEAD
1814
- CFRunLoopTimerRef timer;
1814
+ NSTimer * timer;
1815
+
1815
1816
} Timer;
1816
1817
1817
1818
static PyObject*
1818
1819
Timer_new (PyTypeObject* type, PyObject *args, PyObject *kwds)
1819
1820
{
1820
1821
lazy_init ();
1821
1822
Timer* self = (Timer*)type->tp_alloc (type, 0 );
1822
- if (!self) { return NULL ; }
1823
+ if (!self) {
1824
+ return NULL ;
1825
+ }
1823
1826
self->timer = NULL ;
1824
1827
return (PyObject*) self;
1825
1828
}
1826
1829
1827
1830
static PyObject*
1828
1831
Timer_repr (Timer* self)
1829
1832
{
1830
- return PyUnicode_FromFormat (" Timer object %p wrapping CFRunLoopTimerRef %p " ,
1833
+ return PyUnicode_FromFormat (" Timer object %p wrapping NSTimerRef %p " ,
1831
1834
(void *) self, (void *)(self->timer ));
1832
1835
}
1833
1836
1834
- static void timer_callback (CFRunLoopTimerRef timer, void * info)
1835
- {
1836
- gil_call_method (info, " _on_timer" );
1837
- }
1838
-
1839
- static void context_cleanup (const void * info)
1840
- {
1841
- Py_DECREF ((PyObject*)info);
1842
- }
1843
-
1844
1837
static PyObject*
1845
1838
Timer__timer_start (Timer* self, PyObject* args)
1846
1839
{
1847
- CFRunLoopRef runloop;
1848
- CFRunLoopTimerRef timer;
1849
- CFRunLoopTimerContext context;
1850
- CFAbsoluteTime firstFire;
1851
- CFTimeInterval interval;
1840
+ NSTimeInterval interval;
1852
1841
PyObject* py_interval = NULL , * py_single = NULL , * py_on_timer = NULL ;
1853
1842
int single;
1854
- runloop = CFRunLoopGetMain ();
1855
- if (!runloop) {
1856
- PyErr_SetString (PyExc_RuntimeError, " Failed to obtain run loop" );
1857
- return NULL ;
1858
- }
1859
1843
if (!(py_interval = PyObject_GetAttrString ((PyObject*)self, " _interval" ))
1860
1844
|| ((interval = PyFloat_AsDouble (py_interval) / 1000 .), PyErr_Occurred ())
1861
1845
|| !(py_single = PyObject_GetAttrString ((PyObject*)self, " _single" ))
1862
1846
|| ((single = PyObject_IsTrue (py_single)) == -1 )
1863
1847
|| !(py_on_timer = PyObject_GetAttrString ((PyObject*)self, " _on_timer" ))) {
1864
1848
goto exit ;
1865
1849
}
1866
- // (current time + interval) is time of first fire.
1867
- firstFire = CFAbsoluteTimeGetCurrent () + interval;
1868
- if (single) {
1869
- interval = 0 ;
1870
- }
1871
1850
if (!PyMethod_Check (py_on_timer)) {
1872
1851
PyErr_SetString (PyExc_RuntimeError, " _on_timer should be a Python method" );
1873
1852
goto exit ;
1874
1853
}
1875
- Py_INCREF (self);
1876
- context.version = 0 ;
1877
- context.retain = NULL ;
1878
- context.release = context_cleanup;
1879
- context.copyDescription = NULL ;
1880
- context.info = self;
1881
- timer = CFRunLoopTimerCreate (kCFAllocatorDefault ,
1882
- firstFire,
1883
- interval,
1884
- 0 ,
1885
- 0 ,
1886
- timer_callback,
1887
- &context);
1888
- if (!timer) {
1889
- PyErr_SetString (PyExc_RuntimeError, " Failed to create timer" );
1890
- goto exit ;
1891
- }
1892
- if (self->timer ) {
1893
- CFRunLoopTimerInvalidate (self->timer );
1894
- CFRelease (self->timer );
1895
- }
1896
- CFRunLoopAddTimer (runloop, timer, kCFRunLoopCommonModes );
1897
- /* Don't release the timer here, since the run loop may be destroyed and
1898
- * the timer lost before we have a chance to decrease the reference count
1899
- * of the attribute */
1900
- self->timer = timer;
1854
+
1855
+ // hold a reference to the timer so we can invalidate/stop it later
1856
+ self->timer = [NSTimer scheduledTimerWithTimeInterval: interval
1857
+ repeats: !single
1858
+ block: ^(NSTimer *timer) {
1859
+ gil_call_method ((PyObject*)self, " _on_timer" );
1860
+ }];
1901
1861
exit :
1902
1862
Py_XDECREF (py_interval);
1903
1863
Py_XDECREF (py_single);
@@ -1913,8 +1873,7 @@ static void context_cleanup(const void* info)
1913
1873
Timer__timer_stop (Timer* self)
1914
1874
{
1915
1875
if (self->timer ) {
1916
- CFRunLoopTimerInvalidate (self->timer );
1917
- CFRelease (self->timer );
1876
+ [self ->timer invalidate ];
1918
1877
self->timer = NULL ;
1919
1878
}
1920
1879
Py_RETURN_NONE;
@@ -1935,7 +1894,7 @@ static void context_cleanup(const void* info)
1935
1894
.tp_repr = (reprfunc)Timer_repr,
1936
1895
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1937
1896
.tp_new = (newfunc)Timer_new,
1938
- .tp_doc = " A Timer object wraps a CFRunLoopTimerRef and can add it to the event loop." ,
1897
+ .tp_doc = " A Timer object that contains an NSTimer that gets added to the event loop when started ." ,
1939
1898
.tp_methods = (PyMethodDef[]){ // All docstrings are inherited.
1940
1899
{" _timer_start" ,
1941
1900
(PyCFunction)Timer__timer_start,
0 commit comments