Page 1 of 1
Forum

Welcome to the Tweaking4All community forums!
When participating, please keep the Forum Rules in mind!

Topics for particular software or systems: Start your topic link with the name of the application or system.
For example “MacOS X – Your question“, or “MS Word – Your Tip or Trick“.

Please note that switching to another language when reading a post will not bring you to the same post, in Dutch, as there is no translation for that post!



Share:
Notifications
Clear all

[Solved] Lazarus Pascal - macOS - Determine if the screen is locked or not

1 Posts
1 Users
0 Reactions
9 Views
 Hans
(@hans)
Famed Member Admin
Joined: 13 years ago
Posts: 3042
Topic starter  

Based on a user request, I had to figure out if a screen is locked or not.
So with some tinkering (thank you StackExchange!) I found 2 ways to handle this.

  1. Check if the screen is locked or not with a simple one time call
  2. With the system notifying my application that the lock state changed (so we do not have to poll if a screen is locked or not)

So for this I made a little unit - feel free to use/modify/etc:

unit t4a_macOS_ScreenLocked;

{$mode ObjFPC}{$H+}
{$modeswitch objectivec1}

interface

uses
  Classes, SysUtils, MacOSAll, Forms, process, CocoaAll, CocoaUtils;


type
  TScreenLockUnlockCallback = procedure(isScreenLocked:boolean) of object;

{ T4ALIB - Check if the screen is locked or not (eg. Login screen shows). }
function CheckIfScreenLocked: Boolean;


{ Use Notifications by system}
procedure ScreenLockCallback(Center: CFNotificationCenterRef;
                             Observer: Pointer;
                             Name: CFStringRef;
                             Object_: Pointer;
                             UserInfo: CFDictionaryRef); mwpascal;
procedure RegisterScreenLockNotifications(OptionalCallbackProcedure:TScreenLockUnlockCallback = nil);
procedure UnregisterScreenLockNotifications;

var
  ScreenIsLocked    : boolean; // used for notifications
  CallbackProcedure : TScreenLockUnlockCallback;

implementation

// Onetime call/check
function CheckIfScreenLocked: Boolean;
var
  SessionDict: CFDictionaryRef;
  ValueRef: CFTypeRef;
begin
  Result := False;

  SessionDict := CGSessionCopyCurrentDictionary;
  if SessionDict <> nil then
  begin
    if CFDictionaryGetValueIfPresent(
         SessionDict,
         CFSTR('CGSSessionScreenIsLocked'),
         @ValueRef
       ) then
    begin
      if CFGetTypeID(ValueRef) = CFBooleanGetTypeID then
        Result := CFBooleanGetValue(CFBooleanRef(ValueRef));
    end;

    CFRelease(SessionDict);
  end;

  ScreenIsLocked := Result;
end;

// Notification by system
procedure ScreenLockCallback(Center: CFNotificationCenterRef;
                             Observer: Pointer;
                             Name: CFStringRef;
                             Object_: Pointer;
                             UserInfo: CFDictionaryRef); mwpascal;
var
  NotificationName: String;
begin
  NotificationName := CFStringToString(Name);

  ScreenIsLocked := (NotificationName =  'com.apple.screenIsLocked') and
                    (NotificationName <> 'com.apple.screenIsUnlocked');

  if Assigned(CallbackProcedure) then CallbackProcedure(ScreenIsLocked);
end;

procedure RegisterScreenLockNotifications(OptionalCallbackProcedure:TScreenLockUnlockCallback = nil);
var
  Center: CFNotificationCenterRef;
begin
  CallbackProcedure := OptionalCallbackProcedure;

  Center := CFNotificationCenterGetDistributedCenter;

  CFNotificationCenterAddObserver(
    Center,
    nil, // observer
    @ScreenLockCallback,
    CFSTR('com.apple.screenIsLocked'),
    nil,
    CFNotificationSuspensionBehaviorDeliverImmediately
  );

  CFNotificationCenterAddObserver(
    Center,
    nil,
    @ScreenLockCallback,
    CFSTR('com.apple.screenIsUnlocked'),
    nil,
    CFNotificationSuspensionBehaviorDeliverImmediately
  );
end;

procedure UnregisterScreenLockNotifications;
var
  Center: CFNotificationCenterRef;
begin
  Center := CFNotificationCenterGetDistributedCenter;
  CFNotificationCenterRemoveObserver(Center, nil, nil, nil);
end;

finalization

  UnregisterScreenLockNotifications;

end.

 

Use:

1. One time check:

Just call "CheckIfScreenLocked", which returns TRUE if the screen is locked.

2. Using notifications:

- define a public function that can be called when the screen locked state changes:

// your own procedure
procdure TForm1.ScreenLockChanged(locked:boolean);   { public! }
begin
  if locked the writeln('locked');
end;  

- In the onCreate event of your form, activate the notification observer

procedure TForm1.FormCreate(Sender: TObject);
begin
   RegisterScreenLockNotifications(@ScreenLockChanged);
end;

(the observer will be unregistered automatically when your application closes, or you can call "UnregisterScreenLockNotifications")

 

Hope this is of use to someone out there 😉 



   
ReplyQuote
Share: