diff --git a/demos/Lazarus_Linux_GTK3/GTKBrowser/00-Delete.bat b/demos/Lazarus_Linux_GTK3/GTKBrowser/00-Delete.bat
new file mode 100644
index 00000000..0b5ba5c8
--- /dev/null
+++ b/demos/Lazarus_Linux_GTK3/GTKBrowser/00-Delete.bat
@@ -0,0 +1,2 @@
+rmdir /S /Q lib
+rmdir /S /Q backup
diff --git a/demos/Lazarus_Linux_GTK3/GTKBrowser/GTKBrowser.lpi b/demos/Lazarus_Linux_GTK3/GTKBrowser/GTKBrowser.lpi
new file mode 100644
index 00000000..dc797ae7
--- /dev/null
+++ b/demos/Lazarus_Linux_GTK3/GTKBrowser/GTKBrowser.lpi
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
diff --git a/demos/Lazarus_Linux_GTK3/GTKBrowser/GTKBrowser.lpr b/demos/Lazarus_Linux_GTK3/GTKBrowser/GTKBrowser.lpr
new file mode 100644
index 00000000..99842777
--- /dev/null
+++ b/demos/Lazarus_Linux_GTK3/GTKBrowser/GTKBrowser.lpr
@@ -0,0 +1,24 @@
+program GTKBrowser;
+
+{$mode objfpc}{$H+}
+
+uses
+ {$IFDEF UseCThreads}
+ cthreads,
+ {$ENDIF}
+ uCEFApplication, umainwindow;
+
+begin
+ CreateGlobalCEFApp;
+
+ if StartMainProcess then
+ begin
+ MainWindow := TMainWindow.Create;
+ MainWindow.Show;
+ MainWindow.Run;
+ MainWindow.Free;
+ end;
+
+ DestroyGlobalCEFApp;
+end.
+
diff --git a/demos/Lazarus_Linux_GTK3/GTKBrowser/umainwindow.pas b/demos/Lazarus_Linux_GTK3/GTKBrowser/umainwindow.pas
new file mode 100644
index 00000000..4754d147
--- /dev/null
+++ b/demos/Lazarus_Linux_GTK3/GTKBrowser/umainwindow.pas
@@ -0,0 +1,355 @@
+unit umainwindow;
+
+{$mode ObjFPC}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, SyncObjs,
+ LazGtk3, LazGdk3, LazGObject2, LazGLib2, xlib,
+ uCEFApplication, uCEFConstants, uCEFTypes, uCEFChromium,
+ uCEFMiscFunctions, uCEFLinuxFunctions, uCEFInterfaces;
+
+type
+ TMainWindow = class
+ private
+ FCanClose : boolean;
+ FClosing : boolean;
+ FInitializing : boolean;
+ FLoading : boolean;
+ FWindow : PGtkWidget;
+ FChromium : TChromium;
+
+ function GetTitle : string;
+ function GetWidth : integer;
+ function GetHeight : integer;
+
+ procedure SetTitle(const aValue : string);
+
+ procedure DoAfterCreated;
+ procedure DoBeforeClose;
+ procedure DoCloseQuery(var aCanClose: Boolean);
+ procedure DoResize;
+
+ procedure UpdateBrowserSize(aLeft, aTop, aWidth, aHeight : integer);
+ procedure UpdateXWindowVisibility(aVisible : boolean);
+ procedure NotifyMoveOrResizeStarted;
+ procedure CloseBrowser(aForceClose : boolean);
+ procedure CreateBrowser;
+ procedure CreateWidgets;
+
+ procedure OnAfterCreated(Sender: TObject; const browser: ICefBrowser);
+ procedure OnBeforeClose(Sender: TObject; const browser: ICefBrowser);
+ procedure OnBeforePopup(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; popup_id: Integer; const targetUrl, targetFrameName: ustring; targetDisposition: TCefWindowOpenDisposition; userGesture: Boolean; const popupFeatures: TCefPopupFeatures; var windowInfo: TCefWindowInfo; var client: ICefClient; var settings: TCefBrowserSettings; var extra_info: ICefDictionaryValue; var noJavascriptAccess, Result: Boolean);
+ procedure OnOpenUrlFromTab(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; const targetUrl: ustring; targetDisposition: TCefWindowOpenDisposition; userGesture: Boolean; out Result: Boolean);
+
+ public
+ constructor Create;
+ destructor Destroy; override;
+ procedure AfterConstruction; override;
+ procedure Show;
+ procedure Run;
+
+ property Width : integer read GetWidth;
+ property Height : integer read GetHeight;
+ property Title : string read GetTitle write SetTitle;
+ end;
+
+var
+ MainWindow : TMainWindow = nil;
+
+procedure CreateGlobalCEFApp;
+function StartMainProcess: boolean;
+
+implementation
+
+var
+ MainAppEvent : TEventObject = nil;
+
+{GlobalCEFApp functions}
+{%Region}
+procedure GlobalCEFApp_OnContextInitialized();
+begin
+ MainAppEvent.SetEvent;
+end;
+
+procedure CreateGlobalCEFApp;
+begin
+ GlobalCEFApp := TCefApplication.Create;
+ GlobalCEFApp.LogFile := 'debug.log';
+ GlobalCEFApp.LogSeverity := LOGSEVERITY_INFO;
+ GlobalCEFApp.RootCache := 'RootCache';
+ GlobalCEFApp.DisableZygote := True;
+ GlobalCEFApp.SetCurrentDir := True;
+ GlobalCEFApp.MultiThreadedMessageLoop := False;
+ GlobalCEFApp.ExternalMessagePump := False;
+ GlobalCEFApp.GTKVersion := gtkVersion3;
+ GlobalCEFApp.OzonePlatform := ozpX11;
+ GlobalCEFApp.OnContextInitialized := @GlobalCEFApp_OnContextInitialized;
+end;
+
+function StartMainProcess: boolean;
+begin
+ Result := False;
+
+ if GlobalCEFApp.StartMainProcess then
+ begin
+ // Wait until the context is initialized before initializing GTK.
+ if (MainAppEvent.WaitFor(10000) = wrTimeout) then
+ CefDebugLog('CEF initialization failure!')
+ else
+ Result := True;
+ end;
+end;
+{%Endregion}
+
+{Message handlers}
+{%Region}
+function DeleteEventHandler(widget: PGtkWidget; event: PGdkEventAny): gboolean; cdecl;
+var
+ TempCanClose : boolean;
+begin
+ MainWindow.DoCloseQuery(TempCanClose);
+ Result := not(TempCanClose);
+end;
+
+function DestroyEventHandler(widget: PGtkWidget; event: PGdkEventAny): gboolean; cdecl;
+begin
+ Result := False;
+ GlobalCEFApp.QuitMessageLoop;
+end;
+
+function ShowEventHandler(Widget: PGtkWidget; Data: gPointer): gboolean; cdecl;
+begin
+ Result := False;
+ MainWindow.CreateBrowser;
+end;
+
+function ConfigureEvent(widget: PGtkWidget; event: PGdkEventConfigure): gboolean; cdecl;
+begin
+ Result := False;
+ MainWindow.DoResize;
+ MainWindow.NotifyMoveOrResizeStarted;
+end;
+
+function CustomX11ErrorHandler(Display: PDisplay; ErrorEv: PXErrorEvent) : longint; cdecl;
+begin
+ Result := 0;
+end;
+
+function CustomXIOErrorHandler(Display: PDisplay) : longint; cdecl;
+begin
+ Result := 0;
+end;
+{%Endregion}
+
+{Public methods}
+{%Region}
+constructor TMainWindow.Create;
+begin
+ inherited Create;
+
+ FCanClose := False;
+ FClosing := False;
+ FInitializing := True;
+ FLoading := False;
+ FWindow := nil;
+ FChromium := nil;
+end;
+
+destructor TMainWindow.Destroy;
+begin
+ if (FChromium <> nil) then
+ FreeAndNil(FChromium);
+
+ inherited Destroy;
+end;
+
+procedure TMainWindow.AfterConstruction;
+begin
+ inherited AfterConstruction;
+
+ // Force Gtk to use Xwayland (in case a Wayland compositor is being used).
+ gdk_set_allowed_backends('x11');
+
+ // The Chromium sandbox requires that there only be a single thread during
+ // initialization. Therefore initialize GTK after CEF.
+ gtk_init(@argc, @argv);
+
+ // Install xlib error handlers so that the application won't be terminated
+ // on non-fatal errors. Must be done after initializing GTK.
+ XSetErrorHandler(@CustomX11ErrorHandler);
+ XSetIOErrorHandler(@CustomXIOErrorHandler);
+
+ FChromium := TChromium.Create(nil);
+ FChromium.DefaultURL := 'https://www.google.com';
+ FChromium.OnAfterCreated := @OnAfterCreated;
+ FChromium.OnBeforeClose := @OnBeforeClose;
+ FChromium.OnBeforePopup := @OnBeforePopup;
+ FChromium.OnOpenUrlFromTab := @OnOpenUrlFromTab;
+
+ CreateWidgets;
+end;
+
+procedure TMainWindow.Show;
+begin
+ // Show the GTK window.
+ UseDefaultX11VisualForGtk(FWindow);
+ gtk_widget_show_all(FWindow);
+
+ // Flush the display to make sure the underlying X11 window gets created
+ // immediately.
+ FlushDisplay(FWindow);
+end;
+
+procedure TMainWindow.Run;
+begin
+ GlobalCEFApp.RunMessageLoop;
+end;
+{%Endregion}
+
+{Property setters and getters}
+{%Region}
+function TMainWindow.GetTitle: string;
+begin
+ Result := gtk_window_get_title(PGtkWindow(FWindow));
+end;
+
+function TMainWindow.GetWidth : integer;
+begin
+ Result := gtk_widget_get_allocated_width(FWindow);
+end;
+
+function TMainWindow.GetHeight : integer;
+begin
+ Result := gtk_widget_get_allocated_height(FWindow);
+end;
+
+procedure TMainWindow.SetTitle(const aValue : string);
+begin
+ gtk_window_set_title(PGtkWindow(FWindow), PGChar(aValue));
+end;
+{%Endregion}
+
+{Chromium events}
+{%Region}
+procedure TMainWindow.OnAfterCreated(Sender: TObject; const browser: ICefBrowser);
+begin
+ TThread.Synchronize(nil, @DoAfterCreated);
+end;
+
+procedure TMainWindow.OnBeforeClose(Sender: TObject; const browser: ICefBrowser);
+begin
+ FCanClose := True;
+ TThread.Synchronize(nil, @DoBeforeClose);
+end;
+
+procedure TMainWindow.OnBeforePopup(Sender: TObject;
+ const browser: ICefBrowser; const frame: ICefFrame; popup_id: Integer;
+ const targetUrl, targetFrameName: ustring; targetDisposition: TCefWindowOpenDisposition;
+ userGesture: Boolean; const popupFeatures: TCefPopupFeatures;
+ var windowInfo: TCefWindowInfo; var client: ICefClient;
+ var settings: TCefBrowserSettings; var extra_info: ICefDictionaryValue;
+ var noJavascriptAccess, Result: Boolean);
+begin
+ // For simplicity, this demo blocks all popup windows and new tabs
+ Result := (targetDisposition in [CEF_WOD_NEW_FOREGROUND_TAB, CEF_WOD_NEW_BACKGROUND_TAB, CEF_WOD_NEW_POPUP, CEF_WOD_NEW_WINDOW]);
+end;
+
+procedure TMainWindow.OnOpenUrlFromTab(Sender: TObject;
+ const browser: ICefBrowser; const frame: ICefFrame;
+ const targetUrl: ustring; targetDisposition: TCefWindowOpenDisposition;
+ userGesture: Boolean; out Result: Boolean);
+begin
+ // For simplicity, this demo blocks all popup windows and new tabs
+ Result := (targetDisposition in [CEF_WOD_NEW_FOREGROUND_TAB, CEF_WOD_NEW_BACKGROUND_TAB, CEF_WOD_NEW_POPUP, CEF_WOD_NEW_WINDOW]);
+end;
+{%Endregion}
+
+{Private methods}
+{%Region}
+procedure TMainWindow.UpdateBrowserSize(aLeft, aTop, aWidth, aHeight : integer);
+begin
+ if (FChromium <> nil) and FChromium.Initialized then
+ FChromium.UpdateBrowserSize(aLeft, aTop, aWidth, aHeight);
+end;
+
+procedure TMainWindow.UpdateXWindowVisibility(aVisible : boolean);
+begin
+ if (FChromium <> nil) and FChromium.Initialized then
+ FChromium.UpdateXWindowVisibility(aVisible);
+end;
+
+procedure TMainWindow.DoAfterCreated;
+begin
+ UpdateXWindowVisibility(True);
+ UpdateBrowserSize(0, 0, Width, Height);
+end;
+
+procedure TMainWindow.DoBeforeClose;
+begin
+ gtk_window_close(PGtkWindow(FWindow));
+end;
+
+procedure TMainWindow.DoResize;
+begin
+ UpdateBrowserSize(0, 0, Width, Height);
+end;
+
+procedure TMainWindow.DoCloseQuery(var aCanClose: Boolean);
+begin
+ aCanClose := FCanClose;
+
+ if not(FClosing) then
+ begin
+ FClosing := True;
+ FChromium.CloseBrowser(True);
+ end;
+end;
+
+procedure TMainWindow.CreateBrowser;
+begin
+ if (FChromium <> nil) and not(FChromium.Initialized) then
+ begin
+ if not(FChromium.CreateBrowser(TCefWindowHandle(FWindow), Rect(0, 0, Width, Height))) then
+ CefDebugLog('CreateBrowser failed');
+ end;
+end;
+
+procedure TMainWindow.CreateWidgets;
+begin
+ FWindow := gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+ gtk_window_set_default_size(PGtkWindow(FWindow), 1024, 768);
+ gtk_window_move(PGtkWindow(FWindow), 300, 200);
+
+ g_signal_connect_data(FWindow, 'delete_event', TGCallback(@DeleteEventHandler), nil, nil, G_CONNECT_DEFAULT);
+ g_signal_connect_data(FWindow, 'destroy', TGCallback(@DestroyEventHandler), nil, nil, G_CONNECT_DEFAULT);
+ g_signal_connect_data(FWindow, 'show', TGCallback(@ShowEventHandler), nil, nil, G_CONNECT_DEFAULT);
+ g_signal_connect_data(FWindow, 'configure-event', TGCallback(@ConfigureEvent), nil, nil, G_CONNECT_DEFAULT);
+
+ Title := 'GTKBrowser';
+end;
+
+procedure TMainWindow.NotifyMoveOrResizeStarted;
+begin
+ if (FChromium <> nil) then
+ FChromium.NotifyMoveOrResizeStarted;
+end;
+
+procedure TMainWindow.CloseBrowser(aForceClose : boolean);
+begin
+ if (FChromium <> nil) then
+ FChromium.CloseBrowser(aForceClose);
+end;
+{%Endregion}
+
+initialization
+ MainAppEvent := TEventObject.Create(nil, True, False, 'MainAppEvent');
+
+finalization
+ if assigned(MainAppEvent) then
+ FreeAndNil(MainAppEvent);
+
+end.
+
diff --git a/source/uCEFApplicationCore.pas b/source/uCEFApplicationCore.pas
index f8dd300c..e9ad510d 100644
--- a/source/uCEFApplicationCore.pas
+++ b/source/uCEFApplicationCore.pas
@@ -167,6 +167,7 @@ type
{$IFDEF LINUX}
FPasswordStorage : TCefPasswordStorage;
FGTKVersion : TCefGTKVersion;
+ FOzonePlatform : TCefOzonePlatform;
{$ENDIF}
@@ -1351,6 +1352,13 @@ type
/// See the LoadGtkImpl function in ui/gtk/gtk_compat.cc
///
property GTKVersion : TCefGTKVersion read FGTKVersion write FGTKVersion;
+ ///
+ /// Preferred GTK version loaded by Chromium.
+ ///
+ ///
+ /// Uses the following command line switch: --ozone-platform
+ ///
+ property OzonePlatform : TCefOzonePlatform read FOzonePlatform write FOzonePlatform;
{$ENDIF}
///
/// Ignores certificate-related errors.
@@ -2063,6 +2071,7 @@ begin
{$IFDEF LINUX}
FPasswordStorage := psDefault;
FGTKVersion := gtkVersionDefault;
+ FOzonePlatform := ozpDefault;
{$ENDIF}
// Fields used during the CEF initialization
@@ -3754,6 +3763,12 @@ begin
gtkVersion3 : ReplaceSwitch(aKeys, aValues, '--gtk-version', '3');
gtkVersion4 : ReplaceSwitch(aKeys, aValues, '--gtk-version', '4');
end;
+
+ case FOzonePlatform of
+ ozpWayland : ReplaceSwitch(aKeys, aValues, '--ozone-platform', 'wayland');
+ ozpX11 : ReplaceSwitch(aKeys, aValues, '--ozone-platform', 'x11');
+ ozpHeadless : ReplaceSwitch(aKeys, aValues, '--ozone-platform', 'headless');
+ end;
{$ENDIF}
// The list of features you can enable is here :
diff --git a/source/uCEFLinuxFunctions.pas b/source/uCEFLinuxFunctions.pas
index 07caeecd..3373ca05 100644
--- a/source/uCEFLinuxFunctions.pas
+++ b/source/uCEFLinuxFunctions.pas
@@ -62,6 +62,13 @@ function gdk_screen_get_resolution(screen:PGdkScreen):gdouble; cdecl; external '
function gdk_x11_window_get_xid(window: PGdkWindow): TXID; cdecl; external 'libgdk-3.so.0';
function gdk_x11_get_default_xdisplay: PDisplay; cdecl; external 'libgdk-3.so.0';
procedure gdk_set_allowed_backends(const backends: PGchar); cdecl; external 'libgdk-3.so.0';
+function gdk_x11_display_get_xdisplay(display: PGdkDisplay): PDisplay; cdecl; external 'libgdk-3.so.0';
+function gdk_x11_screen_get_screen_number(screen: PGdkScreen): longint; cdecl; external 'libgdk-3.so.0';
+function gdk_x11_visual_get_xvisual(visual: PGdkVisual): PVisual; cdecl; external 'libgdk-3.so.0';
+procedure UseDefaultX11VisualForGtk(widget : PGtkWidget); overload;
+procedure UseDefaultX11VisualForGtk(aHandle : TCefWindowHandle); overload;
+procedure FlushDisplay(widget : PGtkWidget); overload;
+procedure FlushDisplay(aHandle : TCefWindowHandle); overload;
{$ENDIF}
procedure ShowX11Message(const aMessage : string);
{$ENDIF}{$ENDIF}
@@ -74,6 +81,7 @@ uses
{$ELSE}
SysUtils,
{$ENDIF}
+ {$IFDEF LCLGTK3}gtk3widgets,{$ENDIF}
uCEFLinuxConstants, uCEFConstants;
{$IFDEF LINUX}
@@ -657,6 +665,96 @@ begin
XCloseDisplay(TempDisplay);
end;
-{$ENDIF}{$ENDIF}
+{$ENDIF}
+
+{$IFDEF LCLGTK3}
+procedure UseDefaultX11VisualForGtk(widget : PGtkWidget);
+type
+ PGdkX11Screen = type PGdkScreen;
+var
+ screen : PGdkScreen;
+ visuals, cursor : PGList;
+ x11_screen : PGdkX11Screen;
+ default_xvisual : PVisual;
+ visual : PGdkVisual;
+
+ function GDK_X11_VISUAL(obj : pointer) : PGdkVisual;
+ begin
+ Result := PGdkVisual(obj);
+ end;
+
+ function GDK_SCREEN_X11(obj : pointer) : PGdkX11Screen;
+ begin
+ GDK_SCREEN_X11 := PGdkX11Screen(obj);
+ end;
+
+ function GDK_SCREEN_XDISPLAY(screen : PGdkScreen) : PDisplay;
+ begin
+ GDK_SCREEN_XDISPLAY := gdk_x11_display_get_xdisplay(gdk_screen_get_display(screen));
+ end;
+
+ function GDK_SCREEN_XNUMBER(screen : PGdkScreen) : longint;
+ begin
+ GDK_SCREEN_XNUMBER := gdk_x11_screen_get_screen_number(screen);
+ end;
+
+begin
+ // GTK+ > 3.15.1 uses an X11 visual optimized for GTK+'s OpenGL stuff
+ // since revid dae447728d: https://github.com/GNOME/gtk/commit/dae447728d
+ // However, it breaks CEF: https://github.com/cztomczak/cefcapi/issues/9
+ // Let's use the default X11 visual instead of the GTK's blessed one.
+ // Copied from: https://github.com/cztomczak/cefcapi.
+ screen := gdk_screen_get_default();
+ visuals := gdk_screen_list_visuals(screen);
+ x11_screen := GDK_SCREEN_X11(screen);
+
+ if (x11_screen <> nil) then
+ begin
+ default_xvisual := DefaultVisual(GDK_SCREEN_XDISPLAY(x11_screen),
+ GDK_SCREEN_XNUMBER(x11_screen));
+
+ if (default_xvisual <> nil) then
+ begin
+ cursor := visuals;
+
+ while (cursor <> nil) do
+ begin
+ visual := GDK_X11_VISUAL(cursor^.data);
+
+ if (default_xvisual^.visualid = gdk_x11_visual_get_xvisual(visual)^.visualid) then
+ begin
+ gtk_widget_set_visual(widget, visual);
+ break;
+ end;
+
+ cursor := cursor^.next;
+ end;
+ end;
+ end;
+
+ g_list_free(visuals);
+end;
+
+procedure UseDefaultX11VisualForGtk(aHandle : TCefWindowHandle);
+begin
+ UseDefaultX11VisualForGtk(TGtk3Widget(aHandle).Widget);
+end;
+
+procedure FlushDisplay(widget : PGtkWidget);
+var
+ gdk_window : PGdkWindow;
+ display : PGdkDisplay;
+begin
+ gdk_window := gtk_widget_get_window(widget);
+ display := gdk_window_get_display(gdk_window);
+ gdk_display_flush(display);
+end;
+
+procedure FlushDisplay(aHandle : TCefWindowHandle);
+begin
+ FlushDisplay(TGtk3Widget(aHandle).Widget);
+end;
+{$ENDIF}
+{$ENDIF}
end.
diff --git a/source/uCEFTypes.pas b/source/uCEFTypes.pas
index 3bb979fb..0cac6fee 100644
--- a/source/uCEFTypes.pas
+++ b/source/uCEFTypes.pas
@@ -478,6 +478,31 @@ type
///
gtkVersion4
);
+
+ ///
+ /// Ozone platform implementation type.
+ ///
+ ///
+ /// Used by the --ozone-platform switch
+ ///
+ TCefOzonePlatform = (
+ ///
+ /// Default platform.
+ ///
+ ozpDefault,
+ ///
+ /// Wayland platform.
+ ///
+ ozpWayland,
+ ///
+ /// X11 platform.
+ ///
+ ozpX11,
+ ///
+ /// Headless platform. Not supported by CEF.
+ ///
+ ozpHeadless
+ );
{$ENDIF}
///
diff --git a/source/uCEFWindowInfoWrapper.pas b/source/uCEFWindowInfoWrapper.pas
index bdbe8d3a..22afbf26 100644
--- a/source/uCEFWindowInfoWrapper.pas
+++ b/source/uCEFWindowInfoWrapper.pas
@@ -13,9 +13,9 @@ interface
uses
{$IFDEF DELPHI16_UP}
- {$IFDEF MSWINDOWS}WinApi.Windows,{$ENDIF}System.Classes, System.Types,
+ {$IFDEF MSWINDOWS}WinApi.Windows,{$ENDIF}System.Classes, System.Types, System.SysUtils,
{$ELSE}
- {$IFDEF MSWINDOWS}Windows,{$ENDIF}Classes, Types,
+ {$IFDEF MSWINDOWS}Windows,{$ENDIF}Classes, Types, SysUtils,
{$ENDIF}
uCEFTypes;
@@ -236,7 +236,7 @@ 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, LazGLib2, gtk3widgets,{$ENDIF}
+ {$IFDEF LCLGTK3}LazGdk3, LazGtk3, LazGLib2, Gtk3Widgets, Gtk3Procs, LazGObject2,{$ENDIF}
uCEFLinuxFunctions,
{$ENDIF}{$ENDIF}
uCEFMiscFunctions;
@@ -475,6 +475,9 @@ class procedure TCEFWindowInfoWrapper.AsChild(var aWindowInfo: TCEFWindowInfo; a
{$IFDEF LINUX}
var
TempParent : TCefWindowHandle;
+ {$IFDEF LCLGTK3}
+ TempWidget : PGtkWidget;
+ {$ENDIF}
{$ENDIF}
begin
aWindowInfo.size := SizeOf(TCEFWindowInfo);
@@ -499,24 +502,34 @@ begin
{$IFDEF FPC}
{$IFDEF LCLGTK2}
- if ValidCefWindowHandle(aParent) and (PGtkWidget(aParent)^.window <> nil) then
- TempParent := gdk_window_xwindow(PGtkWidget(aParent)^.window);
+ if ValidCefWindowHandle(aParent) then
+ begin
+ // This is a translation of the GetXWindowForWidget function found in
+ // tests/cefclient/browser/browser_window_std_gtk.cc
+ // That function calls GDK_WINDOW_XID(gtk_widget_get_window(widget)) to get the TempParent value.
+
+ // /usr/include/gtk-2.0/gdk/gdkx.h defines GDK_WINDOW_XID as gdk_x11_drawable_get_xid
+ // /usr/share/lazarus/4.2.0/lcl/interfaces/gtk2/gtk2extrah.inc renames gdk_x11_drawable_get_xid as gdk_window_xwindow
+
+ // aParent is an LCL Handle which can be casted as a PGtkWidget in GTK2.
+ TempParent := gdk_window_xwindow(PGtkWidget(aParent)^.window);
+ end;
{$ENDIF}
{$IFDEF LCLGTK3}
- if ValidCefWindowHandle(aParent) and (TGtk3Widget(aParent).Widget <> nil) then
+ if ValidCefWindowHandle(aParent) then
begin
- // cefclient creates the main window with this code in root_window_gtk.cc
- // window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- // Then if populates window_info with :
- // window_info.SetAsChild(GetXWindowForWidget(parent_handle), rect);
- // GetXWindowForWidget returns this :
- // GDK_WINDOW_XID(gtk_widget_get_window(widget));
- // GDK_WINDOW_XID is a macro equivalent to gdk_x11_drawable_get_xid in gtk2 but
- // in gtk3 we use gdk_x11_window_get_xid instead.
- // LCL sets TGtk3Widget.Widget to gtk_window_new(GTK_WINDOW_TOPLEVEL) for the main form.
- // When we call TChromium.CreateBrowser with the main form as parent we get this error in the console (not in the log) :
- // [19140:19166:0604/174851.690766:ERROR:x11_software_bitmap_presenter.cc(144)] XGetWindowAttributes failed for window XXXXXXX
- TempParent := gdk_x11_window_get_xid(gtk_widget_get_window(TGtk3Widget(aParent).Widget));
+ // This is a translation of the GetXWindowForWidget function found in
+ // tests/cefclient/browser/browser_window_std_gtk.cc
+ // That function calls GDK_WINDOW_XID(gtk_widget_get_window(widget)) to get the TempParent value.
+
+ // /usr/include/gtk-3.0/gdk/x11/gdkx11window.h defines GDK_WINDOW_XID as gdk_x11_window_get_xid
+
+ if Gtk3IsWidget(PGObject(aParent)) then
+ TempWidget := PGtkWidget(aParent)
+ else
+ TempWidget := TGtk3Widget(aParent).Widget; // aParent is an LCL Handle which can be casted as a TGtk3Widget in GTK3.
+
+ TempParent := gdk_x11_window_get_xid(gtk_widget_get_window(TempWidget));
end;
{$ENDIF}
{$ENDIF}