Native Cursors in AIR 2.6

One of the coolest new desktop features in AIR 2.6 is the ability to use native cursors. By "native cursor," I mean custom cursors at the OS level as opposed to the runtime level. In other words, rather than hiding the mouse cursor and rendering a sprite in its place (the old way to do custom cursors which doesn’t always perform well), in AIR 2.6, you can hand one or more bitmaps to the operating system along with a frame rate and a hot spot, and the cursor will be rendered (and optionally animated) in hardware.

Here’s an example:


Here’s everything you need to know about custom cursors in AIR 2.6:

  • The data property of MouseCursorData takes a vector of BitmapData objects so you can create an animation. Use the frameRate property to control the animation’s frame rate.
  • You can control which part of the cursor is the "hot spot" (the portion that registers clicks) using the hotSpot property of MouseCursorData.
  • When the cursor leaves the application’s native window, your custom cursor will revert to the default OS cursor.
  • The maximum cursor size is 32×32.

Full docs are available here.

And here’s the code. (I used the Smurf sprite sheet from here, though I put them all on a single row and scaled them down to 32×32 to simplify the code.)

package
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.ui.Mouse;
    import flash.ui.MouseCursorData;

    [SWF(backgroundColor="0x000000")]
    public class NativeCursorExample extends Sprite
    {
        [Embed(source="smurf.png")] private var SmurfClass:Class;

        private static const SMURF_WIDTH:uint  = 32;
        private static const SMURF_HEIGHT:uint = 32;

        private var SMURF_CURSOR_NAME:String = "smurf";

        public function NativeCursorExample()
        {
            var bitmaps:Vector.<BitmapData> = new Vector.<BitmapData>;

            var spriteSheet:Bitmap = new SmurfClass();

            var r:Rectangle;
            var bmd:BitmapData;
            var p:Point = new Point(0, 0);

            for (var i:uint = 0; i < 16; ++i)
            {
                r = new Rectangle((SMURF_WIDTH * i) , 0, SMURF_WIDTH, SMURF_HEIGHT); 
                bmd = new BitmapData(r.width, r.height, true, 0x000000);
                bmd.copyPixels(spriteSheet.bitmapData, r, p);
                bitmaps.push(bmd);
            }
            var mcd:MouseCursorData = new MouseCursorData();
            mcd.data = bitmaps;
            mcd.hotSpot = new Point(22, 15); // The smurf's nose
            mcd.frameRate = 24;
            Mouse.registerCursor(SMURF_CURSOR_NAME, mcd);
            Mouse.cursor = SMURF_CURSOR_NAME;
        }
    }
}