Cocoa backend for Pyglet

51 views
Skip to first unread message

Tristam MacDonald

unread,
Sep 11, 2009, 1:08:53 PM9/11/09
to pyglet...@googlegroups.com
As some of you know, the release of Snow Leopard signals the end of Carbon development on the Mac, and pyglet's reliance on Carbon prevents us from running pyglet on a stock Snow Leopard install.

The solution to this is to write a new platform backend in Cocoa, but unfortunately this is going to be a fair amount of work. I have had this in private development for a while, and in terms of a functioning alpha, past the 50% mark. However, development is fairly slow, so if there are any others here with the requisite knowledge, skills and time, I would like to open it up for collaboration...

Here is a brief overview of the current status:
  • windowing: basic window and fullscreen working
  • events: cocoa event loop hijacked successfully, but not yet piped into pyglet events
  • fonts: not implemented - using buggy freetype fonts via the installed freetype library for X11
  • codecs: quicktime codec disabled - needs to be adapted to newer QuickTime API
Challenges:
  • PyObjC: the Python <--> Objective-C language bridge is confusing, badly documented, and has missing functionality in places
  • Cocoa: the framework is designed to manage its own run loop, thus we have to subvert a lot of functionality (and guess at how it is implemented). Luckily the SDL project (and myself) pioneered a this a few years back.
So, if you have really deep knowledge of Cocoa (and plentiful free time, of course) I could use your help right away - let me know, and we can figure out collaboration.

If you don't know Cocoa that well, but do know your way around the debugger, stay tuned, because this is going to require a horrendous amount of testing before we approach a release...

Tristam MacDonald

unread,
Sep 12, 2009, 11:01:41 AM9/12/09
to pyglet...@googlegroups.com
First off, a brief status update: I now have a functioning (albeit basic) Cocoa font renderer, and pyglet-cocoa can now execute the hello_world.py, although event handling is still entirely missing.

Now, a question for the design/architecture committee (I guess that would be Alex). How is pyglet's multiple window support intended to interact with fullscreen support? i.e. should it be legal for an application to have multiple windows, of which some are fullscreen and some are not (particularly in multiple monitor/GPU setups)?

The reason I ask is that there are some very thorny issues related to event handling in this situation. As long as all windows are *not* fullscreen, we can retrieve each window's event queue separately - but as soon as one window becomes fullscreen, we have to retrieve events application-wide, and manually handle hit detection and event dispatch for the window system.

Steve Johnson

unread,
Sep 12, 2009, 3:17:47 PM9/12/09
to pyglet-users
I'm no authority and don't have any Cocoa knowledge, but I do have two
things to say:

1. Thank you so much for doing this!
2. Do the least amount of work possible to get it working. For now, it
sounds like that means disallowing mixed fullscreen/non windows.

Keep at it, and send a build my way if you need testing done. I'm
using Leopard on a Core 2 Duo MBP.

On Sep 12, 11:01 am, Tristam MacDonald <swiftco...@gmail.com> wrote:
> On Fri, Sep 11, 2009 at 1:08 PM, Tristam MacDonald <swiftco...@gmail.com>wrote:
>
>
>
> > As some of you know, the release of Snow Leopard signals the end of Carbon
> > development on the Mac, and pyglet's reliance on Carbon prevents us from
> > running pyglet on a stock Snow Leopard install.
> > The solution to this is to write a new platform backend in Cocoa, but
> > unfortunately this is going to be a fair amount of work. I have had this in
> > private development for a while, and in terms of a functioning alpha, past
> > the 50% mark. However, development is fairly slow, so if there are any
> > others here with the requisite knowledge, skills and time, I would like to
> > open it up for collaboration...
>
> > Here is a brief overview of the current status:
>
> >    - windowing: basic window and fullscreen working
> >    - events: cocoa event loop hijacked successfully, but not yet piped
> >    into pyglet events
> >    - fonts: not implemented - using buggy freetype fonts via the installed
> >    freetype library for X11
> >    - codecs: quicktime codec disabled - needs to be adapted to newer
> >    QuickTime API
>
> > Challenges:
>
> >    - PyObjC: the Python <--> Objective-C language bridge is confusing,
> >    badly documented, and has missing functionality in places
> >    - Cocoa: the framework is designed to manage its own run loop, thus we

Greg Ewing

unread,
Sep 12, 2009, 9:08:58 PM9/12/09
to pyglet...@googlegroups.com
Tristam MacDonald wrote:

> * Cocoa: the framework is designed to manage its own run loop, thus


> we have to subvert a lot of functionality (and guess at how it is
> implemented).

I've had to grapple with this to some extent while
implementing PyGUI, so if you have any problems with
the event system, I might be able to help.

--
Greg

Greg Ewing

unread,
Sep 13, 2009, 1:45:52 AM9/13/09
to pyglet...@googlegroups.com
Tristam MacDonald wrote:
> As long as all windows are *not*
> fullscreen, we can retrieve each window's event queue separately - but
> as soon as one window becomes fullscreen, we have to retrieve events
> application-wide, and manually handle hit detection and event dispatch
> for the window system.

