Recent

Author Topic: Prevent Mac from Sleeping  (Read 2717 times)

Igor Kokarev

  • Sr. Member
  • ****
  • Posts: 370
Prevent Mac from Sleeping
« on: February 11, 2021, 01:03:26 pm »
The code below should prevent a Mac from sleeping or screensaver.

We have 2 applications bundles and it works fine in one app and the same code doesn't work in another app (sleeping occurs).

Probably we wrote incorrectly this code?

Code: Pascal  [Select][+][-]
  1. var
  2.   proc_: NSProcessInfo_NSObject;
  3.   token: NSObjectProtocol;
  4.  
  5. begin
  6.   proc_:=NSProcessInfo_NSObject(NSProcessInfo.processInfo);      
  7.   token:=proc_.beginActivityWithOptions_reason(NSActivityIdleDisplaySleepDisabled, StringToNSString('Preventing Sleep'));
  8. end;

FPC 3.2.0, Lazarus 2.0.10, macOS 11.2 and 10.13

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2020
  • Former Delphi 1-7, 10.2 user
Re: Prevent Mac from Sleeping
« Reply #1 on: February 12, 2021, 09:25:11 am »
I've been wrangling with this on and off since last year, but have never managed to get it to work.

Have you tested your token in the working app? In my tests it is never populated and is always Nil.

Igor Kokarev

  • Sr. Member
  • ****
  • Posts: 370
Re: Prevent Mac from Sleeping
« Reply #2 on: February 12, 2021, 02:40:06 pm »
trev,

Thanks for your reply.
token is not nil.

Jonas Maebe

  • Hero Member
  • *****
  • Posts: 1058
Re: Prevent Mac from Sleeping
« Reply #3 on: February 12, 2021, 10:54:52 pm »
Looking at the Cocoa unit source code, that NSProcessInfo_NSObject declaration seems bogus. The actual translation of the Objective-C header should be:
Code: [Select]
type
  NSProcessInfoActivity = objccategory external (NSProcessInfo)
  public
    function beginActivityWithOptions_reason (options: NSActivityOptions; reason: NSString): NSObjectProtocol; message 'beginActivityWithOptions:reason:'; { available in 10_9, 7_0 }
    procedure endActivity (activity: NSObjectProtocol); message 'endActivity:'; { available in 10_9, 7_0 }
    procedure performActivityWithOptions_reason_usingBlock (options: NSActivityOptions; reason: NSString; block: OpaqueCBlock); message 'performActivityWithOptions:reason:usingBlock:'; { available in 10_9, 7_0 }
  end;
Can you try adding that to your program, and replace the NSProcessInfo_NSObject with plain NSProcessInfo?

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2020
  • Former Delphi 1-7, 10.2 user
Re: Prevent Mac from Sleeping
« Reply #4 on: February 13, 2021, 01:53:31 am »
Jonas, that works for me :) Only needed to remove your "public" as not allowed.

Jonas Maebe

  • Hero Member
  • *****
  • Posts: 1058
Re: Prevent Mac from Sleeping
« Reply #5 on: February 13, 2021, 08:53:27 am »
Thanks for checking. Submitted and merged to fixes_3_2. It's unfortunate I missed this when you brought it up earlier.

Igor Kokarev

  • Sr. Member
  • ****
  • Posts: 370
Re: Prevent Mac from Sleeping
« Reply #6 on: February 15, 2021, 01:53:23 pm »
Jonas,

Thanks for your suggested solution!

We used your code. But the problem also was in our code. We called beginActivityWithOptions_reason too late in application loop.

We moved this call as a first call in .lpr project file before application loop and now it works correctly, preventing Mac from sleep/screensaver. We use own application loop for the Metal 3D app.

P.S. I still don't understand why it's important to call beginActivityWithOptions_reason before application loop.
« Last Edit: February 15, 2021, 01:56:40 pm by Igor Kokarev »

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2020
  • Former Delphi 1-7, 10.2 user
Re: Prevent Mac from Sleeping
« Reply #7 on: February 23, 2021, 06:55:09 am »
@Jonas: I think the NSObjectProtocol references should be just NSObject references having just noticed the ObjC declarations on Apple's site:

Quote
- (id<NSObject>)beginActivityWithOptions:(NSActivityOptions)options reason:(NSString *)reason;
- (void)endActivity:(id<NSObject>)activity;

Jonas Maebe

  • Hero Member
  • *****
  • Posts: 1058
Re: Prevent Mac from Sleeping
« Reply #8 on: February 23, 2021, 09:10:57 pm »
In Objective-C, the namespaces for classes and protocols are separate. Foundation has both a class and a protocol called NSObject. In Pascal, all identifiers share the same namespace, so in case of clashes, we have to rename some. For the same reason, unlike in Pascal, in Objective-C you cannot declare an variable as just "protocol_name*", because otherwise it would be impossible for the compiler to decide whether you mean the protocol or the class. Instead, id<NSObject> is Objective-C for "any object that conforms to the NSObject protocol", while "NSObject*" is "any object that is related to the NSObject class".

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2020
  • Former Delphi 1-7, 10.2 user
Re: Prevent Mac from Sleeping
« Reply #9 on: February 24, 2021, 12:23:52 am »
Thanks for the explanation Jonas. I may never get the hang of Objective-C.

 

TinyPortal © 2005-2018