From fc9d9ffdc90dd0cc4ba58a5b4b4819b4ff1429ce Mon Sep 17 00:00:00 2001 From: sekelsenmat Date: Wed, 23 Nov 2011 15:54:52 +0000 Subject: [PATCH] customdrawnws: X11: Starts implementing events. Implements OnMouseMove, form closing, OnClick git-svn-id: trunk@33728 - --- .../customdrawn/customdrawn_x11proc.pas | 19 ++- .../customdrawn/customdrawnobject_x11.inc | 74 +++------- .../customdrawn/customdrawnwsforms.pp | 18 +++ .../customdrawn/customdrawnwsforms_x11.inc | 139 ++++++++++++++++++ 4 files changed, 196 insertions(+), 54 deletions(-) diff --git a/lcl/interfaces/customdrawn/customdrawn_x11proc.pas b/lcl/interfaces/customdrawn/customdrawn_x11proc.pas index a1af8c6e02..061609a9d0 100644 --- a/lcl/interfaces/customdrawn/customdrawn_x11proc.pas +++ b/lcl/interfaces/customdrawn/customdrawn_x11proc.pas @@ -7,7 +7,7 @@ interface uses // rtl+ftl Types, Classes, SysUtils, - fpimage, fpcanvas, + fpimage, fpcanvas, ctypes, X, XLib, // Custom Drawn Canvas IntfGraphics, lazcanvas, @@ -31,7 +31,24 @@ type Canvas: TLazCanvas; end; +function XButtonToMouseButton(const XButton: cint; var MouseButton: TMouseButton): Boolean; + implementation +{ Returns True if the button is indeed a mouse button + and False if it's the mouse wheel } +function XButtonToMouseButton(const XButton: cint; var MouseButton: TMouseButton): Boolean; +const + ButtonTable: array[1..3] of TMouseButton = (mbLeft, mbMiddle, mbRight); +begin + Result := False; + + if (XButton > 3) or (XButton < 1) then Exit; + + MouseButton := ButtonTable[XButton]; + + Result := True; +end; + end. diff --git a/lcl/interfaces/customdrawn/customdrawnobject_x11.inc b/lcl/interfaces/customdrawn/customdrawnobject_x11.inc index 633ff94005..11d946cb6b 100644 --- a/lcl/interfaces/customdrawn/customdrawnobject_x11.inc +++ b/lcl/interfaces/customdrawn/customdrawnobject_x11.inc @@ -162,11 +162,11 @@ procedure TCDWidgetSet.AppRun(const ALoop: TApplicationMainLoop); var XEvent: TXEvent; WindowEntry: TWinControl; - MouseButton: TMouseButton; Sum: Integer; NewEvent: TXEvent; DoBreakRun: Boolean = False; lWindowListIndex: Integer; + CurWindowInfo: TX11WindowInfo; begin while (DoBreakRun = False) do begin @@ -182,11 +182,6 @@ begin else} XNextEvent(FDisplay, @XEvent); - // if the event filter returns true then it ate the message - //if Assigned(FEventFilter) and FEventFilter(XEvent) then continue; - - //if Forms.Count = 0 then continue; - // According to a comment in X.h, the valid event types start with 2! if XEvent._type >= 2 then begin @@ -199,7 +194,12 @@ begin Continue; end; - TX11WindowInfo(WindowList.Items[lWindowListIndex]).XEvent := @XEvent; + CurWindowInfo := TX11WindowInfo(WindowList.Items[lWindowListIndex]); + CurWindowInfo.XEvent := @XEvent; + + {$ifdef VerboseCDEvents} + DebugLn('LCL-CustomDrawn-X11: X11 event received: ', GetXEventName(XEvent._type)); + {$endif} case XEvent._type of X.DestroyNotify: @@ -208,73 +208,39 @@ begin end; X.KeyPress: begin - //TCDWSCustomForm.EvKeyPressed(WindowEntry, TX11WindowInfo(WindowList.Items[lWindowListIndex])); - //WindowEntry.EvKeyPressed(XEvent.xkey.keycode); + TCDWSCustomForm.EvKeyPressed(WindowEntry, CurWindowInfo, XEvent.xkey); end; X.KeyRelease: begin -// WindowEntry.EvKeyReleased(XEvent.xkey.keycode); + TCDWSCustomForm.EvKeyReleased(WindowEntry, CurWindowInfo, XEvent.xkey); end; X.ButtonPress: begin -{ if XButtonToMouseButton(XEvent.xbutton.button, MouseButton) then - WindowEntry.EvMousePressed(MouseButton, - Point(XEvent.xbutton.x, XEvent.xbutton.y)) - else - begin - if XEvent.xbutton.button = 4 then Sum := -1 - else Sum := 1; - - // Check for other mouse wheel messages in the queue - while XCheckTypedWindowEvent(GFApplication.Handle, - WindowEntry.Handle, X.ButtonPress, @NewEvent) do - begin - if NewEvent.xbutton.Button = 4 then Dec(Sum) - else if NewEvent.xbutton.Button = 5 then Inc(Sum) - else - begin - XPutBackEvent(GFApplication.Handle, @NewEvent); - break; - end; - end; - - WindowEntry.EvMouseWheel( - Sum, Point(XEvent.xbutton.x, XEvent.xbutton.y)); - end;} + TCDWSCustomForm.EvMousePressed(WindowEntry, CurWindowInfo, XEvent.xbutton); end; X.ButtonRelease: begin - { Release events are only for mouse buttons, and not mouse wheel moviments } -{ if (XEvent.xbutton.button >= 1) and (XEvent.xbutton.button <= 3) then - begin - XButtonToMouseButton(XEvent.xbutton.button, MouseButton); - - WindowEntry.EvMouseReleased( - MouseButton, - Point(XEvent.xbutton.x, XEvent.xbutton.y)); - end;} + TCDWSCustomForm.EvMouseReleased(WindowEntry, CurWindowInfo, XEvent.xbutton); end; X.EnterNotify: begin -// WindowEntry.EvMouseEnter( -// Point(XEvent.xbutton.x, XEvent.xbutton.y)); + TCDWSCustomForm.EvMouseEnter(WindowEntry, CurWindowInfo); end; X.LeaveNotify: begin -// WindowEntry.EvMouseLeave(); + TCDWSCustomForm.EvMouseLeave(WindowEntry, CurWindowInfo); end; X.MotionNotify: begin -// WindowEntry.EvMouseMove( -// Point(XEvent.xbutton.x, XEvent.xbutton.y)); + TCDWSCustomForm.EvMouseMove(WindowEntry, CurWindowInfo, XEvent.xmotion); end; X.FocusIn: begin -// WindowEntry.EvFocusIn(); + TCDWSCustomForm.EvFocusIn(WindowEntry, CurWindowInfo); end; X.FocusOut: begin -// WindowEntry.EvFocusOut(); + TCDWSCustomForm.EvFocusOut(WindowEntry, CurWindowInfo); end; X.MapNotify: begin @@ -294,22 +260,24 @@ begin For now we are just ignoring all expose messages where Count <> 0 } if XEvent.xexpose.count = 0 then begin - TCDWSCustomForm.EvPaint(WindowEntry, TX11WindowInfo(WindowList.Items[lWindowListIndex])); + TCDWSCustomForm.EvPaint(WindowEntry, CurWindowInfo); end; end; X.ConfigureNotify: begin -// WindowEntry.Dispatch(XEvent); + TCDWSCustomForm.EvConfigureNotify(WindowEntry, CurWindowInfo, XEvent.xconfigure); end; X.ClientMessage: begin -// WindowEntry.Dispatch(XEvent); + TCDWSCustomForm.EvClientMessage(WindowEntry, CurWindowInfo, XEvent.xclient); end; else DebugLn('LCL-CustomDrawn-X11: Unhandled X11 event received: ', GetXEventName(XEvent._type)); end; end; + + DoBreakRun := Application.Terminated; end; DoBreakRun := False; end; diff --git a/lcl/interfaces/customdrawn/customdrawnwsforms.pp b/lcl/interfaces/customdrawn/customdrawnwsforms.pp index cf852dd703..fe6843c47f 100644 --- a/lcl/interfaces/customdrawn/customdrawnwsforms.pp +++ b/lcl/interfaces/customdrawn/customdrawnwsforms.pp @@ -104,7 +104,25 @@ type class procedure DrawRawImageToGC_XPutImage(ARawImage: TRawImage; ADestWindowInfo: TX11WindowInfo; ADestX, ADestY, ADestWidth, ADestHeight: Integer); // Event handling + class procedure EvKeyPressed(const AWinControl: TWinControl; + AWindowInfo: TX11WindowInfo; var Event: TXKeyEvent); + class procedure EvKeyReleased(const AWinControl: TWinControl; + AWindowInfo: TX11WindowInfo; var Event: TXKeyEvent); + class procedure EvMousePressed(const AWinControl: TWinControl; AWindowInfo: TX11WindowInfo; + var Event: TXButtonEvent); + class procedure EvMouseReleased(const AWinControl: TWinControl; AWindowInfo: TX11WindowInfo; + var Event: TXButtonEvent); + class procedure EvMouseEnter(const AWinControl: TWinControl; AWindowInfo: TX11WindowInfo); + class procedure EvMouseLeave(const AWinControl: TWinControl; AWindowInfo: TX11WindowInfo); + class procedure EvMouseMove(const AWinControl: TWinControl; AWindowInfo: TX11WindowInfo; + var Event: TXMotionEvent); + class procedure EvFocusIn(const AWinControl: TWinControl; AWindowInfo: TX11WindowInfo); + class procedure EvFocusOut(const AWinControl: TWinControl; AWindowInfo: TX11WindowInfo); class procedure EvPaint(const AWinControl: TWinControl; AWindowInfo: TX11WindowInfo); + class procedure EvConfigureNotify(const AWinControl: TWinControl; AWindowInfo: TX11WindowInfo; + var Event: TXConfigureEvent); + class procedure EvClientMessage(const AWinControl: TWinControl; + AWindowInfo: TX11WindowInfo; var Event: TXClientMessageEvent); {$endif} published class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override; diff --git a/lcl/interfaces/customdrawn/customdrawnwsforms_x11.inc b/lcl/interfaces/customdrawn/customdrawnwsforms_x11.inc index d969c13acc..ac4d9b50b0 100644 --- a/lcl/interfaces/customdrawn/customdrawnwsforms_x11.inc +++ b/lcl/interfaces/customdrawn/customdrawnwsforms_x11.inc @@ -470,6 +470,101 @@ begin // XDestroyImage(Image); end; +class procedure TCDWSCustomForm.EvKeyPressed(const AWinControl: TWinControl; + AWindowInfo: TX11WindowInfo; var Event: TXKeyEvent); +{var + KeySym: TKeySym;} +begin +{ KeySym := StartComposing(FXEvent^); + + inherited EvKeyPressed(AKey); + + if (FXEvent^.xkey.state and (ControlMask or Mod1Mask)) = 0 then EndComposing;} +end; + +class procedure TCDWSCustomForm.EvKeyReleased(const AWinControl: TWinControl; + AWindowInfo: TX11WindowInfo; var Event: TXKeyEvent); +{var + KeySym: TKeySym;} +begin +{ KeySym := StartComposing(FXEvent^); + + inherited EvKeyReleased(AKey); + + // Do not call EndComposing, as this would generate duplicate KeyChar events!} +end; + +class procedure TCDWSCustomForm.EvMousePressed(const AWinControl: TWinControl; AWindowInfo: TX11WindowInfo; + var Event: TXButtonEvent); +var + MouseButton: TMouseButton; +begin + if XButtonToMouseButton(Event.button, MouseButton) then + begin + LCLSendMouseDownMsg(AWinControl, Event.x, Event.y, MouseButton, []); + end + else + begin +{ if Event.button = 4 then Sum := -1 + else Sum := 1; + + // Check for other mouse wheel messages in the queue + while XCheckTypedWindowEvent(GFApplication.Handle, + WindowEntry.Handle, X.ButtonPress, @NewEvent) do + begin + if NewEvent.xbutton.Button = 4 then Dec(Sum) + else if NewEvent.xbutton.Button = 5 then Inc(Sum) + else + begin + XPutBackEvent(GFApplication.Handle, @NewEvent); + break; + end; + end; + + WindowEntry.EvMouseWheel( + Sum, Point(XEvent.xbutton.x, XEvent.xbutton.y));} + end; +end; + +class procedure TCDWSCustomForm.EvMouseReleased(const AWinControl: TWinControl; AWindowInfo: TX11WindowInfo; + var Event: TXButtonEvent); +var + MouseButton: TMouseButton; +begin + { Release events are only for mouse buttons, and not mouse wheel moviments } + if (Event.button >= 1) and (Event.button <= 3) then + begin + XButtonToMouseButton(Event.button, MouseButton); + + LCLSendMouseUpMsg(AWinControl, Event.x, Event.y, MouseButton, []); + LCLSendClickedMsg(AWinControl); + end; +end; + +class procedure TCDWSCustomForm.EvMouseEnter(const AWinControl: TWinControl; AWindowInfo: TX11WindowInfo); +begin +end; + +class procedure TCDWSCustomForm.EvMouseLeave(const AWinControl: TWinControl; AWindowInfo: TX11WindowInfo); +begin +end; + +class procedure TCDWSCustomForm.EvMouseMove(const AWinControl: TWinControl; AWindowInfo: TX11WindowInfo; + var Event: TXMotionEvent); +begin + LCLSendMouseMoveMsg(AWinControl, Event.x, Event.y, []); +end; + +class procedure TCDWSCustomForm.EvFocusIn(const AWinControl: TWinControl; AWindowInfo: TX11WindowInfo); +begin + LCLSendActivateMsg(AWinControl, True, false); +end; + +class procedure TCDWSCustomForm.EvFocusOut(const AWinControl: TWinControl; AWindowInfo: TX11WindowInfo); +begin + LCLSendDeactivateStartMsg(AWinControl); +end; + class procedure TCDWSCustomForm.EvPaint(const AWinControl: TWinControl; AWindowInfo: TX11WindowInfo); var struct : TPaintStruct; @@ -529,6 +624,50 @@ begin {$ENDIF} end; +class procedure TCDWSCustomForm.EvConfigureNotify(const AWinControl: TWinControl; AWindowInfo: TX11WindowInfo; + var Event: TXConfigureEvent); +begin + // Remove other repeated events + //while XCheckTypedWindowEvent(CDWidget.FDisplay, AWindowInfo.Window, X.ConfigureNotify, @Event) do; + +{ // Move event + if (Event.x <> AWinControl.Left) or (Event.y <> AWinControl.Top) then + begin + LCLSendMoveMsg(AWinControl, Event.x, Event.y); + end; + // Size event + if (Event.Width <> AWinControl.Width) or (Event.Height <> AWinControl.Height) then + begin + //SIZENORMAL, SIZEICONIC, SIZEFULLSCREEN, SIZEZOOMSHOW, SIZEZOOMHIDE. + LCLSendSizeMsg(AWinControl, Event.Width, Event.Height, SIZENORMAL); +// TX11Canvas(Canvas).Resized(ClientWidth, ClientHeight); + end;} +end; + +class procedure TCDWSCustomForm.EvClientMessage(const AWinControl: TWinControl; + AWindowInfo: TX11WindowInfo; var Event: TXClientMessageEvent); +var + CanClose: Boolean; +begin + if Event.message_type = CDWidgetset.FWMProtocols then + begin + if Event.Data.l[0] = CDWidgetset.FWMDeleteWindow then + begin + // Message results : 0 - do nothing, 1 - destroy window (felipe: is this comment correct? taken from lcl-cocoa) + CanClose:=LCLSendCloseQueryMsg(AWinControl)>0; + if {CanClose} True then // CanClose is returning false -> ToDo: find out why + begin + LCLSendCloseUpMsg(AWinControl); + XDestroyWindow(CDWidgetset.FDisplay, AWinControl.Handle); + end; + end + else + DebugLn(Format('LCL-CustomDrawn-X11: Unknown client protocol message: %d', [Event.Data.l[0]])); + end + else + DebugLn(Format('LCL-CustomDrawn-X11: Unknown client message: %d', [Event.message_type])); +end; + {------------------------------------------------------------------------------ Method: TCDWSCustomForm.CreateHandle Params: None