Writing a Mac OS X Screensaver

A screensaver can be seen as a zero-player game used mostly for entertainment or amusement when the computer is idle.

A Mac OS X screensaver is a system plugin. It is loaded dynamically by the Operating System after a given time has elapsed, or embedded into a configuration window within the Settings App.

What is a system plugin? It means we basically write a module that ascribes to a given interface and receives callbacks from the OS to perform an operation. In this case, draw a view.

A custom screensaver that uses OpenGL to render a colorful triangle.

A custom screensaver that uses OpenGL to render a colorful triangle.

Writing a Mac OS X screensaver is surprisingly easy. A special class from the ScreenSaver framework, called ScreenSaverView, provides the callbacks we need to override in order to render our scene. All work related to packing the executable code into a system component is handled by Xcode automatically.

We can render our view using either CoreGraphics or OpenGL. In this sample, I’m going to use OpenGL to draw the scene.

Initialization and Lifecycle Management

We start off by creating a View that extends ScreenSaverView:

#import <ScreenSaver/ScreenSaver.h>

@interface ScreensaverTestView : ScreenSaverView

@property (nonatomic, retain) NSOpenGLView* glView;

- (NSOpenGLView *)createGLView;

@end

Let’s move on to the implementation.

In the init method, we create our OpenGL Context (associated to its own view). We’ll also get the cleanup code out of the way.

- (id)initWithFrame:(NSRect)frame isPreview:(BOOL)isPreview
{
    self = [super initWithFrame:frame isPreview:isPreview];
    if (self)
    {
        self.glView = [self createGLView];
        [self addSubview:self.glView];
        [self setAnimationTimeInterval:1/30.0];
    }
    return self;
}

- (NSOpenGLView *)createGLView
{
	NSOpenGLPixelFormatAttribute attribs[] = {
		NSOpenGLPFAAccelerated,
		0
	};
	
	NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
	NSOpenGLView* glview = [[NSOpenGLView alloc] initWithFrame:NSZeroRect pixelFormat:format];
	
	NSAssert(glview, @"Unable to create OpenGL view!");
	
	[format release];
	
	return [glview autorelease];
}

- (void)dealloc
{
	[self.glView removeFromSuperview];
	self.glView = nil;
	[super dealloc];
}

The above code is self-explanatory.

Notice how we tell the video driver what kind of OpenGL configuration it should allocate for us; In this case, we only request hardware acceleration. We won’t allocate a depth buffer because there is no need for it (yet).

Rendering Callbacks

Now, let’s move on to implementing the rendering callbacks for our screensaver. Most of the methods here will just forward the events to the super class, but we’ll customize the animateOneFrame method in order to do our rendering.

- (void)startAnimation
{
    [super startAnimation];
}

- (void)stopAnimation
{
    [super stopAnimation];
}

- (void)drawRect:(NSRect)rect
{
    [super drawRect:rect];
}

- (void)animateOneFrame
{
	[self.glView.openGLContext makeCurrentContext];
	glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT);
	
	static float vertices[] = {
		1.0f, -1.0f, 0.0f,
		0.0f, 1.0f, 0.0f,
		-1.0f, -1.0f, 0.0f
		
	};
	
	static float colors[] = {
		1.0f, 0.0f, 0.0f,
		1.0f, 0.0f, 1.0f,
		0.0f, 0.0f, 1.0f
	};
		
	glVertexPointer(3, GL_FLOAT, 0, vertices);
	glEnableClientState(GL_VERTEX_ARRAY);
	glColorPointer(3, GL_FLOAT, 0, colors);
	glEnableClientState(GL_COLOR_ARRAY);

	glDrawArrays(GL_TRIANGLES, 0, 3);

	glDisableClientState(GL_COLOR_ARRAY);
	glDisableClientState(GL_VERTEX_ARRAY);
	
	glFlush();
	[self setNeedsDisplay:YES];
    return;
}

- (void)setFrameSize:(NSSize)newSize
{
	[super setFrameSize:newSize];
	[self.glView setFrameSize:newSize];
}

We place our rendering logic in the animateOneFrame method. Here, we define our geometry in terms of vertices and colors and submit it as vertex arrays to OpenGL.

Implementing the setFrameSize: method is very important. This method is called when our screensaver starts and we must use it to adjust our views’ dimensions so we can render on the whole screen.

