|
7 | 7 |
|
8 | 8 | Install instructions. |
9 | 9 | |
10 | | - 1. Install SDL libraries for your OS, e.g. for Fedora: |
11 | | -
|
12 | | - dnf install SDL2 SDL2_ttf SDL2_image SDL2_gfx SDL2_mixer |
| 10 | + 1. Install SDL libraries for your OS, e.g: |
| 11 | + |
| 12 | + Fedora: |
| 13 | + |
| 14 | + sudo dnf install SDL2 SDL2_ttf SDL2_image SDL2_gfx SDL2_mixer |
| 15 | + |
| 16 | + Ubuntu: |
| 17 | + |
| 18 | + sudo apt-get install libsdl2-dev |
13 | 19 |
|
14 | 20 | 2. Install PySDL via PIP: |
15 | 21 |
|
16 | | - pip2 install PySDL2 |
| 22 | + sudo pip2 install PySDL2 |
17 | 23 |
|
18 | 24 | Tested configurations: |
19 | 25 | - SDL2 2.0.5 with PySDL2 0.9.3 on Fedora 25 (x86_64) |
20 | 26 | """ |
21 | 27 |
|
22 | 28 | import os |
23 | 29 | import sys |
24 | | -from cefpython3 import cefpython as cef |
| 30 | +try: |
| 31 | + from cefpython3 import cefpython as cef |
| 32 | +except ImportError: |
| 33 | + print("cefpython3 module not found - please install") |
| 34 | + sys.exit(1) |
25 | 35 | try: |
26 | 36 | import sdl2 |
27 | 37 | import sdl2.ext |
28 | 38 | except ImportError: |
29 | | - print "SDL2 module not found - please install" |
| 39 | + print("SDL2 module not found - please install") |
30 | 40 | sys.exit(1) |
31 | 41 | try: |
32 | 42 | from PIL import Image |
33 | 43 | except ImportError: |
34 | | - print "PIL module not found - please install" |
| 44 | + print("PIL module not found - please install") |
35 | 45 | sys.exit(1) |
36 | 46 |
|
| 47 | +def main(): |
| 48 | + # The following variables control the dimensions of the window |
| 49 | + # and browser display area |
| 50 | + width = 1024 |
| 51 | + height = 768 |
| 52 | + # headerHeight is useful for leaving space for controls |
| 53 | + # at the top of the window (future implementation?) |
| 54 | + headerHeight = 0 |
| 55 | + browserHeight = height - headerHeight |
| 56 | + browserWidth = width |
| 57 | + # Initialise CEF for offscreen rendering |
| 58 | + WindowUtils = cef.WindowUtils() |
| 59 | + sys.excepthook = cef.ExceptHook |
| 60 | + cef.Initialize(settings={"windowless_rendering_enabled": True}) |
| 61 | + window_info = cef.WindowInfo() |
| 62 | + window_info.SetAsOffscreen(0) |
| 63 | + # Initialise SDL2 for video (add other init constants if you |
| 64 | + # require other SDL2 functionality e.g. mixer, |
| 65 | + # TTF, joystick etc. |
| 66 | + sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO) |
| 67 | + # Create the window |
| 68 | + window = sdl2.video.SDL_CreateWindow( |
| 69 | + 'cefpython3 SDL2 Demo', |
| 70 | + sdl2.video.SDL_WINDOWPOS_UNDEFINED, |
| 71 | + sdl2.video.SDL_WINDOWPOS_UNDEFINED, |
| 72 | + width, |
| 73 | + height, |
| 74 | + 0 |
| 75 | + ) |
| 76 | + # Define default background colour (black in this case) |
| 77 | + backgroundColour = sdl2.SDL_Color(0, 0, 0) |
| 78 | + # Create the renderer using hardware acceleration |
| 79 | + renderer = sdl2.SDL_CreateRenderer(window, -1, sdl2.render.SDL_RENDERER_ACCELERATED) |
| 80 | + # Set-up the RenderHandler, passing in the SDL2 renderer |
| 81 | + renderHandler = RenderHandler(renderer, width, height - headerHeight) |
| 82 | + # Create the browser instance |
| 83 | + browser = cef.CreateBrowserSync(window_info, url="https://www.google.com/") |
| 84 | + browser.SetClientHandler(LoadHandler()) |
| 85 | + browser.SetClientHandler(renderHandler) |
| 86 | + # Must call WasResized at least once to let know CEF that |
| 87 | + # viewport size is available and that OnPaint may be called. |
| 88 | + browser.SendFocusEvent(True) |
| 89 | + browser.WasResized() |
| 90 | + # Begin the main rendering loop |
| 91 | + running = True |
| 92 | + while running: |
| 93 | + # Convert SDL2 events into CEF events (where appropriate) |
| 94 | + events = sdl2.ext.get_events() |
| 95 | + for event in events: |
| 96 | + if event.type == sdl2.SDL_QUIT or (event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_ESCAPE): |
| 97 | + running = False |
| 98 | + break |
| 99 | + if event.type == sdl2.SDL_MOUSEBUTTONDOWN: |
| 100 | + if event.button.button == sdl2.SDL_BUTTON_LEFT: |
| 101 | + if event.button.y > headerHeight: |
| 102 | + # Mouse click triggered in browser region |
| 103 | + browser.SendMouseClickEvent(event.button.x, event.button.y - headerHeight, cef.MOUSEBUTTON_LEFT, False, 1) |
| 104 | + elif event.type == sdl2.SDL_MOUSEBUTTONUP: |
| 105 | + if event.button.button == sdl2.SDL_BUTTON_LEFT: |
| 106 | + if event.button.y > headerHeight: |
| 107 | + # Mouse click triggered in browser region |
| 108 | + browser.SendMouseClickEvent(event.button.x, event.button.y - headerHeight, cef.MOUSEBUTTON_LEFT, True, 1) |
| 109 | + elif event.type == sdl2.SDL_MOUSEMOTION: |
| 110 | + if event.button.y > headerHeight: |
| 111 | + # Mouse click triggered in browser region |
| 112 | + browser.SendMouseMoveEvent(event.button.x, event.button.y - headerHeight, True) |
| 113 | + # Clear the renderer |
| 114 | + sdl2.SDL_SetRenderDrawColor(renderer, backgroundColour.r, backgroundColour.g, backgroundColour.b, 255) |
| 115 | + sdl2.SDL_RenderClear(renderer) |
| 116 | + # Tell CEF to update which will trigger the OnPaint |
| 117 | + # method of the RenderHandler instance |
| 118 | + cef.MessageLoopWork() |
| 119 | + # Update display |
| 120 | + sdl2.SDL_RenderCopy(renderer, renderHandler.texture, None, sdl2.SDL_Rect(0, headerHeight, browserWidth, browserHeight)) |
| 121 | + sdl2.SDL_RenderPresent(renderer) |
| 122 | + # User exited |
| 123 | + exit_app() |
| 124 | + |
37 | 125 | class LoadHandler(object): |
38 | 126 | """Simple handler for loading URLs.""" |
39 | 127 |
|
40 | 128 | def OnLoadingStateChange(self, browser, is_loading, **_): |
41 | 129 | if not is_loading: |
42 | | - print "loading complete" |
| 130 | + print("loading complete") |
43 | 131 |
|
44 | 132 | def OnLoadError(self, browser, frame, error_code, failed_url, **_): |
45 | 133 | if not frame.IsMain(): |
46 | 134 | return |
47 | | - print "Failed to load %s" % failed_url |
| 135 | + print("Failed to load %s" % failed_url) |
48 | 136 | cef.PostTask(cef.TID_UI, exit_app, browser) |
49 | 137 |
|
50 | 138 | class RenderHandler(object): |
@@ -81,9 +169,7 @@ def OnPaint(self, browser, element_type, paint_buffer, **_): |
81 | 169 | 'raw', |
82 | 170 | 'BGRA' |
83 | 171 | ) |
84 | | - # |
85 | 172 | # Following PIL to SDL2 surface code from pysdl2 source. |
86 | | - # |
87 | 173 | mode = image.mode |
88 | 174 | rmask = gmask = bmask = amask = 0 |
89 | 175 | if mode == "RGB": |
@@ -116,103 +202,27 @@ def OnPaint(self, browser, element_type, paint_buffer, **_): |
116 | 202 | depth = 32 |
117 | 203 | pitch = self.__width * 4 |
118 | 204 | else: |
119 | | - print "Unsupported mode: %s" % mode |
| 205 | + print("Unsupported mode: %s" % mode) |
120 | 206 | exit_app() |
121 | 207 |
|
122 | 208 | pxbuf = image.tobytes() |
123 | | - # create surface |
| 209 | + # Create surface |
124 | 210 | surface = sdl2.SDL_CreateRGBSurfaceFrom(pxbuf, self.__width, self.__height, depth, pitch, rmask, gmask, bmask, amask) |
125 | 211 | if self.texture: |
126 | 212 | # free memory used by previous texture |
127 | 213 | sdl2.SDL_DestroyTexture(self.texture) |
128 | | - # create texture |
| 214 | + # Create texture |
129 | 215 | self.texture = sdl2.SDL_CreateTextureFromSurface(self.__renderer, surface) |
130 | | - # free the surface |
| 216 | + # Free the surface |
131 | 217 | sdl2.SDL_FreeSurface(surface) |
132 | 218 | else: |
133 | | - print "Unsupport element_type in OnPaint" |
| 219 | + print("Unsupport element_type in OnPaint") |
134 | 220 |
|
135 | 221 | def exit_app(): |
136 | 222 | """Tidy up SDL2 and CEF before exiting.""" |
137 | 223 | sdl2.SDL_Quit() |
138 | 224 | cef.Shutdown() |
139 | | - print "exited" |
140 | | - |
141 | | -def main(): |
142 | | - # the following variables control the dimensions of the window |
143 | | - # and browser display area |
144 | | - width = 1024 |
145 | | - height = 768 |
146 | | - headerHeight = 0 # useful if for leaving space for controls at the top of the window (future implementation?) |
147 | | - browserHeight = height - headerHeight |
148 | | - browserWidth = width |
149 | | - # initialise CEF for offscreen rendering |
150 | | - WindowUtils = cef.WindowUtils() |
151 | | - sys.excepthook = cef.ExceptHook |
152 | | - cef.Initialize(settings={"windowless_rendering_enabled": True}) |
153 | | - window_info = cef.WindowInfo() |
154 | | - window_info.SetAsOffscreen(0) |
155 | | - # initialise SDL2 for video (add other init constants if you |
156 | | - # require other SDL2 functionality e.g. mixer, |
157 | | - # TTF, joystick etc. |
158 | | - sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO) |
159 | | - # create the window |
160 | | - window = sdl2.video.SDL_CreateWindow( |
161 | | - 'cefpython3 SDL2 Demo', |
162 | | - sdl2.video.SDL_WINDOWPOS_UNDEFINED, |
163 | | - sdl2.video.SDL_WINDOWPOS_UNDEFINED, |
164 | | - width, |
165 | | - height, |
166 | | - 0 |
167 | | - ) |
168 | | - # define default background colour (black in this case) |
169 | | - backgroundColour = sdl2.SDL_Color(0, 0, 0) |
170 | | - # create the renderer using hardware acceleration |
171 | | - renderer = sdl2.SDL_CreateRenderer(window, -1, sdl2.render.SDL_RENDERER_ACCELERATED) |
172 | | - # set-up the RenderHandler, passing in the SDL2 renderer |
173 | | - renderHandler = RenderHandler(renderer, width, height - headerHeight) |
174 | | - # create the browser instance |
175 | | - browser = cef.CreateBrowserSync(window_info, url="https://www.google.com/") |
176 | | - browser.SetClientHandler(LoadHandler()) |
177 | | - browser.SetClientHandler(renderHandler) |
178 | | - # must call WasResized at least once to let know CEF that |
179 | | - # viewport size is available and that OnPaint may be called. |
180 | | - browser.SendFocusEvent(True) |
181 | | - browser.WasResized() |
182 | | - # begin the main rendering loop |
183 | | - running = True |
184 | | - while running: |
185 | | - # convert SDL2 events into CEF events (where appropriate) |
186 | | - events = sdl2.ext.get_events() |
187 | | - for event in events: |
188 | | - if event.type == sdl2.SDL_QUIT or (event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_ESCAPE): |
189 | | - running = False |
190 | | - break |
191 | | - if event.type == sdl2.SDL_MOUSEBUTTONDOWN: |
192 | | - if event.button.button == sdl2.SDL_BUTTON_LEFT: |
193 | | - if event.button.y > headerHeight: |
194 | | - # mouse click triggered in browser region |
195 | | - browser.SendMouseClickEvent(event.button.x, event.button.y - headerHeight, cef.MOUSEBUTTON_LEFT, False, 1) |
196 | | - elif event.type == sdl2.SDL_MOUSEBUTTONUP: |
197 | | - if event.button.button == sdl2.SDL_BUTTON_LEFT: |
198 | | - if event.button.y > headerHeight: |
199 | | - # mouse click triggered in browser region |
200 | | - browser.SendMouseClickEvent(event.button.x, event.button.y - headerHeight, cef.MOUSEBUTTON_LEFT, True, 1) |
201 | | - elif event.type == sdl2.SDL_MOUSEMOTION: |
202 | | - if event.button.y > headerHeight: |
203 | | - # mouse click triggered in browser region |
204 | | - browser.SendMouseMoveEvent(event.button.x, event.button.y - headerHeight, True) |
205 | | - # clear the renderer |
206 | | - sdl2.SDL_SetRenderDrawColor(renderer, backgroundColour.r, backgroundColour.g, backgroundColour.b, 255) |
207 | | - sdl2.SDL_RenderClear(renderer) |
208 | | - # tell CEF to update which will trigger the OnPaint |
209 | | - # method of the RenderHandler instance |
210 | | - cef.MessageLoopWork() |
211 | | - # update display |
212 | | - sdl2.SDL_RenderCopy(renderer, renderHandler.texture, None, sdl2.SDL_Rect(0, headerHeight, browserWidth, browserHeight)) |
213 | | - sdl2.SDL_RenderPresent(renderer) |
214 | | - # user exited |
215 | | - exit_app() |
| 225 | + print("exited") |
216 | 226 |
|
217 | 227 | if __name__ == "__main__": |
218 | 228 | main() |
0 commit comments