Recent

Author Topic: [SOLVED] LCLSendUTF8KeyPress AUTF8Char parameter anomaly  (Read 1271 times)

lagprogramming

  • Sr. Member
  • ****
  • Posts: 406
[SOLVED] LCLSendUTF8KeyPress AUTF8Char parameter anomaly
« on: April 15, 2023, 05:50:08 pm »
lcl/lclmessageglue.pas contains the following functions:
Code: Pascal  [Select][+][-]
  1. function LCLSendKeyDownEvent(const Target: TControl; var CharCode: Word; KeyData: PtrInt; BeforeEvent, IsSysKey: Boolean): PtrInt;
  2. function LCLSendKeyUpEvent(const Target: TControl; var CharCode: Word; KeyData: PtrInt; BeforeEvent, IsSysKey: Boolean): PtrInt;
  3. function LCLSendCharEvent(const Target: TControl; var CharCode: Word; KeyData: PtrInt; BeforeEvent, IsSysKey, ANotifyUserInput: Boolean): PtrInt;
  4. function LCLSendUTF8KeyPress(const Target: TWinControl; AUTF8Char: TUTF8Char; IsSysKey: Boolean): PtrInt;
Code: Pascal  [Select][+][-]
  1. function LCLSendUTF8KeyPress(const Target: TWinControl; AUTF8Char: TUTF8Char;
  2.   IsSysKey: Boolean): PtrInt;
  3. begin
  4.   {if not IsControlKey then}
  5.   Target.IntfUTF8KeyPress(AUTF8Char, 1, IsSysKey);
  6.   Result := 1;
  7. end;

Why LCLSendUTF8KeyPress doesn't have a "var" before "AUTF8Char: TUTF8Char;", similar to "var CharCode: Word;"? Especially because AUTF8Char in "Target.IntfUTF8KeyPress(AUTF8Char, 1, IsSysKey);" points to:
Code: Pascal  [Select][+][-]
  1. function IntfUTF8KeyPress(var UTF8Key: TUTF8Char; RepeatCount: Integer; SystemKey: Boolean): Boolean; virtual;
To me it doesn't look right. Are you sure there shouldn't be a "var" before "AUTF8Char: TUTF8Char;" at function LCLSendUTF8KeyPress?
« Last Edit: April 26, 2023, 11:44:00 am by lagprogramming »

AlexTP

  • Hero Member
  • *****
  • Posts: 2402
    • UVviewsoft
Re: LCLSendUTF8KeyPress AUTF8Char parameter anomaly
« Reply #1 on: April 16, 2023, 06:32:09 pm »
Posted to bugtracker, applied to Git there.

Josh

  • Hero Member
  • *****
  • Posts: 1274
Re: [SOLVED] LCLSendUTF8KeyPress AUTF8Char parameter anomaly
« Reply #2 on: April 21, 2023, 11:05:57 am »
but then i cannot send it a const or direct value
ie

const ch='A';
LCLSendUTF8KeyPress(memo1,ch,true);
will fail

and so does
LCLSendUTF8KeyPress(memo1,'B',true);
The best way to get accurate information on the forum is to post something wrong and wait for corrections.

lagprogramming

  • Sr. Member
  • ****
  • Posts: 406
Re: [SOLVED] LCLSendUTF8KeyPress AUTF8Char parameter anomaly
« Reply #3 on: April 21, 2023, 12:21:31 pm »
but then i cannot send it a const or direct value
ie

const ch='A';
LCLSendUTF8KeyPress(memo1,ch,true);
will fail

and so does
LCLSendUTF8KeyPress(memo1,'B',true);

Yes, it has to be a variable parameter not a value parameter.
function LCLSendUTF8KeyPress(const Target: TWinControl; var AUTF8Char: TUTF8Char; IsSysKey: Boolean): PtrInt; calls Target.IntfUTF8KeyPress(AUTF8Char, 1, IsSysKey); and Target.IntfUTF8KeyPress uses AUTF8Char as a variable parameter. This means that a routine that calls function LCLSendUTF8KeyPress would have access to the modified value of AUTF8Char in Target.IntfUTF8KeyPress. This behavior also mimics the traditional KeyPress event handling related routines, like OnKeyPress. Notice that the Key parameter, which is Char/Word type, can be modified too.
Here is an example. Put a TEdit on an empty form and use this code:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: char);
  2. begin
  3.   //The caption of the form will show the Key
  4.   Application.MainForm.Caption:=Key;
  5.   //Now suppress further propagation of the Key
  6.   Key:=#0;
  7.   //Notice that the caption of the form changes whenever you press your keyboard
  8.   //but the Edit.text remains unchanged
  9.  
  10.   //I've tested the above code using linux-gtk2.
  11.   //It doesn't work for customdrawn or fpgui because of additional LCL bugs.
  12. end;