Actionsheet Methods

Mac OS X screensavers may have an associated actionsheet. The actionsheet can be used to let the user customize the experience or configure necessary attributes.

- (BOOL)hasConfigureSheet
{
    return NO;
}

- (NSWindow*)configureSheet
{
    return nil;
}

Testing our Screensaver

Unfortunately, we can’t run our screensaver right off Xcode. Because it’s a system plugin, we need to move its bundle to a specific system folder so Mac OS X can register it. In order to install the screensaver just for ourselves, we place the bundle in the $HOME/Library/Screen\ Savers directory.

Once copied, we need to open the Settings App (if it was open, we need to close it first). Our screensaver will be available in the “Desktop & Screen Saver” group, under the “Other” category.

Conclusion

Screensaver writing for Mac OS X is surprisingly easy! With the full power of desktop OpenGL and C++ at our disposal, we can create compelling experiences that delight users and bystanders.

As usual, there are some caveats when developing OS X screensavers. You can read about them here.

Happy coding!

More on Objective-C Blocks

In 2011 I first blogged about Objective-C blocks, a game changing language construct that allows defining callable functions on-the-fly. In this post, we delve into some advanced properties of blocks in the Objective-C language.

1. Blocks capture their enclosing scope

Consider the following code snippet:

#import <Foundation/Foundation.h>

int main(int argc, char* argv[])
{
	@autoreleasepool
	{

		int capture_me = 10;

		int (^squared)(void) = ^(void){
			return capture_me * capture_me;
		};


		printf("%d\n", squared());

	}
	return 0;
}

In the above example, we create a block that captures local variable “capture_me” and store it into a variable called “squared”. When we invoke the “squared” block, it will access the captured variable’s value, square it and return it to the caller.

This is a great feature that allows referencing local variables from deep within a complex operation’s stack. As Miguel de Icaza points out, however, we need to be careful with this feature to avoid producing hard to maintain code.

As you may have guessed, the code above correctly prints value “100”.

2. Blocks can modify captured variables

Now, consider this snippet. We will change our block not to return the squared variable, but rather to capture a reference to the local variable and store the squared value, overriding the original.

#import <Foundation/Foundation.h>

int main(int argc, char* argv[])
{
	@autoreleasepool
	{

		__block int modify_me = 10;

		void (^squared)(void) = ^(void){
			modify_me *= modify_me;
		};


		squared();
		printf("%d\n", modify_me);

	}
	return 0;
}

The __block keyword signals that variable “modify_me” is captured as a reference by the Block, allowing it to be modified from within its body.

Just like before, this code still prints “100”. If we were to call the “squared” block a second time, we would square the variable again, yielding “10.000”.

3. Blocks are Objective-C Objects allocated on the stack

Unlike any other object instance in Objective-C, blocks are objects that are allocated on the stack. This means blocks need to be treated as a special case when we want to store them for later usage.

As a general rule of thumb: you should never retain a block. If it is to survive the stack frame where it was defined, you must copy it, so the runtime can place it on the heap.

If you forget and accidentally retain a block on the stack it might lead to runtime errors. The Xcode analyzer, thankfully, detects this problem.

Conclusion

If there were a feature I could have added to the Java programming language (when developing Android apps), it would without be, without a doubt, support for blocks or, in general, lambda expressions.

Objective-C blocks are a powerful feature that must be handled with care. When used correctly, they have the power to let us improve our code to make it more streamlined. When used incorrectly, they can lead to unreadable code and/or hard-to-debug memory-management bugs.

If you are interested in learning more about blocks in the Objective-C programming language, this article is a great resource and here’s the official Apple documentation.

Happy coding!

On Java, C#, Objective-C and C++

Objective-C, image taken from bigspaceship.com.

Objective-C, image taken from bigspaceship.com.

I’ve been meaning to write about this for a while. It’s something that comes up rather frequently at work, so I though I’d write it down to organize what’s on my mind.

Contrary to what many may think, the Java and C# languages are not based on C++ as much as on Objective-C. Indeed, Objective-C was a big influence in the design of the Java programming language. And since C# 1.0 was basically Microsoft’s Java, we shall consider it another derived language too.

So, why do people think of Java as a C++-derived language? Java was built on C++’s syntax, this is why Java code “looks like” C++ code. Java’s semantics, however, are heavily based on Objective-C’s.

