Skip to content

Commit 4687bac

Browse files
committed
Fixed keyboard errors in the Kivy example when local keyboard
mode is used and when visiting webpages that contain frames (youtube for example).
1 parent 94c3c68 commit 4687bac

File tree

2 files changed

+58
-30
lines changed

2 files changed

+58
-30
lines changed

cefpython/cef3/linux/binaries_64bit/kivy_.py

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class CefBrowser(Widget):
6464
# Keyboard mode: "global" or "local".
6565
# 1. Global mode forwards keys to CEF all the time.
6666
# 2. Local mode forwards keys to CEF only when an editable
67-
# control is focused (input type=text or textarea).
67+
# control is focused (input type=text|password or textarea).
6868
keyboard_mode = "global"
6969

7070
'''Represent a browser widget for kivy, which can be used like a normal widget.
@@ -208,9 +208,25 @@ def set_js_bindings(self):
208208

209209

210210
def change_url(self, *kwargs):
211-
self.browser.Navigate("http://www.google.com/")
212-
self._client_handler._reset_js_bindings = True
211+
# Doing a javascript redirect instead of Navigate()
212+
# solves the js bindings error. The url here need to
213+
# be preceded with "http://". Calling StopLoad()
214+
# might be a good idea before making the js navigation.
215+
216+
self.browser.StopLoad()
217+
self.browser.GetMainFrame().ExecuteJavascript(
218+
"window.location='http://www.youtube.com/'")
219+
220+
# Do not use Navigate() or GetMainFrame()->LoadURL(),
221+
# as it causes the js bindings to be removed. There is
222+
# a bug in CEF, that happens after a call to Navigate().
223+
# The OnBrowserDestroyed() callback is fired and causes
224+
# the js bindings to be removed. See this topic for more
225+
# details:
226+
# http://www.magpcss.org/ceforum/viewtopic.php?f=6&t=11009
213227

228+
# OFF:
229+
# | self.browser.Navigate("http://www.youtube.com/")
214230

215231
_keyboard = None
216232

@@ -226,13 +242,15 @@ def request_keyboard(self):
226242
self.is_ctrl2 = False
227243
self.is_alt1 = False
228244
self.is_alt2 = False
229-
# Browser lost its focus after the LoadURL() and the
230-
# OnBrowserDestroyed() callback bug. This will only work
231-
# when keyboard mode is local.
245+
# Not sure if it is still required to send the focus
246+
# (some earlier bug), but it shouldn't hurt to call it.
232247
self.browser.SendFocusEvent(True)
233248

234249

235250
def release_keyboard(self):
251+
# When using local keyboard mode, do all the request
252+
# and releases of the keyboard through js bindings,
253+
# otherwise some focus problems arise.
236254
self.is_shift1 = False
237255
self.is_shift2 = False
238256
self.is_ctrl1 = False
@@ -594,15 +612,6 @@ def OnLoadingStateChange(self, browser, isLoading, canGoBack,
594612
canGoForward):
595613
print("OnLoadingStateChange(): isLoading = %s" % isLoading)
596614
browserWidget = browser.GetUserData("browserWidget")
597-
if self._reset_js_bindings and not isLoading:
598-
if browserWidget:
599-
browserWidget.set_js_bindings()
600-
self._reset_js_bindings = False
601-
if isLoading and browserWidget \
602-
and browserWidget.keyboard_mode == "local":
603-
# Release keyboard when navigating to a new page.
604-
browserWidget.release_keyboard()
605-
pass
606615

607616

608617
def OnPaint(self, browser, paintElementType, dirtyRects, buffer, width,

cefpython/cef3/subprocess/cefpython_app.cpp

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "include/cef_runnable.h"
1515
#include "DebugLog.h"
1616
#include <vector>
17+
#include <algorithm>
1718
#include "v8utils.h"
1819
#include "javascript_callback.h"
1920
#include "v8function_handler.h"
@@ -350,36 +351,54 @@ void CefPythonApp::DoJavascriptBindingsForBrowser(
350351
return;
351352
}
352353
std::vector<int64> frameIds;
354+
std::vector<CefString> frameNames;
353355
if (jsBindings->HasKey("bindToFrames")
354356
&& jsBindings->GetType("bindToFrames") == VTYPE_BOOL
355357
&& jsBindings->GetBool("bindToFrames")) {
356-
browser->GetFrameIdentifiers(frameIds);
357-
// CEF BUG: frameIds contain just one frame with frameId=0
358-
if (frameIds.size() == 1 && frameIds[0] == 0) {
359-
frameIds.push_back(browser->GetMainFrame()->GetIdentifier());
358+
// GetFrameIdentifiers() is buggy, returns always a vector
359+
// filled with zeroes (as of revision 1448). Use GetFrameNames()
360+
// instead.
361+
browser->GetFrameNames(frameNames);
362+
for (std::vector<CefString>::iterator it = frameNames.begin(); \
363+
it != frameNames.end(); ++it) {
364+
CefRefPtr<CefFrame> frame = browser->GetFrame(*it);
365+
if (frame.get()) {
366+
frameIds.push_back(frame->GetIdentifier());
367+
// | printf("GetFrameNames(): frameId = %lu\n",
368+
// | frame->GetIdentifier());
369+
}
360370
}
361-
} else {
371+
}
372+
// BUG in CEF:
373+
// GetFrameNames() does not return the main frame (as of revision 1448).
374+
// Make it work for the future when this bug gets fixed.
375+
std::vector<int64>::iterator find_it = std::find(
376+
frameIds.begin(), frameIds.end(),
377+
browser->GetMainFrame()->GetIdentifier());
378+
if (find_it == frameIds.end()) {
379+
// Main frame not found in frameIds vector, add it now.
380+
// | printf("Adding main frame to frameIds: %lu\n",
381+
// | browser->GetMainFrame()->GetIdentifier());
362382
frameIds.push_back(browser->GetMainFrame()->GetIdentifier());
363383
}
364-
/*
365-
Another way:
366-
| for (std::vector<int64>::iterator it = v.begin(); it != v.end(); ++it) {
367-
| CefRefPtr<CefFrame> frame = browser->GetFrame(*it);
368-
*/
369384
if (!frameIds.size()) {
370385
DebugLog("Renderer: DoJavascriptBindingsForBrowser() FAILED: " \
371386
"frameIds.size() == 0");
372387
return;
373388
}
374-
for (std::vector<int>::size_type i = 0; i != frameIds.size(); i++) {
375-
if (frameIds[i] <= 0) {
376-
// Frame not yet created, race condition / bug in CEF.
389+
for (std::vector<int64>::iterator it = frameIds.begin(); \
390+
it != frameIds.end(); ++it) {
391+
if (*it <= 0) {
392+
// GetFrameIdentifiers() bug that returned a vector
393+
// filled with zeros. This problem was fixed by using'
394+
// GetFrameNames() so this block of code should not
395+
// be executed anymore.
377396
DebugLog("Renderer: DoJavascriptBindingsForBrowser() WARNING: " \
378397
"frameId <= 0");
379-
printf("cefpython: Renderer: frameId = %li\n", frameIds[i]);
398+
printf("cefpython: Renderer: frameId = %li\n", *it);
380399
continue;
381400
}
382-
CefRefPtr<CefFrame> frame = browser->GetFrame(frameIds[i]);
401+
CefRefPtr<CefFrame> frame = browser->GetFrame(*it);
383402
if (!frame.get()) {
384403
DebugLog("Renderer: DoJavascriptBindingsForBrowser() WARNING: " \
385404
"GetFrame() failed");

0 commit comments

Comments
 (0)