1
0
mirror of https://github.com/salvadordf/CEF4Delphi.git synced 2025-11-23 21:34:53 +02:00

Added SimpleOSRBrowser demo for QT6 in Linux (work in progress)

This commit is contained in:
Salvador Díaz Fau
2025-09-18 19:31:58 +02:00
parent 9533fc2257
commit e5ad04f1d9
11 changed files with 1448 additions and 7 deletions

View File

@@ -17,8 +17,11 @@ uses
{$IFDEF FPC}
LCLProc, LCLType, LCLIntf, LResources, LMessages, InterfaceBase, {$IFDEF MSWINDOWS}Win32Extra,{$ENDIF}
{$IFDEF LINUXFPC}Messages,{$ENDIF}
{$IFDEF LCLGTK2}glib2, gdk2, gtk2,{$ENDIF}
{$IFDEF LCLGTK2}glib2, gdk2, gtk2,{$ENDIF}
{$IFDEF LCLGTK3}LazGdk3, LazGtk3, LazGObject2, LazGLib2, gtk3procs, gtk3objects, gtk3widgets,{$ENDIF}
{$IFDEF LCLQT}qtobjects, qtwidgets, qt4, QtWSExtCtrls, QtWSControls, WSLCLClasses,{$ENDIF}
{$IFDEF LCLQT5}qtobjects, qtwidgets, qt5, QtWSExtCtrls, QtWSControls, WSLCLClasses,{$ENDIF}
{$IFDEF LCLQT6}qtobjects, qtwidgets, qt6, QtWSExtCtrls, QtWSControls, WSLCLClasses,{$ENDIF}
{$ELSE}
Messages,
{$ENDIF}
@@ -39,6 +42,21 @@ type
{$IFDEF MSWINDOWS}
TOnHandledMessageEvent = procedure(Sender: TObject; var aMessage: TMessage; var aHandled : boolean) of object;
{$ENDIF}
{$IF DEFINED(LCLQT) OR DEFINED(LCLQT5) OR DEFINED(LCLQT6)}
TOnQTKeyPress = procedure(Sender: TObject; Event_: QEventH) of object;
TOnQTKeyRelease = procedure(Sender: TObject; Event_: QEventH) of object;
TQtFrameEx = class(TQtFrame)
public
function EventFilter(Sender: QObjectH; Event: QEventH): Boolean; cdecl; override;
end;
TQtWSBufferPanel = class(TQtWSCustomPanel)
published
class function CreateHandle(const AWinControl: TWinControl;
const AParams: TCreateParams): TLCLHandle; override;
end;
{$IFEND}
{$IFNDEF FPC}{$IFDEF DELPHI16_UP}[ComponentPlatformsAttribute(pfidWindows)]{$ENDIF}{$ENDIF}
/// <summary>
@@ -81,6 +99,10 @@ type
FOnGdkKeyPress : TOnGdkKeyEvent;
FOnGdkKeyRelease : TOnGdkKeyEvent;
{$IFEND}
{$IF DEFINED(LCLQT) OR DEFINED(LCLQT5) OR DEFINED(LCLQT6)}
FOnQTKeyPress : TOnQTKeyPress;
FOnQTKeyRelease : TOnQTKeyRelease;
{$IFEND}
procedure CreateSyncObj;
@@ -133,7 +155,13 @@ type
function DoOnGdkKeyPress(aEvent : PGdkEventKey) : boolean; virtual;
function DoOnGdkKeyRelease(aEvent : PGdkEventKey) : boolean; virtual;
{$IFEND}
{$IF DEFINED(LCLQT) OR DEFINED(LCLQT5) OR DEFINED(LCLQT6)}
procedure DoOnQTKeyPress(Event_: QEventH); virtual;
procedure DoOnQTKeyRelease(Event_: QEventH); virtual;
{$IFEND}
{$IFDEF FPC}
class procedure WSRegisterClass; override;
{$ENDIF}
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
@@ -424,6 +452,24 @@ type
/// </remarks>
property OnGdkKeyRelease : TOnGdkKeyEvent read FOnGdkKeyRelease write FOnGdkKeyRelease;
{$IFEND}
{$IF DEFINED(LCLQT) OR DEFINED(LCLQT5) OR DEFINED(LCLQT6)}
/// <summary>
/// Event triggered when the QEventKeyPress event is received.
/// </summary>
/// <remarks>
/// <para><see href="https://doc.qt.io/qt-6/qkeyevent.html">See the QKeyEvent article.</see></para>
/// <para>This event only works in QT, QT5 and QT6 projects.</para>
/// </remarks>
property OnQTKeyPress : TOnQTKeyPress read FOnQTKeyPress write FOnQTKeyPress;
/// <summary>
/// Event triggered when the QEventKeyRelease event is received.
/// </summary>
/// <remarks>
/// <para><see href="https://doc.qt.io/qt-6/qkeyevent.html">See the QKeyEvent article.</see></para>
/// <para>This event only works in QT, QT5 and QT6 projects.</para>
/// </remarks>
property OnQTKeyRelease : TOnQTKeyRelease read FOnQTKeyRelease write FOnQTKeyRelease;
{$IFEND}
/// <summary>
/// Event triggered before the AlphaBlend call that transfer the web contents from the
/// bitmap buffer to the panel when the Transparent property is True.
@@ -557,6 +603,45 @@ uses
{$ENDIF}
uCEFMiscFunctions, uCEFApplicationCore;
{$IF DEFINED(LCLQT) OR DEFINED(LCLQT5) OR DEFINED(LCLQT6)}
class function TQtWSBufferPanel.CreateHandle(const AWinControl: TWinControl;
const AParams: TCreateParams): TLCLHandle;
var
QtFrame: TQtFrameEx;
begin
QtFrame := TQtFrameEx.Create(AWinControl, AParams);
QtFrame.AttachEvents;
// Set's initial properties
QtFrame.setFrameShape(TBorderStyleToQtFrameShapeMap[TCustomPanel(AWinControl).BorderStyle]);
QtFrame.setFocusPolicy(QtStrongFocus);
// Return the Handle
Result := TLCLHandle(QtFrame);
end;
function TQtFrameEx.EventFilter(Sender: QObjectH; Event: QEventH): Boolean; cdecl;
begin
QEvent_accept(Event);
BeginEventProcessing;
try
if (LCLObject <> nil) and
(Event <> nil) and
(Sender <> nil) and
(Sender = TheObject) then
case QEvent_type(Event) of
QEventKeyPress : TBufferPanel(LCLObject).DoOnQTKeyPress(Event);
QEventKeyRelease : TBufferPanel(LCLObject).DoOnQTKeyRelease(Event);
end;
Result := inherited EventFilter(Sender, Event);
finally
EndEventProcessing;
end;
end;
{$IFEND}
constructor TBufferPanel.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
@@ -595,12 +680,17 @@ begin
FOnIMEPreEditStart := nil;
FOnIMEPreEditEnd := nil;
FOnIMEPreEditChanged := nil;
FOnIMECommit := nil;
FOnIMECommit := nil;
ControlStyle := ControlStyle - [csNoFocus];
TabStop := True;
{$ENDIF}
{$IF DEFINED(LCLGTK2) or DEFINED(LCLGTK3)}
FOnGdkKeyPress := nil;
FOnGdkKeyRelease := nil;
ControlStyle := ControlStyle - [csNoFocus];
{$IFEND}
{$IF DEFINED(LCLQT) OR DEFINED(LCLQT5) OR DEFINED(LCLQT6)}
FOnQTKeyPress := nil;
FOnQTKeyRelease := nil;
{$IFEND}
end;
@@ -690,6 +780,27 @@ begin
end;
{$ENDIF}
{$IF DEFINED(LCLQT) OR DEFINED(LCLQT5) OR DEFINED(LCLQT6)}
procedure RegisterQtBufferPanel;
const
Done : boolean = False;
begin
if Done then exit;
RegisterWSComponent(TBufferPanel, TQtWSBufferPanel);
Done := True;
end;
{$IFEND}
{$IFDEF FPC}
class procedure TBufferPanel.WSRegisterClass;
begin
inherited WSRegisterClass;
{$IF DEFINED(LCLQT) OR DEFINED(LCLQT5) OR DEFINED(LCLQT6)}
RegisterQtBufferPanel;
{$IFEND}
end;
{$ENDIF}
procedure TBufferPanel.CreateIMEHandler;
begin
{$IFDEF MSWINDOWS}
@@ -1220,6 +1331,20 @@ begin
end;
{$IFEND}
{$IF DEFINED(LCLQT) OR DEFINED(LCLQT5) OR DEFINED(LCLQT6)}
procedure TBufferPanel.DoOnQTKeyPress(Event_: QEventH);
begin
if assigned(FOnQTKeyPress) then
FOnQTKeyPress(self, Event_);
end;
procedure TBufferPanel.DoOnQTKeyRelease(Event_: QEventH);
begin
if assigned(FOnQTKeyRelease) then
FOnQTKeyRelease(self, Event_);
end;
{$IFEND}
function TBufferPanel.GetBufferBits : pointer;
begin
if (FBuffer <> nil) and (FBuffer.Height <> 0) then

