diff --git a/setup/extensions.json b/setup/extensions.json index 5f69cc405e..a43568541d 100644 --- a/setup/extensions.json +++ b/setup/extensions.json @@ -186,6 +186,12 @@ "sources": "calibre/devices/usbobserver/usbobserver.c", "ldflags": "-framework CoreServices -framework IOKit" }, + { + "name": "cocoa", + "only": "osx", + "sources": "calibre/utils/cocoa.m calibre/utils/cocoa_wrapper.c", + "ldflags": "-framework Cocoa" + }, { "name": "libusb", "only": "osx linux haiku", diff --git a/src/calibre/constants.py b/src/calibre/constants.py index 1944e77e60..aefd0ea4ba 100644 --- a/src/calibre/constants.py +++ b/src/calibre/constants.py @@ -189,6 +189,7 @@ class Plugins(collections.Mapping): plugins.extend(['winutil', 'wpd', 'winfonts']) if isosx: plugins.append('usbobserver') + plugins.append('cocoa') if isfreebsd or ishaiku or islinux or isosx: plugins.append('libusb') plugins.append('libmtp') diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 218714d498..5eda4391a3 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -894,6 +894,14 @@ class Application(QApplication): # Qt 5 bug: https://bugreports.qt-project.org/browse/QTBUG-41125 self.aboutToQuit.connect(self.flush_clipboard) + if isosx: + cocoa, err = plugins['cocoa'] + if err: + raise RuntimeError('Failed to load cocoa plugin with error: {}'.format(err)) + cft = cocoa.cursor_blink_time() + if cft >= 0: + self.setCursorFlashTime(int(cft)) + def setup_ui_font(self): f = QFont(QApplication.font()) q = (f.family(), f.pointSize()) diff --git a/src/calibre/utils/cocoa.m b/src/calibre/utils/cocoa.m new file mode 100644 index 0000000000..86ce000304 --- /dev/null +++ b/src/calibre/utils/cocoa.m @@ -0,0 +1,25 @@ +/* + * cocoa.m + * Copyright (C) 2019 Kovid Goyal + * + * Distributed under terms of the GPL3 license. + */ + + +#include + + +double +cocoa_cursor_blink_time(void) { + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + double on_period_ms = [defaults doubleForKey:@"NSTextInsertionPointBlinkPeriodOn"]; + double off_period_ms = [defaults doubleForKey:@"NSTextInsertionPointBlinkPeriodOff"]; + double period_ms = [defaults doubleForKey:@"NSTextInsertionPointBlinkPeriod"]; + double max_value = 60 * 1000.0, ans = -1.0; + if (on_period_ms || off_period_ms) { + ans = on_period_ms + off_period_ms; + } else if (period_ms) { + ans = period_ms; + } + return ans > max_value ? 0.0 : ans; +} diff --git a/src/calibre/utils/cocoa_wrapper.c b/src/calibre/utils/cocoa_wrapper.c new file mode 100644 index 0000000000..1d65c4ecb5 --- /dev/null +++ b/src/calibre/utils/cocoa_wrapper.c @@ -0,0 +1,53 @@ +/* + * cocoa_wrapper.c + * Copyright (C) 2019 Kovid Goyal + * + * Distributed under terms of the GPL3 license. + */ + +#include + +extern double cocoa_cursor_blink_time(void); + +static PyObject* +cursor_blink_time(PyObject *self) { + (void)self; + double ans = cocoa_cursor_blink_time(); + return PyFloat_FromDouble(ans); +} + +static PyMethodDef module_methods[] = { + {"cursor_blink_time", (PyCFunction)cursor_blink_time, METH_NOARGS, ""}, + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + + +#if PY_MAJOR_VERSION >= 3 +#define INITERROR return NULL +#define INITMODULE PyModule_Create(&bzzdec_module) +static struct PyModuleDef cocoa_module = { + /* m_base */ PyModuleDef_HEAD_INIT, + /* m_name */ "cocoa", + /* m_doc */ "", + /* m_size */ -1, + /* m_methods */ module_methods, + /* m_slots */ 0, + /* m_traverse */ 0, + /* m_clear */ 0, + /* m_free */ 0, +}; +CALIBRE_MODINIT_FUNC PyInit_cocoa(void) { +#else +#define INITERROR return +#define INITMODULE Py_InitModule3("cocoa", module_methods, "") +CALIBRE_MODINIT_FUNC initcocoa(void) { +#endif + + PyObject *m = INITMODULE; + if (m == NULL) { + INITERROR; + } +#if PY_MAJOR_VERSION >= 3 + return m; +#endif +}