Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pysdl2 example for issue #324 #379

Merged
merged 8 commits into from
Jan 8, 2018
Merged

Conversation

neilmunday
Copy link
Contributor

@neilmunday neilmunday commented Jul 30, 2017

Hi,

I have created a simple pysdl2 example that uses cefpython3 for issue #324

Please feel free to included it in your examples.

Cheers,

Neil.

Copy link
Owner

@cztomczak cztomczak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this example. I have provided many comments for style issues that need to be addressed. There is also a question about copyright and licensing of this code. Also it would be nice if you could provide me quick instructions for installing pysdl2 on my Linux machine. Thanks!

#
# Tested under Fedora Linux (x86_64).
#
# by Neil Munday (www.mundayweb.com)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you agree to release your code under BSD-3 new license that cefpython uses? You can add your name to the Authors file in the root directory along with your email or website. The copyright messages in cefpython source files are using this template:

# Copyright (c) {YEAR_OF_CREATION} CEF Python, see the Authors file.
# All rights reserved. Licensed under BSD 3-clause license.
# Project website: https://github.com/cztomczak/cefpython

The examples from the examples/ directory do not contain any copyright messages and this is intentional, because these examples are intended to be edited freely by users.

When your PR is accepted you will also appear on the Contributors page:
https://github.com/cztomczak/cefpython/graphs/contributors

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am happy for the code to be used freely as people see fit.

#
# Only handles mouse events but could be extended to handle others.
#
# Requires pysdl2 (and SDL2 library).
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please provide quick instructions on installing pysdl2?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pip2 install PySDL2

Note: you will need to make sure you have installed the SDL2 libraries for your OS.

@@ -0,0 +1,182 @@
#!/usr/bin/python2
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be removed.

@@ -0,0 +1,182 @@
#!/usr/bin/python2

#
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove that kind of comments with following empty line.


#
# Simple SDL2 / cefpython3 example.
#
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the blank lines in this block of comment.

if element_type == cef.PET_VIEW:
data = paint_buffer.GetString(mode="rgba", origin="top-left")
image = Image.frombuffer('RGBA', (self.__width, self.__height), data, 'raw', 'BGRA')
#
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary.

surface = sdl2.SDL_CreateRGBSurfaceFrom(pxbuf, self.__width, self.__height, depth, pitch, rmask, gmask, bmask, amask)

if self.texture:
sdl2.SDL_DestroyTexture(self.texture)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use 4x spaces for indentation (pep8).

browserHeight = height - headerHeight
browserWidth = width

WindowUtils = cef.WindowUtils()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too many blank lines between for the next several lines.


sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO)

window = sdl2.video.SDL_CreateWindow('cefpython3 SDL2 Demo', sdl2.video.SDL_WINDOWPOS_UNDEFINED, sdl2.video.SDL_WINDOWPOS_UNDEFINED, width, height, 0)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrap lines to 79 characters.

cef.Shutdown()
print "exited"

if __name__ == "__main__":
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please put here only a call to main(), and define main at the top of the file just below the imports. That's how it is done in all other examples, so it should be consistent in this example as well.

@neilmunday
Copy link
Contributor Author

Hi. Thanks for the feedback. I'll submit a modified version of the example later.

@neilmunday
Copy link
Contributor Author

New changes committed as requested.

Copy link
Owner

@cztomczak cztomczak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, it looks good, although there are still some issues.

I've tested using Ubuntu 14.04 / pysdl2 0.9.5 and it works fine - can be added to top comment.

Installation instructions for Ubuntu - this could be added to top comment as well:

sudo apt-get install libsdl2-dev
sudo pip install pysdl2

The keyboard doesn't work at all. All examples in the examples/ directory are officially supported and they need to be complete. Both mouse and keyboard support is required. How hard would it be to add keyboard support?

I will still have to test it on Windows and Mac.

pip2 install PySDL2

Tested configurations:
- SDL2 2.0.5 with PySDL2 0.9.3 on Fedora 25 (x86_64)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great that you've added this.

import sdl2
import sdl2.ext
except ImportError:
print "SDL2 module not found - please install"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good!


def OnLoadingStateChange(self, browser, is_loading, **_):
if not is_loading:
print "loading complete"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your code should be Python 3 compatible. There is no print statement in Py3.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you able to test it using Python3? If not, not a big issue I can do this, just fix the most obvious issues like the print statement.

cef.PostTask(cef.TID_UI, exit_app, browser)

