mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-15 20:39:14 +02:00
LCL-CustomDrawn-X11: Improves the timer precision, allows bigger waits when no timers are active and implements AppProcessMessages
git-svn-id: trunk@34354 -
This commit is contained in:
parent
a0e93a9f05
commit
eaab533d22
@ -193,6 +193,7 @@ type
|
|||||||
procedure AppRun(const ALoop: TApplicationMainLoop); override;
|
procedure AppRun(const ALoop: TApplicationMainLoop); override;
|
||||||
procedure AppWaitMessage; override;
|
procedure AppWaitMessage; override;
|
||||||
procedure AppProcessMessages; override;
|
procedure AppProcessMessages; override;
|
||||||
|
procedure AppProcessMessage;
|
||||||
procedure AppTerminate; override;
|
procedure AppTerminate; override;
|
||||||
procedure AppMinimize; override;
|
procedure AppMinimize; override;
|
||||||
procedure AppRestore; override;
|
procedure AppRestore; override;
|
||||||
|
@ -142,110 +142,12 @@ end;
|
|||||||
|
|
||||||
procedure TCDWidgetSet.AppRun(const ALoop: TApplicationMainLoop);
|
procedure TCDWidgetSet.AppRun(const ALoop: TApplicationMainLoop);
|
||||||
var
|
var
|
||||||
XEvent: TXEvent;
|
|
||||||
WindowEntry: TWinControl;
|
|
||||||
Sum: Integer;
|
|
||||||
NewEvent: TXEvent;
|
|
||||||
DoBreakRun: Boolean = False;
|
DoBreakRun: Boolean = False;
|
||||||
CurWindowInfo: TX11WindowInfo;
|
|
||||||
begin
|
begin
|
||||||
while (DoBreakRun = False) do
|
while (DoBreakRun = False) do
|
||||||
begin
|
begin
|
||||||
AppWaitMessage();
|
AppWaitMessage();
|
||||||
XNextEvent(FDisplay, @XEvent);
|
AppProcessMessage();
|
||||||
|
|
||||||
// According to a comment in X.h, the valid event types start with 2!
|
|
||||||
if XEvent._type >= 2 then
|
|
||||||
begin
|
|
||||||
WindowEntry := FindWindowByXID(XEvent.XAny.Window, CurWindowInfo);
|
|
||||||
|
|
||||||
if not Assigned(WindowEntry) then
|
|
||||||
begin
|
|
||||||
DebugLn('LCL-CustomDrawn-X11: Received X event "%s" for unknown window %x',
|
|
||||||
[GetXEventName(XEvent._type), PtrInt(XEvent.XAny.Window)]);
|
|
||||||
Continue;
|
|
||||||
end;
|
|
||||||
|
|
||||||
CurWindowInfo.XEvent := @XEvent;
|
|
||||||
|
|
||||||
case XEvent._type of
|
|
||||||
X.DestroyNotify:
|
|
||||||
begin
|
|
||||||
//WindowList.Delete(lWindowListIndex);
|
|
||||||
end;
|
|
||||||
X.KeyPress:
|
|
||||||
begin
|
|
||||||
TCDWSCustomForm.EvKeyPressed(WindowEntry, CurWindowInfo, XEvent.xkey);
|
|
||||||
end;
|
|
||||||
X.KeyRelease:
|
|
||||||
begin
|
|
||||||
TCDWSCustomForm.EvKeyReleased(WindowEntry, CurWindowInfo, XEvent.xkey);
|
|
||||||
end;
|
|
||||||
X.ButtonPress:
|
|
||||||
begin
|
|
||||||
TCDWSCustomForm.EvMousePressed(WindowEntry, CurWindowInfo, XEvent.xbutton);
|
|
||||||
end;
|
|
||||||
X.ButtonRelease:
|
|
||||||
begin
|
|
||||||
TCDWSCustomForm.EvMouseReleased(WindowEntry, CurWindowInfo, XEvent.xbutton);
|
|
||||||
end;
|
|
||||||
X.EnterNotify:
|
|
||||||
begin
|
|
||||||
TCDWSCustomForm.EvMouseEnter(WindowEntry, CurWindowInfo);
|
|
||||||
end;
|
|
||||||
X.LeaveNotify:
|
|
||||||
begin
|
|
||||||
TCDWSCustomForm.EvMouseLeave(WindowEntry, CurWindowInfo);
|
|
||||||
end;
|
|
||||||
X.MotionNotify:
|
|
||||||
begin
|
|
||||||
TCDWSCustomForm.EvMouseMove(WindowEntry, CurWindowInfo, XEvent.xmotion);
|
|
||||||
end;
|
|
||||||
X.FocusIn:
|
|
||||||
begin
|
|
||||||
TCDWSCustomForm.EvFocusIn(WindowEntry, CurWindowInfo);
|
|
||||||
end;
|
|
||||||
X.FocusOut:
|
|
||||||
begin
|
|
||||||
TCDWSCustomForm.EvFocusOut(WindowEntry, CurWindowInfo);
|
|
||||||
end;
|
|
||||||
X.MapNotify:
|
|
||||||
begin
|
|
||||||
// WindowEntry.EvShow();
|
|
||||||
end;
|
|
||||||
X.UnmapNotify:
|
|
||||||
begin
|
|
||||||
// WindowEntry.EvHide();
|
|
||||||
end;
|
|
||||||
X.ReparentNotify:
|
|
||||||
begin
|
|
||||||
// WindowEntry.EvCreate();
|
|
||||||
end;
|
|
||||||
X.Expose:
|
|
||||||
begin
|
|
||||||
// This repeat really helps speeding up when maximized for example
|
|
||||||
repeat
|
|
||||||
until not XCheckTypedWindowEvent(FDisplay, XEvent.xexpose.window, X.Expose, @XEvent);
|
|
||||||
// This check for count=0 is a performance tunning documented in
|
|
||||||
// http://tronche.com/gui/x/xlib/events/exposure/expose.html
|
|
||||||
if XEvent.xexpose.count = 0 then
|
|
||||||
begin
|
|
||||||
TCDWSCustomForm.EvPaint(WindowEntry, CurWindowInfo);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
X.ConfigureNotify:
|
|
||||||
begin
|
|
||||||
TCDWSCustomForm.EvConfigureNotify(WindowEntry, CurWindowInfo, XEvent.xconfigure);
|
|
||||||
end;
|
|
||||||
X.ClientMessage:
|
|
||||||
begin
|
|
||||||
TCDWSCustomForm.EvClientMessage(WindowEntry, CurWindowInfo, XEvent.xclient);
|
|
||||||
end;
|
|
||||||
else
|
|
||||||
DebugLn('LCL-CustomDrawn-X11: Unhandled X11 event received: ', GetXEventName(XEvent._type));
|
|
||||||
end;
|
|
||||||
|
|
||||||
end;
|
|
||||||
|
|
||||||
DoBreakRun := Application.Terminated;
|
DoBreakRun := Application.Terminated;
|
||||||
end;
|
end;
|
||||||
@ -364,7 +266,118 @@ end;*)
|
|||||||
------------------------------------------------------------------------------}
|
------------------------------------------------------------------------------}
|
||||||
procedure TCDWidgetSet.AppProcessMessages;
|
procedure TCDWidgetSet.AppProcessMessages;
|
||||||
begin
|
begin
|
||||||
|
while True do
|
||||||
|
begin
|
||||||
|
if XPending(FDisplay) <= 0 then Exit; // There are no more X messages to process
|
||||||
|
AppProcessMessage();
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Processes 1 X message
|
||||||
|
procedure TCDWidgetSet.AppProcessMessage;
|
||||||
|
var
|
||||||
|
XEvent: TXEvent;
|
||||||
|
WindowEntry: TWinControl;
|
||||||
|
Sum: Integer;
|
||||||
|
NewEvent: TXEvent;
|
||||||
|
CurWindowInfo: TX11WindowInfo;
|
||||||
|
begin
|
||||||
|
XNextEvent(FDisplay, @XEvent);
|
||||||
|
|
||||||
|
// According to a comment in X.h, the valid event types start with 2!
|
||||||
|
if XEvent._type >= 2 then
|
||||||
|
begin
|
||||||
|
WindowEntry := FindWindowByXID(XEvent.XAny.Window, CurWindowInfo);
|
||||||
|
|
||||||
|
if not Assigned(WindowEntry) then
|
||||||
|
begin
|
||||||
|
DebugLn('LCL-CustomDrawn-X11: Received X event "%s" for unknown window %x',
|
||||||
|
[GetXEventName(XEvent._type), PtrInt(XEvent.XAny.Window)]);
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
CurWindowInfo.XEvent := @XEvent;
|
||||||
|
|
||||||
|
case XEvent._type of
|
||||||
|
X.DestroyNotify:
|
||||||
|
begin
|
||||||
|
//WindowList.Delete(lWindowListIndex);
|
||||||
|
end;
|
||||||
|
X.KeyPress:
|
||||||
|
begin
|
||||||
|
TCDWSCustomForm.EvKeyPressed(WindowEntry, CurWindowInfo, XEvent.xkey);
|
||||||
|
end;
|
||||||
|
X.KeyRelease:
|
||||||
|
begin
|
||||||
|
TCDWSCustomForm.EvKeyReleased(WindowEntry, CurWindowInfo, XEvent.xkey);
|
||||||
|
end;
|
||||||
|
X.ButtonPress:
|
||||||
|
begin
|
||||||
|
TCDWSCustomForm.EvMousePressed(WindowEntry, CurWindowInfo, XEvent.xbutton);
|
||||||
|
end;
|
||||||
|
X.ButtonRelease:
|
||||||
|
begin
|
||||||
|
TCDWSCustomForm.EvMouseReleased(WindowEntry, CurWindowInfo, XEvent.xbutton);
|
||||||
|
end;
|
||||||
|
X.EnterNotify:
|
||||||
|
begin
|
||||||
|
TCDWSCustomForm.EvMouseEnter(WindowEntry, CurWindowInfo);
|
||||||
|
end;
|
||||||
|
X.LeaveNotify:
|
||||||
|
begin
|
||||||
|
TCDWSCustomForm.EvMouseLeave(WindowEntry, CurWindowInfo);
|
||||||
|
end;
|
||||||
|
X.MotionNotify:
|
||||||
|
begin
|
||||||
|
TCDWSCustomForm.EvMouseMove(WindowEntry, CurWindowInfo, XEvent.xmotion);
|
||||||
|
end;
|
||||||
|
X.FocusIn:
|
||||||
|
begin
|
||||||
|
TCDWSCustomForm.EvFocusIn(WindowEntry, CurWindowInfo);
|
||||||
|
end;
|
||||||
|
X.FocusOut:
|
||||||
|
begin
|
||||||
|
TCDWSCustomForm.EvFocusOut(WindowEntry, CurWindowInfo);
|
||||||
|
end;
|
||||||
|
X.MapNotify:
|
||||||
|
begin
|
||||||
|
// WindowEntry.EvShow();
|
||||||
|
end;
|
||||||
|
X.UnmapNotify:
|
||||||
|
begin
|
||||||
|
// WindowEntry.EvHide();
|
||||||
|
end;
|
||||||
|
X.ReparentNotify:
|
||||||
|
begin
|
||||||
|
// WindowEntry.EvCreate();
|
||||||
|
end;
|
||||||
|
X.Expose:
|
||||||
|
begin
|
||||||
|
// This repeat really helps speeding up when maximized for example
|
||||||
|
repeat
|
||||||
|
until not XCheckTypedWindowEvent(FDisplay, XEvent.xexpose.window, X.Expose, @XEvent);
|
||||||
|
// This check for count=0 is a performance tunning documented in
|
||||||
|
// http://tronche.com/gui/x/xlib/events/exposure/expose.html
|
||||||
|
if XEvent.xexpose.count = 0 then
|
||||||
|
begin
|
||||||
|
TCDWSCustomForm.EvPaint(WindowEntry, CurWindowInfo);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
X.ConfigureNotify:
|
||||||
|
begin
|
||||||
|
TCDWSCustomForm.EvConfigureNotify(WindowEntry, CurWindowInfo, XEvent.xconfigure);
|
||||||
|
end;
|
||||||
|
X.ClientMessage:
|
||||||
|
begin
|
||||||
|
TCDWSCustomForm.EvClientMessage(WindowEntry, CurWindowInfo, XEvent.xclient);
|
||||||
|
end;
|
||||||
|
else
|
||||||
|
DebugLn('LCL-CustomDrawn-X11: Unhandled X11 event received: ', GetXEventName(XEvent._type));
|
||||||
|
end;
|
||||||
|
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
(*
|
(*
|
||||||
procedure TWinCEWidgetSet.CheckPipeEvents;
|
procedure TWinCEWidgetSet.CheckPipeEvents;
|
||||||
var
|
var
|
||||||
@ -416,7 +429,11 @@ var
|
|||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
{$ifndef CD_X11_DISABLETIMERS}
|
{$ifndef CD_X11_DISABLETIMERS}
|
||||||
lTimeoutInterval := 50;
|
lTimeoutInterval := GetSmallestTimerInterval();
|
||||||
|
// Limit the maximum interval, even if only to process Application.OnIdle or
|
||||||
|
// for general safety
|
||||||
|
if (lTimeoutInterval <= 0) or (lTimeoutInterval >= 1000) then lTimeoutInterval := 1000;
|
||||||
|
|
||||||
while True do
|
while True do
|
||||||
begin
|
begin
|
||||||
xconnnum := XConnectionNumber(FDisplay);
|
xconnnum := XConnectionNumber(FDisplay);
|
||||||
|
@ -7,7 +7,7 @@ interface
|
|||||||
uses
|
uses
|
||||||
// rtl+ftl
|
// rtl+ftl
|
||||||
Types, Classes, SysUtils,
|
Types, Classes, SysUtils,
|
||||||
fpimage, fpcanvas,
|
fpimage, fpcanvas, Math,
|
||||||
// Custom Drawn Canvas
|
// Custom Drawn Canvas
|
||||||
IntfGraphics, lazcanvas, lazregions,
|
IntfGraphics, lazcanvas, lazregions,
|
||||||
// LCL
|
// LCL
|
||||||
@ -137,6 +137,7 @@ procedure InitTimersList();
|
|||||||
procedure AddTimer(ATimer: TCDTimer);
|
procedure AddTimer(ATimer: TCDTimer);
|
||||||
function GetTimer(AIndex: Integer): TCDTimer;
|
function GetTimer(AIndex: Integer): TCDTimer;
|
||||||
function GetTimerCount(): Integer;
|
function GetTimerCount(): Integer;
|
||||||
|
function GetSmallestTimerInterval(): Integer;
|
||||||
procedure RemoveTimer(ATimer: TCDTimer);
|
procedure RemoveTimer(ATimer: TCDTimer);
|
||||||
function FindTimerWithNativeHandle(ANativeHandle: PtrInt): TCDTimer;
|
function FindTimerWithNativeHandle(ANativeHandle: PtrInt): TCDTimer;
|
||||||
|
|
||||||
@ -619,6 +620,20 @@ begin
|
|||||||
Result := TimersList.Count;
|
Result := TimersList.Count;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function GetSmallestTimerInterval: Integer;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
lTimer: TCDTimer;
|
||||||
|
begin
|
||||||
|
Result := High(Integer);
|
||||||
|
for i := 0 to GetTimerCount()-1 do
|
||||||
|
begin
|
||||||
|
lTimer := GetTimer(i);
|
||||||
|
Result := Min(Result, lTimer.Interval);
|
||||||
|
end;
|
||||||
|
if Result = High(Integer) then Result := -1;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure RemoveTimer(ATimer: TCDTimer);
|
procedure RemoveTimer(ATimer: TCDTimer);
|
||||||
begin
|
begin
|
||||||
InitTimersList();
|
InitTimersList();
|
||||||
|
Loading…
Reference in New Issue
Block a user