diff --git a/library/pyjamas/Timer.giwebkit.py b/library/pyjamas/Timer.giwebkit.py
index eb0a1a2d1..2c8ec826d 100644
--- a/library/pyjamas/Timer.giwebkit.py
+++ b/library/pyjamas/Timer.giwebkit.py
@@ -1,57 +1,14 @@
class Timer(object):
- def __setTimeout(self, periodMillis, impl='Timeout'):
- '''
- Coordinate with JavaScript and realize a new Timer.
-
- A private communication channel is established by both sides
- acquiring a ref to the same TextNode; once linked, the node is
- removed from the DOM tree, but can still recieve all events.
- It also serves as a nucleus for adding more nodes to the link -- eg.
- wrapping in
[TextNode]
-- for whatever reason, and
- without limit.
-
- Here we just use the private node to trigger Python callbacks;
- Python registers listeners and JavaScript synthesizes events.
- PyGObject is capable of clearing Timers, but is unable to create
- new ones (upstream bug?).
- '''
- # TODO: Timers/Intervals in JS will not queue for safety reasons;
- # if we're unable to process the first event before another
- # fires, we end up with an unbounded backlog of Timer events.
- # For this reason, JS will only queue one event of this type
- # at-a-time ... we MUST ensure this same behaviour!
- code = r'''
- (function(buf, ms){
- var wnd = window;
- var doc = wnd.document;
- var evt = doc.createEvent('UIEvent');
- var run = function(){buf.dispatchEvent(evt)};
- var tid = wnd.set%s(run, ms);
- doc.head.removeChild(buf);
- tid = buf.data = Number(tid);
- evt.initUIEvent('Timer', true, true, wnd, tid);
- }(document.head.lastChild, %s));
- ''' % (impl, int(periodMillis))
+ def __setTimeout(self, delayMillis):
mf = get_main_frame()
- vw = mf._view
- doc = mf.getDomDocument()
- run = lambda *a: self.__fire()
- buf = doc.createTextNode('')
- doc.head.appendChild(buf)
- mf.addEventListener(buf, 'Timer', run)
- vw.execute_script(code)
- return int(buf.data)
+ return mf.create_timer(delayMillis, self.__fire, __loop=False)
- def __clearTimeout(self, tid, impl='Timeout'):
- '''Cancel a running Timer.'''
- wnd = get_main_frame().getDomWindow()
- return getattr(wnd, 'clear%s' % impl)(int(tid))
+ def __setInterval(self, periodMillis):
+ mf = get_main_frame()
+ return mf.create_timer(periodMillis, self.__fire, __loop=True)
- def __setInterval(self, periodMillis, impl='Interval'):
- '''Passthru to setTimeout(), but call setInterval().'''
- return self.__setTimeout(periodMillis, impl=impl)
+ def __clearTimeout(self, tid):
+ return get_main_frame().cancel_timer(tid)
- def __clearInterval(self, tid, impl='Interval'):
- '''Passthru to clearTimeout(), but call clearInterval().'''
- return self.__clearTimeout(tid, impl=impl)
+ __clearInterval = __clearTimeout
diff --git a/pyjs/runners/giwebkit.py b/pyjs/runners/giwebkit.py
index 1cd5b0dae..4ffeaf3b6 100644
--- a/pyjs/runners/giwebkit.py
+++ b/pyjs/runners/giwebkit.py
@@ -14,7 +14,9 @@
from urlparse import urljoin
import gi
+gi.require_version('Gtk', '3.0')
gi.require_version('WebKit', '3.0')
+from gi.repository import GObject
from gi.repository import Gtk
from gi.repository import Soup
from gi.repository import WebKit
@@ -383,6 +385,26 @@ def _key_gi(self, key):
return self._uppercase_re.sub(r'_\1', key).lower()
+class GITimer(object):
+
+ def __init__(self, args, kwds):
+ args = list(args)
+ self.args = args
+ self.kwds = kwds
+ self.loop = kwds.pop('__loop', False)
+ self.ms = args.pop(0)
+ self.cb = args.pop(0)
+ self.tid = GObject.timeout_add(self.ms, self)
+
+ def __call__(self):
+ try:
+ self.cb(*self.args)
+ except:
+ print_exc()
+ finally:
+ return self.loop
+
+
class Callback(object):
def __init__(self, sender, cb, boolparam):
@@ -556,6 +578,15 @@ def _populate_popup_cb(self, view, menu):
menu.append(entry)
menu.show_all()
+ def create_timer(self, *args, **kwds):
+ return GITimer(args, kwds).tid
+
+ def cancel_timer(self, tid):
+ return GObject.source_remove(tid)
+
+ def get_view(self):
+ return self._view
+
def getDomWindow(self):
return self._wnd
diff --git a/pyjs/runners/imputil.py b/pyjs/runners/imputil.py
index 137086f87..bbb84908a 100644
--- a/pyjs/runners/imputil.py
+++ b/pyjs/runners/imputil.py
@@ -86,10 +86,12 @@ def _import_hook(self, fqname, globals=None, locals=None, fromlist=None,
parts = fqname.split('.')
- #print "_import_hook", parts
- # pyjamas-gtk hack
- if parts[0] in ['gtk', 'gdk', 'pygtk', 'gobject']:
- parts = ['pygtkweb'] + parts
+ #TODO: all of this hacky import stuff MUST GO!
+ # from now on, we will only proceed for namespaces that *may*
+ # need merging -- drop this ASAP for pretty much anything else
+ if parts[0] not in ('pyjamas',):
+ return self.previous_importer(fqname, globals, locals,
+ fromlist, level)
# determine the context of this import
parent = self._determine_import_context(globals)