How are you doing fullscreen windows? I've implemented
fullscreen windows in PyGUI that behave the same way as
other windows with respect to event distribution.

The technique I use is:

* Create a window with no title bar that fills the
screen.

* Override canBecomeKeyWindow_ and canBecomeMainWindow_
to allow it to receive events despite not having a
title bar.

* Override windowDidBecomeMain_ and windowDidResignMain_
to hide and show the menu bar when the window gains
and loses the focus.

--
Greg

Tristam MacDonald

unread,
Sep 13, 2009, 7:48:42 AM9/13/09
to pyglet...@googlegroups.com
That gives you a regular window, which fills the screen. In the Windows world, I believe that is what a fullscreen context is, but unfortunately, things aren't that simple for Mac.In particular, you take a significant performance hit on most hardware, because the graphics card is still in windowed mode.

Instead, we have to capture the display (with CGDisplayCapture/CGDisplayRelease), and then set the context to fullscreen (with [NSOpenGLContext setFullScreen]).

However, you have given me an idea - maybe I will create a dummy window under the capture shield to process events.

Nathan

unread,
Sep 17, 2009, 5:33:14 PM9/17/09
to pyglet...@googlegroups.com

I don't know Cocoa (maybe someday I'll have time to learn), and I have
very little time, but I might be able to pitch in some testing time
when you get close. My department is running Snow leopard on 13"/15"
MBPros and SL Server on an Xserve already.

~ Nathan

Tristam MacDonald

unread,
Sep 24, 2009, 12:22:06 PM9/24/09
to pyglet...@googlegroups.com
Here is an alpha release of the pyglet-cocoa backend, for testing purposes.

I have included the entire pyglet distribution, so you should be able to unpack the zip file into your project directory, which will override the version of pyglet you have previously installed.

The included version of hello_world.py demonstrates basic functionality, but a wider range of tests is needed.

What does work:
* windowed and fullscreen mode
* beautiful Cocoa-based font rendering
* mouse and keyboard events

What may work:
* multiple windows
* fullscreen on a secondary monitor

What doesn't work:
* text input
* various window events

What I need from you:
* confirmation that this runs out of the box on Snow Leopard, Leopard, and/or Tiger with PyObjC installed
* a list of functionality which is missing

Note that Cocoa will spam the console with a lot of error and warning messages - most of these are related to memory management, and can be safely ignored for the moment.
pyglet-cocoa.zip

Nicolas Rougier

unread,
Sep 24, 2009, 12:42:09 PM9/24/09
to pyglet...@googlegroups.com

Hello Tristam,

Thank you so much for your efforts on this port.

I did a quick try but got the following result on Leopard 10.5.8 with Python 2.6

Traceback (most recent call last):
  File "hello_world.py", line 43, in <module>
    from pyglet.window.event import WindowEventLogger
  File "/Volumes/Data/Users/rougier/Downloads/pyglet/pyglet/window/__init__.py", line 1669, in <module>
    from pyglet.window.cocoa import CocoaPlatform, CocoaWindow
  File "/Volumes/Data/Users/rougier/Downloads/pyglet/pyglet/window/cocoa/__init__.py", line 64, in <module>
    from Cocoa import *
ImportError: No module named Cocoa

I ran the hello_world.py example without any installation. I tried to find where to get the Cocoa python package but did not find any hints. Did I miss something obvious ?


Nicolas



<pyglet-cocoa.zip>

Nicolas Rougier

unread,
Sep 24, 2009, 12:49:02 PM9/24/09
to pyglet...@googlegroups.com

Ok, sorry for the last post, I forgot to install pyobj... You can call me stupid.

Here is the output:

pyglet view init
pyglet view init
on_resize(width=1440, height=900)
on_show()
on_expose()
on_resize(width=1440, height=900)
on_show()
Traceback (most recent call last):
  File "hello_world.py", line 61, in <module>
    pyglet.app.run()
  File "/Volumes/Data/Users/rougier/Downloads/pyglet/pyglet/app/__init__.py", line 264, in run
    EventLoop().run()
  File "/Volumes/Data/Users/rougier/Downloads/pyglet/pyglet/app/cocoa.py", line 73, in run
    event = NSApp.nextEventMatchingMask_untilDate_inMode_dequeue_(NSAnyEventMask, NSDate.distantPast(), NSDefaultRunLoopMode, True)
ValueError: depythonifying 'unsigned int', got 'int' of wrong magnitude


On screen, it seems to open a fullscreen black window then exit with the above message.


Nicolas



On 24 Sep, 2009, at 18:22 , Tristam MacDonald wrote:

<pyglet-cocoa.zip>

Nicolas Rougier

unread,
Sep 24, 2009, 1:12:41 PM9/24/09
to pyglet-users


It happenned that the use of -1 for NSAnyEventMask makes pyglet crash
in my case.
I found an old thread discussing this point, but I thought it would
have been fixed by now
(thread http://osdir.com/ml/python.pyobjc.devel/2003-10/msg00130.html).

Putting "NSAnyEventMask = 0xFFFFFFFFL" just before the call (line 73
in cocoa.py) makes things work beautifully.


Nicolas
Reply all
Reply to author
Forward
0 new messages