Skip to content

Commit 707c38c

Browse files
committed
Merge branch 'hotkeys-fix' into develop
2 parents 23ee53a + 2cd0064 commit 707c38c

File tree

4 files changed

+188
-78
lines changed

4 files changed

+188
-78
lines changed

globalkeyhook.pas

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ interface
1717
type
1818

1919
EGlobalKeyHookException = class(Exception);
20+
EGlobalKeyHookRegistrationFailedException = class(EGlobalKeyHookException);
2021

2122
TKeysMap = specialize TFPGMap<string, THotKey>;
2223

@@ -91,8 +92,9 @@ procedure TGlobalKeyHook.RegisterKey(AHotKeyId: Integer; const AHotKey: THotKey
9192
UnregisterKey(AHotKeyId);
9293

9394
if not RegisterHotKey(WndHandle, AHotkeyId, Modifiers, AHotKey.Key) then
94-
raise EGlobalKeyHookException.CreateFmt('Failed to register hot key (RegisterHotKey, error %d)',
95-
[GetLastError]);
95+
raise EGlobalKeyHookRegistrationFailedException.CreateFmt(
96+
'Failed to register hot key %s (error code %d)',
97+
[AHotKey.ToString, GetLastError]);
9698
end;
9799

98100
procedure TGlobalKeyHook.UnregisterKey(AHotKeyId: Integer);
@@ -198,11 +200,15 @@ destructor TGlobalKeyHook.Destroy;
198200

199201
procedure TGlobalKeyHook.RegisterKey(const AStringId: String;
200202
const AHotKey: THotKey);
201-
{$IfDef Windows}
202203
var
204+
{$IfDef Windows}
203205
FullStrId: String;
204206
Id: Integer;
205-
{$EndIf}
207+
{$EndIf}
208+
{$IfDef Linux}
209+
Res: Boolean;
210+
ErrMsg: String;
211+
{$EndIf}
206212
begin
207213
if AHotKey.IsEmpty then
208214
begin // No key set
@@ -213,34 +219,48 @@ procedure TGlobalKeyHook.RegisterKey(const AStringId: String;
213219
DebugLn('Start to register hotkey %s for %s',
214220
[AHotKey.ToString, AStringId]);
215221

216-
{$IfDef Windows}
217-
// Find atom id
218-
FullStrId := GetFullStringId(AStringId);
219-
if KeysMap.IndexOf(AStringId) = -1 then
220-
Id := GlobalAddAtom(PChar(FullStrId))
221-
else
222-
begin
223-
if KeysMap.KeyData[AStringId] = AHotKey then
222+
try
223+
{$IfDef Windows}
224+
// Find atom id
225+
FullStrId := GetFullStringId(AStringId);
226+
if KeysMap.IndexOf(AStringId) = -1 then
227+
Id := GlobalAddAtom(PChar(FullStrId))
228+
else
224229
begin
225-
DebugLn('Hotkey %s for %s not changed', [AHotKey.ToString, AStringId]);
230+
if KeysMap.KeyData[AStringId] = AHotKey then
231+
begin
232+
DebugLn('Hotkey %s for %s not changed', [AHotKey.ToString, AStringId]);
226233

227-
Exit;
234+
Exit;
235+
end;
236+
237+
Id := GlobalFindAtom(PChar(FullStrId));
228238
end;
229239

230-
Id := GlobalFindAtom(PChar(FullStrId));
231-
end;
240+
RegisterKey(Id, AHotKey);
241+
{$EndIf}
242+
{$IfDef Linux}
243+
if (KeysMap.IndexOf(AStringId) <> -1) and (KeysMap.KeyData[AStringId] = AHotKey) then
244+
begin
245+
DebugLn('Hotkey %s for %s not changed', [AHotKey.ToString, AStringId]);
232246

233-
RegisterKey(Id, AHotKey);
234-
{$EndIf}
235-
{$IfDef Linux}
236-
if (KeysMap.IndexOf(AStringId) <> -1) and (KeysMap.KeyData[AStringId] = AHotKey) then
237-
begin
238-
DebugLn('Hotkey %s for %s not changed', [AHotKey.ToString, AStringId]);
247+
Exit;
248+
end;
239249

240-
Exit;
250+
Res := HKCapture.RegisterNotify(AHotKey.Key, AHotKey.ShiftState, @OnHotKeyEvent);
251+
if not Res then
252+
begin
253+
ErrMsg := Format('Failed to register hotkey %s for %s', [AHotKey.ToString, AStringId]);
254+
raise EGlobalKeyHookRegistrationFailedException.Create(ErrMsg);
255+
end;
256+
{$EndIf}
257+
except
258+
on E: Exception do
259+
begin
260+
DebugLn({E.ToString} E.Message);
261+
raise;
262+
end
241263
end;
242-
HKCapture.RegisterNotify(AHotKey.Key, AHotKey.ShiftState, @OnHotKeyEvent);
243-
{$EndIf}
244264

245265
KeysMap.AddOrSetData(AStringId, AHotKey);
246266

libs/Cross.Codebot

uAutoScreen.pas

Lines changed: 76 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,14 @@ TMainForm = class(TForm)
195195
procedure SetStartAutoCaptureHotKey(AHotKey: THotKey);
196196
procedure SetStopAutoCaptureHotKey(AHotKey: THotKey);
197197
procedure SetSingleCaptureHotKey(AHotKey: THotKey);
198+
procedure SetHotKey(AHotKeyId: String; AHotKey: THotKey);
198199
procedure SetCompressionLevel(ALevel: Tcompressionlevel);
199200
function GetCompressionLevel: Tcompressionlevel;
200201
procedure UpdateFormAutoSize;
201202

202203
procedure OnHotKeyEvent(const AHotKeyId: String);
203204
procedure OnDebugLnEvent(Sender: TObject; S: string; var Handled: Boolean);
205+
function OnHotKeysSaving(ASender: TObject; out AErrorMsg: string): Boolean;
204206

205207
{$IfDef Linux}
206208
procedure OnScreenConfigurationChanged(const AEvent: TXEvent);
@@ -467,17 +469,9 @@ procedure TMainForm.ReadSettings;
467469

468470
procedure TMainForm.FormCreate(Sender: TObject);
469471
const
470-
StartAutoCaptureDefaultHotKey: THotKey = (
471-
ShiftState: [ssCtrl];
472-
Key: VK_F5;
473-
);
474-
StopAutoCaptureDefaultHotKey: THotKey = (
475-
ShiftState: [ssCtrl];
476-
Key: VK_F6;
477-
);
478-
SingleCaptureDefaultHotKey: THotKey = (
479-
ShiftState: [ssCtrl];
480-
Key: VK_F7;
472+
NoHotKey: THotKey = (
473+
ShiftState: [];
474+
Key: VK_UNKNOWN;
481475
);
482476
var
483477
///////
@@ -540,12 +534,24 @@ procedure TMainForm.FormCreate(Sender: TObject);
540534
// Enable global hotkeys
541535
KeyHook := TGlobalKeyHook.Create({$IfDef Windows}Handle, 'AutoScreenshot'{$EndIf}
542536
{$IfDef Linux}@OnHotKeyEvent{$EndIf});
543-
HotKey := Ini.ReadHotKey(HotKeysIniSection, 'StartAutoCapture', StartAutoCaptureDefaultHotKey);
544-
KeyHook.RegisterKey('StartAutoCapture', HotKey);
545-
HotKey := Ini.ReadHotKey(HotKeysIniSection, 'StopAutoCapture', StopAutoCaptureDefaultHotKey);
546-
KeyHook.RegisterKey('StopAutoCapture', HotKey);
547-
HotKey := Ini.ReadHotKey(HotKeysIniSection, 'SingleCapture', SingleCaptureDefaultHotKey);
548-
KeyHook.RegisterKey('SingleCapture', HotKey);
537+
HotKey := Ini.ReadHotKey(HotKeysIniSection, 'StartAutoCapture', NoHotKey);
538+
try
539+
KeyHook.RegisterKey('StartAutoCapture', HotKey);
540+
except
541+
KeyHook.RegisterKey('StartAutoCapture', NoHotKey);
542+
end;
543+
HotKey := Ini.ReadHotKey(HotKeysIniSection, 'StopAutoCapture', NoHotKey);
544+
try
545+
KeyHook.RegisterKey('StopAutoCapture', HotKey);
546+
except
547+
KeyHook.RegisterKey('StopAutoCapture', NoHotKey);
548+
end;
549+
HotKey := Ini.ReadHotKey(HotKeysIniSection, 'SingleCapture', NoHotKey);
550+
try
551+
KeyHook.RegisterKey('SingleCapture', HotKey);
552+
except
553+
KeyHook.RegisterKey('SingleCapture', NoHotKey);
554+
end;
549555

550556
{$IfDef Linux}
551557
// Enable monitor confuguration changed updates in Linux
@@ -594,18 +600,15 @@ procedure TMainForm.FormShow(Sender: TObject);
594600
procedure TMainForm.HotKetsSettingsMenuItemClick(Sender: TObject);
595601
var
596602
HotKeysForm: THotKeysForm;
603+
HasErrors: Boolean = False;
597604
begin
598-
HotKeysForm := THotKeysForm.Create(Nil);
605+
// ToDo: Reduce amount of code duplicates
606+
607+
HotKeysForm := THotKeysForm.Create(Nil, @OnHotKeysSaving);
599608
HotKeysForm.StartAutoCaptureKey := Self.KeyHook.FindHotKey('StartAutoCapture');
600609
HotKeysForm.StopAutoCaptureKey := Self.KeyHook.FindHotKey('StopAutoCapture');
601610
HotKeysForm.SingleCaptureKey := Self.KeyHook.FindHotKey('SingleCapture');
602-
if HotKeysForm.ShowModal = mrOK then
603-
begin
604-
SetStartAutoCaptureHotKey(HotKeysForm.StartAutoCaptureKey);
605-
SetStopAutoCaptureHotKey(HotKeysForm.StopAutoCaptureKey);
606-
SetSingleCaptureHotKey(HotKeysForm.SingleCaptureKey);
607-
end;
608-
611+
HotKeysForm.ShowModal;
609612
HotKeysForm.Free;
610613
end;
611614

@@ -1618,20 +1621,23 @@ procedure TMainForm.SetAutoCheckForUpdates(AVal: Boolean);
16181621

16191622
procedure TMainForm.SetStartAutoCaptureHotKey(AHotKey: THotKey);
16201623
begin
1621-
KeyHook.RegisterKey('StartAutoCapture', AHotKey);
1622-
Ini.WriteHotKey(HotKeysIniSection, 'StartAutoCapture', AHotKey);
1624+
SetHotKey('StartAutoCapture', AHotKey);
16231625
end;
16241626

16251627
procedure TMainForm.SetStopAutoCaptureHotKey(AHotKey: THotKey);
16261628
begin
1627-
KeyHook.RegisterKey('StopAutoCapture', AHotKey);
1628-
Ini.WriteHotKey(HotKeysIniSection, 'StopAutoCapture', AHotKey);
1629+
SetHotKey('StopAutoCapture', AHotKey);
16291630
end;
16301631

16311632
procedure TMainForm.SetSingleCaptureHotKey(AHotKey: THotKey);
16321633
begin
1633-
KeyHook.RegisterKey('SingleCapture', AHotKey);
1634-
Ini.WriteHotKey(HotKeysIniSection, 'SingleCapture', AHotKey);
1634+
SetHotKey('SingleCapture', AHotKey);
1635+
end;
1636+
1637+
procedure TMainForm.SetHotKey(AHotKeyId: String; AHotKey: THotKey);
1638+
begin
1639+
KeyHook.RegisterKey(AHotKeyId, AHotKey);
1640+
Ini.WriteHotKey(HotKeysIniSection, AHotKeyId, AHotKey);
16351641
end;
16361642

16371643
procedure TMainForm.SetCompressionLevel(ALevel: Tcompressionlevel);
@@ -1687,6 +1693,45 @@ procedure TMainForm.OnDebugLnEvent(Sender: TObject; S: string;
16871693
Handled := True;
16881694
end;
16891695

1696+
function TMainForm.OnHotKeysSaving(ASender: TObject; out AErrorMsg: string): Boolean;
1697+
var
1698+
HasErrors: Boolean = False;
1699+
HotKeysForm: THotKeysForm;
1700+
begin
1701+
HotKeysForm := THotKeysForm(ASender);
1702+
1703+
try
1704+
SetStartAutoCaptureHotKey(HotKeysForm.StartAutoCaptureKey);
1705+
HotKeysForm.StartAutoCaptureMarked := False;
1706+
except
1707+
HasErrors := True;
1708+
HotKeysForm.StartAutoCaptureMarked := True;
1709+
end;
1710+
1711+
try
1712+
SetStopAutoCaptureHotKey(HotKeysForm.StopAutoCaptureKey);
1713+
HotKeysForm.StopAutoCaptureMarked := False;
1714+
except
1715+
HasErrors := True;
1716+
HotKeysForm.StopAutoCaptureMarked := True;
1717+
end;
1718+
1719+
try
1720+
SetSingleCaptureHotKey(HotKeysForm.SingleCaptureKey);
1721+
HotKeysForm.SingleCaptureMarked := False;
1722+
except
1723+
HasErrors := True;
1724+
HotKeysForm.SingleCaptureMarked := True;
1725+
end;
1726+
1727+
if HasErrors then
1728+
AErrorMsg := Localizer.I18N('HotKeyOccupied')
1729+
else
1730+
AErrorMsg := '';
1731+
1732+
Result := not HasErrors;
1733+
end;
1734+
16901735
{$IfDef Linux}
16911736
procedure TMainForm.OnScreenConfigurationChanged(const AEvent: TXEvent);
16921737
begin

0 commit comments

Comments
 (0)