mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-13 07:49:25 +02:00
Patch from Guiliano Colla for a new painting model no LCL-CustomDrawn-X11 and advances the implementation for shift states in this backend
git-svn-id: trunk@36189 -
This commit is contained in:
parent
376af23998
commit
1ad6cf828c
@ -48,10 +48,17 @@
|
||||
{$define CD_BufferControlImages} // for all wincontrols except the form
|
||||
{ $define CD_BufferFormImage} // for the form itself (excluding child wincontrols)
|
||||
|
||||
|
||||
// ==================
|
||||
// X11 options
|
||||
// ==================
|
||||
{$define CD_X11_NewNativePaint}
|
||||
|
||||
// ==================
|
||||
// Debug options
|
||||
// ==================
|
||||
{.$define VerboseCDPaintProfiler}
|
||||
{.$define VerboseCDDrawing}
|
||||
{.$define VerboseCDBitmap}
|
||||
{ $define VerboseCDForms}
|
||||
|
||||
|
@ -36,7 +36,7 @@ uses
|
||||
// Platform specific
|
||||
{$ifdef CD_Windows}Windows, customdrawn_WinProc,{$endif}
|
||||
{$ifdef CD_Cocoa}MacOSAll, CocoaAll, customdrawn_cocoaproc, CocoaGDIObjects,{$endif}
|
||||
{$ifdef CD_X11}X, XLib, XUtil, BaseUnix, customdrawn_x11proc,{$ifdef CD_UseNativeText}xft, fontconfig,{$endif}{$endif}
|
||||
{$ifdef CD_X11}X, XLib, XUtil, BaseUnix, customdrawn_x11proc, contnrs,{$ifdef CD_UseNativeText}xft, fontconfig,{$endif}{$endif}
|
||||
{$ifdef CD_Android}
|
||||
customdrawn_androidproc, jni, bitmap, log, keycodes,
|
||||
{$endif}
|
||||
@ -150,6 +150,7 @@ type
|
||||
FWMProtocols: TAtom; // Atom for "WM_PROTOCOLS"
|
||||
FWMDeleteWindow: TAtom; // Atom for "WM_DELETE_WINDOW"
|
||||
FWMHints: TAtom; // Atom for "_MOTIF_WM_HINTS"
|
||||
FWMPaint: TAtom; // Atom for "WM_PAINT"
|
||||
|
||||
// For composing character events
|
||||
ComposeBuffer: string;
|
||||
@ -159,12 +160,21 @@ type
|
||||
LastKeySym: TKeySym; // Used for KeyRelease event
|
||||
LastKey: Word; // Used for KeyRelease event
|
||||
|
||||
ShiftState: TShiftState; // Keeps ShiftState from X
|
||||
|
||||
// XConnections list
|
||||
XConnections: TFPList;
|
||||
// Windows Info List
|
||||
XWindowList: TStringList;
|
||||
|
||||
// Functions to keep track of windows needing repaint
|
||||
function CheckInvalidateWindowForX(XWIndowID: X.TWindow): Boolean;
|
||||
procedure WindowUpdated(XWIndowID: X.TWindow);
|
||||
|
||||
function FindWindowByXID(XWindowID: X.TWindow; out AWindowInfo: TX11WindowInfo): TWinControl;
|
||||
procedure AppProcessMessage;
|
||||
procedure AppProcessInvalidates;
|
||||
function XStateToLCLState(XKeyState: cuint): TShiftState;
|
||||
{$endif}
|
||||
{$ifdef CD_Android}
|
||||
CombiningAccent: Cardinal;
|
||||
@ -411,6 +421,7 @@ const
|
||||
{$ifdef CD_X11}
|
||||
const
|
||||
CDBackendNativeHandle = nhtX11TWindow;
|
||||
|
||||
{$define CD_HasNativeFormHandle}
|
||||
{$endif}
|
||||
{$ifdef CD_Cocoa}
|
||||
|
@ -132,6 +132,7 @@ function TCDWidgetSet.PromptUser(const DialogCaption : string;
|
||||
DefaultIndex : LongInt;
|
||||
EscapeResult : LongInt) : LongInt;
|
||||
begin
|
||||
Result := -1;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
@ -166,6 +167,7 @@ end;
|
||||
|
||||
procedure TCDWidgetset.ShowVirtualKeyboard();
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
//##apiwiz##eps## // Do not remove, no wizard declaration after this line
|
||||
|
@ -30,6 +30,38 @@ begin
|
||||
else CDWidgetset.XConnections.Remove(Pointer(fd));
|
||||
end;
|
||||
|
||||
function TCDWidgetSet.CheckInvalidateWindowForX(XWIndowID: X.TWindow): Boolean;
|
||||
var
|
||||
I: integer;
|
||||
AWindowInfo: TX11WindowInfo;
|
||||
begin
|
||||
Result:= False;
|
||||
for I:= 0 to XWindowList.Count -1 do begin
|
||||
AWindowInfo:= TX11WindowInfo(XWindowList.Objects[I]);
|
||||
if AWindowInfo.Window = XWIndowID then begin
|
||||
if XWindowList.Strings[I] <> 'Paint' then begin
|
||||
XWindowList.Strings[I] := 'Paint';
|
||||
Result:= True;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TCDWidgetSet.WindowUpdated(XWIndowID: X.TWindow);
|
||||
var
|
||||
I: integer;
|
||||
AWindowInfo: TX11WindowInfo;
|
||||
begin
|
||||
for I:= 0 to XWindowList.Count -1 do begin
|
||||
AWindowInfo:= TX11WindowInfo(XWindowList.Objects[I]);
|
||||
if AWindowInfo.Window = XWIndowID then begin
|
||||
XWindowList.Strings[I] := 'Done';
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCDWidgetSet.FindWindowByXID(XWindowID: X.TWindow; out AWindowInfo: TX11WindowInfo): TWinControl;
|
||||
var
|
||||
i: Integer;
|
||||
@ -80,6 +112,7 @@ begin
|
||||
ScreenDC := TLazCanvas.Create(ScreenImage);
|
||||
|
||||
XConnections := TFPList.Create;
|
||||
XWindowList := TStringList.Create;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
@ -90,8 +123,13 @@ end;
|
||||
destructor for the class.
|
||||
------------------------------------------------------------------------------}
|
||||
procedure TCDWidgetSet.BackendDestroy;
|
||||
var
|
||||
I: Integer;
|
||||
begin
|
||||
XConnections.Free;
|
||||
for I:= 0 to XWindowList.Count -1 do
|
||||
XWindowList.Objects[I].Free;
|
||||
XWindowList.Free;
|
||||
|
||||
{ Release the screen DC and Image }
|
||||
ScreenDC.Free;
|
||||
@ -303,6 +341,7 @@ end;
|
||||
procedure TCDWidgetSet.AppProcessMessage;
|
||||
var
|
||||
XEvent: TXEvent;
|
||||
XClientEvent: TXClientMessageEvent absolute XEvent ;
|
||||
WindowEntry: TWinControl;
|
||||
Sum: Integer;
|
||||
NewEvent: TXEvent;
|
||||
@ -395,7 +434,15 @@ begin
|
||||
end;
|
||||
X.ClientMessage:
|
||||
begin
|
||||
TCDWSCustomForm.EvClientMessage(WindowEntry, CurWindowInfo, XEvent.xclient);
|
||||
if XClientEvent.message_type = CDWidgetSet.FWMPaint then begin
|
||||
{$ifdef VerboseCDEvents}
|
||||
DebugLn(Format('X11 event WM_PAINT - Window %d',[CurWindowInfo.Window]));
|
||||
{$endif}
|
||||
TCDWSCustomForm.EvPaintEx(WindowEntry, CurWindowInfo);
|
||||
WindowUpdated(CurWindowInfo.Window);
|
||||
end
|
||||
else
|
||||
TCDWSCustomForm.EvClientMessage(WindowEntry, CurWindowInfo, XEvent.xclient);
|
||||
end;
|
||||
else
|
||||
DebugLn('LCL-CustomDrawn-X11: Unhandled X11 event received: ', GetXEventName(XEvent._type));
|
||||
@ -423,6 +470,15 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCDWidgetSet.XStateToLCLState(XKeyState: cuint): TShiftState;
|
||||
begin
|
||||
Result:= [];
|
||||
if (XKeyState and X.ShiftMask) <> 0 then Include(Result,ssShift);
|
||||
if (XKeyState and X.ControlMask) <> 0 then Include(Result,ssCtrl);
|
||||
if (XKeyState and X.Mod1Mask) <> 0 then Include(Result,ssAlt);
|
||||
if (XKeyState and X.Mod5Mask) <> 0 then Include(Result,ssAltGr);
|
||||
end;
|
||||
|
||||
function TCDWidgetSet.GetAppHandle: THandle;
|
||||
begin
|
||||
Result := THandle(FDisplay);
|
||||
|
@ -2861,8 +2861,9 @@ begin
|
||||
{$endif}
|
||||
end;
|
||||
end;
|
||||
*)
|
||||
|
||||
function TQtWidgetSet.GetKeyState(nVirtKey: Integer): Smallint;
|
||||
function TCDWidgetSet.GetKeyState(nVirtKey: Integer): Smallint;
|
||||
const
|
||||
StateDown = SmallInt($FF80);
|
||||
{StateToggled = SmallInt($0001);}
|
||||
@ -2871,14 +2872,16 @@ begin
|
||||
|
||||
case nVirtKey of
|
||||
VK_LSHIFT: nVirtKey := VK_SHIFT;
|
||||
VK_RSHIFT: nVirtKey := VK_SHIFT;
|
||||
VK_LCONTROL: nVirtKey := VK_CONTROL;
|
||||
VK_RCONTROL: nVirtKey := VK_CONTROL;
|
||||
VK_LMENU: nVirtKey := VK_MENU;
|
||||
end;
|
||||
|
||||
// where to track toggle state?
|
||||
|
||||
case nVirtKey of
|
||||
VK_LBUTTON:
|
||||
(* VK_LBUTTON:
|
||||
if (QApplication_mouseButtons and QtLeftButton) > 0 then
|
||||
Result := Result or StateDown;
|
||||
VK_RBUTTON:
|
||||
@ -2896,22 +2899,24 @@ begin
|
||||
VK_MENU:
|
||||
if (QApplication_keyboardModifiers and QtAltModifier) > 0 then
|
||||
Result := Result or StateDown;
|
||||
*)
|
||||
VK_SHIFT:
|
||||
if (QApplication_keyboardModifiers and QtShiftModifier) > 0 then
|
||||
if ssShift in ShiftState then
|
||||
Result := Result or StateDown;
|
||||
VK_CONTROL:
|
||||
if (QApplication_keyboardModifiers and QtControlModifier) > 0 then
|
||||
if ssCtrl in ShiftState then
|
||||
Result := Result or StateDown;
|
||||
VK_LWIN, VK_RWIN:
|
||||
(* VK_LWIN, VK_RWIN:
|
||||
if (QApplication_keyboardModifiers and QtMetaModifier) > 0 then
|
||||
Result := Result or StateDown;
|
||||
{$ifdef VerboseQtWinAPI}
|
||||
else
|
||||
DebugLn('TQtWidgetSet.GetKeyState TODO ', DbgSVKCode(Word(nVirtkey)));
|
||||
{$endif}
|
||||
{$endif} *)
|
||||
end;
|
||||
end;
|
||||
|
||||
(*
|
||||
function TQtWidgetSet.GetMapMode(DC: HDC): Integer;
|
||||
begin
|
||||
if IsValidDC(DC) then
|
||||
|
@ -122,9 +122,9 @@ function GetDeviceCaps(DC: HDC; Index: Integer): Integer; override;
|
||||
(*function GetDIBits(DC: HDC; Bitmap: HBitmap; StartScan, NumScans: UINT; Bits: Pointer; var BitInfo: BitmapInfo; Usage: UINT): Integer; Override;
|
||||
function GetDoubleClickTime: UINT; override;*)
|
||||
function GetFocus: HWND; override;
|
||||
(*function GetForegroundWindow: HWND; override;
|
||||
(*function GetForegroundWindow: HWND; override;*)
|
||||
function GetKeyState(nVirtKey: Integer): Smallint; override;
|
||||
function GetMapMode(DC: HDC): Integer; override;
|
||||
(*function GetMapMode(DC: HDC): Integer; override;
|
||||
function GetMonitorInfo(Monitor: HMONITOR; lpmi: PMonitorInfo): Boolean; override;
|
||||
function GetObject(GDIObj: HGDIOBJ; BufSize: Integer; Buf: Pointer): Integer; override;
|
||||
function GetParent(Handle : HWND): HWND; override;*)
|
||||
|
@ -124,6 +124,7 @@ type
|
||||
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 EvPaintEx(const AWinControl: TWinControl; AWindowInfo: TX11WindowInfo);
|
||||
class procedure EvConfigureNotify(const AWinControl: TWinControl; AWindowInfo: TX11WindowInfo;
|
||||
var Event: TXConfigureEvent);
|
||||
class procedure EvClientMessage(const AWinControl: TWinControl;
|
||||
|
@ -499,6 +499,7 @@ begin
|
||||
lKey := X11KeyToLCLKey(KeySym);
|
||||
CDWidgetset.LastKeySym := KeySym;
|
||||
CDWidgetset.LastKey := lKey;
|
||||
CDWidgetSet.ShiftState := CDWidgetSet.XStateToLCLState(Event.state);
|
||||
|
||||
CallbackKeyDown(lForm, lKey);
|
||||
|
||||
@ -527,6 +528,7 @@ begin
|
||||
lForm := TCDForm(AWinControl.Handle);
|
||||
|
||||
lKey := CDWidgetset.LastKey;
|
||||
CDWidgetSet.ShiftState := CDWidgetSet.XStateToLCLState(Event.state);
|
||||
CallbackKeyUp(lForm, lKey);
|
||||
|
||||
// Do not call EndComposing, as this would generate duplicate KeyChar events!}
|
||||
@ -624,6 +626,8 @@ var
|
||||
lWidth, lHeight: Integer;
|
||||
lBitmap, lMask: HBITMAP;
|
||||
lRawImage: TRawImage;
|
||||
Event: TXClientMessageEvent;
|
||||
reslt: Integer;
|
||||
{$IFDEF VerboseCDPaintProfiler}
|
||||
lTimeStart, lCDTimeEnd, lNativeTimeStart: TDateTime;
|
||||
{$ENDIF}
|
||||
@ -662,9 +666,25 @@ begin
|
||||
lNativeTimeStart := NowUTC();
|
||||
{$ENDIF}
|
||||
|
||||
{$ifdef CD_X11_NewNativePaint}
|
||||
// if not already done, send a message to X
|
||||
if CDWidgetSet.CheckInvalidateWindowForX(AWindowInfo.Window) then
|
||||
begin
|
||||
FillChar(Event,sizeof(Event),0);
|
||||
Event._type:= ClientMessage;
|
||||
Event.display:=CDWidgetSet.FDisplay;
|
||||
Event.window:=AWindowInfo.Window;
|
||||
Event.message_type:= CDWidgetSet.FWMPaint;
|
||||
Event.format:= 32; // Must hold a culong for TXID
|
||||
Event.data.l[0]:= AWindowInfo.Window;
|
||||
reslt := XSendEvent(CDWidgetSet.FDisplay,AWindowInfo.Window,{Propagate=}True,0,@Event);
|
||||
// Painting will carried out from main event loop
|
||||
end;
|
||||
{$else}
|
||||
// Now render it into the control
|
||||
AWindowInfo.Image.GetRawImage(lRawImage);
|
||||
DrawRawImageToGC(lRawImage, AWindowInfo, 0, 0, lWidth, lHeight);
|
||||
{$endif}
|
||||
|
||||
{$IFDEF VerboseCDPaintProfiler}
|
||||
DebugLn(Format('[TCDWSCustomForm.EvPaint] Total Paint duration: %d ms of this CustomDrawn: %d ms Native: %d',
|
||||
@ -675,6 +695,18 @@ begin
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
class procedure TCDWSCustomForm.EvPaintEx(const AWinControl: TWinControl;
|
||||
AWindowInfo: TX11WindowInfo);
|
||||
var
|
||||
lWidth, lHeight: Integer;
|
||||
lRawImage: TRawImage;
|
||||
begin
|
||||
lWidth := Round(AWinControl.width);
|
||||
lHeight := Round(AWinControl.height);
|
||||
AWindowInfo.Image.GetRawImage(lRawImage);
|
||||
DrawRawImageToGC(lRawImage, AWindowInfo, 0, 0, lWidth, lHeight);
|
||||
end;
|
||||
|
||||
class procedure TCDWSCustomForm.EvConfigureNotify(const AWinControl: TWinControl; AWindowInfo: TX11WindowInfo;
|
||||
var Event: TXConfigureEvent);
|
||||
begin
|
||||
@ -1777,9 +1809,9 @@ begin
|
||||
0xfd1d U0000 f # 3270_PrintScreen
|
||||
0xfd1e U0000 f # 3270_Enter
|
||||
0xfe01 U0000 f # ISO_Lock
|
||||
0xfe02 U0000 f # ISO_Level2_Latch
|
||||
0xfe03 U0000 f # ISO_Level3_Shift
|
||||
0xfe04 U0000 f # ISO_Level3_Latch
|
||||
0xfe02 U0000 f # ISO_Level2_Latch}
|
||||
$FE03: Result := VK_RMENU; // ISO_Level3_Shift
|
||||
{0xfe04 U0000 f # ISO_Level3_Latch
|
||||
0xfe05 U0000 f # ISO_Level3_Lock
|
||||
0xfe06 U0000 f # ISO_Group_Latch
|
||||
0xfe07 U0000 f # ISO_Group_Lock
|
||||
@ -1922,8 +1954,8 @@ begin
|
||||
$FF54: Result := VK_DOWN;
|
||||
$FF55: Result := VK_PRIOR;
|
||||
$FF56: Result := VK_NEXT;
|
||||
{ 0xff57 U0000 f # End
|
||||
0xff58 U0000 f # Begin
|
||||
$ff57: Result := VK_END;
|
||||
{ 0xff58 U0000 f # Begin
|
||||
0xff60 U0000 f # Select
|
||||
0xff61 U0000 f # Print
|
||||
0xff62 U0000 f # Execute
|
||||
@ -2015,15 +2047,15 @@ begin
|
||||
{ 0xffe5 U0000 f # Caps_Lock
|
||||
0xffe6 U0000 f # Shift_Lock
|
||||
0xffe7 U0000 f # Meta_L
|
||||
0xffe8 U0000 f # Meta_R
|
||||
0xffe9 U0000 f # Alt_L
|
||||
0xffea U0000 f # Alt_R
|
||||
0xffe8 U0000 f # Meta_R}
|
||||
$FFE9: Result := VK_LMENU;
|
||||
{0xffea U0000 f # Alt_R
|
||||
0xffeb U0000 f # Super_L
|
||||
0xffec U0000 f # Super_R
|
||||
0xffed U0000 f # Hyper_L
|
||||
0xffee U0000 f # Hyper_R
|
||||
0xffff U0000 f # Delete
|
||||
$FFFF: Result := VK_DEL; }
|
||||
0xffff U0000 f # Delete }
|
||||
$FFFF: Result := VK_DELETE;
|
||||
{ 0xffffff U0000 f # VoidSymbol
|
||||
|
||||
# Various XFree86 extensions since X11R6.4
|
||||
@ -2443,7 +2475,6 @@ begin
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
if Result = 0 then DebugLn('[X11KeyToLCLKey] Unknown KeySym: $' + IntToHex(AX11Key, 4));
|
||||
end;
|
||||
|
||||
@ -2569,6 +2600,11 @@ begin
|
||||
CDWidgetSet.FWMProtocols := XInternAtom(CDWidgetSet.FDisplay, 'WM_PROTOCOLS', False);
|
||||
if CDWidgetSet.FWMDeleteWindow = 0 then
|
||||
CDWidgetSet.FWMDeleteWindow := XInternAtom(CDWidgetSet.FDisplay, 'WM_DELETE_WINDOW', False);
|
||||
{$ifdef CD_X11_NewNativePaint}
|
||||
// Client Message for Paint Event
|
||||
if CDWidgetSet.FWMPaint = 0 then
|
||||
CDWidgetSet.FWMPaint := XInternAtom(CDWidgetSet.FDisplay, 'WM_PAINT', False);
|
||||
{$endif}
|
||||
|
||||
// send close event instead of quitting the whole application...
|
||||
XSetWMProtocols(CDWidgetSet.FDisplay, lWindow, @CDWidgetSet.FWMDeleteWindow, 1);
|
||||
@ -2592,6 +2628,10 @@ begin
|
||||
CreateX11Canvas(lWindowInfo);
|
||||
Result := TLCLIntfHandle(lWindowInfo);
|
||||
|
||||
{$ifdef CD_X11_NewNativePaint}
|
||||
CDWidgetSet.XWindowList.AddObject('New',TObject(lWindowInfo));
|
||||
{$endif}
|
||||
|
||||
{$ifdef VerboseCDForms}
|
||||
DebugLn(Format(':<[TCDWSCustomForm.CreateHandle] Result=%x',
|
||||
[Result]));
|
||||
|
Loading…
Reference in New Issue
Block a user