AddNewCursors

All the changes added to the original OpenOffice.org source code provided in this page, are :


 * Copyright Eric Bachard January 2010
 * '''Under LGPLv3 license ( and you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation)

Important: If you use this information, don't forget everything you'll find here is under CC by-sa License, and you must mention your sources in what you write ...

Thanks to Ben Bois for the nice cursors  he provided

Additional note : once some known issues will be solved (mostly due to the eraser behavior), a backport should be proposed into OpenOffice.org, to improve the extra presenter features.

Introduction
Below, you'll find a technical description describing how to add new cursors in OOo4Kids. It is question of OpenOffice.org source code (mainly C++ and some objective C on Mac OS X), e.g. the internal source code organisation in OpenOffice.org, like with the graphical part aka vcl (Visual Class Libraries), the Office API (aka offapi) where we'll add new constant for the new cursor "Eraser". The description will concern all operating systems, but when something specific to one of them will be needed, this will be mentionned.

The pre-requisites to read this article still have to be defined, but if the reader is not used with some notions, we invite him to have a look at the OpenOffice.org wiki to complete his knowledge, and read this article in the best conditions.

Idea
The new feature will be based on the current annotation mode in Impress.

Prerequisite : "Mouse pointer visible", and "Mouse pointer as a pen" must be enabled in your presentation. The code around that, has been written by students from Ecole Centrale Nantes (under OpenOffice.org Education Project applications), and has been integrated into OpenOffice.org. So far, only go-oo and OOo4Kids have the feature enabled by default to my knowledge. If this pre-condition is ok, then, the "pen feature" must be visible and available in presentation mode.

e.g. : the new eraser cursor look below :



Common part
In this part, will be described the common changes, for all operating systems, and a short description of the changes in slideshow will be added, to introduce how things work in Impress.

Concerned modules
//- 	/** specifies a mouse pointer which symbolizes an eraser. */	const long ERASER = 94;
 * offapi : Impress is an UNO product, so we need to introduce a new constant in the interface, thus the cursor will exist for Impress in offapi/com/sun/star/awt/SystemPointer.idl


 * vcl : we need to add the new cursor in the interface, and change the cursor count (if wrong, the build will break anyway).
 * 1) ifdef OOo4Kids
 * 2) define POINTER_ERASER             ((PointerStyle)94)
 * 3) define POINTER_COUNT                  95
 * 4) else
 * 5) define POINTER_COUNT                  94


 * slideshow : we need to use the eraser cursor in annotations mode.



Mac OS X only
On Mac OS X, the cursors are managed in vcl, more precisely in vcl/aqua, the implemented part of vcl.


 * vcl/aqua :
 * add the cursor as .png in vcl/aqua/source/res/cursors
 * modify the list + the hotspot value to make it match with the new cursor in vcl/aqua/source/app/saldata.cxx


 * vcl/aqua/source/app/saldata.cxx
 * add the eraser96 cursor in the array containing all existing cursors used on Mac OS X.

const aCursorTab[ POINTER_COUNT ] = {

....

{ "pntbrsh", { 9, 16 } }, //POINTER_PAINTBRUSH 93 { "eraser96", { 19, 37 } } //POINTER_ERASER 94 };

Note: the first part is a hack to add the big arrow cursor on Mac OS X. Please, notice the hotspot coordinates, who must be adapted to the cursor. const aCursorTab[ POINTER_COUNT ] = {                                                                                                                { "arrow", { 16, 12 } }, //POINTER_ARROW  0 { NULL, { 0, 0 } }, //POINTER_ARROW
 * 1) ifdef OOo4Kids
 * 1) else
 * 1) endif

The second important part of the hack is to undefine the arrow cursor in vcl/aqua/source/window/salframe.cxx, thus the big arrow will replace it (when NULL, the system arrow pointer is the fallback, but we provide our own arrow pointer, who is basicaly a big arrow pointer instead) NSCursor* AquaSalFrame::getCurrentCursor const {                                                                                                                    NSCursor* pCursor = nil; switch( mePointerStyle ) {                                                                                                                case POINTER_TEXT:      pCursor = [NSCursor IBeamCursor];           break; case POINTER_CROSS:    pCursor = [NSCursor crosshairCursor];       break; case POINTER_HAND: case POINTER_MOVE:     pCursor = [NSCursor openHandCursor];        break; case POINTER_NSIZE:    pCursor = [NSCursor resizeUpCursor];        break; case POINTER_SSIZE:    pCursor = [NSCursor resizeDownCursor];      break; case POINTER_ESIZE:    pCursor = [NSCursor resizeRightCursor];      break; case POINTER_WSIZE:    pCursor = [NSCursor resizeLeftCursor];     break; case POINTER_ARROW:    pCursor = [NSCursor arrowCursor];           break;
 * 1) ifndef OOo4Kids
 * 1) endif

'''That's all for Mac OS X !! And the eraser cursor will be used if requested by any application (e.g. slideshow).'''

Windows only
The Windows stuff is in vcl/win


 * vcl/win/source/src (ressources) :

The cursor is a bitmap with .cur extension, for instance eraser96.cur, and containing several images. On Windows XP (means in OpenOffice.org too), the cursor must be a 32x32 image, and one of the contained image must be 2 colors only. FIXME : why ?

Extremely important  : the hotspot must be correctly adjusted. Tested : in some cases, where the hotspot is not correct, the cursor may even not appear !!

Same directory, in the resource file, add a new constant, matching with the cursor name (ARROW96.CUR) Index: vcl/win/source/src/salsrc.rc

