1
0
mirror of https://github.com/salvadordf/CEF4Delphi.git synced 2025-06-12 22:07:39 +02:00

FireMonkey support added

- New Delphi package called CEF4Delphi_FMX.dpk that includes VCL and FMX components.
- New FMX comopnents : TFMXChromium, TFMXBufferPanel and TFMXWorkScheduler.
- New FMX demo :  FMXExternalPumpBrowser
- Improved WorkScheduler for VCL too.
- New GlobalCEFApp.DisableWebSecurity property.
This commit is contained in:
Salvador Díaz Fau
2018-01-25 21:34:04 +01:00
parent 45b4965cb8
commit b47a8e2d52
60 changed files with 8748 additions and 719 deletions

View File

@ -52,35 +52,41 @@ uses
{$ELSE}
Windows, Messages, Classes, Controls, Graphics, Forms,
{$ENDIF}
uCEFTypes, uCEFInterfaces, uCEFLibFunctions, uCEFMiscFunctions, uCEFConstants;
const
TIMER_NIDEVENT = 1;
TIMER_DEPLETEWORK_CYCLES = 10;
TIMER_DEPLETEWORK_DELAY = 50;
uCEFConstants, uCEFWorkSchedulerThread;
type
TCEFWorkScheduler = class(TComponent)
protected
FCompHandle : HWND;
FThread : TCEFWorkSchedulerThread;
FDepleteWorkCycles : cardinal;
FDepleteWorkDelay : cardinal;
FTimerPending : boolean;
FIsActive : boolean;
FReentrancyDetected : boolean;
FDefaultInterval : integer;
FStopped : boolean;
{$IFDEF MSWINDOWS}
{$WARN SYMBOL_PLATFORM OFF}
FPriority : TThreadPriority;
{$WARN SYMBOL_PLATFORM ON}
{$ENDIF}
procedure WndProc(var aMessage: TMessage);
function SendCompMessage(aMsg, wParam : cardinal; lParam : integer) : boolean;
procedure CreateTimer(const delay_ms : int64);
procedure TimerTimeout;
procedure DoWork;
procedure ScheduleWork(const delay_ms : int64);
procedure DoMessageLoopWork;
function PerformMessageLoopWork : boolean;
procedure DestroyTimer;
procedure CreateThread;
procedure DestroyThread;
procedure DeallocateWindowHandle;
procedure DepleteWork;
procedure WndProc(var aMessage: TMessage);
procedure NextPulse(aInterval : integer);
procedure ScheduleWork(const delay_ms : int64);
procedure DoWork;
procedure DoMessageLoopWork;
procedure SetDefaultInterval(aValue : integer);
{$IFDEF MSWINDOWS}
{$WARN SYMBOL_PLATFORM OFF}
procedure SetPriority(aValue : TThreadPriority);
{$WARN SYMBOL_PLATFORM ON}
{$ENDIF}
procedure Thread_OnPulse(Sender : TObject);
public
constructor Create(AOwner: TComponent); override;
@ -89,11 +95,15 @@ type
procedure ScheduleMessagePumpWork(const delay_ms : int64);
procedure StopScheduler;
property IsTimerPending : boolean read FTimerPending;
published
property DepleteWorkCycles : cardinal read FDepleteWorkCycles write FDepleteWorkCycles default TIMER_DEPLETEWORK_CYCLES;
property DepleteWorkDelay : cardinal read FDepleteWorkDelay write FDepleteWorkDelay default TIMER_DEPLETEWORK_DELAY;
{$IFDEF MSWINDOWS}
{$WARN SYMBOL_PLATFORM OFF}
property Priority : TThreadPriority read FPriority write SetPriority default tpNormal;
{$WARN SYMBOL_PLATFORM ON}
{$ENDIF}
property DefaultInterval : integer read FDefaultInterval write SetDefaultInterval default CEF_TIMER_MAXDELAY;
property DepleteWorkCycles : cardinal read FDepleteWorkCycles write FDepleteWorkCycles default CEF_TIMER_DEPLETEWORK_CYCLES;
property DepleteWorkDelay : cardinal read FDepleteWorkDelay write FDepleteWorkDelay default CEF_TIMER_DEPLETEWORK_DELAY;
end;
implementation
@ -104,25 +114,29 @@ uses
{$ELSE}
SysUtils, Math,
{$ENDIF}
uCEFApplication;
uCEFMiscFunctions, uCEFApplication;
constructor TCEFWorkScheduler.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FThread := nil;
FCompHandle := 0;
FTimerPending := False;
FIsActive := False;
FReentrancyDetected := False;
FStopped := False;
FDepleteWorkCycles := TIMER_DEPLETEWORK_CYCLES;
FDepleteWorkDelay := TIMER_DEPLETEWORK_DELAY;
{$IFDEF MSWINDOWS}
{$WARN SYMBOL_PLATFORM OFF}
FPriority := tpNormal;
{$WARN SYMBOL_PLATFORM ON}
{$ENDIF}
FDefaultInterval := CEF_TIMER_MAXDELAY;
FDepleteWorkCycles := CEF_TIMER_DEPLETEWORK_CYCLES;
FDepleteWorkDelay := CEF_TIMER_DEPLETEWORK_DELAY;
end;
destructor TCEFWorkScheduler.Destroy;
begin
DestroyTimer;
DestroyThread;
DeallocateWindowHandle;
inherited Destroy;
@ -133,35 +147,49 @@ begin
inherited AfterConstruction;
if not(csDesigning in ComponentState) then
FCompHandle := AllocateHWnd(WndProc);
begin
FCompHandle := AllocateHWnd(WndProc);
CreateThread;
end;
end;
procedure TCEFWorkScheduler.CreateThread;
begin
FThread := TCEFWorkSchedulerThread.Create;
{$IFDEF MSWINDOWS}
FThread.Priority := FPriority;
{$ENDIF}
FThread.DefaultInterval := FDefaultInterval;
FThread.OnPulse := Thread_OnPulse;
{$IFDEF DELPHI8_UP}
FThread.Start;
{$ELSE}
FThread.Resume;
{$ENDIF}
end;
procedure TCEFWorkScheduler.DestroyThread;
begin
try
if (FThread <> nil) then
begin
FThread.Terminate;
FThread.NextPulse(0);
FThread.WaitFor;
FreeAndNil(FThread);
end;
except
on e : exception do
if CustomExceptionHandler('TCEFWorkScheduler.DestroyThread', e) then raise;
end;
end;
procedure TCEFWorkScheduler.WndProc(var aMessage: TMessage);
begin
case aMessage.Msg of
WM_TIMER : TimerTimeout;
CEF_PUMPHAVEWORK : ScheduleWork(aMessage.lParam);
else aMessage.Result := DefWindowProc(FCompHandle, aMessage.Msg, aMessage.WParam, aMessage.LParam);
end;
end;
function TCEFWorkScheduler.SendCompMessage(aMsg, wParam : cardinal; lParam : integer) : boolean;
begin
Result := not(FStopped) and (FCompHandle <> 0) and PostMessage(FCompHandle, aMsg, wParam, lParam);
end;
procedure TCEFWorkScheduler.CreateTimer(const delay_ms : int64);
begin
if not(FTimerPending) and
not(FStopped) and
(delay_ms > 0) and
(SetTimer(FCompHandle, TIMER_NIDEVENT, cardinal(delay_ms), nil) <> 0) then
FTimerPending := True;
end;
procedure TCEFWorkScheduler.DestroyTimer;
begin
if FTimerPending and KillTimer(FCompHandle, TIMER_NIDEVENT) then FTimerPending := False;
if (aMessage.Msg = CEF_PUMPHAVEWORK) then
ScheduleWork(aMessage.lParam)
else
aMessage.Result := DefWindowProc(FCompHandle, aMessage.Msg, aMessage.WParam, aMessage.LParam);
end;
procedure TCEFWorkScheduler.DeallocateWindowHandle;
@ -173,6 +201,27 @@ begin
end;
end;
procedure TCEFWorkScheduler.DoMessageLoopWork;
begin
if (GlobalCEFApp <> nil) then GlobalCEFApp.DoMessageLoopWork;
end;
procedure TCEFWorkScheduler.SetDefaultInterval(aValue : integer);
begin
FDefaultInterval := aValue;
if (FThread <> nil) then FThread.DefaultInterval := aValue;
end;
{$IFDEF MSWINDOWS}
{$WARN SYMBOL_PLATFORM OFF}
procedure TCEFWorkScheduler.SetPriority(aValue : TThreadPriority);
begin
FPriority := aValue;
if (FThread <> nil) then FThread.Priority := aValue;
end;
{$WARN SYMBOL_PLATFORM ON}
{$ENDIF}
procedure TCEFWorkScheduler.DepleteWork;
var
i : cardinal;
@ -189,78 +238,43 @@ end;
procedure TCEFWorkScheduler.ScheduleMessagePumpWork(const delay_ms : int64);
begin
SendCompMessage(CEF_PUMPHAVEWORK, 0, LPARAM(delay_ms));
if not(FStopped) and (FCompHandle <> 0) then
PostMessage(FCompHandle, CEF_PUMPHAVEWORK, 0, LPARAM(delay_ms));
end;
procedure TCEFWorkScheduler.StopScheduler;
begin
FStopped := True;
DestroyTimer;
NextPulse(0);
DepleteWork;
DeallocateWindowHandle;
end;
procedure TCEFWorkScheduler.TimerTimeout;
procedure TCEFWorkScheduler.Thread_OnPulse(Sender: TObject);
begin
if not(FStopped) then
begin
DestroyTimer;
DoWork;
end;
if not(FStopped) then DoMessageLoopWork;
end;
procedure TCEFWorkScheduler.DoWork;
var
TempWasReentrant : boolean;
begin
TempWasReentrant := PerformMessageLoopWork;
if TempWasReentrant then
ScheduleMessagePumpWork(0)
else
if not(IsTimerPending) then
ScheduleMessagePumpWork(CEF_TIMER_DELAY_PLACEHOLDER);
DoMessageLoopWork;
NextPulse(FDefaultInterval);
end;
procedure TCEFWorkScheduler.ScheduleWork(const delay_ms : int64);
begin
if FStopped or
((delay_ms = CEF_TIMER_DELAY_PLACEHOLDER) and IsTimerPending) then
exit;
DestroyTimer;
if (delay_ms <= 0) then
DoWork
else
if (delay_ms > CEF_TIMER_MAXDELAY) then
CreateTimer(CEF_TIMER_MAXDELAY)
else
CreateTimer(delay_ms);
end;
procedure TCEFWorkScheduler.DoMessageLoopWork;
begin
if (GlobalCEFApp <> nil) then GlobalCEFApp.DoMessageLoopWork;
end;
function TCEFWorkScheduler.PerformMessageLoopWork : boolean;
begin
Result := False;
if FIsActive then
if not(FStopped) then
begin
FReentrancyDetected := True;
exit;
if (delay_ms <= 0) then
DoWork
else
NextPulse(delay_ms);
end;
end;
FReentrancyDetected := False;
FIsActive := True;
DoMessageLoopWork;
FIsActive := False;
Result := FReentrancyDetected;
procedure TCEFWorkScheduler.NextPulse(aInterval : integer);
begin
if (FThread <> nil) then FThread.NextPulse(aInterval);
end;
end.