1
0
mirror of https://github.com/moparisthebest/Simba synced 2024-11-11 11:55:02 -05:00

Adding X Error Handling per THREAD.

git-svn-id: http://www.villavu.com/repositories/merlijn/mufasa@546 3f818213-9676-44b0-a9b4-5e4c4e03d09d
This commit is contained in:
Wizzup? 2010-02-23 17:17:50 +00:00
parent 98a669575e
commit 5bba118c09
5 changed files with 195 additions and 47 deletions

View File

@ -1191,6 +1191,11 @@ var
x, y: Integer; x, y: Integer;
begin begin
Self.Manager.GetMousePos(x, y); Self.Manager.GetMousePos(x, y);
if self.Manager.ReceivedError() then
begin
formWriteln('Our window no longer exists -> Resetting to desktop');
self.Manager.SetDesktop;
end;
StatusBar.Panels[Panel_Coords].Text := Format('(%d, %d)', [x, y]); StatusBar.Panels[Panel_Coords].Text := Format('(%d, %d)', [x, y]);
end; end;

View File

@ -85,14 +85,14 @@ var
x_root, y_root : cint; x_root, y_root : cint;
xmask : cuint; xmask : cuint;
x, y : cint; x, y : cint;
Old_Handler : TXErrorHandler; //Old_Handler : TXErrorHandler;
window_opacity: TAtom; window_opacity: TAtom;
opacity_75: culong; opacity_75: culong;
opacity_100: culong; opacity_100: culong;
begin begin
Old_Handler := XSetErrorHandler(@MufasaXErrorHandler); //Old_Handler := XSetErrorHandler(@MufasaXErrorHandler);
Result := 0; Result := 0;
@ -143,7 +143,7 @@ begin
XChangeProperty(manager.display, Result, window_opacity, XA_CARDINAL, 32, PropModeReplace, @opacity_100, 1); XChangeProperty(manager.display, Result, window_opacity, XA_CARDINAL, 32, PropModeReplace, @opacity_100, 1);
XFlush(manager.display); XFlush(manager.display);
XSetErrorHandler(Old_handler); //XSetErrorHandler(Old_handler);
end; end;
{$ELSE} {$ELSE}

View File

@ -49,6 +49,11 @@ interface
procedure ActivateClient; virtual; procedure ActivateClient; virtual;
function TargetValid: boolean; virtual; function TargetValid: boolean; virtual;
{ Sucky implementation }
function GetError: String; virtual; abstract;
function ReceivedError: Boolean; virtual; abstract;
procedure ResetError; virtual; abstract;
{ ONLY override the following methods if the target provides mouse functions, defaults to { ONLY override the following methods if the target provides mouse functions, defaults to
| raise exceptions } | raise exceptions }
procedure GetMousePosition(var x,y: integer); virtual; procedure GetMousePosition(var x,y: integer); virtual;
@ -104,6 +109,7 @@ interface
function ReturnData(xs, ys, width, height: Integer): TRetData; override; abstract; function ReturnData(xs, ys, width, height: Integer): TRetData; override; abstract;
function TargetValid: boolean; override; abstract; function TargetValid: boolean; override; abstract;
procedure ActivateClient; override; abstract; procedure ActivateClient; override; abstract;
procedure GetMousePosition(var x,y: integer); override; abstract; procedure GetMousePosition(var x,y: integer); override; abstract;
procedure MoveMouse(x,y: integer); override; abstract; procedure MoveMouse(x,y: integer); override; abstract;
@ -244,6 +250,11 @@ interface
constructor Create; constructor Create;
constructor Create(plugin_dir: string); constructor Create(plugin_dir: string);
destructor Destroy; override; destructor Destroy; override;
{ Sucky implementation }
function GetError: String;
function ReceivedError: Boolean;
procedure ResetError;
procedure SetDesktop; virtual; abstract; procedure SetDesktop; virtual; abstract;
function SetTarget(ArrPtr: PRGB32; Size: TPoint): integer; overload; function SetTarget(ArrPtr: PRGB32; Size: TPoint): integer; overload;
@ -631,6 +642,27 @@ begin
result := keymouse.GetKeyCode(c); result := keymouse.GetKeyCode(c);
end; end;
function TIOManager_Abstract.GetError: String;
begin
if keymouse.ReceivedError then
exit(keymouse.GetError);
if image.ReceivedError then
exit(image.GetError);
raise Exception.Create('TIOManager_Abstract.GetError: NO ERROR!');
exit('');
end;
function TIOManager_Abstract.ReceivedError: Boolean;
begin
exit(keymouse.ReceivedError or image.ReceivedError);
end;
procedure TIOManager_Abstract.ResetError;
begin
keymouse.ResetError;
image.ResetError;
end;
// TRUE when STOPPING. // TRUE when STOPPING.
procedure TIOManager_Abstract.SetState(val: Boolean); procedure TIOManager_Abstract.SetState(val: Boolean);
begin begin