=
====================================================== --- vcl/win/source/src/salsrc.rc	(revision 453) +++ vcl/win/source/src/salsrc.rc	(working copy) @@ -118,6 +118,7 @@ SAL_RESID_POINTER_TAB_SELECT_W         CURSOR          TBLSELW.CUR SAL_RESID_POINTER_TAB_SELECT_SW        CURSOR          TBLSELSW.CUR SAL_RESID_POINTER_PAINTBRUSH           CURSOR          PNTBRSH.CUR +SAL_RESID_POINTER_ERASER           	CURSOR          ERASER96.CUR SAL_RESID_BITMAP_50                            BITMAP          50.BMP

Of course, add the new cursor in the makefile, to be builtin, and contained in the libvclmi.dll tblselsw.cur                    \ pntbrsh.cur                 \ eraser96.cur			\ 50.bmp                         \ sd.ico

Plus add the constant in the array ( in vcl/win/source/window/salframe.cxx )

// --> FME 2004-08-16 #i20119# Paintbrush tool { 0, 0, SAL_RESID_POINTER_PAINTBRUSH },         // POINTER_PAINTBRUSH 93 // <--

{ 0, 0, SAL_RESID_POINTER_ERASER }         // POINTER_ERASER 94

Define the constant value : Index: vcl/win/inc/salids.hrc --- vcl/win/inc/salids.hrc	(revision 453) +++ vcl/win/inc/salids.hrc	(working copy) @@ -115,6 +115,7 @@ +#define SAL_RESID_POINTER_ERASER					10079 '''That's all for Windows !! And the cursor if selected somewhere in OpenOffice.org will be provided at low level by the libvclmi.dll'''
 * 1) define SAL_RESID_POINTER_TAB_SELECT_W                         10076
 * 2) define SAL_RESID_POINTER_TAB_SELECT_SW                        10077
 * 3) define SAL_RESID_POINTER_PAINTBRUSH                           10078
 * 1) define SAL_RESID_BITMAP_50                                            11000

without gtk
On Linux, the cursors, must be provided as sources files, compiled and loaded at runtime in vcl/win/source/app/saldisplay.cxx, as described below.

// Pointer // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=                                      XCreateBitmapFromData( pDisp_, \                                                                                                         DefaultRootWindow( pDisp_ ), \                                                                                    name##_bits, \                                                                                                    name##_width, \                                                                                                   name##_height ) aCursBitmap = MAKE_BITMAP( name##curs ); \ aMaskBitmap = MAKE_BITMAP( name##mask ); \ nXHot = name##curs_x_hot; \ nYHot = name##curs_y_hot
 * 1) define MAKE_BITMAP( name ) \
 * 1) define MAKE_CURSOR( name ) \

And later, use it :

XLIB_Cursor SalDisplay::GetPointer( int ePointerStyle ) {   if( ePointerStyle >= POINTER_COUNT ) return 0;

XLIB_Cursor &aCur = aPointerCache_[ePointerStyle];

if( aCur != None ) return aCur;

Pixmap         aCursBitmap = None, aMaskBitmap = None; unsigned int   nXHot = 0, nYHot = 0;

switch( ePointerStyle ) { // OOo4Kids : hack the big arrow ? case POINTER_NULL: ....

case POINTER_ERASER: MAKE_CURSOR( eraser96_ );

To create a new cursor on Linux, the most simple way is to start (e.g) from an .svg version of the cursor, and to convert it into .xbm file including the .mask associated file, and using the name the cursor will have at the end, using The Gimp. You'll have to adjust the hotspot too, and to fix a bit the build, but once adjusted, you'll be able to do what you want.

For further information, the source files, for the eraser96, are ( the .xbm.h and the .xbm.mask) in vcl/unx/source/inc


 * vcl/unx/source/inc/eraser96_mask.h
 * vcl/unx/source/inc/eraser96_curs.h

Declare the new cursor in vcl/unx/source/inc/salcursors.h :

Index: vcl/unx/source/inc/salcursors.h

=
====================================================== --- vcl/unx/source/inc/salcursors.h	(révision 523) +++ vcl/unx/source/inc/salcursors.h	(copie de travail) @@ -163,3 +163,6 @@ +#include "eraser96_curs.h" +#include "eraser96_mask.h" +
 * 1) include "tblselsw_mask.h"
 * 2) include "paintbrush_curs.h"
 * 3) include "paintbrush_mask.h"

using gtk
The cursors are either gtk cursors (nice cursors), or the vcl cursors, but this needs to be mentionned. Below, we simply add our eraser, to see it in annotations mode (Impress). Index: vcl/unx/gtk/app/gtkdata.cxx

=
====================================================== --- vcl/unx/gtk/app/gtkdata.cxx (revision 634) +++ vcl/unx/gtk/app/gtkdata.cxx (working copy) @@ -443,7 +443,10 @@            // --> FME 2004-08-16 #i20119# Paintbrush tool MAKE_CURSOR( POINTER_PAINTBRUSH, paintbrush_ ); // <-- - +#ifdef OOo4Kids +          // ericb : was missing when gtk is enabled +           MAKE_CURSOR( POINTER_ERASER, eraser96_ ); +#endif default: fprintf( stderr, "pointer %d not implemented", ePointerStyle ); break;

Unit test: verified working on Linux PowerPC.

other cases
TO BE CONTINUED : add an example of the use of POINTER_ERASER in Impress, in the next step for the new canvas in progress.

Known issues : mostly Windows where the cursor's size is naturaly limited to 32 x 32, at least with Windows XP (minimal required version)