So, the good practice is to use a variable parameter, not to pass a constant as a parameter, even if you don't use it's returned value. Same for UTF8Key events.

Josh

  • Hero Member
  • *****
  • Posts: 1274
Re: [SOLVED] LCLSendUTF8KeyPress AUTF8Char parameter anomaly
« Reply #4 on: April 21, 2023, 12:28:00 pm »
Umm.

So i cant send any virtual keys constants, as was available before??

i do not see an advantage, just the opposite. How much code will this break...?

The best way to get accurate information on the forum is to post something wrong and wait for corrections.

lagprogramming

  • Sr. Member
  • ****
  • Posts: 406
Re: [SOLVED] LCLSendUTF8KeyPress AUTF8Char parameter anomaly
« Reply #5 on: April 22, 2023, 09:37:45 am »
i do not see an advantage, just the opposite. How much code will this break...?

For sure, exactly the same amount of code that successfully used the result of LCLSendUTF8KeyPress. :)) Which means none. Why!? The follow up is at:
Lazarus » Forum » Miscellaneous » Suggestions » LCL » LCLSendUTF8KeyPress always returns 1


Josh

  • Hero Member
  • *****
  • Posts: 1274
Re: [SOLVED] LCLSendUTF8KeyPress AUTF8Char parameter anomaly
« Reply #6 on: April 22, 2023, 10:51:21 am »
by adding a var, it breaks my code, i now have to redo code, that was not broken before but is broken now, due to a non necessary change. that has NO advantage.
The best way to get accurate information on the forum is to post something wrong and wait for corrections.

Bart

  • Hero Member
  • *****
  • Posts: 5290
    • Bart en Mariska's Webstek
Re: [SOLVED] LCLSendUTF8KeyPress AUTF8Char parameter anomaly
« Reply #7 on: April 22, 2023, 11:27:57 am »
by adding a var, it breaks my code, i now have to redo code, that was not broken before but is broken now, due to a non necessary change. that has NO advantage.

Please report this regression in the bugtracker (issue 40224).

Bart

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: [SOLVED] LCLSendUTF8KeyPress AUTF8Char parameter anomaly
« Reply #8 on: April 22, 2023, 04:08:02 pm »
I must agree with Jose on this one. I see a lot of holes in this change.
The only true wisdom is knowing you know nothing

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4468
  • I like bugs.
Re: [SOLVED] LCLSendUTF8KeyPress AUTF8Char parameter anomaly
« Reply #9 on: April 22, 2023, 05:05:19 pm »
Please report this regression in the bugtracker (issue 40224).
No, it is https://gitlab.com/freepascal.org/lazarus/lazarus/-/issues/40211
I reopened it and will revert the change. Indeed it can break existing code.

@lagprogramming, why do you refuse to use the bug tracker and even to write a comment there?
« Last Edit: April 22, 2023, 05:23:35 pm by JuhaManninen »
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

lagprogramming

  • Sr. Member
  • ****
  • Posts: 406
Re: [SOLVED] LCLSendUTF8KeyPress AUTF8Char parameter anomaly
« Reply #10 on: April 23, 2023, 11:08:46 am »
Please report this regression in the bugtracker (issue 40224).
No, it is https://gitlab.com/freepascal.org/lazarus/lazarus/-/issues/40211
I reopened it and will revert the change. Indeed it can break existing code.

You've just reintroduced a bug that was fixed.
As I was writing in one of the above replies:
function LCLSendUTF8KeyPress(const Target: TWinControl; AUTF8Char: TUTF8Char; IsSysKey: Boolean): PtrInt; calls
function IntfUTF8KeyPress(var UTF8Key: TUTF8Char; RepeatCount: Integer; SystemKey: Boolean): Boolean; virtual; which calls
function  DoUTF8KeyPress(var UTF8Key: TUTF8Char): Boolean; virtual;
This means that the routines that use LCLSendUTF8KeyPress will never be able to read the modified value of UTF8Key in IntfUTF8KeyPress/DoUTF8KeyPress.
One of the routines that uses LCLSendUTF8KeyPress is:
Code: Pascal  [Select][+][-]
  1. procedure CallbackKeyChar(AWindowHandle: TCDForm; AKeyData: Word; AChar: TUTF8Char);
  2. var
  3.   lTarget: TWinControl;
  4.   lCharCode: Word;
  5. begin
  6.   lTarget := AWindowHandle.GetFocusedControl();
  7.   {$ifdef VerboseCDEvents}
  8.    DebugLn(Format('CallbackKeyChar FocusedControl=%s:%s', [lTarget.Name, lTarget.ClassName]));
  9.   {$endif}
  10.  
  11.   if lTarget = nil then Exit; // Fixes a crash
  12.   if Length(AChar) = 1 then
  13.     lCharCode := Byte(AChar[1])
  14.   else
  15.     lCharCode:=0;
  16.  
  17.   if AChar<>'' then LCLSendUTF8KeyPress(lTarget, AChar, False);
  18.   if lCharCode <> 0 then LCLSendCharEvent(lTarget, lCharCode, AKeyData, True, False, True);
  19.  
  20.   // If this is a interface control, send the message to the main LCL control too
  21.   if IsIntfControl(lTarget) then
  22.   begin
  23.     lTarget := lTarget.Parent;
  24.     if AChar<>'' then LCLSendUTF8KeyPress(lTarget, AChar, False);
  25.     if lCharCode <> 0 then LCLSendCharEvent(lTarget, lCharCode, AKeyData, True, False, True);
  26.   end;
  27. end;
