Skip to content

Commit 9bd3acc

Browse files
committed
Fix issues with examples on Windows with v55+ (cztomczak#294)...
All examples do run fine on Windows now. Add run_examples.py tool to run all examples that can be run on current configuration.
1 parent 97712b3 commit 9bd3acc

File tree

12 files changed

+396
-106
lines changed

12 files changed

+396
-106
lines changed

examples/gtk2.py

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Example of embedding CEF Python browser using PyGTK library (GTK 2).
2-
# Tested with GTK 2.24 and CEF Python v55.3+, only on Linux.
2+
# Tested with GTK 2.24 and CEF Python v55.3+, on Windows/Linux.
33
# Known issue on Linux: Keyboard focus problem (Issue #284).
44

55
from cefpython3 import cefpython as cef
@@ -8,16 +8,25 @@
88
import gobject
99
import sys
1010
import os
11+
import platform
12+
13+
# Fix for PyCharm hints warnings
14+
WindowUtils = cef.WindowUtils()
15+
16+
# Platforms
17+
WINDOWS = (platform.system() == "Windows")
18+
LINUX = (platform.system() == "Linux")
19+
MAC = (platform.system() == "Darwin")
1120

1221
# In CEF you can run message loop in two ways (see API docs for more details):
13-
# 1. By calling cef.MessageLoop() instead of an application-provided
22+
# 1. By calling cef.MessageLoopWork() in a timer - each call performs
23+
# a single iteration of CEF message loop processing.
24+
# 2. By calling cef.MessageLoop() instead of an application-provided
1425
# message loop to get the best balance between performance and CPU
1526
# usage. This function will block until a quit message is received by
16-
# the system.
17-
# 2. By calling cef.MessageLoopWork() in a timer - each call performs
18-
# a single iteration of CEF message loop processing.
19-
MESSAGE_LOOP_BEST = 1
20-
MESSAGE_LOOP_TIMER = 2 # Pass --message-loop-timer flag to script to use this
27+
# the system. This seem to work only on Linux in GTK example.
28+
MESSAGE_LOOP_TIMER = 1
29+
MESSAGE_LOOP_CEF = 2 # Pass --message-loop-cef flag to script on Linux
2130
g_message_loop = None
2231

2332

@@ -28,7 +37,7 @@ def main():
2837
cef.Initialize()
2938
gobject.threads_init()
3039
Gtk2Example()
31-
if g_message_loop == MESSAGE_LOOP_BEST:
40+
if g_message_loop == MESSAGE_LOOP_CEF:
3241
cef.MessageLoop()
3342
else:
3443
gtk.main()
@@ -46,13 +55,13 @@ def check_versions():
4655

4756
def configure_message_loop():
4857
global g_message_loop
49-
if "--message-loop-timer" in sys.argv:
58+
if "--message-loop-cef" in sys.argv:
59+
print("[gkt2.py] Message loop mode: CEF (best performance)")
60+
g_message_loop = MESSAGE_LOOP_CEF
61+
sys.argv.remove("--message-loop-cef")
62+
else:
5063
print("[gkt2.py] Message loop mode: TIMER")
5164
g_message_loop = MESSAGE_LOOP_TIMER
52-
sys.argv.remove("--message-loop-timer")
53-
else:
54-
print("[gkt2.py] Message loop mode: BEST")
55-
g_message_loop = MESSAGE_LOOP_BEST
5665
if len(sys.argv) > 1:
5766
print("[gkt2.py] ERROR: unknown argument passed")
5867
sys.exit(1)
@@ -83,7 +92,7 @@ def __init__(self):
8392
self.main_window.add(self.vbox)
8493

8594
windowInfo = cef.WindowInfo()
86-
windowInfo.SetAsChild(self.main_window.window.xid)
95+
windowInfo.SetAsChild(self.get_handle())
8796
self.browser = cef.CreateBrowserSync(windowInfo, settings={},
8897
url="https://www.google.com/")
8998
self.browser.SetClientHandler(LoadHandler())
@@ -95,6 +104,12 @@ def __init__(self):
95104
if g_message_loop == MESSAGE_LOOP_TIMER:
96105
gobject.timeout_add(10, self.on_timer)
97106

107+
def get_handle(self):
108+
if LINUX:
109+
return self.main_window.window.xid
110+
else:
111+
return self.main_window.window.handle
112+
98113
def create_menu(self):
99114
item1 = gtk.MenuItem('MenuBar')
100115
item1.show()
@@ -131,16 +146,22 @@ def on_vbox_size_allocate(self, _, data):
131146
y = data.y + self.menubar_height
132147
width = data.width
133148
height = data.height - self.menubar_height
134-
self.browser.SetBounds(x, y, width, height)
149+
if WINDOWS:
150+
WindowUtils.OnSize(self.get_handle(), 0, 0, 0)
151+
elif LINUX:
152+
self.browser.SetBounds(x, y, width, height)
135153

136154
def on_menubar_size_allocate(self, _, data):
137155
self.menubar_height = data.height
138156

139157
def on_exit(self, *_):
158+
if self.exiting:
159+
print("[gtk2.py] on_exit() called, but already exiting")
160+
return
140161
self.exiting = True
141162
self.browser.CloseBrowser(True)
142163
self.browser = None
143-
if g_message_loop == MESSAGE_LOOP_BEST:
164+
if g_message_loop == MESSAGE_LOOP_CEF:
144165
cef.QuitMessageLoop()
145166
else:
146167
gtk.main_quit()
@@ -158,9 +179,10 @@ def OnLoadStart(self, browser, **_):
158179
# sometimes during initial loading, keyboard focus may
159180
# break and it is not possible to type anything, even
160181
# though a type cursor blinks in web view.
161-
print("[gtk2.py] LoadHandler.OnLoadStart:"
162-
" keyboard focus fix (#284)")
163-
browser.SetFocus(True)
182+
if LINUX:
183+
print("[gtk2.py] LoadHandler.OnLoadStart:"
184+
" keyboard focus fix (#284)")
185+
browser.SetFocus(True)
164186
self.initial_app_loading = False
165187

166188

examples/gtk3.py

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,33 @@
1-
# ! CURRENTLY BROKEN ! with v54+ (Issue #261).
2-
# Example of embedding CEF Python browser using PyGObject library (GTK 3).
3-
# Tested with GTK 3.10 and CEF Python v53.1+, only on Linux.
1+
# Example of embedding CEF Python browser using PyGObject/PyGI (GTK 3).
2+
3+
# Linux note: This example is currently broken in v54+ on Linux (Issue #261).
4+
# It works fine with cefpython v53.
5+
6+
# Tested configurations:
7+
# - GTK 3.18 on Windows
8+
# - GTK 3.10 on Linux
9+
# - CEF Python v53.1+
410

511
from cefpython3 import cefpython as cef
12+
import ctypes
613
# noinspection PyUnresolvedReferences
7-
from gi.repository import GdkX11, Gtk, GObject, GdkPixbuf
14+
from gi.repository import Gtk, GObject, Gdk, GdkPixbuf
815
import sys
916
import os
17+
import platform
18+
19+
# Fix for PyCharm hints warnings
20+
WindowUtils = cef.WindowUtils()
21+
22+
# Platforms
23+
WINDOWS = (platform.system() == "Windows")
24+
LINUX = (platform.system() == "Linux")
25+
MAC = (platform.system() == "Darwin")
26+
27+
# Linux imports
28+
if LINUX:
29+
# noinspection PyUnresolvedReferences
30+
from gi.repository import GdkX11
1031

1132

1233
def main():
@@ -25,9 +46,10 @@ def main():
2546
class Gtk3Example(Gtk.Application):
2647

2748
def __init__(self):
28-
super(Gtk3Example, self).__init__(application_id='cefpython.gtk')
49+
super(Gtk3Example, self).__init__(application_id='cefpython.gtk3')
2950
self.browser = None
3051
self.window = None
52+
self.win32_handle = None
3153

3254
def run(self, argv):
3355
GObject.threads_init()
@@ -36,6 +58,22 @@ def run(self, argv):
3658
self.connect("shutdown", self.on_shutdown)
3759
return super(Gtk3Example, self).run(argv)
3860

61+
def get_handle(self):
62+
if LINUX:
63+
return self.window.get_property("window").get_xid()
64+
elif WINDOWS:
65+
Gdk.threads_enter()
66+
ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p
67+
ctypes.pythonapi.PyCapsule_GetPointer.argtypes = \
68+
[ctypes.py_object]
69+
gpointer = ctypes.pythonapi.PyCapsule_GetPointer(
70+
self.window.get_property("window").__gpointer__, None)
71+
gdk_dll = ctypes.CDLL("libgdk-3-0.dll")
72+
self.win32_handle = gdk_dll.gdk_win32_window_get_handle(
73+
gpointer)
74+
Gdk.threads_leave()
75+
return self.win32_handle
76+
3977
def on_timer(self):
4078
cef.MessageLoopWork()
4179
return True
@@ -51,10 +89,13 @@ def on_activate(self, *_):
5189
self.setup_icon()
5290
self.window.realize()
5391
window_info = cef.WindowInfo()
54-
window_info.SetAsChild(self.window.get_property("window").get_xid())
92+
window_info.SetAsChild(self.get_handle())
5593
self.browser = cef.CreateBrowserSync(window_info,
5694
url="https://www.google.com/")
5795
self.window.show_all()
96+
# Must set size of the window again after it was shown,
97+
# otherwise browser occupies only part of the window area.
98+
self.window.resize(*self.window.get_default_size())
5899

59100
def on_configure(self, *_):
60101
if self.browser:
@@ -63,7 +104,11 @@ def on_configure(self, *_):
63104

64105
def on_size_allocate(self, _, data):
65106
if self.browser:
66-
self.browser.SetBounds(data.x, data.y, data.width, data.height)
107+
if WINDOWS:
108+
WindowUtils.OnSize(self.win32_handle, 0, 0, 0)
109+
elif LINUX:
110+
self.browser.SetBounds(data.x, data.y,
111+
data.width, data.height)
67112

68113
def on_focus_in(self, *_):
69114
if self.browser:

examples/hello_world.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Hello world example. Doesn't depend on any third party GUI framework.
2-
# Tested with CEF Python v55.3+, only on Linux.
2+
# Tested with CEF Python v55.3+.
33

44
from cefpython3 import cefpython as cef
55
import sys

0 commit comments

Comments
 (0)