View File

@ -26,7 +26,8 @@ unit os_linux;
interface interface
uses uses
Classes, SysUtils, mufasatypes, xlib, x, xutil, IOManager, XKeyInput, ctypes, xtest, keysym; Classes, SysUtils, mufasatypes, xlib, x, xutil, IOManager, XKeyInput, ctypes, xtest, keysym,
syncobjs;
type type
@ -48,6 +49,10 @@ interface
function ReturnData(xs, ys, width, height: Integer): TRetData; override; function ReturnData(xs, ys, width, height: Integer): TRetData; override;
procedure FreeReturnData; override; procedure FreeReturnData; override;
function GetError: String; override;
function ReceivedError: Boolean; override;
procedure ResetError; override;
function TargetValid: boolean; override; function TargetValid: boolean; override;
procedure ActivateClient; override; procedure ActivateClient; override;
procedure GetMousePosition(var x,y: integer); override; procedure GetMousePosition(var x,y: integer); override;
@ -69,6 +74,8 @@ interface
buffer: PXImage; buffer: PXImage;
dirty: Boolean; //true if image loaded dirty: Boolean; //true if image loaded
keyinput: TKeyInput; keyinput: TKeyInput;
oldXHandler: TXErrorHandler;
end; end;
TIOManager = class(TIOManager_Abstract) TIOManager = class(TIOManager_Abstract)
@ -92,19 +99,14 @@ implementation
uses GraphType, interfacebase, lcltype; uses GraphType, interfacebase, lcltype;
// Too global. { PROBLEM: .Create is called on the main thread. ErrorCS etc aren't
function MufasaXErrorHandler(para1:PDisplay; para2:PXErrorEvent):cint;cdecl; created on other threads. We will create them on the fly... }
begin; threadvar
result := 0; xerror: string;
Writeln('X Error: '); threadvar
writeln('Error code: ' + inttostr(para2^.error_code)); ErrorCS: syncobjs.TCriticalSection;
writeln('Display: ' + inttostr(LongWord(para2^.display)));
writeln('Minor code: ' + inttostr(para2^.minor_code));
writeln('Request code: ' + inttostr(para2^.request_code));
writeln('Resource ID: ' + inttostr(para2^.resourceid));
writeln('Serial: ' + inttostr(para2^.serial));
writeln('Type: ' + inttostr(para2^._type));
end;
//***implementation*** TKeyInput //***implementation*** TKeyInput
@ -120,6 +122,60 @@ implementation
//***implementation*** TWindow //***implementation*** TWindow
// Too global.
function MufasaXErrorHandler(para1:PDisplay; para2:PXErrorEvent):cint; cdecl;
begin
{ if someone understands the pascal syntax on how to define an array with
constant values, please change this to use an array }
case para2^.error_code of
1: xerror := 'BadRequest';
2: xerror := 'BadValue';
3: xerror := 'BadWindow';
4: xerror := 'BadPixmap';
5: xerror := 'BadAtom';
6: xerror := 'BadCursor';
7: xerror := 'BadFont';
8: xerror := 'BadMatch';
9: xerror := 'BadDrawable';
10: xerror := 'BadAccess';
11: xerror := 'BadAlloc';
12: xerror := 'BadColor';
13: xerror := 'BadGC';
14: xerror := 'BadIDChoice';
15: xerror := 'BadName';
16: xerror := 'BadLength';
17: xerror := 'BadImplementation';
else
xerror := 'UNKNOWN';
end;
result := 0;
Writeln('X Error: ');
writeln('Error code: ' + inttostr(para2^.error_code));
writeln('Display: ' + inttostr(LongWord(para2^.display)));
writeln('Minor code: ' + inttostr(para2^.minor_code));
writeln('Request code: ' + inttostr(para2^.request_code));
writeln('Resource ID: ' + inttostr(para2^.resourceid));
writeln('Serial: ' + inttostr(para2^.serial));
writeln('Type: ' + inttostr(para2^._type));
end;
function TWindow.GetError: String;
begin
exit(xerror);
end;
function TWindow.ReceivedError: Boolean;
begin
result := xerror <> '';
end;
procedure TWindow.ResetError;
begin
xerror := '';
end;
constructor TWindow.Create(display: PDisplay; screennum: integer; window: x.TWindow); constructor TWindow.Create(display: PDisplay; screennum: integer; window: x.TWindow);
begin begin
inherited Create; inherited Create;
@ -127,14 +183,47 @@ implementation
self.screennum:= screennum; self.screennum:= screennum;
self.window:= window; self.window:= window;
self.dirty:= false; self.dirty:= false;
self.keyinput:= TKeyInput.Create self.keyinput:= TKeyInput.Create;
xerror := '';
writeln('creating twindow');
{ XXX FIXME TODO O GOD WTF }
if not assigned(ErrorCS) then
ErrorCS := syncobjs.TCriticalSection.Create;
ErrorCS.Enter;
try
oldXHandler:=XSetErrorHandler(@MufasaXErrorHandler);
finally
ErrorCS.Leave;
end;
end; end;
destructor TWindow.Destroy; destructor TWindow.Destroy;
var
erh: TXErrorHandler;
begin begin
FreeReturnData; FreeReturnData;
keyinput.Free; keyinput.Free;
inherited Destroy;
{ XXX FIXME TODO O GOD WTF }
if not assigned(ErrorCS) then
ErrorCS := syncobjs.TCriticalSection.Create;
ErrorCS.Enter;
if self.ReceivedError then
writeln('recieved error: ' + GetError)
else
writeln('got no error');
erh := XSetErrorHandler(oldXHandler);
try
if erh <> @MufasaXErrorHandler then
XSetErrorHandler(erh);
finally
ErrorCS.Leave;
end;
inherited Destroy;
end; end;
function TWindow.GetNativeWindow: TNativeWindow; function TWindow.GetNativeWindow: TNativeWindow;
@ -144,12 +233,12 @@ implementation
procedure TWindow.GetTargetDimensions(var w, h: integer); procedure TWindow.GetTargetDimensions(var w, h: integer);
var var
Old_Handler: TXErrorHandler; // Old_Handler: TXErrorHandler;
Attrib: TXWindowAttributes; Attrib: TXWindowAttributes;
newx, newy: integer; newx, newy: integer;
childwindow: x.TWindow; childwindow: x.TWindow;
begin begin
Old_Handler := XSetErrorHandler(@MufasaXErrorHandler); //Old_Handler := XSetErrorHandler(@MufasaXErrorHandler);
if XGetWindowAttributes(display, window, @Attrib) <> 0 Then if XGetWindowAttributes(display, window, @Attrib) <> 0 Then
begin begin
{ I don't think we need this XTranslateCoordinates... :D } { I don't think we need this XTranslateCoordinates... :D }
@ -162,35 +251,38 @@ implementation
W := -1; W := -1;
H := -1; H := -1;
end; end;
XSetErrorHandler(Old_Handler); //XSetErrorHandler(Old_Handler);
end; end;
function TWindow.TargetValid: boolean; function TWindow.TargetValid: boolean;
var var
old_handler: TXErrorHandler; //old_handler: TXErrorHandler;
Attrib: TXWindowAttributes; Attrib: TXWindowAttributes;
begin begin
old_handler := XSetErrorHandler(@MufasaXErrorHandler); //old_handler := XSetErrorHandler(@MufasaXErrorHandler);
//This was in the repos, but it doesn't seem to work... //This was in the repos, but it doesn't seem to work...
//Maybe I missed something? //Maybe I missed something?
result:= XGetWindowAttributes(display, window, @Attrib) <> 0;
XSetErrorHandler(old_handler); {result:= XGetWindowAttributes(display, window, @Attrib) <> 0; }
XGetWindowAttributes(display, window, @Attrib);
result := not ReceivedError;
//XSetErrorHandler(old_handler);
end; end;
procedure TWindow.ActivateClient; procedure TWindow.ActivateClient;
var //var
Old_Handler: TXErrorHandler; //Old_Handler: TXErrorHandler;
begin begin
Old_Handler := XSetErrorHandler(@MufasaXErrorHandler); //Old_Handler := XSetErrorHandler(@MufasaXErrorHandler);
{ TODO: Check if Window is valid? } { TODO: Check if Window is valid? }
XSetInputFocus(display,window,RevertToParent,CurrentTime); XSetInputFocus(display,window,RevertToParent,CurrentTime);
XFlush(display); XFlush(display);
XSetErrorHandler(Old_Handler); //XSetErrorHandler(Old_Handler);
end; end;
function TWindow.ReturnData(xs, ys, width, height: Integer): TRetData; function TWindow.ReturnData(xs, ys, width, height: Integer): TRetData;
var var
Old_Handler: TXErrorHandler; //Old_Handler: TXErrorHandler;
w,h: integer; w,h: integer;
begin begin
GetTargetDimensions(w,h); GetTargetDimensions(w,h);
@ -200,7 +292,7 @@ implementation
raise Exception.CreateFmt('ReturnData was called again without freeing'+ raise Exception.CreateFmt('ReturnData was called again without freeing'+
' the previously used data. Do not forget to'+ ' the previously used data. Do not forget to'+
' call FreeReturnData', []); ' call FreeReturnData', []);
Old_Handler := XSetErrorHandler(@MufasaXErrorHandler); //Old_Handler := XSetErrorHandler(@MufasaXErrorHandler);
buffer := XGetImage(display, window, xs, ys, width, height, AllPlanes, ZPixmap); buffer := XGetImage(display, window, xs, ys, width, height, AllPlanes, ZPixmap);
if buffer = nil then if buffer = nil then
begin begin
@ -209,7 +301,7 @@ implementation
', ' + inttostr(width) + ', ' + inttostr(height)); ', ' + inttostr(width) + ', ' + inttostr(height));
Result.Ptr := nil; Result.Ptr := nil;
Result.IncPtrWith := 0; Result.IncPtrWith := 0;
XSetErrorHandler(Old_Handler); //XSetErrorHandler(Old_Handler);
raise Exception.CreateFMT('TMWindow.ReturnData: ReturnData: XGetImage Error', []); raise Exception.CreateFMT('TMWindow.ReturnData: ReturnData: XGetImage Error', []);
exit; exit;
end; end;
@ -217,7 +309,7 @@ implementation
Result.IncPtrWith := 0; Result.IncPtrWith := 0;
Result.RowLen := width; Result.RowLen := width;
dirty:= true; dirty:= true;
XSetErrorHandler(Old_Handler); //XSetErrorHandler(Old_Handler);
end; end;
procedure TWindow.FreeReturnData; procedure TWindow.FreeReturnData;
@ -236,32 +328,32 @@ implementation
b:integer; b:integer;
root, child: twindow; root, child: twindow;
xmask: Cardinal; xmask: Cardinal;
Old_Handler: TXErrorHandler; //Old_Handler: TXErrorHandler;
begin begin
Old_Handler := XSetErrorHandler(@MufasaXErrorHandler); //Old_Handler := XSetErrorHandler(@MufasaXErrorHandler);
XQueryPointer(display,window,@root,@child,@b,@b,@x,@y,@xmask); XQueryPointer(display,window,@root,@child,@b,@b,@x,@y,@xmask);
XSetErrorHandler(Old_Handler); //XSetErrorHandler(Old_Handler);
end; end;
procedure TWindow.MoveMouse(x,y: integer); procedure TWindow.MoveMouse(x,y: integer);
var var
Old_Handler: TXErrorHandler; //Old_Handler: TXErrorHandler;
w,h: integer; w,h: integer;
begin begin
GetTargetDimensions(w, h); GetTargetDimensions(w, h);
if (x < 0) or (y < 0) or (x > w) or (y > h) then if (x < 0) or (y < 0) or (x > w) or (y > h) then
raise Exception.CreateFmt('SetMousePos: X, Y (%d, %d) is not valid (0,0,%d,%d)', [x, y, w, h]); raise Exception.CreateFmt('SetMousePos: X, Y (%d, %d) is not valid (0,0,%d,%d)', [x, y, w, h]);
Old_Handler := XSetErrorHandler(@MufasaXErrorHandler); //Old_Handler := XSetErrorHandler(@MufasaXErrorHandler);
XWarpPointer(display, 0, window, 0, 0, 0, 0, X, Y); XWarpPointer(display, 0, window, 0, 0, 0, 0, X, Y);
XFlush(display); XFlush(display);
XSetErrorHandler(Old_Handler); //XSetErrorHandler(Old_Handler);
end; end;
procedure TWindow.HoldMouse(x,y: integer; button: TClickType); procedure TWindow.HoldMouse(x,y: integer; button: TClickType);
var var
ButtonP: cuint; ButtonP: cuint;
_isPress: cbool; _isPress: cbool;
Old_Handler: TXErrorHandler; //Old_Handler: TXErrorHandler;
begin begin
Old_Handler := XSetErrorHandler(@MufasaXErrorHandler); // Old_Handler := XSetErrorHandler(@MufasaXErrorHandler);
_isPress := cbool(1); _isPress := cbool(1);
case button of case button of
mouse_Left: ButtonP:= Button1; mouse_Left: ButtonP:= Button1;
@ -269,15 +361,15 @@ implementation
mouse_Right: ButtonP:= Button3; mouse_Right: ButtonP:= Button3;
end; end;
XTestFakeButtonEvent(display, ButtonP, _isPress, CurrentTime); XTestFakeButtonEvent(display, ButtonP, _isPress, CurrentTime);
XSetErrorHandler(Old_Handler); // XSetErrorHandler(Old_Handler);
end; end;
procedure TWindow.ReleaseMouse(x,y: integer; button: TClickType); procedure TWindow.ReleaseMouse(x,y: integer; button: TClickType);
var var
ButtonP: cuint; ButtonP: cuint;
_isPress: cbool; _isPress: cbool;
Old_Handler: TXErrorHandler; // Old_Handler: TXErrorHandler;
begin begin
Old_Handler := XSetErrorHandler(@MufasaXErrorHandler); // Old_Handler := XSetErrorHandler(@MufasaXErrorHandler);
_isPress := cbool(0); _isPress := cbool(0);
case button of case button of
mouse_Left: ButtonP:= Button1; mouse_Left: ButtonP:= Button1;
@ -285,7 +377,7 @@ implementation
mouse_Right: ButtonP:= Button3; mouse_Right: ButtonP:= Button3;
end; end;
XTestFakeButtonEvent(display, ButtonP, _isPress, CurrentTime); XTestFakeButtonEvent(display, ButtonP, _isPress, CurrentTime);
XSetErrorHandler(Old_Handler); //XSetErrorHandler(Old_Handler);
end; end;
procedure TWindow.SendString(str: string); procedure TWindow.SendString(str: string);

View File

@ -49,6 +49,10 @@ interface
function ReturnData(xs, ys, width, height: Integer): TRetData; override; function ReturnData(xs, ys, width, height: Integer): TRetData; override;
function GetColor(x,y : integer) : TColor; override; function GetColor(x,y : integer) : TColor; override;
function GetError: String; override;
function ReceivedError: Boolean; override;
procedure ResetError; override;
function TargetValid: boolean; override; function TargetValid: boolean; override;
procedure ActivateClient; override; procedure ActivateClient; override;
procedure GetMousePosition(var x,y: integer); override; procedure GetMousePosition(var x,y: integer); override;
@ -165,6 +169,21 @@ implementation
inherited Destroy; inherited Destroy;
end; end;
function TWindow.GetError: String;
begin
exit('');
end;
function TWindow.ReceivedError: Boolean;
begin
exit(false);
end;
procedure TWindow.ResetError;
begin
end;
function TWindow.GetNativeWindow: TNativeWindow; function TWindow.GetNativeWindow: TNativeWindow;
begin begin
result := handle; result := handle;