Skip to content

Commit eb842cd

Browse files
committed
Create GTK 2 [PyGTK] example and rename GTK 3 [PyGObject] example (cztomczak#261).
1 parent 0cc124e commit eb842cd

File tree

4 files changed

+159
-8
lines changed

4 files changed

+159
-8
lines changed

examples/gtk2.py

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
# Example of embedding CEF Python browser using PyGTK library (GTK 2).
2+
# Tested with GTK 2.24 and CEF Python v54+.
3+
4+
from cefpython3 import cefpython as cef
5+
import pygtk
6+
import gtk
7+
import gobject
8+
import sys
9+
import time
10+
11+
# In CEF you can run message loop in two ways (see API docs for more details):
12+
# 1. By calling cef.MessageLoop() instead of an application-provided
13+
# message loop to get the best balance between performance and CPU
14+
# usage. This function will block until a quit message is received by
15+
# the system.
16+
# 2. By calling cef.MessageLoopWork() in a timer - each call performs
17+
# a single iteration of CEF message loop processing.
18+
MESSAGE_LOOP_BEST = 1
19+
MESSAGE_LOOP_TIMER = 2 # Pass --message-loop-timer flag to script to use this
20+
g_message_loop = None
21+
22+
23+
def main():
24+
check_versions()
25+
sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error
26+
configure_message_loop()
27+
cef.Initialize()
28+
gobject.threads_init()
29+
Gtk2Example()
30+
if g_message_loop == MESSAGE_LOOP_BEST:
31+
cef.MessageLoop()
32+
else:
33+
gtk.main()
34+
cef.Shutdown()
35+
36+
37+
def check_versions():
38+
print("CEF Python {ver}".format(ver=cef.__version__))
39+
print("Python {ver}".format(ver=sys.version[:6]))
40+
print("GTK {ver}".format(ver='.'.join(map(str, list(gtk.gtk_version)))))
41+
assert cef.__version__ >= "54.0", "CEF Python v54+ required to run this"
42+
pygtk.require('2.0')
43+
44+
45+
def configure_message_loop():
46+
global g_message_loop
47+
if "--message-loop-timer" in sys.argv:
48+
print("Message loop mode: TIMER")
49+
g_message_loop = MESSAGE_LOOP_TIMER
50+
sys.argv.remove("--message-loop-timer")
51+
else:
52+
print("Message loop mode: BEST")
53+
g_message_loop = MESSAGE_LOOP_BEST
54+
if len(sys.argv) > 1:
55+
print("ERROR: unknown argument passed")
56+
sys.exit(1)
57+
58+
59+
class Gtk2Example:
60+
61+
def __init__(self):
62+
self.menubar_height = 0
63+
self.exiting = False
64+
65+
self.main_window = gtk.Window(gtk.WINDOW_TOPLEVEL)
66+
self.main_window.connect('focus-in-event', self.on_focus_in)
67+
self.main_window.connect('configure-event', self.on_configure)
68+
self.main_window.connect('destroy', self.on_exit)
69+
self.main_window.set_size_request(width=800, height=600)
70+
self.main_window.set_title('GTK 2 example (PyGTK)')
71+
self.main_window.realize()
72+
73+
self.vbox = gtk.VBox(False, 0)
74+
self.vbox.connect('size-allocate', self.on_vbox_size_allocate)
75+
self.menubar = self.create_menu()
76+
self.menubar.connect('size-allocate', self.on_menubar_size_allocate)
77+
self.vbox.pack_start(self.menubar, False, False, 0)
78+
self.main_window.add(self.vbox)
79+
80+
windowInfo = cef.WindowInfo()
81+
windowInfo.SetAsChild(self.main_window.window.xid)
82+
self.browser = cef.CreateBrowserSync(windowInfo, settings={},
83+
url="https://www.google.com/")
84+
85+
self.vbox.show()
86+
self.main_window.show()
87+
self.vbox.get_window().focus()
88+
self.main_window.get_window().focus()
89+
if g_message_loop == MESSAGE_LOOP_TIMER:
90+
gobject.timeout_add(10, self.on_timer)
91+
92+
def create_menu(self):
93+
item1 = gtk.MenuItem('MenuBar')
94+
item1.show()
95+
item1_0 = gtk.Menu()
96+
item1_1 = gtk.MenuItem('Just a menu')
97+
item1_0.append(item1_1)
98+
item1_1.show()
99+
item1.set_submenu(item1_0)
100+
menubar = gtk.MenuBar()
101+
menubar.append(item1)
102+
menubar.show()
103+
return menubar
104+
105+
def on_timer(self):
106+
if self.exiting:
107+
return False
108+
cef.MessageLoopWork()
109+
return True
110+
111+
def on_focus_in(self, *_):
112+
if self.browser:
113+
self.browser.SetFocus(True)
114+
return True
115+
return False
116+
117+
def on_configure(self, *_):
118+
if self.browser:
119+
self.browser.NotifyMoveOrResizeStarted()
120+
return False
121+
122+
def on_vbox_size_allocate(self, _, data):
123+
if self.browser:
124+
x = data.x
125+
y = data.y + self.menubar_height
126+
width = data.width
127+
height = data.height - self.menubar_height
128+
self.browser.SetBounds(x, y, width, height)
129+
130+
def on_menubar_size_allocate(self, _, data):
131+
self.menubar_height = data.height
132+
133+
def on_exit(self, *_):
134+
self.exiting = True
135+
self.browser.CloseBrowser(True)
136+
self.browser = None
137+
if g_message_loop == MESSAGE_LOOP_BEST:
138+
# Run some message loop work for the browser to close cleanly
139+
for i in range(0, 10):
140+
cef.MessageLoopWork()
141+
time.sleep(0.01)
142+
cef.QuitMessageLoop()
143+
else:
144+
gtk.main_quit()
145+
146+
147+
if __name__ == '__main__':
148+
main()

examples/gtk.py renamed to examples/gtk3.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Example of embedding CEF Python browser using PyGObject/Gtk library.
1+
# Example of embedding CEF Python browser using PyGObject library (GTK 3).
22
# Tested with GTK 3.10 and CEF Python v53+.
33

44
from cefpython3 import cefpython as cef
@@ -17,14 +17,14 @@ def main():
1717
assert cef.__version__ >= "53.1", "CEF Python v53.1+ required to run this"
1818
sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error
1919
cef.Initialize()
20-
app = GtkExample()
20+
app = Gtk3Example()
2121
SystemExit(app.run(sys.argv))
2222

2323

24-
class GtkExample(Gtk.Application):
24+
class Gtk3Example(Gtk.Application):
2525

2626
def __init__(self):
27-
super(GtkExample, self).__init__(application_id='cefpython.gtk')
27+
super(Gtk3Example, self).__init__(application_id='cefpython.gtk')
2828
self.browser = None
2929
self.window = None
3030

@@ -33,15 +33,15 @@ def run(self, argv):
3333
GObject.timeout_add(10, self.on_timer)
3434
self.connect("activate", self.on_activate)
3535
self.connect("shutdown", self.on_shutdown)
36-
return super(GtkExample, self).run(argv)
36+
return super(Gtk3Example, self).run(argv)
3737

3838
def on_timer(self):
3939
cef.MessageLoopWork()
4040
return True
4141

4242
def on_activate(self, *_):
4343
self.window = Gtk.ApplicationWindow.new(self)
44-
self.window.set_title("Gtk example")
44+
self.window.set_title("GTK 3 example (PyGObject)")
4545
self.window.set_default_size(800, 600)
4646
self.window.connect("configure-event", self.on_configure)
4747
self.window.connect("size-allocate", self.on_size_allocate)

examples/tkinter_.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
# This example has two widgets: a navigation bar and a browser.
33
# Tested with Tk 8.6 and CEF Python v53+.
44

5-
# TODO: url entry loses keyboard focus when mouse hovers over browser (#255)
5+
# Issue #255: when typing url, mouse must be over url entry widget
6+
# otherwise keyboard focus is lost.
67

78
from cefpython3 import cefpython as cef
89
try:

src/linux/compile.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,9 @@
278278
run_examples = " && {python} kivy_.py"
279279
else:
280280
run_examples = (" && {python} hello_world.py"
281-
" && {python} gtk.py"
281+
" && {python} gtk2.py"
282+
" && {python} gtk2.py --message-loop-timer"
283+
" && {python} gtk3.py"
282284
" && {python} tkinter_.py")
283285
commands = ("cd ./installer/"
284286
" && {python} make-setup.py --version {ver}"

0 commit comments

Comments
 (0)