Some Java and C# features borrowed directly from Objective-C include:

  • Dynamic binding.
  • Dynamic loading.
  • Single inheritance.
  • Interfaces (called “protocols” in Objective-C).
  • Large runtime.
  • “Class” objects.
  • Reflection.
  • Objects cannot be allocated in the stack.
  • Garbage Collection (deprecated in Objective-C).
  • All methods virtual by default (Java).
  • Properties (C#).
  • int, float, double, etc. wrapper classes.

Patrick Naughton, one of the original designers of the Java programming language, confirms this story in this discussion on usenet:

Usually, this kind of urban legend stuff turns out to be completely inaccurate, but in this case, they are right on. When I left Sun to go to NeXT, I thought Objective-C was the coolest thing since sliced bread, and I hated C++. So, naturally when I stayed to start the (eventually) Java project, Obj-C had a big influence. James Gosling, being much older than I was, he had lots of experience with SmallTalk and Simula68, which we also borrowed from liberally.

The other influence, was that we had lots of friends working at NeXT at the time, whose faith in the black cube was flagging. Bruce Martin was working on the NeXTStep 486 port, Peter King, Mike Demoney, and John Seamons were working on the mysterious (and never shipped) NRW (NeXT RISC Workstation, 88110???). They all joined us in late ’92 – early ’93 after we had written the first version of Oak. I’m pretty sure that Java’s ‘interface’ is a direct rip-off of Obj-C’s ‘protocol’ which was largely designed by these ex-NeXT’ers… Many of those strange primitive wrapper classes, like Integer and Number came from Lee Boynton, one of the early NeXT Obj-C class library guys who hated ‘int’ and ‘float’ types.

So, next time you look at Objective-C thinking how weird its syntax looks, remember this story and consider how much it influenced the programming language landscape.

Dynamic Method Injection (in Objective-C)

When asked what I like the most from the Objective-C programming language, I often refer to its dynamic underpinnings.

Although Objective-C is a superset of C, the way its designers decided to implement the Object model was dynamic. This provides a strong contrast with C++, which, although a superset of C as well, is a static-typed language.

In this post I will show how you can use the Objective-C runtime to dynamically add a method to an (Objective-C) class at runtime.

Let’s start by creating a Dummy class that has no methods whatsoever. I will put everything in the same file for the sake of simplicity, but in real-life code, you’d want to have separate files for the interface and the implementation.

#import <Foundation/Foundation.h>

@interface Dummy : NSObject
@end

@implementation Dummy
@end

Now, let’s implement a method to be dynamically added to Dummy. Interestingly enough, methods to add need to be implemented as C functions.

Here’s our implementation:

void newMethod(id self, SEL _cmd)
{
  printf("Hello from a dynamically added method! (self=%p)\n", self);
}

Now, let’s go to the main function and see how we can inject “newMethod” into the Dummy class. We will need to import the Objective-C runtime.

#import <objc/runtime.h>

int main(int argc, char* argv[])
{
  NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
  
  // Add method to Dummy class (args explained below)
  class_addMethod([Dummy class], @selector(printHello), (IMP)newMethod, "v@:");
  
  Dummy* instance = [[Dummy alloc] init];
  [instance printHello];
  [instance release];
  
  [pool release];
  return 0;
}

When running this program, an output similar to this will be produced:

Hello from a dynamically added method! (self=0x10ad143a0)

So, let’s see how the method was added.

The heavylifting here is done by the class_addMethod function. This function, coming from the Objective-C runtime, allows you to register a new method in a class.

This feat requires a pointer to the function that implements the method (“newMethod”), but lets you assign any name you want to it (I chose “printHello”). Notice that’s the message I send to the Dummy instance.

The strangest parameter is perhaps the last “v@:”. This is actually a code for the argument types received by the “newMethod” function. All valid type codes can be found in the Apple reference, but to make things easier, “v@:” means that the function returns void (v) and receives an Object and a selector.

Objective-C Blocks

Lately, I have been playing with Objective-C blocks.

These are easy to use constructs that enable defining functions “on the fly” when programming in Objective-C and are very similar to Python’s lambdas.

The syntax might look a little weird at first, but it is not that different from working with function pointers in C.

Here’s a simple example of a function f that receives a block b as a parameter and calls it. The only restriction imposed on b by f is that it must be a block that takes an int argument and returns an int.

#include <stdio.h>

// f is a function that receives a block:
void f(int (^b)(int))
{
	b(0); //call the block
}

int main(int argc, char* argv[])
{
	// Define and pass a block to f():
	f(^(int p){ printf("%d\n", p); return 0; });

	return 0;
}

The output of this program is just the int supplied by f to the block b.

Let’s try a more interesting example. Here, as inspired by this post, we use blocks to define a general-purpose for_each function that receives a list of objects and a block and then applies the block on each element of the list.

In order to define a general-purpose for_each function, we take advantage of Objective-C’s dynamic typing and name our types id.

void for_each(NSArray* array, void (^b)(id))
{
	for (id obj in array)
	{
		b(obj);
	}
}

Now, let’s develop a short program to test the for_each. This program creates a list of strings and uses the for_each function to output all of its contents.

int main(int argc, char* argv[])
{
	// Default autorelease pool:
	NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
	
	// Create an array. The contents could be anything,
	// as long as the block can handle them:
	NSArray* array = 
	[NSArray arrayWithObjects:@"a", @"b", @"c", @"d", @"e", nil];

	// Print every string instance:
	for_each(array, 
		^(id str){ printf("%s\n", [str UTF8String]); });

	[pool release];
	
	return 0;
}

Suppose now that we wanted to print out strings in uppercase. No problem, we can keep all the same structure, we just need to change the block:

	for_each(array, 
		^(id str){ 
			printf("%s\n", [[str uppercaseString] UTF8String]); 
		});

So, what happens if we place an object of a type different from a NSString instance in the array? Well, the for_each is very general and doesn’t know anything about the array’s elements or the block’s internals. Thus, if there is a problem, it will be triggered inside the block code.

Imagine we attempt to send uppercaseString to an object that does not recognize that message. If this happens, an error will be triggered at runtime and abort() will be called, canceling our program.

As we move into dynamic coding, the code becomes more flexible, but we must be more careful not to trigger runtime errors in our programs. It’s important that we develop our blocks to be consistent with our data structures.

Brief Introduction to Objective-C

Objective-C is a superset of the C programming language that adds object-oriented constructs. Unlike C++, which was influenced by Simula, Objective-C was influenced by Smalltalk, something we can definitely see in its braces syntax.

Just like C, Objective-C keeps the tradition of separating the source code in two files: a header that defines an interface (.h) and a source file that provides the implementation of said interfaces (.m).

Contrary to popular belief, you do not need a computer running Mac OS X to develop Objective-C programs. The GNUstep project is an open source implementation of the OpenStep reference that provides a basic runtime environment and an implementation of part of the library, including Strings, Arrays and Dictionaries. GNUstep is available for Linux, other UNIX-based OSs and even Windows.

Here’s a short example that defines a 2D point structure with two operations: initialize from a given pair of (x,y) coordinates and printing to stdout.

#import <Foundation/Foundation.h>

@interface Point2D : NSObject
{
	float x;
	float y;
}

- (id) initWithX:(float)xval andY:(float)yval;
- (void) print;

@end

Now, we implement this interface in its own file:


#import "point2d.h"
#include <stdio.h>

@implementation Point2D

- (id) initWithX:(float)xval andY:(float)yval;
{
	self = [super init];
	if (self)
	{
		x = xval;
		y = yval;
	}
	return self;
}

- (void) print
{
	printf("(%.2f, %.2f)\n", x, y);
}

@end

Finally, let me show you how to instantiate and send messages to a Point2D object.

#import "point2d.h"
int main()
{
	NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

	Point2D* p = [[Point2D alloc] initWithX:1.0f andY:2.0f];

	[p print];
	[p release];

	[pool release];
	return 0;
}

Although the Autorelease pool was not really necessary, it is a good practice to have one in place.

If you are trying this example on a Mac, then it’s relatively simple to get it to compile and run. Using GNUstep it gets a little harder however. Here’s a simple Makefile for building this application:

CC=gcc -x objective-c

CFLAGS=-I$(GNUSTEP_HOME)/Local/Library/Headers/ -Wall
LDFLAGS=-L$(GNUSTEP_HOME)/Local/Library/Libraries/ -lgnustep-base

all:
	$(CC) $(CFLAGS) $(LDFLAGS) main.m