class RenderHandler(object):
"""
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding comments like this.

'raw',
'BGRA'
)
#
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That blank comment can be removed and the one further.

print "exited"

def main():
# the following variables control the dimensions of the window
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments should start from upper case letter - there are more fixes like this required.

# and browser display area
width = 1024
height = 768
headerHeight = 0 # useful if for leaving space for controls at the top of the window (future implementation?)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrap comments to 79 characters as well.

cef.Shutdown()
print "exited"

def main():
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main() function should go to the top just below imports.

The main() function also seems very long, could this be split into more functions like for example: initialize(), embed_browser() and message_loop() - these would be called from main()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be split up, but the functions would only be called from main() and quiet a few of the variables would have to become global.

@neilmunday
Copy link
Contributor Author

neilmunday commented Aug 2, 2017

On the keyboard event front, I did try adding support for this in the original version, but I got stumped trying to send the key events to cefpython3. I couldn't work out from the docs how to translate the SDL2 key event characters to ones expected by cefpython3 despite reading the docs. I'll have another look though.

@cztomczak
Copy link
Owner

cztomczak commented Aug 2, 2017

Keyboard support can be tricky. Take a look at the kivy_.py example. This might be strange, but setting "windows_key_code" on Linux is the way to go.

@neilmunday
Copy link
Contributor Author

neilmunday commented Aug 3, 2017

I've made progress thanks to digging through the kivy example, and now have key events working for ASCII characters. Just need to handle modifiers and some special keys.

@cztomczak
Copy link
Owner

Great to hear that.

@neilmunday
Copy link
Contributor Author

I've now added keyboard support. Please feel free to test.

Copy link
Owner

@cztomczak cztomczak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding keyboard support. A few issues, see my review comments for details:

  • OnLoadError should be handled differently
  • An error when calling exit_app
  • Some more info on keyboard/mouse support is required in comments
  • Mouse move events and mouse scroll events do not work. Add at least comments explaining what needs to be done. See my comments.
  • getKeyCode should be a dict mapping. Users may be extending this, so let's get rid of those ifs to make it easier for them.

1
)
elif event.type == sdl2.SDL_MOUSEMOTION:
if event.button.y > headerHeight:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this condition? Why aren't you sending all mouse move events? When I hover over a link at Google I don't see link being underlined, because mouse move event is not being sent.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there available event.position.x/y or similar? If so implementing move events should be easy.

Copy link
Contributor Author

@neilmunday neilmunday Aug 4, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As stated in the comments in the main() function, headerHeight has been defined for use to create a toolbar at the top of the window as a future exercise. SDL unlike other toolkits doesn't provide any kind of GUI widgets - the user has to write their own which as you can imagine can be quite complex. I therefore left this variable in so that mouse events that occur in the region of the window used to paint the cef browser are sent to cef. I could of course remove the headerHeight stuff entirely, but this assumes that the entire window is under cef's control. Let me know what you think.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant why only mouse event is sent when there is a click. I see your other comment saying you will add these mouse move events, great!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ha, I see I am trapping mouse motion events for SDL but processing it as a button press. Oops. That's a bug on my part!

if not frame.IsMain():
return
print("Failed to load %s" % failed_url)
cef.PostTask(cef.TID_UI, exit_app, browser)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like an error here, wrong number of args. Got this exception:

Failed to load http://www.speedtest.net/pl/
[CEF Python] ExceptHook: catched exception, will shutdown CEF

Traceback (most recent call last):
  File "task.pyx", line 57, in cefpython_py27.PyTaskRunnable (cefpython_py27.cpp:33940)
TypeError: exit_app() takes no arguments (1 given)

When displaying "Failed to load %s" it would be nice to display also error_code. I currently have no idea what happened while loading that speedtest.pl website. Is it really necessary to exit app here on error? I would just display a message that url failed and an error code for a reason why it failed. A website may send 404 error, but it will display some webpage and it should be displayed in browser and not exited.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, the app doesn't have to exit here. As mentioned above in another comment, SDL doesn't provide any GUI widgets - it's quite low level in comparison to other GUI toolkits. In order to display an error in the window I would have to either implement some kind of message box or clear the renderer and render text to the window. The latter would be quite simple. However, at that the point without any controls for the user to use they wouldn't be able to go back to the previous page. Is showing errors in the console ok for now?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, showing errors in console is okay. Web page even with error code might contain important information and should be displayed.


def getKeyCode(key):
"""Helper function to convert SDL2 key codes to cef ones"""
if key == sdl2.SDLK_RETURN:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This mapping could be done using a dict:

map_keys = {
    sdl2.SDLK_RETURN: 13,
    sdl2.SDLK_DELETE: 46,
    ...
]

Key mappings is incomplete, so this code will probably be extended by user, so let's get rid of those ifs to make it more clear.

Copy link
Contributor Author

@neilmunday neilmunday Aug 4, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do.

return 36
if key == sdl2.SDLK_END:
return 35
raise Exception("Invalid key")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should say that Keyboard mapping is incomplete and should be extended instead of "Invalid".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do.

"""
Simple SDL2 / cefpython3 example.