View File

@@ -15,8 +15,11 @@ uses
{$IFDEF LINUX}
{$IFDEF FPC}
ctypes, keysym, xf86keysym, x, xlib, LCLVersion,
{$IFDEF LCLGTK2}gtk2, glib2, gdk2, gtk2proc, gtk2int, Gtk2Def, gdk2x, Gtk2Extra,{$ENDIF}
{$IFDEF LCLGTK2}gtk2, glib2, gdk2, gtk2proc, gtk2int, Gtk2Def, gdk2x, Gtk2Extra,{$ENDIF}
{$IFDEF LCLGTK3}LazGdk3, LazGtk3, LazGObject2, LazGLib2, gtk3objects, gtk3procs,{$ENDIF}
{$IFDEF LCLQT}qt4,{$ENDIF}
{$IFDEF LCLQT5}qt5,{$ENDIF}
{$IFDEF LCLQT6}qt6,{$ENDIF}
{$ENDIF}
{$ENDIF}
uCEFLinuxTypes, uCEFTypes;
@@ -41,6 +44,11 @@ function GetControlCharacter(windows_key_code : integer; shift : boolean) : int
procedure GdkEventKeyToCEFKeyEvent(GdkEvent: PGdkEventKey; var aCEFKeyEvent : TCEFKeyEvent);
function GdkEventToWindowsKeyCode(Event: PGdkEventKey) : integer;
{$IFEND}
{$IF DEFINED(LCLQT) OR DEFINED(LCLQT5) OR DEFINED(LCLQT6)}
function GetCefStateModifiers(KeyboardModifiers : QtKeyboardModifiers; NativeModifiers : LongWord) : TCefEventFlags;
function GetCefWindowsKeyCode(key : QtKey) : integer;
procedure QTKeyEventToCEFKeyEvent(Event_ : QKeyEventH; var aCEFKeyEvent : TCEFKeyEvent);
{$IFEND}
{$IFDEF FMX}
type
@@ -560,7 +568,7 @@ var
windows_key_code : integer;
begin
windows_key_code := GdkEventToWindowsKeyCode(GdkEvent);
aCEFKeyEvent.size := SizeOf(TCEFKeyEvent);
aCEFKeyEvent.size := SizeOf(TCEFKeyEvent);
aCEFKeyEvent.windows_key_code := GetWindowsKeyCodeWithoutLocation(windows_key_code);
aCEFKeyEvent.native_key_code := GdkEvent^.hardware_keycode;
aCEFKeyEvent.modifiers := GetCefStateModifiers(GdkEvent^.state);
@@ -607,6 +615,132 @@ begin
end;
{$IFEND}
{$IF DEFINED(LCLQT) OR DEFINED(LCLQT5) OR DEFINED(LCLQT6)}
function GetCefStateModifiers(KeyboardModifiers : QtKeyboardModifiers; NativeModifiers : LongWord) : TCefEventFlags;
Const
GDK_SHIFT_MASK = 1 shl 0;
GDK_LOCK_MASK = 1 shl 1;
GDK_CONTROL_MASK = 1 shl 2;
GDK_MOD1_MASK = 1 shl 3;
GDK_BUTTON1_MASK = 1 shl 8;
GDK_BUTTON2_MASK = 1 shl 9;
GDK_BUTTON3_MASK = 1 shl 10;
begin
Result := EVENTFLAG_NONE;
if (KeyboardModifiers and QtShiftModifier) <> 0 then Result := Result or EVENTFLAG_SHIFT_DOWN;
if (KeyboardModifiers and QtControlModifier) <> 0 then Result := Result or EVENTFLAG_CONTROL_DOWN;
if (KeyboardModifiers and QtAltModifier) <> 0 then Result := Result or EVENTFLAG_ALT_DOWN;
if (KeyboardModifiers and QtKeypadModifier) <> 0 then Result := Result or EVENTFLAG_IS_KEY_PAD;
if (NativeModifiers and GDK_SHIFT_MASK) <> 0 then Result := Result or EVENTFLAG_SHIFT_DOWN;
if (NativeModifiers and GDK_LOCK_MASK) <> 0 then Result := Result or EVENTFLAG_CAPS_LOCK_ON;
if (NativeModifiers and GDK_CONTROL_MASK) <> 0 then Result := Result or EVENTFLAG_CONTROL_DOWN;
if (NativeModifiers and GDK_MOD1_MASK) <> 0 then Result := Result or EVENTFLAG_ALT_DOWN;
if (NativeModifiers and GDK_BUTTON1_MASK) <> 0 then Result := Result or EVENTFLAG_LEFT_MOUSE_BUTTON;
if (NativeModifiers and GDK_BUTTON2_MASK) <> 0 then Result := Result or EVENTFLAG_MIDDLE_MOUSE_BUTTON;
if (NativeModifiers and GDK_BUTTON3_MASK) <> 0 then Result := Result or EVENTFLAG_RIGHT_MOUSE_BUTTON;
end;
function GetCefWindowsKeyCode(key : QtKey): integer;
begin
case key of
QtKey_Escape : Result := VKEY_ESCAPE;
QtKey_Tab,
QtKey_Backtab : Result := VKEY_TAB;
QtKey_Backspace : Result := VKEY_BACK;
QtKey_Return,
QtKey_Enter : Result := VKEY_RETURN;
QtKey_Insert : Result := VKEY_INSERT;
QtKey_Delete : Result := VKEY_DELETE;
QtKey_Pause : Result := VKEY_PAUSE;
QtKey_Print : Result := VKEY_PRINT;
QtKey_Clear : Result := VKEY_CLEAR;
QtKey_Home : Result := VKEY_HOME;
QtKey_End : Result := VKEY_END;
QtKey_Left : Result := VKEY_LEFT;
QtKey_Up : Result := VKEY_UP;
QtKey_Right : Result := VKEY_RIGHT;
QtKey_Down : Result := VKEY_DOWN;
QtKey_PageUp : Result := VKEY_PRIOR;
QtKey_PageDown : Result := VKEY_NEXT;
QtKey_Shift : Result := VKEY_SHIFT;
QtKey_Control : Result := VKEY_CONTROL;
QtKey_Alt : Result := VKEY_MENU;
QtKey_CapsLock : Result := VKEY_CAPITAL;
QtKey_NumLock : Result := VKEY_NUMLOCK;
QtKey_ScrollLock : Result := VKEY_SCROLL;
QtKey_F1..QtKey_F24 : Result := key - QtKey_F1 + VKEY_F1;
QtKey_Help : Result := VKEY_HELP;
QtKey_Space : Result := VKEY_SPACE;
QtKey_Exclam : Result := VKEY_1;
QtKey_QuoteDbl : Result := VKEY_OEM_7;
QtKey_NumberSign : Result := VKEY_3;
QtKey_Dollar : Result := VKEY_4;
QtKey_Percent : Result := VKEY_5;
QtKey_Ampersand : Result := VKEY_7;
QtKey_Apostrophe : Result := VKEY_OEM_7;
QtKey_ParenLeft : Result := VKEY_9;
QtKey_ParenRight : Result := VKEY_0;
QtKey_Asterisk : Result := VKEY_8;
QtKey_Plus : Result := VKEY_OEM_PLUS;
QtKey_Comma : Result := VKEY_OEM_COMMA;
QtKey_Minus : Result := VKEY_OEM_MINUS;
QtKey_Period : Result := VKEY_OEM_PERIOD;
QtKey_Slash : Result := VKEY_OEM_2;
QtKey_0..QtKey_9 : Result := key;
QtKey_Colon,
QtKey_Semicolon : Result := VKEY_OEM_1;
QtKey_Less : Result := VKEY_OEM_COMMA;
QtKey_Equal : Result := VKEY_OEM_PLUS;
QtKey_Greater : Result := VKEY_OEM_PERIOD;
QtKey_Question : Result := VKEY_OEM_2;
QtKey_At : Result := VKEY_2;
QtKey_A..QtKey_Z : Result := key;
QtKey_BracketLeft : Result := VKEY_OEM_4;
QtKey_Backslash : Result := VKEY_OEM_5;
QtKey_BracketRight : Result := VKEY_OEM_6;
QtKey_AsciiCircum : Result := VKEY_6;
QtKey_Underscore : Result := VKEY_OEM_MINUS;
QtKey_QuoteLeft : Result := VKEY_OEM_3;
QtKey_BraceLeft : Result := VKEY_OEM_4;
QtKey_Bar : Result := VKEY_OEM_5;
QtKey_BraceRight : Result := VKEY_OEM_6;
QtKey_AsciiTilde : Result := VKEY_OEM_3;
QtKey_multiply : Result := VKEY_MULTIPLY;
QtKey_VolumeDown : Result := VKEY_VOLUME_DOWN;
QtKey_VolumeMute : Result := VKEY_VOLUME_MUTE;
QtKey_VolumeUp : Result := VKEY_VOLUME_UP;
QtKey_MediaPlay : Result := VKEY_MEDIA_PLAY_PAUSE;
QtKey_MediaStop : Result := VKEY_MEDIA_STOP;
QtKey_Select : Result := VKEY_SELECT;
QtKey_Printer : Result := VKEY_SNAPSHOT;
QtKey_Execute : Result := VKEY_EXECUTE;
else Result := 0;
end;
end;
procedure QTKeyEventToCEFKeyEvent(Event_: QKeyEventH; var aCEFKeyEvent : TCEFKeyEvent);
var
windows_key_code : integer;
begin
windows_key_code := GetCefWindowsKeyCode(QKeyEvent_key(Event_));
aCEFKeyEvent.size := SizeOf(TCEFKeyEvent);
aCEFKeyEvent.modifiers := GetCefStateModifiers(QKeyEvent_modifiers(Event_), QKeyEvent_nativeModifiers(Event_));
aCEFKeyEvent.windows_key_code := GetWindowsKeyCodeWithoutLocation(windows_key_code);
aCEFKeyEvent.native_key_code := QKeyEvent_nativeScanCode(Event_);
aCEFKeyEvent.is_system_key := ord((aCEFKeyEvent.modifiers and EVENTFLAG_ALT_DOWN) <> 0);
aCEFKeyEvent.unmodified_character := WideChar(QKeyEvent_nativeVirtualKey(Event_));
aCEFKeyEvent.focus_on_editable_field := ord(False);
if ((aCEFKeyEvent.modifiers and EVENTFLAG_CONTROL_DOWN) <> 0) then
aCEFKeyEvent.character := WideChar(GetControlCharacter(windows_key_code, ((aCEFKeyEvent.modifiers and EVENTFLAG_SHIFT_DOWN) <> 0)))
else
aCEFKeyEvent.character := aCEFKeyEvent.unmodified_character;
end;
{$IFEND}
{$IFDEF FMX}
function g_signal_connect(instance: gpointer; detailed_signal: Pgchar; c_handler: TGCallback; data: gpointer): gulong;
begin