mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-17 18:39:10 +02:00
carbon: fix with application event loop calling, caused by previous update.
git-svn-id: trunk@19689 -
This commit is contained in:
parent
a168077e2a
commit
84e400ca0c
@ -72,8 +72,6 @@ type
|
|||||||
FOpenEventHandlerUPP: AEEventHandlerUPP;
|
FOpenEventHandlerUPP: AEEventHandlerUPP;
|
||||||
FQuitEventHandlerUPP: AEEventHandlerUPP;
|
FQuitEventHandlerUPP: AEEventHandlerUPP;
|
||||||
|
|
||||||
FEventLoopUPP: EventHandlerUPP;
|
|
||||||
FEventLoopHandler: EventHandlerRef;
|
|
||||||
FAppLoop: TApplicationMainLoop;
|
FAppLoop: TApplicationMainLoop;
|
||||||
|
|
||||||
{$ifdef CarbonUseCocoa}
|
{$ifdef CarbonUseCocoa}
|
||||||
@ -87,9 +85,6 @@ type
|
|||||||
|
|
||||||
procedure RegisterEvents;
|
procedure RegisterEvents;
|
||||||
|
|
||||||
procedure InitMainLoop;
|
|
||||||
procedure ReleaseMainLoop;
|
|
||||||
|
|
||||||
public
|
public
|
||||||
constructor Create; override;
|
constructor Create; override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
@ -358,7 +358,7 @@ begin
|
|||||||
ReleaseDC(0, ScreenDC);
|
ReleaseDC(0, ScreenDC);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
InitMainLoop;
|
fMainEventQueue:=GetMainEventQueue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{------------------------------------------------------------------------------
|
{------------------------------------------------------------------------------
|
||||||
@ -371,12 +371,74 @@ procedure TCarbonWidgetSet.AppRun(const ALoop: TApplicationMainLoop);
|
|||||||
// rest of your application to maintain a global variable,
|
// rest of your application to maintain a global variable,
|
||||||
// gNumberOfRunningThreads, that reflects the number of threads
|
// gNumberOfRunningThreads, that reflects the number of threads
|
||||||
// that are ready to run.
|
// that are ready to run.
|
||||||
|
var
|
||||||
|
DummyEvent: EventRef;
|
||||||
|
EventSpec: EventTypeSpec;
|
||||||
|
EventLoopUPP: EventHandlerUPP;
|
||||||
|
EventLoopHandler: EventHandlerRef;
|
||||||
begin
|
begin
|
||||||
{$IFDEF VerboseObject}
|
{$IFDEF VerboseObject}
|
||||||
DebugLn('TCarbonWidgetSet.AppRun');
|
DebugLn('TCarbonWidgetSet.AppRun');
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
FAppLoop:=ALoop;
|
FAppLoop:=ALoop;
|
||||||
RunApplicationEventLoop;
|
DummyEvent := nil;
|
||||||
|
|
||||||
|
// Create a UPP for EventLoopEventHandler and QuitEventHandler
|
||||||
|
|
||||||
|
EventLoopUPP := NewEventHandlerUPP(EventHandlerProcPtr(
|
||||||
|
Pointer(@EventLoopEventHandler)));
|
||||||
|
if EventLoopUPP = nil then
|
||||||
|
RaiseGDBException('TCarbonWidgetSet.InitMainLoop no eventhandler');
|
||||||
|
|
||||||
|
// Install EventLoopEventHandler, create a dummy event and post it,
|
||||||
|
// and then call RunApplicationEventLoop. The rationale for this
|
||||||
|
// is as follows: We want to unravel RunApplicationEventLoop so
|
||||||
|
// that we can can yield to cooperative threads. In fact, the
|
||||||
|
// core code for RunApplicationEventLoop is pretty easy (you
|
||||||
|
// can see it above in EventLoopEventHandler). However, if you
|
||||||
|
// just execute this code you miss out on all the standard event
|
||||||
|
// handlers. These are relatively easy to reproduce (handling
|
||||||
|
// the quit event and so on), but doing so is a pain because
|
||||||
|
// a) it requires a bunch boilerplate code, and b) if Apple
|
||||||
|
// extends the list of standard event handlers, your application
|
||||||
|
// wouldn't benefit. So, we execute our event loop from within
|
||||||
|
// a Carbon event handler that we cause to be executed by
|
||||||
|
// explicitly posting an event to our event loop. Thus, the
|
||||||
|
// standard event handlers are installed while our event loop runs.
|
||||||
|
|
||||||
|
EventSpec := MakeEventSpec(LCLCarbonEventClass, LCLCarbonEventKindMain);
|
||||||
|
if not InstallApplicationEventHandler(EventLoopUPP, 1, @EventSpec, Self,
|
||||||
|
@EventLoopHandler) then Exit;
|
||||||
|
try
|
||||||
|
if CreateEvent(nil, EventSpec.eventClass, EventSpec.eventKind, 0,
|
||||||
|
kEventAttributeNone, DummyEvent) <> noErr
|
||||||
|
then
|
||||||
|
RaiseGDBException('TCarbonWidgetSet.InitMainLoop create first dummy event failed');
|
||||||
|
|
||||||
|
try
|
||||||
|
{if SetEventParameter(DummyEvent, MakeFourCC('Loop'),
|
||||||
|
MakeFourCC('TAML'), SizeOf(ALoop),
|
||||||
|
@ALoop) <> noErr
|
||||||
|
then
|
||||||
|
RaiseGDBException('TCarbonWidgetSet.InitMainLoop setparam to first event failed');}
|
||||||
|
|
||||||
|
//DebuglnThrea dLog('TCarbonWidgetSet.AppRun '+dbgs(GetMainEventQueue));
|
||||||
|
if PostEventToQueue(FMainEventQueue, DummyEvent,
|
||||||
|
kEventPriorityHigh) <> noErr
|
||||||
|
then
|
||||||
|
RaiseGDBException('TCarbonWidgetSet.AppRun post dummy event failed');
|
||||||
|
finally
|
||||||
|
ReleaseEvent(DummyEvent);
|
||||||
|
end;
|
||||||
|
|
||||||
|
SignalFirstAppEvent;
|
||||||
|
RunApplicationEventLoop;
|
||||||
|
|
||||||
|
finally
|
||||||
|
MacOSAll.RemoveEventHandler(EventLoopHandler);
|
||||||
|
DisposeEventHandlerUPP(EventLoopUPP);
|
||||||
|
end;
|
||||||
|
|
||||||
{$IFDEF VerboseObject}
|
{$IFDEF VerboseObject}
|
||||||
DebugLn('TCarbonWidgetSet.AppRun END');
|
DebugLn('TCarbonWidgetSet.AppRun END');
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
@ -488,7 +550,6 @@ end;
|
|||||||
------------------------------------------------------------------------------}
|
------------------------------------------------------------------------------}
|
||||||
destructor TCarbonWidgetSet.Destroy;
|
destructor TCarbonWidgetSet.Destroy;
|
||||||
begin
|
begin
|
||||||
ReleaseMainLoop;
|
|
||||||
FreeAndNil(FTimerMap);
|
FreeAndNil(FTimerMap);
|
||||||
DisposeAEEventHandlerUPP(FOpenEventHandlerUPP);
|
DisposeAEEventHandlerUPP(FOpenEventHandlerUPP);
|
||||||
DisposeAEEventHandlerUPP(FQuitEventHandlerUPP);
|
DisposeAEEventHandlerUPP(FQuitEventHandlerUPP);
|
||||||
@ -898,86 +959,6 @@ begin
|
|||||||
Self, SName, 'AEInstallEventHandler');
|
Self, SName, 'AEInstallEventHandler');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCarbonWidgetSet.InitMainLoop;
|
|
||||||
// A reimplementation of RunApplicationEventLoop that supports
|
|
||||||
// yielding time to cooperative threads. It relies on the
|
|
||||||
// rest of your application to maintain a global variable,
|
|
||||||
// gNumberOfRunningThreads, that reflects the number of threads
|
|
||||||
// that are ready to run.
|
|
||||||
var
|
|
||||||
DummyEvent: EventRef;
|
|
||||||
EventSpec: EventTypeSpec;
|
|
||||||
CurMainEventQueue: EventQueueRef;
|
|
||||||
begin
|
|
||||||
{$IFDEF VerboseObject}
|
|
||||||
DebugLn('TCarbonWidgetSet.InitMainLoop');
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
DummyEvent := nil;
|
|
||||||
|
|
||||||
// Create a UPP for EventLoopEventHandler and QuitEventHandler
|
|
||||||
|
|
||||||
FEventLoopUPP := NewEventHandlerUPP(EventHandlerProcPtr(
|
|
||||||
Pointer(@EventLoopEventHandler)));
|
|
||||||
if FEventLoopUPP = nil then
|
|
||||||
RaiseGDBException('TCarbonWidgetSet.InitMainLoop no eventhandler');
|
|
||||||
|
|
||||||
// Install EventLoopEventHandler, create a dummy event and post it,
|
|
||||||
// and then call RunApplicationEventLoop. The rationale for this
|
|
||||||
// is as follows: We want to unravel RunApplicationEventLoop so
|
|
||||||
// that we can can yield to cooperative threads. In fact, the
|
|
||||||
// core code for RunApplicationEventLoop is pretty easy (you
|
|
||||||
// can see it above in EventLoopEventHandler). However, if you
|
|
||||||
// just execute this code you miss out on all the standard event
|
|
||||||
// handlers. These are relatively easy to reproduce (handling
|
|
||||||
// the quit event and so on), but doing so is a pain because
|
|
||||||
// a) it requires a bunch boilerplate code, and b) if Apple
|
|
||||||
// extends the list of standard event handlers, your application
|
|
||||||
// wouldn't benefit. So, we execute our event loop from within
|
|
||||||
// a Carbon event handler that we cause to be executed by
|
|
||||||
// explicitly posting an event to our event loop. Thus, the
|
|
||||||
// standard event handlers are installed while our event loop runs.
|
|
||||||
|
|
||||||
EventSpec := MakeEventSpec(LCLCarbonEventClass, LCLCarbonEventKindMain);
|
|
||||||
if not InstallApplicationEventHandler(FEventLoopUPP, 1, @EventSpec, Self,
|
|
||||||
@FEventLoopHandler) then Exit;
|
|
||||||
|
|
||||||
if CreateEvent(nil, EventSpec.eventClass, EventSpec.eventKind, 0,
|
|
||||||
kEventAttributeNone, DummyEvent) <> noErr
|
|
||||||
then
|
|
||||||
RaiseGDBException('TCarbonWidgetSet.InitMainLoop create first dummy event failed');
|
|
||||||
|
|
||||||
try
|
|
||||||
{if SetEventParameter(DummyEvent, MakeFourCC('Loop'),
|
|
||||||
MakeFourCC('TAML'), SizeOf(ALoop),
|
|
||||||
@ALoop) <> noErr
|
|
||||||
then
|
|
||||||
RaiseGDBException('TCarbonWidgetSet.InitMainLoop setparam to first event failed');}
|
|
||||||
|
|
||||||
//DebuglnThrea dLog('TCarbonWidgetSet.AppRun '+dbgs(GetMainEventQueue));
|
|
||||||
CurMainEventQueue:=GetMainEventQueue;
|
|
||||||
if PostEventToQueue(CurMainEventQueue, DummyEvent,
|
|
||||||
kEventPriorityHigh) <> noErr
|
|
||||||
then
|
|
||||||
RaiseGDBException('TCarbonWidgetSet.AppRun post dummy event failed');
|
|
||||||
finally
|
|
||||||
ReleaseEvent(DummyEvent);
|
|
||||||
end;
|
|
||||||
|
|
||||||
fMainEventQueue:=CurMainEventQueue;
|
|
||||||
SignalFirstAppEvent;
|
|
||||||
|
|
||||||
{$IFDEF VerboseObject}
|
|
||||||
DebugLn('TCarbonWidgetSet.InitMainLoop END');
|
|
||||||
{$ENDIF}
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TCarbonWidgetSet.ReleaseMainLoop;
|
|
||||||
begin
|
|
||||||
fMainEventQueue:=nil;
|
|
||||||
if Assigned(FEventLoopHandler) then MacOSAll.RemoveEventHandler(FEventLoopHandler);
|
|
||||||
if Assigned(FEventLoopUPP) then DisposeEventHandlerUPP(FEventLoopUPP);
|
|
||||||
end;
|
|
||||||
|
|
||||||
{------------------------------------------------------------------------------
|
{------------------------------------------------------------------------------
|
||||||
Method: TCarbonWidgetSet.AppTerminate
|
Method: TCarbonWidgetSet.AppTerminate
|
||||||
|
Loading…
Reference in New Issue
Block a user