Only handles mouse events but could be extended to handle others.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be updated. It should say that keyboard and mouse support is incomplete:

  • Keyboard support may be extended to support:
    • marking text in inputs with the shift key
    • selecting all text with ctrl+a
    • not all special keys may be supported, but can be extended by modifying the getKeyCode() function
  • Mouse support may be extended to support:
    • mouse hover by calling SendMouseMoveEvent()
    • mouse wheel scrolling by calling SendMouseWheelEvent()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add mouse move etc. events and update the comments.


sudo pip2 install PySDL2

Tested configurations:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's put Tested configurations just below "Simple SDL2 / cefpython3 example." text. There are many instructions and notes and list of tested configurations is more important to display first.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You've missed that comment. Let's move "Tested configurations" further up.

@neilmunday
Copy link
Contributor Author

Please see inline comments above.

@cztomczak
Copy link
Owner

cztomczak commented Aug 4, 2017

It will be great to have this example complete and working. Currently there is only screenshot.py very basic example that shows how to use OSR mode. There is the kivy_.py example, but it needs a big refactoring before being moved to the examples/ directory. You're doing great job.

@neilmunday
Copy link
Contributor Author

Cheers. I originally looked at cefpython3 as I wanted to use it as a basis for an application on the Raspberry Pi. If an ARM version of cefpython3 needs testing in the future, let me know :-)

@cztomczak
Copy link
Owner

I guess you've seen Issue #267. It says what changes need to be done to the build scripts to build CEF Python on ARM. Some more modifications may also be required in other tools and in cefpython's source code. There was one PR already, but with issues.

Copy link
Owner

@cztomczak cztomczak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks very good now, found just one minor style issue. I will test it on Windows/Mac and then merge it.


Where possible SDL2 events are mapped to CEF ones. Not all keyboard
modifiers are handled in this example but these could be
add by the reader (if desired).
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add some example of what what doesn't yet work:

marking text in inputs with the shift key
selecting all text with ctrl+a


sudo pip2 install PySDL2

Tested configurations:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You've missed that comment. Let's move "Tested configurations" further up.

be extended by create some simple SDL2 widgets. An example of
widgets made using PySDL2 can be found as part of the Pi
Entertainment System at:
https://github.com/neilmunday/pes/blob/master/lib/pes/ui.py
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for such comments, that is useful.

if key in keyMap:
return keyMap[key]
# Key not mapped, raise exception
print("Keyboard mapping incomplete: unsupported SDL key %d. See https://wiki.libsdl.org/SDLKeycodeLookup for mapping." % key)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrap this line at 79 characters.

@cztomczak
Copy link
Owner

Put your name and email (or website) to the Authors file (the root dir).

@neilmunday
Copy link
Contributor Author

Hopefully all done now :-)

Copy link
Owner

@cztomczak cztomczak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good :)

"""
Simple SDL2 / cefpython3 example.

Only handles mouse events but could be extended to handle others.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is no more valid:

Only handles mouse events but could be extended to handle others.

@neilmunday neilmunday closed this Aug 7, 2017
@neilmunday neilmunday reopened this Aug 7, 2017
@cztomczak
Copy link
Owner

I have tested on Ubuntu 14.04 and it works fine. I will merge it now and test on Windows later, and make some code changes as well. Thanks.

@cztomczak cztomczak merged commit acaf76b into cztomczak:master Jan 8, 2018
@cztomczak
Copy link
Owner

Further changes in commit ddd6264.

@cztomczak
Copy link
Owner

I have tested pysdl2 example on Windows and it works very slow, not usable. See this comment:
#324 (comment)

@neilmunday
Copy link
Contributor Author

Hmmm... I've never tried PySDL2 on Windows. Perhaps adding a call to SDL_Delay at the end of the rendering loop might do the trick?

@cztomczak
Copy link
Owner

@neilmunday Please let's continue discussion in Issue #324. See this comment with new details: #324 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants