8

I want to hide the cursor from a statusbar app and i've done some research. It seems as though the solution to this problem was found a while ago:

Globally hide mouse cursor in Cocoa/Carbon? or http://lists.apple.com/archives/carbon-dev/2006/Jan/msg00555.html

But the code that is referred to will not compile. Do any of you guys know either how to make the code compile (by importing some old API or something) or another way of achieving this (some kind of hack)?

(I know it is generally a bad idea to hide the cursor from a background app, but i making an app where this functionality is pretty essential)

Edit:

Here's the old hack, that doesn't work anymore.

long sysVers = GetSystemVersion();

// This trick doesn't work on 10.1 
if (sysVers >= 0x1020)
{
    void CGSSetConnectionProperty(int, int, int, int);
    int CGSCreateCString(char *);
    int CGSCreateBoolean(BOOL);
    int _CGSDefaultConnection();
    void CGSReleaseObj(int);
    int propertyString, boolVal;

    // Hack to make background cursor setting work
    propertyString = CGSCreateCString("SetsCursorInBackground");
    boolVal = CGSCreateBoolean(TRUE);
    CGSSetConnectionProperty(_CGSDefaultConnection(), _CGSDefaultConnection(), propertyString, boolVal);
    CGSReleaseObj(propertyString);
    CGSReleaseObj(boolVal);
}

It gives me 4 errors:

"_CGSCreateBoolean", referenced from: -[MyClass myMethod] in MyClass.o

"_GetSystemVersion", referenced from: -[MyClass myMethod] in MyClass.o

"_CGSCreateCString", referenced from: -[MyClass myMethod] in MyClass.o

"_CGSReleaseObj", referenced from: -[MyClass myMethod] in MyClass.o

Community
  • 1
  • 1
Sorig
  • 1,200
  • 11
  • 24

1 Answers1

12

You need to link against the Application Services framework to get rid of the linker errors.

Here's a complete example of the hack (updated to use Core Foundation):

cat >t.c<<EOF
#include <ApplicationServices/ApplicationServices.h>

int main(void)
{
    void CGSSetConnectionProperty(int, int, CFStringRef, CFBooleanRef);
    int _CGSDefaultConnection();
    CFStringRef propertyString;

    // Hack to make background cursor setting work
    propertyString = CFStringCreateWithCString(NULL, "SetsCursorInBackground", kCFStringEncodingUTF8);
    CGSSetConnectionProperty(_CGSDefaultConnection(), _CGSDefaultConnection(), propertyString, kCFBooleanTrue);
    CFRelease(propertyString);
    // Hide the cursor and wait
    CGDisplayHideCursor(kCGDirectMainDisplay);
    pause();
    return 0;
}
EOF
gcc -framework ApplicationServices t.c
./a.out

On Mac OS 10.5 this hides the cursor until the program is interrupted. However, performing any window server or dock tasks shows the cursor.

ejsherry
  • 136
  • 1
  • 3
  • I fixed the reappearing of the cursor when performing a window server/dock task by calling a `-hideCursor` repeatedly using an `NSTimer`. Works even if the application is not in the foreground. – fabian789 Jan 08 '12 at 19:00
  • 1
    Anyone know why this code breaks when using a c++ compiler? This example works fine as mentioned above, but when doing "clang++ -framework ApplicationServices t.c" the following error occurs: `Undefined symbols for architecture x86_64: "_CGSDefaultConnection()", referenced from: _main in testCursor-p78PsB.o "CGSSetConnectionProperty(int, int, __CFString const*, __CFBoolean const*)", referenced from: _main in testCursor-p78PsB.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)` – Vivek Gani Nov 22 '13 at 00:35
  • 4
    Does anyone know how to convert this code to Swift 2? I'm having difficulty making it work. – MAH Dec 30 '15 at 03:52
  • This works for hiding, but I can't get it to unhide. (I tried `CGDisplayShowCursor()`, `CGSShowCursor()` and `[NSCursor unhide]`) – Noah Nuebling Dec 01 '21 at 11:37
  • 1
    @NoahNuebling I believe you have to keep track of how many times you hid the cursor and then unhide it as many times. They have to be balanced. – MAH Jan 22 '22 at 06:22