CEF4Delphi/source/uCEFLinuxFunctions.pas
salvadordf 7f3e3415ef Added partial GTK3 support
Converted the OSRExternalPumpBrowser demo to GTK3
Converted the TinyBrowser demo to GTK3
Converted the TinyBrowser2 demo to GTK3
Moved all Lazarus demos for Linux to the Lazarus_Linux_GTK2 directory
Fixed the Copy.CEF.DLLs tool thanks to fraurino
2022-06-25 16:41:34 +02:00

659 lines
17 KiB
ObjectPascal

// ************************************************************************
// ***************************** CEF4Delphi *******************************
// ************************************************************************
//
// CEF4Delphi is based on DCEF3 which uses CEF to embed a chromium-based
// browser in Delphi applications.
//
// The original license of DCEF3 still applies to CEF4Delphi.
//
// For more information about CEF4Delphi visit :
// https://www.briskbard.com/index.php?lang=en&pageid=cef
//
// Copyright © 2022 Salvador Diaz Fau. All rights reserved.
//
// ************************************************************************
// ************ vvvv Original license and comments below vvvv *************
// ************************************************************************
(*
* Delphi Chromium Embedded 3
*
* Usage allowed under the restrictions of the Lesser GNU General Public License
* or alternatively the restrictions of the Mozilla Public License 1.1
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* Unit owner : Henri Gourvest <hgourvest@gmail.com>
* Web site : http://www.progdigy.com
* Repository : http://code.google.com/p/delphichromiumembedded/
* Group : http://groups.google.com/group/delphichromiumembedded
*
* Embarcadero Technologies, Inc is not permitted to use or redistribute
* this source code without explicit permission.
*
*)
unit uCEFLinuxFunctions;
{$IFDEF FPC}
{$MODE OBJFPC}{$H+}
{$ENDIF}
{$I cef.inc}
{$IFNDEF TARGET_64BITS}{$ALIGN ON}{$ENDIF}
{$MINENUMSIZE 4}
interface
uses
{$IFDEF LINUX}
{$IFDEF FPC}
ctypes, keysym, xf86keysym, x, xlib,
{$IFDEF LCLGTK2}gtk2, glib2, gdk2, gtk2proc, gtk2int, Gtk2Def, gdk2x, Gtk2Extra,{$ENDIF}
{$IFDEF LCLGTK3}LazGdk3, LazGtk3, LazGObject2, LazGLib2, gtk3objects, gtk3procs,{$ENDIF}
{$ENDIF}
{$ENDIF}
uCEFLinuxTypes, uCEFTypes;
{$IFDEF LINUX}
procedure GdkEventKeyToCEFKeyEvent(GdkEvent: PGdkEventKey; var aCEFKeyEvent : TCEFKeyEvent);
function KeyboardCodeFromXKeysym(keysym : uint32) : integer;
function GetCefStateModifiers(state : uint32) : integer;
function GdkEventToWindowsKeyCode(Event: PGdkEventKey) : integer;
function GetWindowsKeyCodeWithoutLocation(key_code : integer) : integer;
function GetControlCharacter(windows_key_code : integer; shift : boolean) : integer;
{$IFDEF FMX}
type
TXErrorHandler = function (para1:PDisplay; para2:PXErrorEvent):longint; cdecl;
TXIOErrorHandler = function (para1:PDisplay):longint; cdecl;
function XSetErrorHandler(para1:TXErrorHandler):TXErrorHandler; cdecl; external 'libX11.so';
function XSetIOErrorHandler(para1:TXIOErrorHandler):TXIOErrorHandler; cdecl; external 'libX11.so';
function gdk_keyval_to_unicode(keyval: guint): guint32; cdecl; external 'libgdk-3.so';
function g_signal_connect_data(instance: gpointer; detailed_signal: Pgchar; c_handler: TGCallback; data: gpointer; destroy_data: TGClosureNotify; connect_flags: TGConnectFlags): gulong; cdecl; external 'libgobject-2.0.so';
function g_signal_connect(instance: gpointer; detailed_signal: Pgchar; c_handler: TGCallback; data: gpointer): gulong; overload;
function g_signal_connect(instance: gpointer; const detailed_signal: AnsiString; c_handler: TGCallback; data: gpointer): gulong; overload;
function gdk_screen_width:gint; cdecl; external 'libgdk-3.so';
function gdk_screen_width_mm:gint; cdecl; external 'libgdk-3.so';
function gdk_screen_get_default:PGdkScreen; cdecl; external 'libgdk-3.so';
function gdk_screen_get_resolution(screen:PGdkScreen):gdouble; cdecl; external 'libgdk-3.so';
{$ENDIF}
{$IFDEF FPC}
{$IFDEF LCLGTK3}
function gdk_x11_window_get_xid(window: PGdkWindow): TWindow; cdecl; external Gdk3_library;
function gdk_x11_get_default_xdisplay: PDisplay; cdecl; external Gdk3_library;
procedure gdk_set_allowed_backends(const backends: PGchar); cdecl; external Gdk3_library;
{$ENDIF}
procedure ShowX11Message(const aMessage : string);
{$ENDIF}{$ENDIF}
implementation
uses
{$IFDEF DELPHI16_UP}
System.SysUtils,
{$ELSE}
SysUtils,
{$ENDIF}
uCEFLinuxConstants, uCEFConstants;
{$IFDEF LINUX}
function KeyboardCodeFromXKeysym(keysym : uint32) : integer;
begin
case keysym of
XK_BackSpace:
Result := VKEY_BACK;
XK_Delete,
XK_KP_Delete:
Result := VKEY_DELETE;
XK_Tab,
XK_KP_Tab,
XK_ISO_Left_Tab,
XK_3270_BackTab:
Result := VKEY_TAB;
XK_Linefeed,
XK_Return,
XK_KP_Enter,
XK_ISO_Enter:
Result := VKEY_Return;
XK_Clear,
XK_KP_Begin:
Result := VKEY_CLEAR;
XK_KP_Space,
XK_space:
Result := VKEY_SPACE;
XK_Home,
XK_KP_Home:
Result := VKEY_HOME;
XK_End,
XK_KP_End:
Result := VKEY_END;
XK_Page_Up,
XK_KP_Page_Up:
Result := VKEY_PRIOR;
XK_Page_Down,
XK_KP_Page_Down:
Result := VKEY_NEXT;
XK_Left,
XK_KP_Left:
Result := VKEY_LEFT;
XK_Right,
XK_KP_Right:
Result := VKEY_RIGHT;
XK_Down,
XK_KP_Down:
Result := VKEY_DOWN;
XK_Up,
XK_KP_Up:
Result := VKEY_UP;
XK_Escape:
Result := VKEY_ESCAPE;
XK_Kana_Lock,
XK_Kana_Shift:
Result := VKEY_KANA;
XK_Hangul:
Result := VKEY_HANGUL;
XK_Hangul_Hanja:
Result := VKEY_HANJA;
XK_Kanji:
Result := VKEY_KANJI;
XK_Henkan:
Result := VKEY_CONVERT;
XK_Muhenkan:
Result := VKEY_NONCONVERT;
XK_Zenkaku_Hankaku:
Result := VKEY_DBE_DBCSCHAR;
XKc_A,
XK_a:
Result := VKEY_A;
XKc_B,
XK_b:
Result := VKEY_B;
XKc_C,
XK_c:
Result := VKEY_C;
XKc_D,
XK_d:
Result := VKEY_D;
XKc_E,
XK_e:
Result := VKEY_E;
XKc_F,
XK_f:
Result := VKEY_F;
XKc_G,
XK_g:
Result := VKEY_G;
XKc_H,
XK_h:
Result := VKEY_H;
XKc_I,
XK_i:
Result := VKEY_I;
XKc_J,
XK_j:
Result := VKEY_J;
XKc_K,
XK_k:
Result := VKEY_K;
XKc_L,
XK_l:
Result := VKEY_L;
XKc_M,
XK_m:
Result := VKEY_M;
XKc_N,
XK_n:
Result := VKEY_N;
XKc_O,
XK_o:
Result := VKEY_O;
XKc_P,
XK_p:
Result := VKEY_P;
XKc_Q,
XK_q:
Result := VKEY_Q;
XKc_R,
XK_r:
Result := VKEY_R;
XKc_S,
XK_s:
Result := VKEY_S;
XKc_T,
XK_t:
Result := VKEY_T;
XKc_U,
XK_u:
Result := VKEY_U;
XKc_V,
XK_v:
Result := VKEY_V;
XKc_W,
XK_w:
Result := VKEY_W;
XKc_X,
XK_x:
Result := VKEY_X;
XKc_Y,
XK_y:
Result := VKEY_Y;
XKc_Z,
XK_z:
Result := VKEY_Z;
XK_0,
XK_1,
XK_2,
XK_3,
XK_4,
XK_5,
XK_6,
XK_7,
XK_8,
XK_9:
Result := VKEY_0 + (keysym - XK_0);
XK_parenright:
Result := VKEY_0;
XK_exclam:
Result := VKEY_1;
XK_at:
Result := VKEY_2;
XK_numbersign:
Result := VKEY_3;
XK_dollar:
Result := VKEY_4;
XK_percent:
Result := VKEY_5;
XK_asciicircum:
Result := VKEY_6;
XK_ampersand:
Result := VKEY_7;
XK_asterisk:
Result := VKEY_8;
XK_parenleft:
Result := VKEY_9;
XK_KP_0,
XK_KP_1,
XK_KP_2,
XK_KP_3,
XK_KP_4,
XK_KP_5,
XK_KP_6,
XK_KP_7,
XK_KP_8,
XK_KP_9:
Result := VKEY_NUMPAD0 + (keysym - XK_KP_0);
XK_multiply,
XK_KP_Multiply:
Result := VKEY_MULTIPLY;
XK_KP_Add:
Result := VKEY_ADD;
XK_KP_Separator:
Result := VKEY_SEPARATOR;
XK_KP_Subtract:
Result := VKEY_SUBTRACT;
XK_KP_Decimal:
Result := VKEY_DECIMAL;
XK_KP_Divide:
Result := VKEY_DIVIDE;
XK_KP_Equal,
XK_equal,
XK_plus:
Result := VKEY_OEM_PLUS;
XK_comma,
XK_less:
Result := VKEY_OEM_COMMA;
XK_minus,
XK_underscore:
Result := VKEY_OEM_MINUS;
XK_greater,
XK_period:
Result := VKEY_OEM_PERIOD;
XK_colon,
XK_semicolon:
Result := VKEY_OEM_1;
XK_question,
XK_slash:
Result := VKEY_OEM_2;
XK_asciitilde,
XK_quoteleft:
Result := VKEY_OEM_3;
XK_bracketleft,
XK_braceleft:
Result := VKEY_OEM_4;
XK_backslash,
XK_bar:
Result := VKEY_OEM_5;
XK_bracketright,
XK_braceright:
Result := VKEY_OEM_6;
XK_quoteright,
XK_quotedbl:
Result := VKEY_OEM_7;
XK_ISO_Level5_Shift:
Result := VKEY_OEM_8;
XK_Shift_L,
XK_Shift_R:
Result := VKEY_SHIFT;
XK_Control_L,
XK_Control_R:
Result := VKEY_CONTROL;
XK_Meta_L,
XK_Meta_R,
XK_Alt_L,
XK_Alt_R:
Result := VKEY_MENU;
XK_ISO_Level3_Shift:
Result := VKEY_ALTGR;
XK_Multi_key:
Result := VKEY_COMPOSE;
XK_Pause:
Result := VKEY_PAUSE;
XK_Caps_Lock:
Result := VKEY_CAPITAL;
XK_Num_Lock:
Result := VKEY_NUMLOCK;
XK_Scroll_Lock:
Result := VKEY_SCROLL;
XK_Select:
Result := VKEY_SELECT;
XK_Print:
Result := VKEY_PRINT;
XK_Execute:
Result := VKEY_EXECUTE;
XK_Insert,
XK_KP_Insert:
Result := VKEY_INSERT;
XK_Help:
Result := VKEY_HELP;
XK_Super_L:
Result := VKEY_LWIN;
XK_Super_R:
Result := VKEY_RWIN;
XK_Menu:
Result := VKEY_APPS;
XK_F1,
XK_F2,
XK_F3,
XK_F4,
XK_F5,
XK_F6,
XK_F7,
XK_F8,
XK_F9,
XK_F10,
XK_F11,
XK_F12,
XK_F13,
XK_F14,
XK_F15,
XK_F16,
XK_F17,
XK_F18,
XK_F19,
XK_F20,
XK_F21,
XK_F22,
XK_F23,
XK_F24:
Result := VKEY_F1 + (keysym - XK_F1);
XK_KP_F1,
XK_KP_F2,
XK_KP_F3,
XK_KP_F4:
Result := VKEY_F1 + (keysym - XK_KP_F1);
XK_guillemotleft,
XK_guillemotright,
XK_degree,
XK_ugrave,
XKc_Ugrave,
XK_brokenbar:
Result := VKEY_OEM_102;
XF86XK_Tools:
Result := VKEY_F13;
XF86XK_Launch5:
Result := VKEY_F14;
XF86XK_Launch6:
Result := VKEY_F15;
XF86XK_Launch7:
Result := VKEY_F16;
XF86XK_Launch8:
Result := VKEY_F17;
XF86XK_Launch9:
Result := VKEY_F18;
XF86XK_Refresh,
XF86XK_History,
XF86XK_OpenURL,
XF86XK_AddFavorite,
XF86XK_Go,
XF86XK_ZoomIn,
XF86XK_ZoomOut:
Result := VKEY_UNKNOWN;
XF86XK_Back:
Result := VKEY_BROWSER_BACK;
XF86XK_Forward:
Result := VKEY_BROWSER_FORWARD;
XF86XK_Reload:
Result := VKEY_BROWSER_REFRESH;
XF86XK_Stop:
Result := VKEY_BROWSER_STOP;
XF86XK_Search:
Result := VKEY_BROWSER_SEARCH;
XF86XK_Favorites:
Result := VKEY_BROWSER_FAVORITES;
XF86XK_HomePage:
Result := VKEY_BROWSER_HOME;
XF86XK_AudioMute:
Result := VKEY_VOLUME_MUTE;
XF86XK_AudioLowerVolume:
Result := VKEY_VOLUME_DOWN;
XF86XK_AudioRaiseVolume:
Result := VKEY_VOLUME_UP;
XF86XK_AudioNext:
Result := VKEY_MEDIA_NEXT_TRACK;
XF86XK_AudioPrev:
Result := VKEY_MEDIA_PREV_TRACK;
XF86XK_AudioStop:
Result := VKEY_MEDIA_STOP;
XF86XK_AudioPlay:
Result := VKEY_MEDIA_PLAY_PAUSE;
XF86XK_Mail:
Result := VKEY_MEDIA_LAUNCH_MAIL;
XF86XK_LaunchA:
Result := VKEY_MEDIA_LAUNCH_APP1;
XF86XK_LaunchB,
XF86XK_Calculator:
Result := VKEY_MEDIA_LAUNCH_APP2;
XF86XK_WLAN:
Result := VKEY_WLAN;
XF86XK_PowerOff:
Result := VKEY_POWER;
XF86XK_MonBrightnessDown:
Result := VKEY_BRIGHTNESS_DOWN;
XF86XK_MonBrightnessUp:
Result := VKEY_BRIGHTNESS_UP;
XF86XK_KbdBrightnessDown:
Result := VKEY_KBD_BRIGHTNESS_DOWN;
XF86XK_KbdBrightnessUp:
Result := VKEY_KBD_BRIGHTNESS_UP;
else Result := VKEY_UNKNOWN;
end;
end;
function GetCefStateModifiers(state : uint32) : integer;
begin
Result := EVENTFLAG_NONE;
if ((state and GDK_SHIFT_MASK) <> 0) then
Result := Result or EVENTFLAG_SHIFT_DOWN;
if ((state and GDK_LOCK_MASK) <> 0) then
Result := Result or EVENTFLAG_CAPS_LOCK_ON;
if ((state and GDK_CONTROL_MASK) <> 0) then
Result := Result or EVENTFLAG_CONTROL_DOWN;
if ((state and GDK_MOD1_MASK) <> 0) then
Result := Result or EVENTFLAG_ALT_DOWN;
if ((state and GDK_BUTTON1_MASK) <> 0) then
Result := Result or EVENTFLAG_LEFT_MOUSE_BUTTON;
if ((state and GDK_BUTTON2_MASK) <> 0) then
Result := Result or EVENTFLAG_MIDDLE_MOUSE_BUTTON;
if ((state and GDK_BUTTON3_MASK) <> 0) then
Result := Result or EVENTFLAG_RIGHT_MOUSE_BUTTON;
end;
function GdkEventToWindowsKeyCode(event: PGdkEventKey) : integer;
var
windows_key_code, keyval : integer;
begin
windows_key_code := KeyboardCodeFromXKeysym(event^.keyval);
if (windows_key_code <> 0) then
begin
Result := windows_key_code;
exit;
end;
if (event^.hardware_keycode < length(kHardwareCodeToGDKKeyval)) then
begin
keyval := kHardwareCodeToGDKKeyval[event^.hardware_keycode];
if (keyval <> 0) then
begin
Result := KeyboardCodeFromXKeysym(keyval);
exit;
end;
end;
Result := KeyboardCodeFromXKeysym(event^.keyval);
end;
function GetWindowsKeyCodeWithoutLocation(key_code : integer) : integer;
begin
case key_code of
VKEY_LCONTROL, VKEY_RCONTROL : Result := VKEY_CONTROL;
VKEY_LSHIFT, VKEY_RSHIFT : Result := VKEY_SHIFT;
VKEY_LMENU, VKEY_RMENU : Result := VKEY_MENU;
else Result := key_code;
end;
end;
function GetControlCharacter(windows_key_code : integer; shift : boolean) : integer;
begin
if (windows_key_code >= VKEY_A) and (windows_key_code <= VKEY_Z) then
Result := windows_key_code - VKEY_A + 1
else
if shift then
case windows_key_code of
VKEY_2 : Result := 0;
VKEY_6 : Result := $1E;
VKEY_OEM_MINUS : Result := $1F;
else Result := 0;
end
else
case windows_key_code of
VKEY_OEM_4 : Result := $1B;
VKEY_OEM_5 : Result := $1C;
VKEY_OEM_6 : Result := $1D;
VKEY_RETURN : Result := $0A;
else Result := 0;
end;
end;
procedure GdkEventKeyToCEFKeyEvent(GdkEvent: PGdkEventKey; var aCEFKeyEvent : TCEFKeyEvent);
var
windows_key_code : integer;
begin
windows_key_code := GdkEventToWindowsKeyCode(GdkEvent);
aCEFKeyEvent.windows_key_code := GetWindowsKeyCodeWithoutLocation(windows_key_code);
aCEFKeyEvent.native_key_code := GdkEvent^.hardware_keycode;
aCEFKeyEvent.modifiers := GetCefStateModifiers(GdkEvent^.state);
aCEFKeyEvent.focus_on_editable_field := 0;
if (GdkEvent^.keyval >= GDK_KP_Space) and (GdkEvent^.keyval <= GDK_KP_9) then
aCEFKeyEvent.modifiers := aCEFKeyEvent.modifiers or EVENTFLAG_IS_KEY_PAD;
aCEFKeyEvent.is_system_key := ord((aCEFKeyEvent.modifiers and EVENTFLAG_ALT_DOWN) <> 0);
if (windows_key_code = VKEY_RETURN) then
aCEFKeyEvent.unmodified_character := #13
else
aCEFKeyEvent.unmodified_character := WideChar(gdk_keyval_to_unicode(GdkEvent^.keyval));
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;
{$IFDEF FMX}
function g_signal_connect(instance: gpointer; detailed_signal: Pgchar; c_handler: TGCallback; data: gpointer): gulong;
begin
Result := g_signal_connect_data(instance, detailed_signal, c_handler, data, nil, TGConnectFlags(0));
end;
function g_signal_connect(instance: gpointer; const detailed_signal: AnsiString; c_handler: TGCallback; data: gpointer): gulong;
begin
Result := g_signal_connect(instance, @detailed_signal[1], c_handler, data);
end;
{$ENDIF}
{$IFDEF FPC}
// This function is almost an identical copy of "ModalShowX11Window" available
// at https://wiki.lazarus.freepascal.org/X11
procedure ShowX11Message(const aMessage : string);
var
TempDisplay : PDisplay;
TempWindow : TWindow;
TempEvent : TXEvent;
TempMessage : PChar;
TempScreen : cint;
begin
TempMessage := PChar(trim(copy(aMessage, 1, pred(pos(#13, aMessage)))));
TempDisplay := XOpenDisplay(nil);
if (TempDisplay = nil) then
begin
WriteLn(aMessage);
exit;
end;
TempScreen := DefaultScreen(TempDisplay);
TempWindow := XCreateSimpleWindow(TempDisplay,
RootWindow(TempDisplay, TempScreen),
10, 10, 200, 100, 1,
BlackPixel(TempDisplay, TempScreen),
WhitePixel(TempDisplay, TempScreen));
XSelectInput(TempDisplay, TempWindow, ExposureMask or KeyPressMask);
XMapWindow(TempDisplay, TempWindow);
while (True) do
begin
XNextEvent(TempDisplay, @TempEvent);
if (TempEvent._type = Expose) then
XDrawString(TempDisplay,
TempWindow,
DefaultGC(TempDisplay, TempScreen),
40, 50,
TempMessage,
strlen(TempMessage));
if (TempEvent._type = KeyPress) then Break;
end;
XCloseDisplay(TempDisplay);
end;
{$ENDIF}{$ENDIF}
end.