Arrow keys don't work correctly with Gtk2 (and Gtk3?) and custom controls
Original Reporter info from Mantis: sysrpl
-
Reporter name: Anthony Walter
Original Reporter info from Mantis: sysrpl
- Reporter name: Anthony Walter
Description:
If you write a control that requires processing of the arrow keys in Gtk2 (and also likely Gtk3) the Gtk system may change the input focus of your control instead of allowing it to process arrow key presses.
This bug will present itself only in controls that do not have scroll bars.
See this example video (bug description are 3:00): https://cache.getlazarus.org/videos/scrabble.mp4
Steps to reproduce:
Create a custom control, add the following code:
// interface
procedure WMGetDlgCode(var Msg: TLMNoParams); message LM_GETDLGCODE;
// implementation
procedure TYourControl.WMGetDlgCode(var Msg: TLMNoParams);
begin
Msg.Result := DLGC_WANTARROWS or DLGC_WANTCHARS;
end;
Add an edit box to the form and align to top.
Add TYourControl and align to client.
Click you control to set the input focus.
Press left, right, down, then up.
When up is pressed, instead of your control handling the up key, Gtk will see the edit box above your control and change the focus to the edit control.
What should happen is that you control handles all arrow key events without losing input focus.
Note: This bug will not present itself if the control has scrollbars, hence it's not a problem for the grid controls in Lazarus, but it is for any control in Lazarus with gtk2 that wants to handle the arrow keys and does not have scroll bars.
Additional information:
See this discussion about the problem: https://mail.gnome.org/archives/gtk-list/1999-May/msg00663.html
My small fix is yet another band aid on an already terrible LCL callback. Really this entire thing should be redesigned to not patch every control in one main Gtk signal handler:
in gtk2proc.inc procedure EmulateEatenKeys add this to the end for a fix:
if (
GtkWidgetIsA(TargetWidget, gtk_type_entry) or
GtkWidgetIsA(TargetWidget, gtk_type_text_view) or
GtkWidgetIsA(TargetWidget, gtk_type_tree_view)
)
and
(gdk_event_get_type(AEvent) = GDK_KEY_PRESS) and
((VKey = VK_RETURN) or (VKey = VK_TAB)) then
begin
// DebugLn(['EmulateKeysEatenByGtk ']);
FillChar(Msg, SizeOf(Msg), 0);
Msg.CharCode := VKey;
if SysKey then
Msg.msg := LM_SYSKEYDOWN
else
Msg.msg := LM_KEYDOWN;
Msg.KeyData := CommonKeyData or (Flags shl 16) or $0001 {TODO: repeatcount};
// send the (Sys)KeyDown message directly to the LCL
NotifyApplicationUserInput(TControl(TargetObj), Msg.Msg);
DeliverKeyMessage(TargetObj, Msg);
end;
// fix arrow keys start
if VKey in [VK_LEFT..VK_DOWN] then
begin
Msg.Msg := LM_GETDLGCODE;
TObject(TargetObj).Dispatch(Msg);
EventStopped := Msg.Result and DLGC_WANTARROWS = DLGC_WANTARROWS;
end;
// fix arrow keys end
end;
Mantis conversion info:
- Mantis ID: 35942
- OS: Ubuntu
- OS Build: 16.04
- Platform: Gtk2
- Version: 2.0.4