[OSX/맥] 맥의 스크린세이버 비활성화/활성화 시키기

2016.04.04 13:25

볼랜드포럼에서 무대뽀님이 남겨준 팁 공유합니다.(작업한 내용 공유해주셔서 감사합니다^^)



무대뽀님께서 맥용 애플리케이션 개잘 중 맥의 스크린 세이버를 비활성화 시키는 질문을 볼랜드포럼에 올려서 간단히 댓글을 드렸더니 멋지게 기능을 완성하셨네요.(http://firemonkey.borlandforum.com/impboard/impboard.dll?action=read&db=firemonkey_qna&no=146)


제가 작성한 답변입니다.

맥 개발자 라이브러리에 아래와 같은 샘플이 있습니다. 

https://developer.apple.com/library/mac/samplecode/SceneKitWWDC2014/Listings/Scene_Kit_Session_WWDC_2014_AAPLAppDelegate_m.html 

그 중 아래 코드를 호출하면 됩니다. 
IOPMAssertionID _assertionID; 

- (void)disableDisplaySleeping { 
    CFStringRef reasonForActivity = CFSTR("Scene Kit Presentation"); 
    IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, kIOPMAssertionLevelOn, reasonForActivity, &_assertionID); 


- (void)enableDisplaySleeping { 
    if (_assertionID) 
        IOPMAssertionRelease(_assertionID); 


위가 잠자는걸 막는 거고 아래는 막은걸 해지하는 겁니다. 

위 메소드 들은 Macapi 중 IOKit에 구현되어 있습니다.(즉 맥의 라이브러리를 이용해야 한다는 거죠.) 
아쉽게도 파이어몽키에 구현된 IOKit을 보면 구현된 API가 몇가지 안됩니다. 
(C:\Program Files (x86)\Embarcadero\Studio\17.0\source\rtl\osx\Macapi.IOKit.pas) 

위 문서와 애플 기술문서를 참고하셔서 필요한 API를 추가하시고 호출하는 코드를 작성해 보시기 바랍니다. 
아래 애플 기술문서가 도움이 될것입니다. 
https://developer.apple.com/library/mac/documentation/IOKit/Reference/IOPMLib_header_reference/#//apple_ref/c/econst/kIOPMAssertionLevelOn 


위 내용을 참고로 Macapi.IOKit.pas에 필요한 메소드를 추가/확장했습니다.

기존의 유닛(C:\Program Files (x86)\Embarcadero\Studio\17.0\source\rtl\osx\Macapi.IOKit.pas)을 확장하기 위해서는 유닛파일(*.pas)를 복사 해 프로젝트 파일(*.dpr)과 같은 경로에 복사후 수정하면 프로젝트 파일과 같은 경로의 유닛을 먼저 참조합니다.


unit Macapi.IOKit 

... 

const 
  kIOMasterPortDefault: mach_port_t = 0; 
  kIOPlatformUUIDKey = 'IOPlatformUUID'; 

  // add 
  kIOPMAssertionLevelOff = 0; 
  kIOPMAssertionLevelOn  = 255; 
  kIOPMAssertionTypeNoDisplaySleep = 'NoDisplaySleepAssertion'; 

... 
type 
... 
function ... 
... 
function IOObjectRelease(anObject: io_object_t): kern_return_t; cdecl; external libIOKit name _PU + 'IOObjectRelease'; 

// add // AssertionID는 Uint32의 포인터형 
function IOPMAssertionCreateWithName(AssertionType : CFStringRef; AssertLevel : uint32_t; 
  AssertionName : CFStringRef; AssertionID : uint32_t) : uint32_t; cdecl; external libIOKit name _PU + 'IOPMAssertionCreateWithName'; 
function IOPMAssertionRelease(AssertionID : uint32_t) : uint32_t; cdecl; external libIOKit name _PU + 'IOPMAssertionRelease'; 


추가한 API를 사용하는 코드는 아래와 같습니다. 버튼을 눌러 비활성화/활성화 시킵니다.

TForm1 = class(TForm) 
  procedure BtnDisableClick(Sender: TObject); 
  procedure BtnEnableClick(Sender: TObject); 
private 
  FSleepAssert : UInt32; 
public 
end; 

implementation 

uses 
  Macapi.IOKit, Macapi.CoreFoundation; 

............ 
procedure TForm1.BtnDisableClick(Sender: TObject); 
begin 
  FSleepAssert := 0; 
  IOPMAssertionCreateWithName(CFSTR(kIOPMAssertionTypeNoDisplaySleep), kIOPMAssertionLevelOn, CFSTR('MyProject is Good'), FSleepAssert); 
  if FSleepAssert = 0 then 
    ShowMessage('Disable Failed!!'); 
end; 

procedure TForm1.BtnEnableClick(Sender: TObject); 
begin 
  if FSleepAssert > 0 then 
    IOPMAssertionRelease(@FSleepAssert); 
end; 

다시한번 좋은 자료 공유해 주신 무대뽀님에게 감사인사를 전합니다.

험프리.김현수 파이어몽키

  1. Blog Icon
    무대뽀

    제가 Disable에만 신경쓰느라 미쳐 못봐서 실수한부분이 있었네요. 번거롭지만 다시 수정 부탁드려요 ^^;;
    function IOPMAssertionRelease(AssertionID : Pointer) : uint32_t; ... 에서
    파라메터가 Pointer가 아닌 uint32_t 입니다. ㅠ_ㅠ
    function IOPMAssertionRelease(AssertionID : uint32_t) : ... 이고
    예제의 파라메터도 @FSleepAssert가 아닌 @뺀 FSleepAssert로 수정 부탁드릴께요.

    정리된 자료들 아주 잘 보고있습니다. 정말 도움이 많이 되고있습니다.!!
    이자리에서나마 정말 고마움을 표합니다. ^^*

  2. 네. 수정했습니다.
    도움이 되셨다니 제가 감사합니다.
    무대뽀님도 정리차원에서 많은 자료 공유 부탁드립니다.