The above routine is included in lcl and as can be seen, the code needs to know if the key has been handled or not. So the patch was good.

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: [SOLVED] LCLSendUTF8KeyPress AUTF8Char parameter anomaly
« Reply #11 on: April 23, 2023, 03:39:36 pm »
Although I don't agree with your assessment of this, you can always just create another function with the style you wish.

 I know having a Bug that was removed and then reintroduced is a mind stressing effect, especially when it breaks a crap lot of code you have written that matches native OS behaviors. In your case I cannot say but, the function you are complaining about must be able to process constants.

  You can do what I do, as I am sure many others here also do, and that is when the release gets to public consumption, remove the bugs and put in what you think works for you.

 You see, I learned at some point in life, those with the keys to the Cassel will have it their way no matter what, so don't fight it and just be thankful you are able to correct the faults to suit your needs.

 Its not like Delphi, where you can't do this.
The only true wisdom is knowing you know nothing

lagprogramming

  • Sr. Member
  • ****
  • Posts: 406
Re: [SOLVED] LCLSendUTF8KeyPress AUTF8Char parameter anomaly
« Reply #12 on: April 26, 2023, 11:45:03 am »
The following patch modifies procedure CallbackKeyChar(AWindowHandle: TCDForm; AKeyData: Word; AChar: TUTF8Char);
It replaces the lines that look like
if AChar<>'' then LCLSendUTF8KeyPress(lTarget, AChar, False);
with
if AChar<>'' then lTarget.IntfUTF8KeyPress(AChar, 1, False);
If the patch is accepted the customdrawn bug will be fixed without modifying the function LCLSendUTF8KeyPress in lclmessageglue.pas. Also, none of the routines in the official source code of Lazarus will use the function LCLSendUTF8KeyPress. This means that you can close the Lazarus issues #40211 and #40224. Everybody should be happy, except for an eventual fpgui lcl implentation developer.
Code: Pascal  [Select][+][-]
  1. diff --git a/lcl/interfaces/customdrawn/customdrawnprivate.pas b/lcl/interfaces/customdrawn/customdrawnprivate.pas
  2. index 7a95139583..755d7aa8f5 100644
  3. --- a/lcl/interfaces/customdrawn/customdrawnprivate.pas
  4. +++ b/lcl/interfaces/customdrawn/customdrawnprivate.pas
  5. @@ -301,14 +301,16 @@ begin
  6.    else
  7.      lCharCode:=0;
  8.  
  9. -  if AChar<>'' then LCLSendUTF8KeyPress(lTarget, AChar, False);
  10. +  // Do not use LCLSendUTF8KeyPress! See Lazarus issues: #40211 and #40224
  11. +  if AChar<>'' then lTarget.IntfUTF8KeyPress(AChar, 1, False);
  12.    if lCharCode <> 0 then LCLSendCharEvent(lTarget, lCharCode, AKeyData, True, False, True);
  13.  
  14.    // If this is a interface control, send the message to the main LCL control too
  15.    if IsIntfControl(lTarget) then
  16.    begin
  17.      lTarget := lTarget.Parent;
  18. -    if AChar<>'' then LCLSendUTF8KeyPress(lTarget, AChar, False);
  19. +    // Do not use LCLSendUTF8KeyPress! See Lazarus issues: #40211 and #40224
  20. +    if AChar<>'' then lTarget.IntfUTF8KeyPress(AChar, 1, False);
  21.      if lCharCode <> 0 then LCLSendCharEvent(lTarget, lCharCode, AKeyData, True, False, True);
  22.    end;
  23.  end;


 

TinyPortal © 2005-2018