lazarus/lcl/interfaces/gtk3/gtk3winapi.inc

4036 lines
117 KiB
PHP

{%MainUnit gtk3int.pas}
function TGtk3WidgetSet.Arc(DC: HDC; Left, top, right, bottom, angle1,
angle2: Integer): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.Arc not implemented ...');
{$ENDIF}
Result:=inherited Arc(DC, Left, top, right, bottom, angle1, angle2);
end;
function TGtk3WidgetSet.AngleChord(DC: HDC; x1, y1, x2, y2, angle1,
angle2: Integer): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.AngleChord not implemented ...');
{$ENDIF}
Result:=inherited AngleChord(DC, x1, y1, x2, y2, angle1, angle2);
end;
function TGtk3WidgetSet.BeginPaint(Handle: hWnd; var PS: TPaintStruct): hdc;
var
Widget: TGtk3Widget;
GtkWidget: PGtkWidget;
DC: TGtk3DeviceContext;
begin
Widget := TGtk3Widget(Handle);
if Widget <> nil then
begin
GtkWidget := Widget.GetContainerWidget;
if Widget.CairoContext <> nil then
DC := TGtk3DeviceContext.CreateFromCairo(GtkWidget, Widget.CairoContext)
else
DC := TGtk3DeviceContext.Create(GtkWidget, True);
end
else
DC := TGtk3DeviceContext.Create(PGtkWidget(nil), True);
PS.hdc := HDC(DC);
if Handle<>0 then
begin
DC.vClipRect := Widget.PaintData.ClipRect^;
(*
// if current handle has paintdata information,
// setup hdc with it
//DC.DebugClipRect('BeginPaint: Before');
if Widget.PaintData.ClipRegion <> nil then
begin
//Write('>>> Setting Paint ClipRegion: ');
//DebugRegion('PaintData.ClipRegion: ', Widget.PaintData.ClipRegion);
DC.setClipRegion(Widget.PaintData.ClipRegion);
DC.setClipping(True);
end;
if Widget.PaintData.ClipRect <> nil then
begin
New(DC.vClipRect);
DC.vClipRect^ := Widget.PaintData.ClipRect^;
end;
*)
end;
Result := PS.hdc;
end;
function TGtk3WidgetSet.BitBlt(DestDC: HDC; X, Y, Width, Height: Integer;
SrcDC: HDC; XSrc, YSrc: Integer; Rop: DWORD): Boolean;
begin
{$ifdef VerboseGtk3DeviceContext}
DebugLn('Trace:> [TGtk3WidgetSet.BitBlt]');
{$endif}
Result := StretchBlt(DestDC, X, Y, Width, Height, SrcDC, XSrc, YSrc, Width,
Height, ROP);
{$ifdef VerboseGtk3DeviceContext}
DebugLn('Trace:< [TGtk3WidgetSet.BitBlt]');
{$endif}
end;
function TGtk3WidgetSet.CallNextHookEx(hHk: HHOOK; ncode: Integer;
wParam: WParam; lParam: LParam): Integer;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.CallNextHookEx not implemented ...');
{$ENDIF}
Result:=inherited CallNextHookEx(hHk, ncode, wParam, lParam);
end;
function TGtk3WidgetSet.CallWindowProc(lpPrevWndFunc: TFarProc; Handle: HWND;
Msg: UINT; wParam: WParam; lParam: lParam): Integer;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.CallWindowProc not implemented ...');
{$ENDIF}
Result:=inherited CallWindowProc(lpPrevWndFunc, Handle, Msg, wParam, lParam);
end;
function TGtk3WidgetSet.ClientToScreen(Handle: HWND; var P: TPoint): Boolean;
begin
{$ifdef VerboseGtk3WinApi}
DebugLn('Trace:> [TGtk3WidgetSet.ClientToScreen] ',dbgs(P));
{$endif}
// Result:=inherited ClientToScreen(Handle, P);
Result := False;
P := Point(0, 0);
if IsValidHandle(Handle) then
Result := TGtk3Widget(Handle).ClientToScreen(P);
{$ifdef VerboseGtk3WinApi}
DebugLn('Trace:< [TGtk3WidgetSet.ClientToScreen] ',dbgs(P),' result=',dbgs(Result));
{$endif}
end;
function TGtk3WidgetSet.ClipboardFormatToMimeType(FormatID: TClipboardFormat
): string;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.ClipboardFormatToMimeType not implemented ...');
{$ENDIF}
Result:=inherited ClipboardFormatToMimeType(FormatID);
end;
const
sPrimary = 'PRIMARY';
sClipboard = 'CLIPBOARD';
function TGtk3WidgetSet.ClipboardGetData(ClipboardType: TClipboardType;
FormatID: TClipboardFormat; Stream: TStream): boolean;
var
pclp:PGtkClipboard;
pc:pgchar;
pcname:PgdkAtom;
begin
case ClipboardType of
ctPrimarySelection: pcname:=TGdkAtom.intern(sPrimary,false);
ctSecondarySelection: pcname:=nil;
ctClipboard: pcname:=TGdkAtom.intern(sClipboard,false);
end;
if not Assigned(pcname) then exit;
pclp:=TGtkClipboard.get(pcname);
if not Assigned(pclp) then exit(false);
// text handling
//pclp^.request_text(@ClipboardTextReceivedFunc,Stream);
pc:=pclp^.wait_for_text;
Stream.Write(pc^,strlen(pc));
Result:=true;
end;
function TGtk3WidgetSet.ClipboardGetFormats(ClipboardType: TClipboardType;
var Count: integer; var List: PClipboardFormat): boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.ClipboardGetFormats not implemented ...');
{$ENDIF}
Result:=inherited ClipboardGetFormats(ClipboardType, Count, List);
end;
function TGtk3WidgetSet.ClipboardGetOwnerShip(ClipboardType: TClipboardType;
OnRequestProc: TClipboardRequestEvent; FormatCount: integer;
Formats: PClipboardFormat): boolean;
var
pclp:PGtkClipboard;
pcname:PgdkAtom;
begin
case ClipboardType of
ctPrimarySelection: pcname:=TGdkAtom.intern(sPrimary,false);
ctSecondarySelection: pcname:=nil;
ctClipboard: pcname:=TGdkAtom.intern(sClipboard,false);
end;
if not Assigned(pcname) then exit;
pclp:=TGtkClipboard.get(pcname);
if not Assigned(pclp) then exit(false);
{ // text handling
//pclp^.request_text(@ClipboardTextReceivedFunc,Stream);
pc:=pclp^.wait_for_text;
Stream.Write(pc^,strlen(pc)); }
Result:=true;
end;
function TGtk3WidgetSet.ClipboardRegisterFormat(const AMimeType: string): TClipboardFormat;
var xGA:PGdkAtom;
begin
if Assigned(Application) then
begin
xGA:=TGdkAtom.intern(PChar(AMimeType), False);
Result := TClipboardFormat(xGA);
end else
RaiseGDBException(
'ERROR: TGtk3WidgetSet.ClipboardRegisterFormat gdk not initialized');
end;
function TGtk3WidgetSet.CombineRgn(Dest, Src1, Src2: HRGN;
fnCombineMode: Longint): Longint;
var
RDest,RSrc1,RSrc2: Pcairo_region_t;
AStatus: cairo_status_t;
ACairoRect: Tcairo_rectangle_int_t;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
// DebugLn('WARNING: TGtk3WidgetSet.CombineRgn not implemented ...');
{$ENDIF}
Result := ERROR;
if not IsValidGDIObject(Dest) or not IsValidGDIObject(Src1) then
exit;
RDest := TGtk3Region(Dest).Handle;
RSrc1 := TGtk3Region(Src1).Handle;
if (fnCombineMode<>RGN_COPY) and not IsValidGDIObject(Src2) then
exit
else
RSrc2 := TGtk3Region(Src2).Handle;
AStatus := CAIRO_STATUS_READ_ERROR;
case fnCombineMode of
RGN_AND:
begin
AStatus := cairo_region_intersect(RSrc1, RSrc2);
// cairo cannot intersect empty region
if cairo_region_is_empty(RDest) then
begin
cairo_region_destroy(TGtk3Region(Dest).Handle);
cairo_region_get_extents(RSrc1, @ACairoRect);
TGtk3Region(Dest).Handle := cairo_region_create_rectangle(@ACairoRect);
RDest := TGtk3Region(Dest).Handle;
//cairo_region_translate(RDest, -ACairoRect.x, -ACairoRect.y);
end else
AStatus := cairo_region_intersect(RDest, RSrc1);
end;
RGN_COPY:
begin
AStatus := cairo_region_intersect(RDest, RSrc1);
//DebugLn(['CombineRgn RGN_COPY ',AStatus]);
end;
RGN_DIFF:
begin
AStatus := cairo_region_subtract(RSrc1, RSrc2);
if cairo_region_is_empty(RDest) then
begin
cairo_region_destroy(TGtk3Region(Dest).Handle);
cairo_region_get_extents(RSrc1, @ACairoRect);
TGtk3Region(Dest).Handle := cairo_region_create_rectangle(@ACairoRect);
RDest := TGtk3Region(Dest).Handle;
cairo_region_translate(RDest, -ACairoRect.x, -ACairoRect.y);
end else
AStatus := cairo_region_subtract(RDest, RSrc1);
end;
RGN_OR:
begin
AStatus := cairo_region_union(RSrc1, RSrc2);
AStatus := cairo_region_union(RDest, RSrc1);
end;
RGN_XOR:
begin
AStatus := cairo_region_xor(RSrc1, RSrc2);
AStatus := cairo_region_xor(RDest, RSrc1);
end;
end;
if (AStatus <> CAIRO_STATUS_SUCCESS) or cairo_region_is_empty(RDest) then
Result := NullRegion
else
begin
if cairo_region_num_rectangles(RDest) > 1 then
Result := ComplexRegion
else
Result := SimpleRegion;
end;
end;
function TGtk3WidgetSet.CreateBitmap(Width, Height: Integer; Planes,
BitCount: Longint; BitmapBits: Pointer): HBITMAP;
var
Format: cairo_format_t;
NewBits: PByte;
NewBitsSize: PtrUInt;
ARowStride, RSS: Integer;
begin
{$IFDEF VerboseGtk3WinAPI}
DebugLn('Trace:> [Gtk3WinAPI CreateBitmap]',
' Width:', dbgs(Width),
' Height:', dbgs(Height),
' Planes:', dbgs(Planes),
' BitCount:', dbgs(BitCount),
' BitmapBits: ', dbgs(BitmapBits));
{$ENDIF}
case BitCount of
1: Format := CAIRO_FORMAT_A1;
8: Format := CAIRO_FORMAT_A8;
24: Format := CAIRO_FORMAT_RGB24;
else
Format := CAIRO_FORMAT_ARGB32;
end;
RSS := GetBytesPerLine(Width, BitCount, rileWordBoundary);
if BitmapBits <> nil then
begin
ARowStride := GetBytesPerLine(Width, BitCount, rileDWordBoundary);
if not CopyImageData(Width, Height, RSS, BitCount, BitmapBits, Rect(0, 0, Width, Height),
riloBottomToTop, riloBottomToTop, rileDWordBoundary, NewBits, NewBitsSize) then
begin
// this was never tested
ARowStride := RSS;
NewBits := AllocMem(RSS * Height);
Move(BitmapBits^, NewBits^, RSS * Height);
end;
Result := HBitmap(TGtk3Image.Create(NewBits, Width, Height, ARowStride, Format, True));
end
else
Result := HBitmap(TGtk3Image.Create(nil, Width, Height, Format));
{$IFDEF VerboseGtk3WinAPI}
DebugLn('Trace:< [Gtk3WinAPI CreateBitmap] Bitmap:', dbghex(Result));
{$ENDIF}
end;
function TGtk3WidgetSet.CreateBrushIndirect(const LogBrush: TLogBrush): HBRUSH;
var
ABrush: TGtk3Brush;
begin
Result := 0;
// DebugLn('TGtk3WidgetSet.CreateBrushIndirect color=',dbgs(logBrush.lbColor),' style=',dbgs(logBrush.lbStyle));
ABrush := TGtk3Brush.Create;
try
// todo: hatch
ABrush.Style := LogBrush.lbStyle;
ABrush.Color := ColorToRGB(TColor(logBrush.lbColor));
ABrush.LogBrush := LogBrush;
// ABrush.LogBrush.lbColor := ABrush.Color;
Result := HBRUSH(ABrush);
except
Result := 0;
DebugLn('TGtk3WidgetSet.CreateBrushIndirect: Failed');
end;
{$IFDEF VerboseGtk3DeviceContext}
DebugLn('Trace:< [Gtk3WinAPI CreateBrushIndirect] Result: ', dbghex(Result));
{$ENDIF}
end;
function TGtk3WidgetSet.CreateCaret(Handle: HWND; Bitmap: hBitmap; width,
Height: Integer): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.CreateCaret not implemented ...');
{$ENDIF}
Result := inherited CreateCaret(Handle, Bitmap, width, Height);
end;
function TGtk3WidgetSet.CreateCompatibleBitmap(DC: HDC; Width, Height: Integer
): HBITMAP;
var
Gtk3DC: TGtk3DeviceContext;
Format: cairo_format_t = CAIRO_FORMAT_ARGB32;
ADepth: Integer;
AVisual: PGdkVisual;
ABpp: gint;
ARowStride: PtrUInt;
begin
{$IFDEF VerboseGtk3WinAPI}
DebugLn('Trace:> [WinAPI CreateCompatibleBitmap]',
' DC:', dbghex(DC),
' Width:', dbgs(Width),
' Height:', dbgs(Height));
{$ENDIF}
Result := 0;
if IsValidDC(DC) then
begin
Gtk3DC := TGtk3DeviceContext(DC);
ADepth := Gtk3DC.getDepth;
ABpp := Gtk3DC.getBpp;
end else
begin
AVisual := gdk_window_get_visual(gdk_get_default_root_window);
ADepth := gdk_visual_get_depth(AVisual);
ABpp := AVisual^.get_bits_per_rgb;
g_object_unref(AVisual);
end;
case ADepth of
1: Format := CAIRO_FORMAT_A1;
2: Format := CAIRO_FORMAT_A8;
24: Format := CAIRO_FORMAT_RGB24;
else
Format := CAIRO_FORMAT_ARGB32;
end;
ARowStride := GetBytesPerLine(Width, ABpp, rileDWordBoundary);
Result := HBitmap(TGtk3Image.Create(nil, Width, Height, ARowStride, Format));
{$IFDEF VerboseGtk3WinAPI}
DebugLn('Trace:< [Gtk3WinAPI CreateCompatibleBitmap] Bitmap:', dbghex(Result));
{$ENDIF}
end;
function TGtk3WidgetSet.CreateCompatibleDC(DC: HDC): HDC;
begin
Result := HDC(TGtk3DeviceContext.Create(PGtkWidget(nil), False));
end;
function TGtk3WidgetSet.CreateEllipticRgn(X1, Y1, X2, Y2: Integer): HRGN;
begin
Result:=HRGN(TGtk3Region.CreateEllipse(X1,Y1,X2,Y2));
end;
function TGtk3WidgetSet.CreateRoundRectRgn(X1, Y1, X2, Y2, nW, nH: Integer): HRGN;
begin
Result:=HRGN(TGtk3Region.Create(X1,Y1,X2,Y2,nW,nH));
end;
function TGtk3WidgetSet.CreateFontIndirect(const LogFont: TLogFont): HFONT;
begin
Result := CreateFontIndirectEx(LogFont, '');
end;
function TGtk3WidgetSet.CreateFontIndirectEx(const LogFont: TLogFont;
const LongFontName: string): HFONT;
begin
Result := HFONT(TGtk3Font.Create(LogFont, LongFontName));
end;
function TGtk3WidgetSet.CreateIconIndirect(IconInfo: PIconInfo): HICON;
begin
Result := 0;
if IsValidGDIObject(IconInfo^.hbmColor) then
begin
if IconInfo^.fIcon then
begin
Result := HICON(TGtk3Image.Create(TGtk3Image(IconInfo^.hbmColor).Handle));
end else
begin
Result := HCURSOR({%H-}PtrUInt(gdk_cursor_new_from_pixbuf(gdk_display_get_default,
TGtk3Image(IconInfo^.hbmColor).Handle, IconInfo^.xHotSpot, IconInfo^.yHotSpot)));
// create cursor from pixbuf
{ W := gdk_pixbuf_get_width(TGtk3Image(IconInfo^.hbmColor).Handle);
H := gdk_pixbuf_get_height(TGtk3Image(IconInfo^.hbmColor).Handle);
DebugLn('TGtk3WidgetSet.CreateIconIndirect W=',dbgs(W),' H=',dbgs(H));
PixBuf := gdk_pixbuf_new_subpixbuf(TGtk3Image(IconInfo^.hbmColor).Handle, 0, 0, W, H);
Result := HCURSOR({%H-}PtrUInt(gdk_cursor_new_from_pixbuf(gdk_display_get_default,
pixbuf, IconInfo^.xHotSpot, IconInfo^.yHotSpot)));
if pixbuf <> nil then
g_object_unref(PixBuf); }
end;
end;
end;
function TGtk3WidgetSet.CreatePalette(const LogPalette: TLogPalette): HPALETTE;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.CreatePalette not implemented ...');
{$ENDIF}
Result := 0;
end;
function TGtk3WidgetSet.CreatePenIndirect(const LogPen: TLogPen): HPEN;
var
APen: TGtk3Pen;
begin
Result := 0;
APen := TGtk3Pen.Create;
with LogPen do
begin
case lopnStyle and PS_STYLE_MASK of
PS_SOLID: APen.Style := psSolid;
PS_DASH: APen.Style := psDash;
PS_DOT: APen.Style := psDot;
PS_DASHDOT: APen.Style := psDashDot;
PS_DASHDOTDOT: APen.Style := psDashDotDot;
PS_NULL: APen.Style := psClear;
else
APen.Style := psSolid;
end;
APen.Color := ColorToRgb(TColor(lopnColor));
APen.Cosmetic := lopnWidth.X <= 0 ;
if not APen.Cosmetic then
APen.Width := lopnWidth.X;
end;
APen.LogPen := LogPen;
Result := HPEN(APen);
end;
function TGtk3WidgetSet.CreatePolygonRgn(Points: PPoint; NumPts: Integer;
FillMode: integer): HRGN;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.CreatePolygonRgn not implemented ...');
{$ENDIF}
Result:=inherited CreatePolygonRgn(Points, NumPts, FillMode);
end;
function TGtk3WidgetSet.CreateRectRgn(X1, Y1, X2, Y2: Integer): HRGN;
begin
Result := HRGN(TGtk3Region.Create(True, X1, Y1, X2, Y2));
end;
procedure TGtk3WidgetSet.DeleteCriticalSection(var CritSection: TCriticalSection
);
var
ACritSec: System.PRTLCriticalSection;
begin
ACritSec:=System.PRTLCriticalSection(CritSection);
System.DoneCriticalsection(ACritSec^);
Dispose(ACritSec);
CritSection:=0;
end;
function TGtk3WidgetSet.DeleteDC(hDC: HDC): Boolean;
begin
{$ifdef VerboseGtk3DeviceContext}
DebugLn('TGtk3WidgetSet.DeleteDC Handle: ', dbghex(hDC));
{$endif}
if not IsValidDC(hDC) then
exit(False);
TGtk3DeviceContext(hDC).Free;
Result := True;
end;
function TGtk3WidgetSet.DeleteObject(GDIObject: HGDIOBJ): Boolean;
begin
Result := False;
if GDIObject = 0 then
Exit(True);
if not IsValidGDIObject(GDIObject) then
Exit;
{$ifdef VerboseGtk3DeviceContext}
DebugLn('TGtk3WidgetSet.DeleteObject GDIObject: ', dbghex(GdiObject),' name ',dbgsName(TObject(GdiObject)));
{$endif}
if TObject(GDIObject) is TGtk3ContextObject then
begin
if TGtk3ContextObject(GDIOBJECT).Shared then
// DebugLn('ERROR: TGtk3WidgetSet.DeleteObject trial to delete shared object ',dbgsName(TGtk3ContextObject(GdiObject)))
else
TGtk3ContextObject(GDIObject).Free;
end else
TObject(GDIObject).Free;
end;
function TGtk3WidgetSet.DestroyCaret(Handle: HWND): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.DestroyCaret not implemented ...');
{$ENDIF}
Result:=inherited DestroyCaret(Handle);
end;
function TGtk3WidgetSet.DestroyCursor(Handle: HCURSOR): Boolean;
begin
Result := Handle <> 0;
if Result then
g_object_unref(PGdkCursor(Handle));
// gdk_cursor_destroy({%H-}PGdkCursor(Handle));
end;
function TGtk3WidgetSet.DestroyIcon(Handle: HICON): Boolean;
begin
Result := False;
if IsValidGDIObject(Handle) then
begin
TGtk3Image(Handle).Free;
Result := True;
end;
end;
function TGtk3WidgetSet.DPtoLP(DC: HDC; var Points; Count: Integer): BOOL;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.DPToLP not implemented ...');
{$ENDIF}
Result:=inherited DPtoLP(DC, Points, Count);
end;
function TGtk3WidgetSet.DrawFrameControl(DC: HDC; const aRect: TRect; uType,
uState: Cardinal): Boolean;
begin
Result:=false;
if IsValidDC(DC) then
Result:=TGtk3DeviceContext(DC).drawFrameControl(aRect,uType,uState);
end;
function TGtk3WidgetSet.DrawFocusRect(DC: HDC; const aRect: TRect): boolean;
begin
Result := False;
if IsValidDC(DC) then
Result:=TGtk3DeviceContext(DC).drawFocusRect(aRect);
end;
function TGtk3WidgetSet.DrawEdge(DC: HDC; var ARect: TRect; Edge: Cardinal;
grfFlags: Cardinal): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.DrawEdge not implemented ...');
{$ENDIF}
Result := False; // inherited DrawEdge(DC, ARect, Edge, grfFlags);
end;
function TGtk3WidgetSet.DrawText(DC: HDC; Str: PChar; Count: Integer;
var Rect: TRect; Flags: Cardinal): Integer;
const
TabString = ' ';
var
pIndex: Longint;
AStr: String;
TM: TTextmetric;
theRect: TRect;
Lines: PPChar;
I, NumLines: Longint;
TempDC: HDC;
TempPen: HPEN;
TempBrush: HBRUSH;
l: LongInt;
Pt: TPoint;
SavedRect: TRect; // if font orientation <> 0
LineHeight: Integer;
Size: TSize;
function LeftOffset: Longint;
begin
if (Flags and DT_RIGHT) = DT_RIGHT then
Result := DT_RIGHT
else
if (Flags and DT_CENTER) = DT_CENTER then
Result := DT_CENTER
else
Result := DT_LEFT;
end;
function TopOffset: Longint;
begin
if (Flags and DT_BOTTOM) = DT_BOTTOM then
Result := DT_BOTTOM
else
if (Flags and DT_VCENTER) = DT_VCENTER then
Result := DT_VCENTER
else
Result := DT_TOP;
end;
function CalcRect: Boolean;
begin
Result := (Flags and DT_CALCRECT) = DT_CALCRECT;
end;
function TextExtentPoint(Str: PChar; Count: Integer; var Sz: TSize): Boolean;
var
NewStr: String;
begin
if (Flags and DT_EXPANDTABS) <> 0 then
begin
NewStr := StringReplace(Str, #9, TabString, [rfReplaceAll]);
Result := GetTextExtentPoint(DC, PChar(NewStr), Length(NewStr), Sz);
end
else
Result := GetTextExtentPoint(Dc, Str, Count, Sz);
end;
procedure DoCalcRect;
var
AP: TSize;
J, MaxWidth,
LineWidth, LineHeight: Integer;
begin
theRect := Rect;
MaxWidth := theRect.Right - theRect.Left;
//DefHeight := theRect.Bottom - theRect.Top;
(*
if Flags and DT_CENTER <> 0then
Alignment := DT_CENTER
else
if Flags and DT_RIGHT <> 0 then
Alignment := DT_RIGHT
else
Alignment := DT_LEFT;
TGtk3DeviceContext(DC).CurrentFont.Layout^.set_alignment(Alignment);
if Flags and DT_WORDBREAK <> 0 then
TGtk3DeviceContext(DC).CurrentFont.Layout^.set_wrap(PANGO_WRAP_WORD);
// ADevOffset := TGtk3DeviceContext(DC).Offset;
// TGtk3DeviceContext(DC).CurrentFont.Layout^.set_width(Rect.Right - Rect.Left);
// TGtk3DeviceContext(DC).CurrentFont.Layout^.set_height(Rect.Bottom - Rect.Top);
TGtk3DeviceContext(DC).CurrentFont.Layout^.set_text(Str, Count);
// TGtk3DeviceContext(DC).CurrentFont.Layout^.get_iter^.get_line_extents(@PR1, @PR2);
// DebugLn('DoCalcRect LINE EXTENTS Rect=',dbgs(Rect),' PR1 ',dbgs(RectFromGdkRect(TGdkRectangle(PR1))),' PR2 ',dbgs(RectFromGdkRect(TGdkRectangle(PR2))));
TGtk3DeviceContext(DC).CurrentFont.Layout^.get_extents(@PR1, @PR2);
// get_extents(@PR1, @PR2);
DebugLn('DoCalcRect Rect=',dbgs(Rect),' PR1 ',dbgs(RectFromPangoRect(PR1)),' PR2 ',dbgs(RectFromPangoRect(PR2)),' ALIGNMENT ',dbgs(Alignment));
// DebugLn('DoCalcRect Rect=',dbgs(Rect),' PR1 ',Format('x %d y %d width %d height %d'
*)
if (Flags and DT_SINGLELINE) > 0 then
begin
// ignore word and line breaks
TextExtentPoint(PChar(AStr), length(AStr), AP{%H-});
theRect.Bottom := theRect.Top + TM.tmHeight;
if (Flags and DT_CALCRECT)<>0 then
begin
theRect.Right := theRect.Left + AP.cX;
theRect.Bottom := theRect.Top + AP.cY;
end
else
begin
theRect.Right := theRect.Left + Min(MaxWidth, AP.cX);
theRect.Bottom := theRect.Top + AP.cY;
if (Flags and DT_VCENTER) > 0 then
begin
OffsetRect(theRect, 0, ((Rect.Bottom - Rect.Top) - (theRect.Bottom - theRect.Top)) div 2);
end
else
if (Flags and DT_BOTTOM) > 0 then
begin
OffsetRect(theRect, 0, (Rect.Bottom - Rect.Top) - (theRect.Bottom - theRect.Top));
end;
end;
end
else
begin
// consider line breaks
if (Flags and DT_WORDBREAK) = 0 then
begin
// do not break at word boundaries
TextExtentPoint(PChar(AStr), length(AStr), AP);
MaxWidth := AP.cX;
//DefHeight := AP.cY;
end;
Gtk3WordWrap(DC, PChar(AStr), MaxWidth, Lines, NumLines);
//DebugLn(['WORD WRAP RESULTED IN ',NumLines,' lines for ',AStr,' MAX=',MaxWidth]);
if (Flags and DT_CALCRECT)<>0 then
begin
LineWidth := 0;
LineHeight := 0;
if (Lines <> nil) then
begin
for J := 0 to NumLines - 1 do
begin
TextExtentPoint(Lines[J], StrLen(Lines[J]), AP);
LineWidth := Max(LineWidth, AP.cX);
Inc(LineHeight, AP.cY);
end;
end;
LineWidth := Min(MaxWidth, LineWidth);
end else
begin
LineWidth := MaxWidth;
LineHeight := NumLines*TM.tmHeight;
end;
theRect.Right := theRect.Left + LineWidth;
theRect.Bottom := theRect.Top + LineHeight;
if NumLines>1 then
Inc(theRect.Bottom, (NumLines-1)*TM.tmExternalLeading);// space between lines
//DebugLn('TGtk3WidgetSet.DrawText A ',dbgs(theRect),' TM.tmHeight=',dbgs(TM.tmHeight),
// ' LineWidth=',dbgs(LineWidth),' NumLines=',dbgs(NumLines));
end;
if not CalcRect then
case LeftOffset of
DT_CENTER:
OffsetRect(theRect, (Rect.Right - theRect.Right) div 2, 0);
DT_RIGHT:
OffsetRect(theRect, Rect.Right - theRect.Right, 0);
end;
end;
// if our Font.Orientation <> 0 we must recalculate X,Y offset
// also it works only with DT_TOP DT_LEFT. Gtk2 can handle multiline
// text in this case too.
procedure CalculateOffsetWithAngle(const AFontAngle: Integer;
var TextLeft,TextTop: Integer);
var
OffsX, OffsY: integer;
Angle: Double;
Size: TSize;
R: TRect;
begin
R := SavedRect;
OffsX := R.Right - R.Left;
OffsY := R.Bottom - R.Top;
Size.cx := OffsX;
Size.cy := OffsY;
Angle := AFontAngle / 10;
if Angle < 0 then
Angle := 360 + Angle;
if Angle <= 90 then
begin
OffsX := 0;
OffsY := Trunc(Size.cx * sin(Angle * Pi / 180));
end else
if Angle <= 180 then
begin
OffsX := Trunc(Size.cx * -cos(Angle * Pi / 180));
OffsY := Trunc(Size.cx * sin(Angle * Pi / 180) +
Size.cy * cos((180 - Angle) * Pi / 180));
end else
if Angle <= 270 then
begin
OffsX := Trunc(Size.cx * -cos(Angle * Pi / 180) +
Size.cy * sin((Angle - 180) * Pi / 180));
OffsY := Trunc(Size.cy * sin((270 - Angle) * Pi / 180));
end else
if Angle <= 360 then
begin
OffsX := Trunc(Size.cy * sin((360 - Angle) * Pi / 180));
OffsY := 0;
end;
TextTop := OffsY;
TextLeft := OffsX;
end;
function NeedOffsetCalc: Boolean;
begin
Result := (TGtk3DeviceContext(DC).CurrentFont.LogFont.lfOrientation <> 0) and
(Flags and DT_SINGLELINE <> 0) and
(Flags and DT_VCENTER = 0) and (Flags and DT_CENTER = 0) and
(Flags and DT_RIGHT = 0) and (Flags and DT_BOTTOM = 0) and
(Flags and DT_CALCRECT = 0) and not IsRectEmpty(SavedRect);
end;
procedure DrawLineRaw(theLine: PChar; LineLength, TopPos: Longint);
var
Points: array[0..1] of TSize;
LeftPos: Longint;
begin
if LeftOffset <> DT_LEFT then
GetTextExtentPoint(DC, theLine, LineLength, {%H-}Points[0]);
if TempBrush = HBRUSH(-1) then
TempBrush := SelectObject(DC, GetStockObject(NULL_BRUSH));
case LeftOffset of
DT_LEFT:
LeftPos := theRect.Left;
DT_CENTER:
LeftPos := theRect.Left + (theRect.Right - theRect.Left) div 2
- Points[0].cX div 2;
DT_RIGHT:
LeftPos := theRect.Right - Points[0].cX;
end;
Pt := Point(0, 0);
// Draw line of Text
if NeedOffsetCalc then
begin
Pt.X := SavedRect.Left;
Pt.Y := SavedRect.Top;
CalculateOffsetWithAngle(TGtk3DeviceContext(DC).CurrentFont.LogFont.lfOrientation, Pt.X, Pt.Y);
end;
TextUtf8Out(DC, LeftPos + Pt.X, TopPos + Pt.Y, theLine, lineLength);
end;
procedure DrawLine(theLine: PChar; LineLength, TopPos: Longint);
var
Points: array[0..1] of TSize;
LogP: TLogPen;
LeftPos: Longint;
begin
if TempBrush = HBRUSH(-1) then
TempBrush := SelectObject(DC, GetStockObject(NULL_BRUSH));
FillByte({%H-}Points[0],SizeOf(Points[0])*2,0);
if LeftOffset <> DT_Left then
GetTextExtentPoint(DC, theLine, LineLength, Points[0]);
case LeftOffset of
DT_LEFT:
LeftPos := theRect.Left;
DT_CENTER:
LeftPos := theRect.Left + (theRect.Right - theRect.Left) div 2
- Points[0].cX div 2;
DT_RIGHT:
LeftPos := theRect.Right - Points[0].cX;
end;
Pt := Point(0, 0);
if NeedOffsetCalc then
begin
Pt.X := SavedRect.Left;
Pt.Y := SavedRect.Top;
CalculateOffsetWithAngle(TGtk3DeviceContext(DC).CurrentFont.LogFont.lfOrientation, Pt.X, Pt.Y);
end;
// Draw line of Text
TextUtf8Out(DC, LeftPos + Pt.X, TopPos + Pt.Y, theLine, LineLength);
// Draw Prefix
if (pIndex > 0) and (pIndex<=LineLength) then
begin
// Create & select pen of font color
if TempPen = HPEN(-1) then
begin
LogP.lopnStyle := PS_SOLID;
LogP.lopnWidth.X := 1;
LogP.lopnColor := GetTextColor(DC);
TempPen := SelectObject(DC, CreatePenIndirect(LogP));
end;
{Get prefix line position}
GetTextExtentPoint(DC, theLine, pIndex - 1, Points[0]);
Points[0].cX := LeftPos + Points[0].cX;
Points[0].cY := TopPos + tm.tmHeight - TM.tmDescent + 1;
GetTextExtentPoint(DC, @aStr[pIndex], UTF8CodepointSize(@aStr[pIndex]), Points[1]);
Points[1].cX := Points[0].cX + Points[1].cX;
Points[1].cY := Points[0].cY;
{Draw prefix line}
Polyline(DC, PPoint(@Points[0]), 2);
end;
end;
begin
Result := 0;
if (Str=nil) or (Str[0]=#0) or not IsValidDC(DC) then
begin
// DebugLn('TGtk3DeviceContext.DrawText params error Str Valid ? ',dbgs(Str<>nil),' DC Valid ? ',dbgs(IsValidDC(DC)),' Str#0 ',dbgs(Str[0] = #0));
exit;
end;
if (Count < -1) or (IsRectEmpty(Rect) and
((Flags and DT_CALCRECT = 0) and (Flags and DT_NOCLIP = 0))) then Exit;
// Don't try to use StrLen(Str) in cases count >= 0
// In those cases str is NOT required to have a null terminator !
if Count = -1 then
Count := StrLen(Str);
Lines := nil;
NumLines := 0;
TempDC := HDC(-1);
TempPen := HPEN(-1);
TempBrush := HBRUSH(-1);
// DebugLn('TGtk3DeviceContext.DrawText ',Str,' count=',dbgs(Count),' DT_CALCRECT ',dbgs(Flags and DT_CALCRECT <> 0),' ARect=',dbgs(Rect));
try
if (Flags and (DT_SINGLELINE or DT_CALCRECT or DT_NOPREFIX or DT_NOCLIP or DT_EXPANDTABS)) =
(DT_SINGLELINE or DT_NOPREFIX or DT_NOCLIP) then
begin
System.Move(Rect, TheRect, SizeOf(TRect));
SavedRect := Rect;
DrawLineRaw(Str, Count, Rect.Top);
Result := Rect.Bottom - Rect.Top;
Exit;
end;
SetLength(AStr{%H-},Count);
if Count>0 then
System.Move(Str^,AStr[1],Count);
if (Flags and DT_EXPANDTABS) <> 0 then
AStr := StringReplace(AStr, #9, TabString, [rfReplaceAll]);
if (Flags and DT_NOPREFIX) <> DT_NOPREFIX then
pIndex := DeleteAmpersands(AStr)
else
pIndex := -1;
GetTextMetrics(DC, TM{%H-});
DoCalcRect;
Result := theRect.Bottom - theRect.Top;
if (Flags and DT_CALCRECT) = DT_CALCRECT then
begin
// DebugLn('TGtk3WidgetSet.DrawText DT_CALCRECT Rect ',dbgs(Rect),' TheRect ',dbgs(theRect),' Result ',dbgs(Result));
System.Move(TheRect, Rect, SizeOf(TRect));
exit;
end;
TempDC := SaveDC(DC);
if (Flags and DT_NOCLIP) <> DT_NOCLIP then
begin
if theRect.Right > Rect.Right then
theRect.Right := Rect.Right;
if theRect.Bottom > Rect.Bottom then
theRect.Bottom := Rect.Bottom;
// DebugLn('******* CALLING NOT IMPLEMENTED INTERSECTCLIP RECT ');
IntersectClipRect(DC, theRect.Left, theRect.Top,
theRect.Right, theRect.Bottom);
end;
if (Flags and DT_SINGLELINE) = DT_SINGLELINE
then begin
// DebugLn(['TGtk2WidgetSet.DrawText Draw single line']);
SavedRect := TheRect;
DrawLine(PChar(AStr), length(AStr), theRect.Top);
Exit; //we're ready
end;
// multiple lines
if Lines = nil then Exit; // nothing to do
if NumLines = 0 then Exit; //
//DebugLn(['TGtk2WidgetSet.DrawText Draw multiline']);
SavedRect := Classes.Rect(0, 0, 0, 0); // no font orientation change if multilined text
for i := 0 to NumLines - 1 do
begin
if theRect.Top > theRect.Bottom then Break;
if ((Flags and DT_EDITCONTROL) = DT_EDITCONTROL)
and (tm.tmHeight > (theRect.Bottom - theRect.Top+1))
then Break;
if Lines[i] <> nil then
begin
l:=StrLen(Lines[i]);
DrawLine(Lines[i], l, theRect.Top);
dec(pIndex,l+length(LineEnding));
Size:=default(TSize);
GetTextExtentPoint(DC, Lines[i], l, Size);
LineHeight := Size.cY;
end
else
LineHeight := TM.tmHeight;
Inc(theRect.Top, LineHeight + TM.tmExternalLeading); // space between lines
end;
finally
Reallocmem(Lines, 0);
if TempBrush <> HBRUSH(-1) then
SelectObject(DC, TempBrush);// DeleteObject not needed here, because it was a default Brush
if TempPen <> HPEN(-1) then
DeleteObject(SelectObject(DC, TempPen));
if TempDC <> HDC(-1) then
RestoreDC(DC, TempDC);
end;
end;
function TGtk3WidgetSet.Ellipse(DC: HDC; x1, y1, x2, y2: Integer): Boolean;
var
bFill, bBorder: Boolean;
begin
bFill := TGtk3DeviceContext(DC).CurrentBrush.Style <> BS_NULL;
bBorder := TGtk3DeviceContext(DC).CurrentPen.Style <> psClear;
TGtk3DeviceContext(DC).drawEllipse(x1, y1, x2 - x1 - 1, y2 - y1 - 1, bFill, bBorder);
Result := True;
end;
function TGtk3WidgetSet.EnableScrollBar(Wnd: HWND; wSBflags, wArrows: Cardinal
): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.EnableScrollBar not implemented ...');
{$ENDIF}
Result := inherited EnableScrollBar(Wnd, wSBflags, wArrows);
end;
function TGtk3WidgetSet.EnableWindow(hWnd: HWND; bEnable: Boolean): Boolean;
begin
Result := False;
if hWnd <> 0 then
begin
Result := TGtk3Widget(HWND).Enabled;
TGtk3Widget(HWND).Enabled := bEnable;
end;
end;
function TGtk3WidgetSet.EndPaint(Handle: hwnd; var PS: TPaintStruct): Integer;
begin
Result := 0;
if IsValidDC(PS.HDC) then
begin
TGtk3DeviceContext(PS.HDC).Free;
PS.HDC := 0;
Result := 1;
end;
end;
procedure TGtk3WidgetSet.EnterCriticalSection(var CritSection: TCriticalSection
);
var
ACritSec: System.PRTLCriticalSection;
begin
ACritSec:=System.PRTLCriticalSection(CritSection);
System.EnterCriticalsection(ACritSec^);
end;
function TGtk3WidgetSet.EnumDisplayMonitors(hdc: HDC; lprcClip: PRect;
lpfnEnum: MonitorEnumProc; dwData: LPARAM): LongBool;
var
i: integer;
begin
Result := True;
for i := 0 to gdk_screen_get_n_monitors(gdk_screen_get_default) - 1 do
begin
Result := Result and lpfnEnum(i + 1, 0, nil, dwData);
if not Result then break;
end;
end;
function TGtk3WidgetSet.EnumFontFamiliesEx(DC: HDC; lpLogFont: PLogFont;
Callback: FontEnumExProc; Lparam: LParam; Flags: dword): longint;
type
TPangoFontFaces = packed record
FamilyName: String;
Faces: Array of String;
end;
PPangoFontFaces = Array of TPangoFontFaces;
var
i: Integer;
FontType: Integer;
EnumLogFont: TEnumLogFontEx;
Metric: TNewTextMetricEx;
FontList: TStringList;
Faces: PPangoFontFaces;
AStyle: String;
StylesCount: Integer;
StylesList: TStringList;
y: Integer;
CharsetList: TByteList;
CS: Byte;
function Gtk3GetFontFamiliesDefault(var AList: TStringList): Integer;
var
i, j: Integer;
AFamilies: PPPangoFontFamily;
AFaces: PPPangoFontFace;
ANumFaces: Integer;
begin
AList.Clear;
SetLength(Faces, 0);
Result := -1;
AFamilies := nil;
pango_context_list_families(gdk_pango_context_get, @AFamilies, @Result);
SetLength(Faces, Result);
for i := 0 to Result - 1 do
begin
j := AList.Add(StrPas(pango_font_family_get_name(AFamilies[i])));
AList.Objects[j] := TObject(PtrUInt(pango_font_family_is_monospace(AFamilies[i])));
Faces[i].FamilyName := AList[j];
AFaces := nil;
pango_font_family_list_faces(AFamilies[i], @AFaces, @ANumFaces);
SetLength(Faces[i].Faces, ANumFaces);
for j := 0 to ANumFaces - 1 do
Faces[i].Faces[j] := StrPas(pango_font_face_get_face_name(AFaces[j]));
g_free(AFaces);
end;
g_free(AFamilies);
end;
function Gtk3GetFontFamilies(var List: TStringList;
const APitch: Byte;
const AFamilyName: String;
const {%H-}AWritingSystem: Byte): Integer;
var
StrLst: TStringList;
NewList: TStringList;
S: String;
j: integer;
begin
Result := -1;
StrLst := TStringList.Create;
NewList := TStringList.Create;
try
Gtk3GetFontFamiliesDefault(StrLst);
for j := 0 to StrLst.Count - 1 do
begin
S := StrLst[j];
if APitch <> DEFAULT_PITCH then
begin
case APitch of
FIXED_PITCH, MONO_FONT:
begin
if StrLst.Objects[j] <> nil then
NewList.Add(S);
end;
VARIABLE_PITCH:
begin
if StrLst.Objects[j] = nil then
NewList.Add(S);
end;
end;
end else
NewList.Add(S);
end;
if AFamilyName <> '' then
begin
for j := NewList.Count - 1 downto 0 do
begin
S := NewList[j];;
if S <> AFamilyName then
NewList.Delete(J);
end;
end;
for j := 0 to NewList.Count - 1 do
begin
S := NewList[j];
List.Add(S);
end;
Result := List.Count;
finally
StrLst.Free;
NewList.Free;
end;
end;
function GetStyleAt(AIndex: Integer): String;
var
S: String;
begin
Result := '';
if (AIndex >= 0) and (AIndex < StylesList.Count) then
begin
S := StylesList[AIndex];
Result := S;
end;
end;
function FillLogFontA(const AIndex: Integer; var ALogFontA: TLogFontA;
var {%H-}AMetric: TNewTextMetricEx; var {%H-}AFontType: Integer;
out AStyle: String): Integer;
var
Font: PPangoFontDescription;
FontStyle: TPangoStyle;
FontWeight: TPangoWeight;
S: String;
i: Integer;
begin
S := FontList[AIndex];
Font := pango_font_description_from_string(PChar(S));
FontStyle := pango_font_description_get_style(Font);
FontWeight := pango_font_description_get_weight(Font);
ALogFontA.lfItalic := Byte(FontStyle = PANGO_STYLE_ITALIC);
// keep newer pango compat to LCL
if FontWeight = 380 {PANGO_WEIGHT_BOOK as of pango 1.24} then
FontWeight := PANGO_WEIGHT_NORMAL
else
if FontWeight = 1000 {PANGO_WEIGHT_ULTRAHEAVY as of pango 1.24} then
FontWeight := PANGO_WEIGHT_HEAVY;
ALogFontA.lfWeight := FontWeight;
ALogFontA.lfHeight := pango_font_description_get_size(Font);
if not pango_font_description_get_size_is_absolute(Font) then
ALogFontA.lfHeight := PANGO_PIXELS(ALogFontA.lfHeight);
// pango does not have underline and strikeout params for font
// ALogFontA.lfUnderline := ;
// ALogFontA.lfStrikeOut := ;
StylesList.Clear;
for i := High(Faces[AIndex].Faces) downto 0 do
StylesList.Add(Faces[AIndex].Faces[i]);
AStyle := '';
Result := StylesList.Count;
if StylesList.Count > 0 then
AStyle := GetStyleAt(0);
// current pango support in fpc is really poor, we cannot
// get PangoScript since it's in pango >= 1.4
// FillCharsetListForFont()
end;
begin
Result := 0;
{$ifdef VerboseEnumFonts}
DebugLn(['[TGtk3WidgetSet.EnumFontFamiliesEx] Charset=',lpLogFont^.lfCharSet,
' face ',lpLogFont^.lfFaceName,' pitchAndFamily=',lpLogFont^.lfPitchAndFamily]);
{$endif}
Result := 0;
Metric.ntmentm.ntmAvgWidth := 0; // just to shutup compiler
if (lpLogFont^.lfCharSet = DEFAULT_CHARSET) and
(lpLogFont^.lfFaceName= '') and
(lpLogFont^.lfPitchAndFamily = 0) then
begin
FontType := 0;
FontList := TStringList.create;
try
if Gtk3GetFontFamiliesDefault(FontList) > 0 then
begin
for i := 0 to FontList.Count - 1 do
begin
EnumLogFont.elfLogFont.lfFaceName := FontList[i];
Result := Callback(EnumLogFont, Metric, FontType, LParam);
end;
end;
finally
FontList.free;
end;
end else
begin
Result := 0;
FontType := TRUETYPE_FONTTYPE;
FontList := TStringList.Create;
StylesList := TStringList.Create;
CharsetList := TByteList.Create;
for i := 0 to CharsetEncodingList.Count - 1 do
begin
CS := TCharSetEncodingRec(CharsetEncodingList.Items[i]^).CharSet;
if CharsetList.IndexOf(CS) = -1 then
CharsetList.Add(CS);
end;
try
if Gtk3GetFontFamilies(FontList, lpLogFont^.lfPitchAndFamily,
lpLogFont^.lfFaceName, lpLogFont^.lfCharSet) > 0 then
begin
for i := 0 to FontList.Count - 1 do
begin
EnumLogFont.elfLogFont.lfFaceName := FontList[i];
EnumLogFont.elfLogFont.lfPitchAndFamily := lpLogFont^.lfPitchAndFamily;
EnumLogFont.elfFullName := FontList[i];
StylesCount := FillLogFontA(i, EnumLogFont.elfLogFont, Metric, FontType, AStyle);
EnumLogFont.elfStyle := AStyle;
if CharSetList.Count > 0 then
EnumLogFont.elfLogFont.lfCharSet := CharsetList.Items[0];
Result := Callback(EnumLogFont, Metric, FontType, LParam);
for y := 1 to StylesCount - 1 do
begin
AStyle := GetStyleAt(y);
EnumLogFont.elfStyle := AStyle;
Result := Callback(EnumLogFont, Metric, FontType, LParam);
end;
for y := 1 to CharSetList.Count - 1 do
begin
EnumLogFont.elfLogFont.lfCharSet := CharsetList.Items[y];
Result := Callback(EnumLogFont, Metric, FontType, LParam);
end;
end;
end;
finally
CharSetList.Free;
StylesList.Free;
FontList.Free;
end;
end;
end;
function TGtk3WidgetSet.EqualRgn(Rgn1: HRGN; Rgn2: HRGN): Boolean;
begin
Result := Rgn1 = Rgn2;
if Result then
exit;
if not IsValidGDIObject(Rgn1) or not IsValidGDIObject(Rgn2) then
exit;
Result := cairo_region_equal(TGtk3Region(Rgn1).Handle,TGtk3Region(Rgn2).Handle);
end;
function TGtk3WidgetSet.IntersectClipRect(dc: hdc; Left, Top, Right,Bottom: Integer): Integer;
var
rgn,clip:HRGN;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.ExcludeClipRect not implemented ...');
{$ENDIF}
rgn:=Self.CreateRectRgn(Left,Top,Right,Bottom);
//Self.SelectClipRGN(dc,rgn);
clip:=Self.CreateEmptyRegion;
Self.GetClipRGN(dc,clip);
Self.CombineRgn(clip,rgn,clip,RGN_AND);
Self.SelectClipRGN(dc,clip);
DeleteObject(clip);
DeleteObject(rgn);
// fail Self.ExtSelectClipRGN(dc,rgn,RGN_AND);
{ ncorg:=Tgtk3DeviceContext(dc).fncOrigin;
GetWindowOrgEx(DC, @DCOrigin);
Result:=inherited IntersectClipRect(dc, Left, Top, Right, Bottom);}
Result:=0;
end;
function TGtk3WidgetSet.ExcludeClipRect(dc: hdc; Left, Top, Right,
Bottom: Integer): Integer;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.ExcludeClipRect not implemented ...');
{$ENDIF}
Result:=inherited ExcludeClipRect(dc, Left, Top, Right, Bottom);
end;
function TGtk3WidgetSet.ExtCreatePen(dwPenStyle, dwWidth: DWord;
const lplb: TLogBrush; dwStyleCount: DWord; lpStyle: PDWord): HPEN;
var
APen: TGtk3Pen;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
// DebugLn('WARNING: TGtk3WidgetSet.ExtCreatePen not implemented ...');
{$ENDIF}
APen := TGtk3Pen.Create;
APen.IsExtPen := True;
case dwPenStyle and PS_STYLE_MASK of
PS_SOLID: APen.Style := psSolid;
PS_DASH: APen.Style := psDash;
PS_DOT: APen.Style := psDot;
PS_DASHDOT: APen.Style := psDashDot;
PS_DASHDOTDOT: APen.Style := psDashDotDot;
PS_NULL: APen.Style := psClear;
else
APen.Style := psSolid;
end;
APen.Cosmetic := (dwPenStyle and PS_TYPE_MASK) = PS_COSMETIC;
if (dwPenStyle and PS_TYPE_MASK) = PS_GEOMETRIC then
begin
APen.Width := dwWidth;
case dwPenStyle and PS_JOIN_MASK of
PS_JOIN_ROUND: APen.JoinStyle := pjsRound;
PS_JOIN_BEVEL: APen.JoinStyle := pjsBevel;
PS_JOIN_MITER: APen.JoinStyle := pjsMiter;
end;
case dwPenStyle and PS_ENDCAP_MASK of
PS_ENDCAP_ROUND: APen.EndCap := pecRound;
PS_ENDCAP_SQUARE: APen.EndCap := pecSquare;
PS_ENDCAP_FLAT: APen.EndCap := pecFlat;
end;
end;
if (dwPenStyle and PS_STYLE_MASK) = PS_USERSTYLE then
begin
//TODO: APen.setDashPattern
end;
APen.Color := TColor(lplb.lbColor); // ColorToRGB() ?
APen.LogPen.lopnColor := lplb.lbColor;
APen.LogPen.lopnStyle := (dwPenStyle and PS_STYLE_MASK) or (dwPenStyle and PS_JOIN_MASK) or (dwPenStyle and PS_ENDCAP_MASK);
APen.LogPen.lopnWidth.X := dwWidth;
APen.LogPen.lopnWidth.Y := dwWidth;
Result := HPen(APen);
end;
function TGtk3WidgetSet.ExtSelectClipRGN(dc: hdc; rgn: hrgn; Mode: Longint): Integer;
var
GtkDC: TGtk3DeviceContext absolute DC;
ARect: TGdkRectangle;
DCOrigin: TPoint;
R: Classes.TRect;
Clip: HRGN;
Tmp: HRGN;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
// DebugLn('WARNING: TGtk3WidgetSet.ExtSelectClipRGN not implemented ...');
{$ENDIF}
if not IsValidDC(DC) then
begin
Result := ERROR;
exit;
end else
Result := SIMPLEREGION;
// DebugLn('WARNING: TGtk3WidgetSet.ExtSelectClipRGN not implemented ...Mode=',dbgs(Mode));
case Mode of
RGN_COPY: Result := SelectClipRGN(DC, RGN);
RGN_OR,
RGN_XOR,
RGN_AND:
begin
// as MSDN says only RGN_COPY allows NULL RGN param.
if not IsValidGDIObject(RGN) then
begin
Result := ERROR;
exit;
end;
// get existing clip
gdk_cairo_get_clip_rectangle(GtkDC.pcr, @ARect);
R := RectFromGdkRect(ARect);
if IsRectEmpty(R) then
begin
// no clip, just select RGN
Result := SelectClipRGN(DC, RGN);
exit;
end;
// get transformation
GetWindowOrgEx(DC, @DCOrigin);
// DebugLn('ExtSelectClipRgn DCOrigin=',dbgs(DCOrigin),' R=',dbgs(R));
// OffsetRect(R, -DCOrigin.X, -DCOrigin.Y);
// DebugLn('ExtSelectClipRgn after DCOrigin=',dbgs(DCOrigin),' R=',dbgs(R));
Clip := CreateRectRGN(0, 0, R.Right - R.Left, R.Bottom - R.Top);
cairo_region_translate(TGtk3Region(Clip).Handle, -DCOrigin.X, -DCOrigin.Y);
// create target clip
Tmp := CreateEmptyRegion;
// CreateEmptyRegion;
// combine
Result := CombineRGN(Tmp, Clip, RGN, Mode);
// commit
SelectClipRGN(DC, Tmp);
// clean up
DeleteObject(Clip);
DeleteObject(Tmp);
end;
RGN_DIFF:
begin
//DebugLn('WARNING: TGtk3DeviceContext.ExtSelectClipRgn RGN_DIFF not implemented .');
//exit;
// when substracting we must have active clipregion
// with all of its rects.
gdk_cairo_get_clip_rectangle(GtkDC.pcr, @ARect);
R := RectFromGdkRect(ARect);
if IsRectEmpty(R) then
begin
// no clip, just select RGN
Result := SelectClipRGN(DC, RGN);
exit;
end;
Clip := CreateRectRGN(R.Left, R.Top, R.Right, R.Bottom);
Tmp := CreateEmptyRegion;
Result := CombineRGN(Tmp, HRGN(Clip), RGN, MODE);
// X11 paintEngine comment only !
// we'll NOT reset num of rects here (performance problem) like we do
// in ExcludeClipRect, because this function must be correct,
// if someone want accurate ExcludeClipRect with X11 then
// use code from intfbasewinapi.inc TWidgetSet.ExcludeClipRect()
// which calls this function and then combineRgn.
SelectClipRGN(DC, Tmp);
DeleteObject(Clip);
DeleteObject(Tmp);
end;
end;
end;
function TGtk3WidgetSet.ExtTextOut(DC: HDC; X, Y: Integer; Options: Longint;
Rect: PRect; Str: PChar; Count: Longint; Dx: PInteger): Boolean;
var
GtkDC: TGtk3DeviceContext absolute DC;
AHWND: HWND;
AOffset: TPoint;
AScrollinfo: TScrollInfo;
begin
Result := False;
{$IFDEF VerboseGtk3DeviceContext}
DebugLn(Format('TGtk3WidgetSet.ExtTextOut x=%d y=%d Text=%s count=%d ',[X, Y, String(Str), Count]));
{$ENDIF}
if IsValidDC(DC)then
begin
cairo_save(GtkDc.pcr);
if Options and ETO_CLIPPED = ETO_CLIPPED then
begin
cairo_rectangle(GtkDc.pcr, Rect^.Left, Rect^.Top, Rect^.Right - Rect^.Left, Rect^.Bottom - Rect^.Top);
cairo_clip(GtkDc.pcr);
end;
if Options and ETO_OPAQUE = ETO_OPAQUE then
TGtk3DeviceContext(DC).fillRect(Rect, HBRUSH(GtkDC.CurrentBrush));
TGtk3DeviceContext(DC).drawText(X, Y, Str, Count);
cairo_restore(GtkDc.pcr);
Result := True;
end;
end;
function TGtk3WidgetSet.FillRect(DC: HDC; const Rect: TRect; Brush: HBRUSH
): Boolean;
begin
Result := False;
if IsValidDC(DC) then
begin
with Rect do
TGtk3DeviceContext(DC).fillRect(Left, Top, Right - Left, Bottom - Top, Brush);
Result := True;
end;
end;
function TGtk3WidgetSet.FillRgn(DC: HDC; RegionHnd: HRGN; hbr: HBRUSH): Bool;
var
R: TRect;
begin
Result := False;
if IsValidDC(DC) and IsValidGDIObject(RegionHnd) then
begin
R := TGtk3Region(RegionHnd).GetExtents;
TGtk3DeviceContext(DC).fillRect(R.Left, R.Top, R.Right - R.Left, R.Bottom - R.Top);
Result := True;
end;
end;
function TGtk3WidgetSet.Frame3d(DC: HDC; var ARect: TRect;
const FrameWidth: integer; const Style: TBevelCut): Boolean;
const
PixelOffset = 0.5;
NColorLight = clWindow;
NColorDark = clBtnShadow;
var
Color1, Color2: TGdkRGBA;
cr: Pcairo_t;
i: Integer;
begin
Result := False;
if not IsValidDC(DC) then
Exit;
Result := True;
if FrameWidth <= 0 then
Exit;
case Style of
bvNone:
Exit;
bvSpace:
begin
InflateRect(ARect, -FrameWidth, -FrameWidth);
Exit;
end;
bvRaised:
begin
Color1 := TColorToTGdkRGBA(ColorToRGB(NColorLight));
Color2 := TColorToTGdkRGBA(ColorToRGB(NColorDark));
end;
bvLowered:
begin
Color1 := TColorToTGdkRGBA(ColorToRGB(NColorDark));
Color2 := TColorToTGdkRGBA(ColorToRGB(NColorLight));
end;
end;
cr := TGtk3DeviceContext(DC).pcr;
cairo_save(cr);
try
cairo_set_line_width(cr, 1);
cairo_set_line_cap(cr, cairo_line_cap_t.CAIRO_LINE_CAP_ROUND);
cairo_set_line_join(cr, cairo_line_join_t.CAIRO_LINE_JOIN_ROUND);
for i := 1 to FrameWidth do
begin
cairo_set_source_rgb(cr, Color1.red, Color1.green, Color1.blue);
cairo_move_to(cr, ARect.Left+PixelOffset, ARect.Top+PixelOffset);
cairo_line_to(cr, ARect.Right+PixelOffset-1, ARect.Top+PixelOffset);
cairo_move_to(cr, ARect.Left+PixelOffset, ARect.Top+PixelOffset);
cairo_line_to(cr, ARect.Left+PixelOffset, ARect.Bottom+PixelOffset-1);
cairo_stroke(cr);
cairo_set_source_rgb(cr, Color2.red, Color2.green, Color2.blue);
cairo_move_to(cr, ARect.Left+PixelOffset, ARect.Bottom+PixelOffset-1);
cairo_line_to(cr, ARect.Right+PixelOffset-1, ARect.Bottom+PixelOffset-1);
cairo_move_to(cr, ARect.Right+PixelOffset-1, ARect.Top+PixelOffset);
cairo_line_to(cr, ARect.Right+PixelOffset-1, ARect.Bottom+PixelOffset-1);
cairo_stroke(cr);
InflateRect(ARect, -1, -1);
end;
finally
cairo_restore(cr);
end;
end;
function TGtk3WidgetSet.FrameRect(DC: HDC; const ARect: TRect; hBr: HBRUSH): Integer;
const
PixelOffset = 0.5;
var
cr: Pcairo_t;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('TGtk3WidgetSet.FrameRect ARect=',dbgs(ARect));
{$ENDIF}
Result := 0;
if not IsValidDC(DC) then
exit;
cr := TGtk3DeviceContext(DC).pcr;
cairo_rectangle(cr, ARect.Left+PixelOffset, ARect.Top+PixelOffset, ARect.Right-ARect.Left-1, ARect.Bottom-ARect.Top-1);
if IsValidGDIObject(hBr) then
TGtk3DeviceContext(DC).SetSourceColor(TGtk3Brush(HBR).Color);
cairo_set_line_width(cr, 1);
cairo_stroke(cr); //Don't touch
end;
function TGtk3WidgetSet.HideCaret(hWnd: HWND): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.HideCaret not implemented ...');
{$ENDIF}
Result:=inherited HideCaret(hWnd);
end;
function TGtk3WidgetSet.GetActiveWindow: HWND;
var
AWindow: PGdkWindow;
AData: gpointer;
AWidget: PGtkWidget;
i: Integer;
begin
Result := 0;
AWindow := gdk_screen_get_active_window(gdk_screen_get_default);
if AWindow <> nil then
begin
gdk_window_get_user_data(AWindow,@AWidget);
if AWidget <> nil then
begin
AData := g_object_get_data(AWidget, 'lclwidget');
// DebugLn('TGtk3WidgetSet.GetActiveWindow found window from data ...',dbgsName(TGtk3Widget(AData).LCLObject));
exit({%H-}HWND(AData));
end;
for i := 0 to Screen.FormCount - 1 do
begin
if Screen.Forms[i].HandleAllocated then
begin
if PGtkWindow(TGtk3Window(Screen.Forms[i].Handle).Widget)^.get_window = AWindow then
begin
AWidget := PGtkWindow(TGtk3Window(Screen.Forms[i].Handle).Widget)^.get_focus;
Result := HWND(Screen.Forms[i].Handle);
end;
end;
end;
end;
end;
function TGtk3WidgetSet.GetBitmapBits(Bitmap: HBITMAP; Count: Longint;
Bits: Pointer): Longint;
begin
Result:=inherited GetBitmapBits(Bitmap, Count, Bits);
end;
function TGtk3WidgetSet.GetBkColor(DC: HDC): TColorRef;
begin
Result := 0;
if IsValidDC(DC) then
Result := TGtk3DeviceContext(DC).CurrentBrush.Color;
end;
function TGtk3WidgetSet.GetCapture: HWND;
begin
Result := HwndFromGtkWidget(gtk_grab_get_current);
{$IFDEF VerboseGtk3WinApi}
DebugLn('TGtk3WidgetSet.GetCapture ',dbgHex(Result));
{$ENDIF}
end;
function TGtk3WidgetSet.GetCaretPos(var lpPoint: TPoint): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.GetCaretPos not implemented ...');
{$ENDIF}
Result:=inherited GetCaretPos(lpPoint);
end;
function TGtk3WidgetSet.GetCaretRespondToFocus(handle: HWND;
var ShowHideOnFocus: boolean): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.GetCaretPosRespondToFocus not implemented ...');
{$ENDIF}
Result:=inherited GetCaretRespondToFocus(handle, ShowHideOnFocus);
end;
function TGtk3WidgetSet.GetCharABCWidths(DC: HDC; p2, p3: UINT; const ABCStructs
): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.GetCharABCWidths not implemented ...');
{$ENDIF}
Result:=inherited GetCharABCWidths(DC, p2, p3, ABCStructs);
end;
function TGtk3WidgetSet.GetClientBounds(handle: HWND; var ARect: TRect
): Boolean;
begin
{$IF DEFINED(VerboseGtk3WinAPI) OR DEFINED(GTK3DEBUGSIZE)}
DebugLn('[Gtk3WinAPI GetClientBounds]');
{$ENDIF}
if Handle = 0 then
Exit(False);
ARect := TGtk3Widget(handle).getClientBounds;
Result := True;
end;
function TGtk3WidgetSet.GetClientRect(handle: HWND; var ARect: TRect): Boolean;
begin
{$IF DEFINED(VerboseGtk3WinAPI) OR DEFINED(GTK3DEBUGSIZE)}
DebugLn('[Gtk3WinAPI GetClientRect]');
{$ENDIF}
if Handle = 0 then
Exit(False);
ARect := TGtk3Widget(handle).getClientRect;
Result := True;
end;
function TGtk3WidgetSet.GetClipBox(DC: hDC; lpRect: PRect): Longint;
var
GtkDC: TGtk3DeviceContext absolute DC;
cr: Pcairo_t;
//Pt: TPoint;
ARect: TGdkRectangle;
begin
//{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
//DebugLn('WARNING: TGtk3WidgetSet.GetClipBox not implemented ...');
//{$ENDIF}
Result := NULLREGION;
if lpRect <> nil then
lpRect^ := Rect(0,0,0,0);
if not IsValidDC(DC) then
Result := ERROR;
if Result <> ERROR then
begin
cr := GtkDC.pcr;
if gdk_cairo_get_clip_rectangle(cr, @ARect) then
begin
lpRect^ := RectFromGdkRect(ARect);
Result := SimpleRegion;
end;
end;
end;
function TGtk3WidgetSet.GetClipRGN(DC: hDC; RGN: hRGN): Longint;
var
ARect: TGdkRectangle;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
// DebugLn('WARNING: TGtk3WidgetSet.GetClipRgn not implemented ...');
{$ENDIF}
Result := -1;
if not IsValidDC(DC) or (RGN = 0) then
exit;
gdk_cairo_get_clip_rectangle(TGtk3DeviceContext(DC).pcr, @ARect);
// DebugLn('GetClipRgn ',dbgs(TGtk3Region(RGN).GetExtents),' clipRect ',dbgs(RectFromGdkRect(ARect)));
if IsRectEmpty(RectFromGdkRect(ARect)) then
exit(0)
else
begin
cairo_region_destroy(TGtk3Region(RGN).Handle);
TGtk3Region(RGN).Handle := cairo_region_create_rectangle(@ARect);
Result := 1;
end;
end;
function TGtk3WidgetSet.GetCmdLineParamDescForInterface: string;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.GetCmdLineParamDescForInterface not implemented ...');
{$ENDIF}
Result:=inherited GetCmdLineParamDescForInterface;
end;
function TGtk3WidgetSet.GetCurrentObject(DC: HDC; uObjectType: UINT): HGDIOBJ;
var
GtkDC: TGtk3DeviceContext absolute DC;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
// DebugLn('WARNING: TGtk3WidgetSet.GetCurrentObject not implemented ...');
{$ENDIF}
// Result:=inherited GetCurrentObject(DC, uObjectType);
Result := 0;
if not IsValidDC(DC) then
Exit;
case uObjectType of
OBJ_BITMAP: Result := HGDIOBJ(GtkDC.CurrentImage);
OBJ_BRUSH: Result := HGDIOBJ(GtkDC.CurrentBrush);
OBJ_FONT: Result := HGDIOBJ(GtkDC.CurrentFont);
OBJ_PEN: Result := HGDIOBJ(GtkDC.CurrentPen);
OBJ_REGION: Result := HGDIOBJ(GtkDC.CurrentRegion);
end;
end;
function TGtk3WidgetSet.GetCursorPos(var lpPoint: TPoint): Boolean;
var
ADeviceManager: PGdkDeviceManager;
APointer: PGdkDevice;
AScreen: PGdkScreen;
begin
ADeviceManager := gdk_display_get_device_manager(gdk_display_get_default);
APointer := gdk_device_manager_get_client_pointer(ADeviceManager);
AScreen := gdk_screen_get_default;
gdk_device_get_position(APointer, @AScreen, @lpPoint.X, @lpPoint.Y);
Result := True;
end;
function TGtk3WidgetSet.GetDC(hWnd: HWND): HDC;
var
Widget: TGtk3Widget;
begin
if Gtk3WidgetSet.IsValidHandle(hWnd) then
begin
Widget := TGtk3Widget(hWnd);
Result := Widget.Context;
if Result = 0 then
Result := HDC(Gtk3DefaultContext);
end else
Result := HDC(Gtk3ScreenContext);
end;
function TGtk3WidgetSet.GetDCOriginRelativeToWindow(PaintDC: HDC;
WindowHandle: HWND; var OriginDiff: TPoint): boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.GetDCOriginRelativeToWindow not implemented ...');
{$ENDIF}
Result:=inherited GetDCOriginRelativeToWindow(PaintDC, WindowHandle,
OriginDiff);
end;
function TGtk3WidgetSet.GetDesignerDC(WindowHandle: HWND): HDC;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.GetDesignerDC not implemented ...');
{$ENDIF}
Result:=inherited GetDesignerDC(WindowHandle);
end;
function TGtk3WidgetSet.GetDeviceCaps(DC: HDC; Index: Integer): Integer;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
if (Index <> BITSPIXEL) and (Index <> LOGPIXELSX) and (Index <> LOGPIXELSY) then
DebugLn('WARNING: TGtk3WidgetSet.GetDeviceCaps not implemented ...Index=',dbgs(Index),' DC=',dbgs(DC));
{$ENDIF}
Result := 0; // inherited GetDeviceCaps(DC, Index);
case Index of
HORZRES : { Horizontal width in pixels }
begin
if IsValidDC(DC) then
begin
Result := TGtk3DeviceContext(DC).getDeviceSize.X;
end else
Result := GetSystemMetrics(SM_CXSCREEN);
end;
VERTRES : { Vertical height in pixels }
begin
if IsValidDC(DC) then
begin
Result := TGtk3DeviceContext(DC).getDeviceSize.Y;
end else
Result := GetSystemMetrics(SM_CYSCREEN);
end;
HORZSIZE : { Horizontal size in millimeters }
Result := LazUtilities.RoundToInt((GetDeviceCaps(DC, HORZRES) * 100) /
(GetDeviceCaps(DC, LOGPIXELSX) * 25.4));
VERTSIZE : { Vertical size in millimeters }
Result := LazUtilities.RoundToInt((GetDeviceCaps(DC, VERTRES) * 100) /
(GetDeviceCaps(DC, LOGPIXELSY) * 25.4));
BITSPIXEL:
begin
if IsValidDC(DC) then
Result := TGtk3DeviceContext(DC).getDepth
else
Result := gdk_window_get_visual(gdk_get_default_root_window)^.get_depth;
end;
PLANES: Result := 1;
SIZEPALETTE: Result := gdk_window_get_visual(gdk_get_default_root_window)^.get_colormap_size;
LOGPIXELSX : { Logical pixels per inch in X }
begin
Result := LazUtilities.RoundToInt(gdk_screen_width / (gdk_screen_width_mm / 25.4));
end;
LOGPIXELSY : { Logical pixels per inch in Y }
begin
Result := LazUtilities.RoundToInt(gdk_screen_height / (gdk_screen_height_mm / 25.4));
end;
end;
end;
function TGtk3WidgetSet.GetDeviceSize(DC: HDC; var p: TPoint): boolean;
var
ARect: TGdkRectangle;
begin
Result := False;
if not IsValidDC(DC) then
exit;
if TGtk3DeviceContext(DC).Parent <> nil then
begin
if Gtk3IsGdkWindow(TGtk3DeviceContext(DC).Parent^.window) then
begin
p.X := gdk_window_get_width(TGtk3DeviceContext(DC).Parent^.window);
p.Y := gdk_window_get_height(TGtk3DeviceContext(DC).Parent^.window);
Result := True;
end;
end else
if (TGtk3DeviceContext(DC).ParentPixmap <> nil) and
Gtk3IsGdkPixbuf(TGtk3DeviceContext(DC).ParentPixmap) then
begin
p.X := TGtk3DeviceContext(DC).ParentPixmap^.get_width;
p.Y := TGtk3DeviceContext(DC).ParentPixmap^.get_height;
Result := True;
end else
if TGtk3DeviceContext(DC).pcr <> nil then
begin
gdk_cairo_get_clip_rectangle(TGtk3DeviceContext(DC).pcr, @ARect);
p.X := ARect.Width;
p.Y := ARect.Height;
Result := True;
end;
end;
function TGtk3WidgetSet.GetDIBits(DC: HDC; Bitmap: HBitmap; StartScan,
NumScans: UINT; Bits: Pointer; var BitInfo: BitmapInfo; Usage: UINT): Integer;
begin
Result:=inherited GetDIBits(DC, Bitmap, StartScan, NumScans, Bits, BitInfo,
Usage);
end;
function TGtk3WidgetSet.GetDpiForMonitor(hmonitor: HMONITOR;
dpiType: TMonitorDpiType; out dpiX: UINT; out dpiY: UINT): HRESULT;
var
w,w_mm,h,h_mm:gint;
rr:double;
pscr:PGdkScreen;
begin
(* MONITOR_DPI_TYPE = (
MDT_EFFECTIVE_DPI = 0,
MDT_ANGULAR_DPI = 1,
MDT_RAW_DPI = 2,
MDT_DEFAULT = MDT_EFFECTIVE_DPI);
TMonitorDpiType = MONITOR_DPI_TYPE;
*)
pscr:=TGdkScreen.get_default;
w:=pscr^.get_width;
w_mm:=pscr^.get_width_mm;
h:=pscr^.get_height;
h_mm:=pscr^.get_height_mm;
dpiX:=round(25.4*w/w_mm);
dpiY:=round(25.4*h/h_mm);
rr:=TGdkScreen.get_default^.get_resolution();
Result:=0;
//Result:=inherited GetDpiForMonitor(hmonitor, dpiType, dpiX, dpiY);
end;
function TGtk3WidgetSet.GetFocus: HWND;
var
i: Integer;
AWidget: PGtkWidget;
AList: PGList;
AHandle: TGtk3Window;
AWindow: PGtkWindow;
AActiveWindow: HWND;
begin
AWidget := nil;
AActiveWindow := GetActiveWindow;
if AActiveWindow <> 0 then
begin
AWidget := PGtkWindow(TGtk3Widget(AActiveWindow).Widget)^.get_focus;
end else
begin
// worst case scenario is to search for widget or when application
// isn't active anymore
AList := gtk_window_list_toplevels;
for i := 0 to g_list_length(AList) - 1 do
begin
if Gtk3IsGtkWindow(PGObject(g_list_nth(AList, i)^.data)) then
begin
// gtk3 this is really ugly, it returns .is_active for non active
// windows, while docs says that is_active is window with kbd focus
AWindow := PGtkWindow(g_list_nth(AList, i)^.data);
AHandle := TGtk3Window(HwndFromGtkWidget(AWindow));
if Assigned(AHandle) and (Screen.FocusedForm = AHandle.LCLObject) and
(AWindow^.is_active) then
begin
AWidget := PGtkWindow(g_list_nth(AList, i)^.data)^.get_focus;
if AWidget <> nil then
break;
end;
end;
end;
g_list_free(AList);
end;
Result := HwndFromGtkWidget(AWidget);
{$IFDEF GTK3DEBUGFOCUS}
DebugLn('TGtk3WidgetSet.GetFocus current focus ',dbgHex(Result));
if IsValidHandle(Result) then
DebugLn('TGtk3WidgetSet.GetFocus current focus ',dbgsName(TGtk3Widget(Result).LCLObject));
{$ENDIF}
end;
function TGtk3WidgetSet.GetFontLanguageInfo(DC: HDC): DWord;
begin
Result:=inherited GetFontLanguageInfo(DC);
end;
function TGtk3WidgetSet.GetForegroundWindow: HWND;
var
i: Integer;
AWidget: PGtkWindow;
AWindow: PGtkWindow;
AList: PGList;
begin
Result := 0;
AWidget := nil;
AWindow := nil;
AList := gtk_window_list_toplevels;
for i := 0 to g_list_length(AList) - 1 do
begin
if Gtk3IsGtkWindow(PGObject(g_list_nth(AList, i)^.data)) then
begin
AWidget := g_list_nth(AList, i)^.data;
if AWidget^.get_visible and AWidget^.is_toplevel and AWidget^.is_active then
begin
AWindow := AWidget;
break;
end;
end;
end;
g_list_free(AList);
Result := HwndFromGtkWidget(AWindow);
end;
function TGtk3WidgetSet.GetKeyState(nVirtKey: Integer): Smallint;
const
StateDown = SmallInt($FF80);
var
AKeyMap: PGdkKeymap;
AModifiers: guint;
begin
Result := 0;
Result := 0;
case nVirtKey of
VK_LSHIFT: nVirtKey := VK_SHIFT;
VK_LCONTROL: nVirtKey := VK_CONTROL;
VK_LMENU: nVirtKey := VK_MENU;
end;
(*
// GdkModifierType
GDK_SHIFT_MASK: TGdkModifierType = 1;
GDK_LOCK_MASK: TGdkModifierType = 2;
GDK_CONTROL_MASK: TGdkModifierType = 4;
GDK_MOD1_MASK: TGdkModifierType = 8;
GDK_MOD2_MASK: TGdkModifierType = 16;
GDK_MOD3_MASK: TGdkModifierType = 32;
GDK_MOD4_MASK: TGdkModifierType = 64;
GDK_MOD5_MASK: TGdkModifierType = 128;
GDK_BUTTON1_MASK: TGdkModifierType = 256;
GDK_BUTTON2_MASK: TGdkModifierType = 512;
GDK_BUTTON3_MASK: TGdkModifierType = 1024;
GDK_BUTTON4_MASK: TGdkModifierType = 2048;
GDK_BUTTON5_MASK: TGdkModifierType = 4096;
GDK_MODIFIER_RESERVED_13_MASK: TGdkModifierType = 8192;
GDK_MODIFIER_RESERVED_14_MASK: TGdkModifierType = 16384;
GDK_MODIFIER_RESERVED_15_MASK: TGdkModifierType = 32768;
GDK_MODIFIER_RESERVED_16_MASK: TGdkModifierType = 65536;
GDK_MODIFIER_RESERVED_17_MASK: TGdkModifierType = 131072;
GDK_MODIFIER_RESERVED_18_MASK: TGdkModifierType = 262144;
GDK_MODIFIER_RESERVED_19_MASK: TGdkModifierType = 524288;
GDK_MODIFIER_RESERVED_20_MASK: TGdkModifierType = 1048576;
GDK_MODIFIER_RESERVED_21_MASK: TGdkModifierType = 2097152;
GDK_MODIFIER_RESERVED_22_MASK: TGdkModifierType = 4194304;
GDK_MODIFIER_RESERVED_23_MASK: TGdkModifierType = 8388608;
GDK_MODIFIER_RESERVED_24_MASK: TGdkModifierType = 16777216;
GDK_MODIFIER_RESERVED_25_MASK: TGdkModifierType = 33554432;
GDK_SUPER_MASK: TGdkModifierType = 67108864;
GDK_HYPER_MASK: TGdkModifierType = 134217728;
GDK_META_MASK: TGdkModifierType = 268435456;
GDK_MODIFIER_RESERVED_29_MASK: TGdkModifierType = 536870912;
GDK_RELEASE_MASK: TGdkModifierType = 1073741824;
GDK_MODIFIER_MASK: TGdkModifierType = 1543512063;
*)
// AModifierMask := gdk_keymap_get_modifier_mask(AKeyMap, 0);
AKeyMap := gdk_keymap_get_default;
AModifiers := gdk_keymap_get_modifier_state(AKeyMap);
case nVirtKey of
VK_LBUTTON:
if AModifiers and GDK_BUTTON1_MASK <> 0 then
Result := Result or StateDown;
VK_RBUTTON:
if AModifiers and GDK_BUTTON2_MASK <> 0 then
Result := Result or StateDown;
VK_MBUTTON:
if AModifiers and GDK_BUTTON3_MASK <> 0 then
Result := Result or StateDown;
VK_XBUTTON1:
if AModifiers and GDK_BUTTON4_MASK <> 0 then
Result := Result or StateDown;
VK_XBUTTON2:
if AModifiers and GDK_BUTTON5_MASK <> 0 then
Result := Result or StateDown;
VK_MENU:
if AModifiers and GDK_MOD1_MASK <> 0 then
Result := Result or StateDown;
VK_SHIFT:
if AModifiers and GDK_SHIFT_MASK <> 0 then
Result := Result or StateDown;
VK_CONTROL:
if AModifiers and GDK_CONTROL_MASK <> 0 then
Result := Result or StateDown;
VK_LWIN, VK_RWIN:
if AModifiers and GDK_META_MASK <> 0 then
Result := Result or StateDown;
{$ifdef VerboseGtk3WinAPI}
else
DebugLn('TGtk3WidgetSet.GetKeyState TODO ', DbgSVKCode(Word(nVirtkey)));
{$endif}
end;
end;
function TGtk3WidgetSet.GetMapMode(DC: HDC): Integer;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.GetMapMode not implemented ...');
{$ENDIF}
Result:=inherited GetMapMode(DC);
end;
function TGtk3WidgetSet.GetMonitorInfo(Monitor: HMONITOR; lpmi: PMonitorInfo
): Boolean;
var
MonitorRect, MonitorWorkArea: TGdkRectangle;
begin
Result := (lpmi <> nil) and (lpmi^.cbSize >= SizeOf(TMonitorInfo)) or (Monitor = 0);
if not Result then Exit;
Dec(Monitor);
gdk_screen_get_monitor_geometry(gdk_screen_get_default, Monitor, @MonitorRect);
with MonitorRect do
lpmi^.rcMonitor := Bounds(x, y, width, height);
// there is no way to determine workarea in gtk
gdk_screen_get_monitor_workarea(gdk_screen_get_default, Monitor, @MonitorWorkArea);
with MonitorWorkArea do
lpmi^.rcWork := Bounds(x, y, width, height);
lpmi^.rcWork := lpmi^.rcMonitor;
if Monitor = gdk_screen_get_primary_monitor(gdk_screen_get_default) then
lpmi^.dwFlags := MONITORINFOF_PRIMARY
else
lpmi^.dwFlags := 0;
end;
function TGtk3WidgetSet.GetObject(GDIObj: HGDIOBJ; BufSize: Integer;
Buf: Pointer): Integer;
begin
Result := 0;
if not IsValidGDIObject(GDIObj) then
begin
{$ifdef VerboseGtk3WinAPI}
DebugLn('Trace:< TGtk3WidgetSet.GetObject Invalid GDI Object');
{$endif}
Exit;
end;
Result:=TGtk3ContextObject(GDIObj).Get(bufsize, buf);
end;
function TGtk3WidgetSet.GetParent(Handle: HWND): HWND;
begin
if Handle <> 0 then
Result := HWND(TGtk3Widget(Handle).getParent)
else
Result := 0;
end;
function TGtk3WidgetSet.GetProp(Handle: hwnd; Str: PChar): Pointer;
begin
Result := nil;
if not IsValidHandle(Handle) then
exit;
Result := g_object_get_data(TGtk3Widget(Handle).Widget, PgChar(Str));
end;
function TGtk3WidgetSet.GetRgnBox(RGN: HRGN; lpRect: PRect): Longint;
begin
Result := SIMPLEREGION;
if IsValidGDIObject(RGN) then
begin
lpRect^ := TGtk3Region(RGN).GetExtents;
end;
end;
function TGtk3WidgetSet.GetROP2(DC: HDC): Integer;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.GetROP2 not implemented ...');
{$ENDIF}
Result := inherited GetROP2(DC);
end;
function TGtk3WidgetSet.GetScrollBarSize(Handle: HWND; BarKind: Integer
): integer;
var
BarWidget: PGtkWidget;
Scrolled: PGtkScrolledWindow;
begin
Result := 0;
if not IsValidHandle(Handle) then
exit;
BarWidget := nil;
if wtScrollbar in TGtk3Widget(Handle).WidgetType then
BarWidget := TGtk3Widget(Handle).Widget
else
if wtScrollingWin in TGtk3Widget(Handle).WidgetType then
begin
Scrolled := TGtk3ScrollableWin(Handle).GetScrolledWindow;
if Scrolled <> nil then
begin
if BarKind = SM_CYVSCROLL then
BarWidget := Scrolled^.get_vscrollbar
else
BarWidget := Scrolled^.get_hscrollbar;
end;
end;
if BarWidget <> nil then
begin
if BarKind = SM_CYVSCROLL then
Result := BarWidget^.get_allocated_width
else
Result := BarWidget^.get_allocated_height;
end;
end;
function TGtk3WidgetSet.GetScrollbarVisible(Handle: HWND; SBStyle: Integer
): boolean;
var
AWidget: TGtk3Widget;
begin
Result := False;
if not IsValidHandle(Handle) then
exit;
AWidget := TGtk3Widget(Handle);
if wtScrollBar in AWidget.WidgetType then
Result := AWidget.Visible
else
begin
if wtScrollingWin in AWidget.WidgetType then
begin
if SBStyle = SB_Horz then
Result := TGtk3ScrollableWin(Handle).getHorizontalScrollbar^.get_visible
else
if SBStyle = SB_Vert then
Result := TGtk3ScrollableWin(Handle).getVerticalScrollbar^.get_visible
end;
end;
end;
function TGtk3WidgetSet.GetScrollInfo(Handle: HWND; SBStyle: Integer;
var ScrollInfo: TScrollInfo): Boolean;
var
Adjustment: PGtkAdjustment;
AWidget: TGtk3Widget;
AScrollWin: PGtkScrolledWindow;
begin
Result := False;
if not IsValidHandle(Handle) then
exit;
AWidget := TGtk3Widget(Handle);
Adjustment := nil;
AScrollWin := nil;
if wtScrollBar in AWidget.WidgetType then
Adjustment := PGtkScrollBar(AWidget.Widget)^.adjustment
else
if wtScrollingWin in AWidget.WidgetType then
AScrollWin := TGtk3ScrollableWin(Handle).GetScrolledWindow;
case SBStyle of
SB_Horz:
begin
if not Assigned(Adjustment) and Assigned(AScrollWin) then
Adjustment := AScrollWin^.get_hadjustment;
end;
SB_Vert:
begin
if not Assigned(Adjustment) and Assigned(AScrollWin) then
Adjustment := AScrollWin^.get_vadjustment;
end;
SB_CTL:
begin
end;
SB_BOTH:
begin
end;
end;
if Adjustment = nil then
begin
DebugLn('TGtk3WidgetSet.GetScrollInfo error: cannot get PGtkAdjustment from ',dbgsName(AWidget.LCLObject));
exit;
end;
// POS
if (ScrollInfo.fMask and SIF_POS) <> 0 then
ScrollInfo.nPos := Round(Adjustment^.Value);
// RANGE
if (ScrollInfo.fMask and SIF_RANGE) <> 0 then
begin
ScrollInfo.nMin:= Round(Adjustment^.Lower);
ScrollInfo.nMax:= Round(Adjustment^.Upper);
end;
// PAGE
if (ScrollInfo.fMask and SIF_PAGE) <> 0 then
begin
ScrollInfo.nPage := Round(Adjustment^.Page_Size);
end;
// TRACKPOS
if (ScrollInfo.fMask and SIF_TRACKPOS) <> 0 then
begin
ScrollInfo.nTrackPos := Round(Adjustment^.Value);
end;
Result := True;
end;
function TGtk3WidgetSet.GetStockObject(Value: Integer): THandle;
begin
Result := 0;
case Value of
BLACK_BRUSH: // Black brush.
Result := FStockBlackBrush;
DKGRAY_BRUSH: // Dark gray brush.
Result := FStockDKGrayBrush;
GRAY_BRUSH: // Gray brush.
Result := FStockGrayBrush;
LTGRAY_BRUSH: // Light gray brush.
Result := FStockLtGrayBrush;
NULL_BRUSH: // Null brush (equivalent to HOLLOW_BRUSH).
Result := FStockNullBrush;
WHITE_BRUSH: // White brush.
Result := FStockWhiteBrush;
BLACK_PEN: // Black pen.
Result := FStockBlackPen;
NULL_PEN: // Null pen.
Result := FStockNullPen;
WHITE_PEN: // White pen.
Result := FStockWhitePen;
{System font. By default, Windows uses the system font to draw menus,
dialog box controls, and text. In Windows versions 3.0 and later,
the system font is a proportionally spaced font; earlier versions of
Windows used a monospace system font.}
DEFAULT_GUI_FONT, SYSTEM_FONT:
begin
If FStockSystemFont <> 0 then
begin
DeleteObject(FStockSystemFont);
FStockSystemFont := 0;
end;
If FStockSystemFont = 0 then
FStockSystemFont := CreateDefaultFont;
Result := FStockSystemFont;
end;
end;
end;
function TGtk3WidgetSet.GetSysColor(nIndex: Integer): DWORD;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn(['TGtk3WidgetSet.GetSysColor WARNING: SOME SYSCOLORS ARE STILL HARDCODED nIndex=',nIndex]);
{$ENDIF}
if (nIndex = COLOR_WINDOW) or (nIndex = COLOR_WINDOWTEXT) or
(nIndex = COLOR_HIGHLIGHT) or (nIndex = COLOR_HIGHLIGHTTEXT) then
GetStyleWidget(lgsMemo)
else
if (nIndex = COLOR_MENU) or (nIndex = COLOR_MENUHILIGHT) or
(nIndex = COLOR_MENUTEXT) then
begin
GetStyleWidget(lgsMenu);
GetStyleWidget(lgsMenuitem);
end else
if (nIndex = COLOR_MENUBAR) then
GetStyleWidget(lgsMenuBar)
else
if (nIndex = COLOR_SCROLLBAR) then
GetStyleWidget(lgsVerticalScrollbar)
else
if (nIndex = COLOR_BTNFACE) or (nIndex = COLOR_BTNTEXT) or
(nIndex = COLOR_BTNSHADOW) or (nIndex = COLOR_BTNHIGHLIGHT) then
GetStyleWidget(lgsButton)
else
if (nIndex = COLOR_BACKGROUND) or (nIndex = COLOR_FORM) then
GetStyleWidget(lgsWindow);
Result := SysColorMap[nIndex];
end;
function TGtk3WidgetSet.GetSysColorBrush(nIndex: Integer): HBrush;
begin
if (nIndex < 0) or (nIndex > MAX_SYS_COLORS) then
begin
Result := 0;
DebugLn(Format('ERROR: [TGtk3WidgetSet.GetSysColorBrush] Bad Value: %d. Valid Range between 0 and %d', [nIndex, MAX_SYS_COLORS]));
end else
begin
Result := FSysColorBrushes[nIndex];
if Result = HBRUSH(-1) then
begin
InitSysColorBrushes;
Result := FSysColorBrushes[nIndex];
if Result = HBRUSH(-1) then
DebugLn('WARNING: GetSysColorBrush SysColorBrushes arent''t initialized properly....');
end;
end;
end;
function TGtk3WidgetSet.GetSystemMetrics(nIndex: Integer): Integer;
var
auw: guint;
auh: guint;
ascreen: PGdkScreen;
ARect: TGdkRectangle;
begin
Result := 0;
case nIndex of
SM_CXCURSOR,
SM_CYCURSOR:
begin
// Width and height of a cursor, in pixels. For win32 system cannot create cursors of other sizes.
// For gtk this should be maximal cursor sizes
gdk_display_get_maximal_cursor_size(gdk_display_get_default, @auw, @auh);
if nIndex = SM_CXCURSOR then
Result := auw // return width
else
Result := auh; // return height
end;
SM_CXDRAG:
begin
Result := 2;
end;
SM_CYDRAG:
begin
Result := 2;
end;
SM_CXEDGE:
begin
Result := 2;
end;
SM_CYEDGE:
begin
Result := 2;
end;
SM_CXICON,
SM_CYICON:
// big icon size
// gtk recommends sizes 16,32,48. optional: 64 and 128
Result := 128;
SM_CXMAXIMIZED:
begin
ascreen := gdk_screen_get_default();
gdk_screen_get_monitor_workarea(ascreen, 0, @ARect);
Result := ARect.width;
end;
SM_CYMAXIMIZED:
begin
ascreen := gdk_screen_get_default();
gdk_screen_get_monitor_workarea(ascreen, 0, @ARect);
Result := ARect.height;
end;
SM_CXFULLSCREEN,
SM_CXSCREEN:
begin
ascreen := gdk_screen_get_default();
gdk_screen_get_monitor_geometry(ascreen, 0, @ARect);
Result := ARect.width;
end;
SM_CXVIRTUALSCREEN:
begin
Result := gdk_Screen_Width;
end;
SM_CYFULLSCREEN,
SM_CYSCREEN:
begin
ascreen := gdk_screen_get_default();
gdk_screen_get_monitor_geometry(ascreen, 0, @ARect);
Result := ARect.height;
end;
SM_CYVIRTUALSCREEN:
begin
result := gdk_Screen_Height;
end;
SM_LCLHasFormAlphaBlend:
Result := 1;
end;
end;
function TGtk3WidgetSet.GetTextColor(DC: HDC): TColorRef;
begin
Result := CLR_INVALID;
if IsValidDC(DC) then
Result := TColorRef(TGtk3DeviceContext(DC).CurrentTextColor);
end;
function TGtk3WidgetSet.GetTextExtentPoint(DC: HDC; Str: PChar; Count: Integer;
var Size: TSize): Boolean;
begin
Result := False;
if not IsValidDC(DC) then
exit;
if (Count <= 0) or (Str = nil) or (StrPas(Str) = '') then
begin
FillChar(Size, SizeOf(Size), 0);
Exit;
end;
TGtk3DeviceContext(DC).CurrentFont.Layout^.set_text(Str, Count);
TGtk3DeviceContext(DC).CurrentFont.Layout^.get_pixel_size(@Size.Cx, @Size.CY);
// DebugLn('TGtk3WidgetSet.GetTextExtentPoint pixel size is ',dbgs(Size),
// ' avgcharwidth ',dbgs(ACharWidth div PANGO_SCALE),' avgdigitwidth ',dbgs(ADigitWidth div PANGO_SCALE));
Result := True;
end;
function TGtk3WidgetSet.GetTextMetrics(DC: HDC; var TM: TTextMetric): Boolean;
const
TestString: array[boolean] of string = (
// single byte char font
'{ABCDEFGHIJKLMNOPQRSTUVWXYZXYZabcdefghijklmnopqrstuvwxyz|_}',
// double byte char font
#0'{'#0'A'#0'B'#0'C'#0'D'#0'E'#0'F'#0'G'#0'H'#0'I'#0'J'#0'K'#0'L'#0'M'#0'N'
+#0'O'#0'P'#0'Q'#0'R'#0'S'#0'T'#0'U'#0'V'#0'W'#0'X'#0'Y'#0'Z'#0'X'#0'Y'#0'Z'
+#0'a'#0'b'#0'c'#0'd'#0'e'#0'f'#0'g'#0'h'#0'i'#0'j'#0'k'#0'l'#0'm'#0'n'#0'o'
+#0'p'#0'q'#0'r'#0's'#0't'#0'u'#0'v'#0'w'#0'x'#0'y'#0'z'#0'|'#0'_'#0'}'
);
var
AFont: TGtk3Font;
APangoMetrics: PPangoFontMetrics;
aRect: TPangoRectangle;
APangoWeight: TPangoWeight;
begin
Result := False;
if IsValidDC(DC) then
begin
//TODO add metrics to cache of font, so if we have valid metrics just return.
//or create metrics when font is created (like qt uses)
AFont := TGtk3DeviceContext(DC).CurrentFont;
APangoMetrics := pango_context_get_metrics(AFont.Layout^.get_context,
AFont.Handle, AFont.Layout^.get_context^.get_language);
if APangoMetrics = nil then
begin
DebugLn(['TGtk3WidgetSet.UpdateDCTextMetric WARNING: no pango metrics']);
exit;
end;
FillChar(TM, SizeOf(TM), #0);
TM.tmAveCharWidth := Max(1,
PANGO_PIXELS(pango_font_metrics_get_approximate_char_width(APangoMetrics))
);
TM.tmAscent := PANGO_PIXELS(APangoMetrics^.get_ascent);
TM.tmDescent := PANGO_PIXELS(APangoMetrics^.get_descent);
TM.tmHeight := TM.tmAscent + TM.tmDescent;
pango_layout_set_text(AFont.Layout, PChar(TestString[True]),
length(PChar(TestString[True])));
pango_layout_get_extents(AFont.Layout, nil, @aRect);
// lBearing := 0; // PANGO_LBEARING(aRect) div PANGO_SCALE;
// rBearing := 0; // PANGO_RBEARING(aRect) div PANGO_SCALE;
pango_layout_set_text(AFont.Layout, 'M', 1);
pango_layout_get_pixel_size(AFont.Layout, @aRect.width, @aRect.height);
TM.tmMaxCharWidth := Max(1,aRect.width);
pango_layout_set_text(AFont.Layout, 'W', 1);
pango_layout_get_pixel_size(AFont.Layout, @aRect.width, @aRect.height);
TM.tmMaxCharWidth := Max(TM.tmMaxCharWidth,aRect.width);
APangoWeight := AFont.Handle^.get_weight;
if APangoWeight < PANGO_WEIGHT_THIN then
APangoWeight := PANGO_WEIGHT_THIN;
if APangoWeight > PANGO_WEIGHT_HEAVY then
APangoWeight := PANGO_WEIGHT_HEAVY;
TM.tmWeight := APangoWeight;
TM.tmFirstChar := 'a';
TM.tmLastChar := 'z';
TM.tmDefaultChar := 'x';
TM.tmBreakChar := '?';
TM.tmItalic := Ord(AFont.Handle^.get_style = PANGO_STYLE_ITALIC);
// APangoMetrics^.get_underline_position;
// TM.tmUnderlined :=
// TM.tmStruckOut :=
pango_font_metrics_unref(APangoMetrics);
Result := True;
end;
end;
function TGtk3WidgetSet.GetViewPortExtEx(DC: HDC; Size: PSize): Integer;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.GetViewportExtEx not implemented ...');
{$ENDIF}
Result:=inherited GetViewPortExtEx(DC, Size);
end;
function TGtk3WidgetSet.GetViewPortOrgEx(DC: HDC; P: PPoint): Integer;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.GetViewportOrgEx not implemented ...');
{$ENDIF}
Result:=inherited GetViewPortOrgEx(DC, P);
end;
function TGtk3WidgetSet.GetWindowExtEx(DC: HDC; Size: PSize): Integer;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.GetWindowExtEx not implemented ...');
{$ENDIF}
Result:=inherited GetWindowExtEx(DC, Size);
end;
function TGtk3WidgetSet.GetWindowLong(Handle: HWND; int: Integer): PtrInt;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.GetWindowLong not implemented ...');
{$ENDIF}
Result:=inherited GetWindowLong(Handle, int);
end;
function TGtk3WidgetSet.GetWindowOrgEx(dc: hdc; P: PPoint): Integer;
var
Matrix: cairo_matrix_t;
dx, dy: Double;
OrigX, OrigY: LongInt;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
// DebugLn('WARNING: TGtk3WidgetSet.GetWindowOrgEx not implemented ...');
{$ENDIF}
Result := 0;
if not IsValidDC(DC) and (P <> nil) then
begin
{$ifdef VerboseGtk3WinAPI}
DebugLn('Trace: < [WinAPI GetWindowOrgEx] No valid DC or P is nil');
{$endif}
exit;
end;
cairo_get_matrix(TGtk3DeviceContext(DC).pcr, @Matrix);
dx := 0;
dy := 0;
cairo_matrix_transform_point(@Matrix, @dx, @dy);
if P <> nil then
begin
OrigX := TGtk3DeviceContext(DC).fncOrigin.X;
OrigY := TGtk3DeviceContext(DC).fncOrigin.Y;
//DebugLn('GetWindowOrgEx POINT ',Format('OrigX=%d, OrigY=%d, dx=%d, dy=%d',
// [OrigX, OrigY, Trunc(dx), Trunc(dy)]));
P^.X := OrigX-Trunc(dx);
P^.Y := OrigY-Trunc(dy);
end;
Result := 1;
end;
function TGtk3WidgetSet.GetWindowRect(Handle: hwnd; var ARect: TRect): Integer;
var
AWindow: PGdkWindow;
x, y: gint;
//w, h: gint;
GRect: TGdkRectangle;
Allocation: TGtkAllocation;
begin
Result := 0;
if Handle <> 0 then
begin
AWindow := TGtk3Widget(Handle).GetWindow;
if AWindow <> nil then
begin
AWindow^.get_origin(@x, @y);
//w := AWindow^.get_width;
//h := AWindow^.get_height;
AWindow^.get_frame_extents(@GRect);
// R := RectFromGdkRect(GRect);
ARect := Bounds(0, 0, GRect.width, GRect.Height);
Result := 1;
end else
begin
TGtk3Widget(Handle).Widget^.get_allocation(@Allocation);
ARect := Bounds(Allocation.x, Allocation.y, Allocation.width, Allocation.height);
end;
end;
end;
function TGtk3WidgetSet.GetWindowRelativePosition(Handle: hwnd; var Left,
Top: integer): boolean;
var
AWidget: TGtk3Widget;
APos: TPoint;
begin
Left:=0;
Top:=0;
if Handle = 0 then
exit(False);
AWidget := TGtk3Widget(Handle);
Result := AWidget.GetPosition(APos);
Left:=APos.X;
Top:=APos.Y;
end;
function TGtk3WidgetSet.GetWindowSize(Handle: hwnd; var Width, Height: integer
): boolean;
var
aWidget: PGtkWidget;
begin
Result := False;
if Handle <> 0 then
begin
aWidget:= TGtk3Widget(Handle).Widget;
if aWidget<>nil then
begin
Width := aWidget^.get_allocated_width;
Height := aWidget^.get_allocated_Height;
Result := True;
end;
end;
end;
procedure TGtk3WidgetSet.InitializeCriticalSection(
var CritSection: TCriticalSection);
var
ACritSec: System.PRTLCriticalSection;
begin
New(ACritSec);
System.InitCriticalSection(ACritSec^);
CritSection:=TCriticalSection(ACritSec);
end;
function TGtk3WidgetSet.InvalidateRect(aHandle: HWND; Rect: pRect;
bErase: Boolean): Boolean;
begin
Result := False;
if AHandle <> 0 then
begin
TGtk3Widget(AHandle).Update(Rect);
Result := True;
end;
end;
function TGtk3WidgetSet.InvalidateRgn(Handle: HWND; Rgn: HRGN; Erase: Boolean): Boolean;
//var
// R: TRect;
begin
Result := False; // inherited InvalidateRgn(Handle, Rgn, Erase);
if IsValidHandle(Handle) then
begin
if IsValidGDIObject(RGN) then
begin
gtk_widget_queue_draw_region(TGtk3Widget(Handle).GetContainerWidget,
TGtk3Region(RGN).Handle)
end else
TGtk3Widget(Handle).Update(nil);
//TODO: TGtk3Region must be implemented as Pcairo_region_t
// GetRgnBox(Rgn, @R);
// InvalidateRect(Handle, @R, True);
Result := True;
// gtk_widget_queue_draw_region();
end;
end;
function TGtk3WidgetSet.IsIconic(handle: HWND): boolean;
begin
Result := (handle <> 0) and TGtk3Widget(Handle).IsIconic;
end;
function TGtk3WidgetSet.IsWindow(handle: HWND): boolean;
begin
Result := (handle <> 0) and
Gtk3IsWidget(TGtk3Widget(Handle).Widget);
end;
function TGtk3WidgetSet.IsWindowEnabled(handle: HWND): boolean;
begin
Result := (handle <> 0) and TGtk3Widget(Handle).Enabled and
TGtk3Widget(Handle).Visible;
end;
function TGtk3WidgetSet.IsWindowVisible(handle: HWND): boolean;
begin
Result := (handle <> 0) and TGtk3Widget(Handle).Visible;
end;
function TGtk3WidgetSet.IsZoomed(handle: HWND): boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.IsZoomed not implemented ...');
{$ENDIF}
Result:=inherited IsZoomed(handle);
end;
procedure TGtk3WidgetSet.LeaveCriticalSection(var CritSection: TCriticalSection
);
var
ACritSec: System.PRTLCriticalSection;
begin
ACritSec:=System.PRTLCriticalSection(CritSection);
System.LeaveCriticalsection(ACritSec^);
end;
function TGtk3WidgetSet.LineTo(DC: HDC; X, Y: Integer): Boolean;
begin
if not IsValidDC(DC) then
exit(False);
Result := TGtk3DeviceContext(DC).LineTo(X, Y);
end;
function TGtk3WidgetSet.LPtoDP(DC: HDC; var Points; Count: Integer): BOOL;
var
//Matrix: cairo_matrix_t;
cr: PCairo_t;
P: PPoint;
dx, dy: Double;
//Pt: TPoint;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
// DebugLn('WARNING: TGtk3WidgetSet.LPtoDP not implemented ...');
{$ENDIF}
Result := False;
// inherited LPtoDP(DC, Points, Count);
if not IsValidDC(DC) then
exit;
cr := TGtk3DeviceContext(DC).pcr;
P := @Points;
while Count > 0 do
begin
Dec(Count);
DX := P^.X;
DY := P^.Y;
// DebugLn('LPTODP INPUT ',Format('dx %2.2n dy %2.2n',[dx, dy]));
//cairo_matrix_translate(@Matrix, Dx, Dy);
//cairo_matrix_transform_point(@Matrix, @Dx, @Dy);
cairo_user_to_device(cr,@dx,@dy);
// DebugLn('LPTODP Output ',Format('dx %2.2n dy %2.2n',[dx, dy]));
P^.X := Round(DX)-TGtk3DeviceContext(DC).fncOrigin.x;
P^.Y := Round(DY)-TGtk3DeviceContext(DC).fncOrigin.y;
Inc(P);
end;
Result:=true;
end;
function TGtk3WidgetSet.MessageBox(hWnd: HWND; lpText, lpCaption: PChar;
uType: Cardinal): integer;
var
fact:TGtk3DialogFactory;
begin
fact:=TGtk3DialogFactory.CreateMsgBox(hWnd,lpText,lpCaption,uType);
try
fact.run;
Result:=fact.lcl_result;
finally
fact.Free;
end;
end;
function TGtk3WidgetSet.MonitorFromPoint(ptScreenCoords: TPoint; dwFlags: DWord
): HMONITOR;
var
pscr:PGdkScreen;
nmon:gint;
begin
pscr:=TGdkScreen.get_default;
nmon:=pscr^.get_monitor_at_point(ptScreenCoords.X,ptScreenCoords.Y);
Result:=HMONITOR(nmon+1);
end;
function TGtk3WidgetSet.MonitorFromWindow(hWnd: HWND; dwFlags: DWord): HMONITOR;
var
pscr:PGdkScreen;
nmon:gint;
begin
pscr:=TGdkScreen.get_default;
nmon:=pscr^.get_monitor_at_window(TGtk3Widget(hWnd).GetWindow);
Result:=HMONITOR(nmon+1);
end;
function TGtk3WidgetSet.MoveToEx(DC: HDC; X, Y: Integer; OldPoint: PPoint
): Boolean;
begin
if not IsValidDC(DC) then
exit(False);
Result := TGtk3DeviceContext(DC).MoveTo(X, Y, OldPoint);
end;
function TGtk3WidgetSet.OffsetRgn(RGN: HRGN; nXOffset, nYOffset: Integer
): Integer;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.OffsetRgn not implemented ...');
{$ENDIF}
Result:=inherited OffsetRgn(RGN, nXOffset, nYOffset);
end;
function TGtk3WidgetSet.PaintRgn(DC: HDC; RGN: HRGN): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.PaintRgn not implemented ...');
{$ENDIF}
Result:=inherited PaintRgn(DC, RGN);
end;
function TGtk3WidgetSet.PeekMessage(var lpMsg: TMsg; Handle: HWND;
wMsgFilterMin, wMsgFilterMax, wRemoveMsg: UINT): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.PeekMessage not implemented ...');
{$ENDIF}
Result:=inherited PeekMessage(lpMsg, Handle, wMsgFilterMin, wMsgFilterMax,
wRemoveMsg);
end;
function TGtk3WidgetSet.PolyBezier(DC: HDC; Points: PPoint; NumPts: Integer;
Filled, Continuous: boolean): boolean;
begin
if not IsValidDC(DC) then
exit(False);
TGtk3DeviceContext(DC).drawPolyBezier(Points, NumPts, Filled, Continuous);
Result:=True;
end;
function TGtk3WidgetSet.Polygon(DC: HDC; Points: PPoint; NumPts: Integer;
Winding: boolean): boolean;
var
NFillRule: integer;
bFill, bBorder: boolean;
begin
if not IsValidDC(DC) then
exit(False);
if Winding then
NFillRule := Ord(CAIRO_FILL_RULE_WINDING)
else
NFillRule := Ord(CAIRO_FILL_RULE_EVEN_ODD);
bFill := TGtk3DeviceContext(DC).CurrentBrush.Style <> BS_NULL;
bBorder := TGtk3DeviceContext(DC).CurrentPen.Style <> psClear;
TGtk3DeviceContext(DC).drawPolygon(Points, NumPts, NFillRule, bFill, bBorder);
Result:= True;
end;
function TGtk3WidgetSet.Polyline(DC: HDC; Points: PPoint; NumPts: Integer): boolean;
begin
if not IsValidDC(DC) then
exit(False);
if TGtk3DeviceContext(DC).CurrentPen.Style = psClear then Exit;
TGtk3DeviceContext(DC).drawPolyLine(Points, NumPts);
Result:=True;
end;
type
PCustomGtk3Message = ^TCustomGtk3Message;
TCustomGtk3Message = record
Handle: HWND;
Msg: Cardinal;
AwParam: WParam;
AlParam: LParam;
Result: LRESULT;
end;
function Gtk3ProcessPostMessage(user_data: gpointer): gboolean; cdecl;
var
AMsg: TCustomGtk3Message;
AMessage: TLMessage;
begin
Result := False;
if user_data <> nil then
begin
AMsg := TCustomGtk3Message(user_data^);
if AMsg.Handle <> 0 then
begin
FillChar(AMessage{%H-}, SizeOf(AMessage), #0);
AMessage.Msg := AMsg.Msg;
AMessage.WParam := AMsg.AwParam;
AMessage.LParam := AMsg.AlParam;
TGtk3Widget(AMsg.Handle).DeliverMessage(AMessage);
end;
g_idle_remove_by_data(user_data);
Freemem(user_data);
user_data := nil;
Result := True;
end;
end;
function TGtk3WidgetSet.PostMessage(Handle: HWND; Msg: Cardinal;
wParam: WParam; lParam: LParam): Boolean;
var
AEvent: PCustomGtk3Message;
begin
Result := False;
if Handle <> 0 then
begin
AEvent := GetMem(SizeOf(TCustomGtk3Message));
AEvent^.Handle := Handle;
AEvent^.Msg := Msg;
AEvent^.AwParam := wParam;
AEvent^.AlParam := lParam;
AEvent^.Result := 0;
g_idle_add(@Gtk3ProcessPostMessage, AEvent);
if GetCurrentThreadId <> MainThreadID then
begin
// writeln('TGtk3WidgetSet.PostMessage from different thread !');
g_main_context_wakeup(g_main_context_default);
end;
Result := True;
end;
end;
function TGtk3WidgetSet.PtInRegion(RGN: HRGN; X, Y: Integer): Boolean;
begin
Result := False;
if IsValidGDIObject(RGN) then
Result := TGtk3Region(RGN).ContainsPoint(Point(X, Y));
end;
function TGtk3WidgetSet.RadialArc(DC: HDC; left, top, right, bottom, sx, sy,
ex, ey: Integer): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.RadialArc not implemented ...');
{$ENDIF}
Result:=inherited RadialArc(DC, left, top, right, bottom, sx, sy, ex, ey);
end;
function TGtk3WidgetSet.RadialChord(DC: HDC; x1, y1, x2, y2, sx, sy, ex,
ey: Integer): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.RadialChord not implemented ...');
{$ENDIF}
Result:=inherited RadialChord(DC, x1, y1, x2, y2, sx, sy, ex, ey);
end;
function TGtk3WidgetSet.RealizePalette(DC: HDC): Cardinal;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.RealizePalette not implemented ...');
{$ENDIF}
Result := inherited RealizePalette(DC);
end;
function TGtk3WidgetSet.Rectangle(DC: HDC; X1, Y1, X2, Y2: Integer): Boolean;
var
R: TRect;
bFill, bBorder: Boolean;
begin
if not IsValidDC(DC) then
exit(False);
R := NormalizeRect(Rect(X1, Y1, X2, Y2));
if IsRectEmpty(R) then Exit(True);
bFill := TGtk3DeviceContext(DC).CurrentBrush.Style <> BS_NULL;
bBorder := TGtk3DeviceContext(DC).CurrentPen.Style <> psClear;
TGtk3DeviceContext(DC).drawRect(R.Left, R.Top, R.Right - R.Left, R.Bottom - R.Top, bFill, bBorder);
Result := True;
end;
function TGtk3WidgetSet.RectInRegion(RGN: HRGN; ARect: TRect): Boolean;
begin
Result := False;
if IsValidGDIObject(RGN) then
Result := TGtk3Region(Rgn).ContainsRect(ARect);
end;
function TGtk3WidgetSet.RectVisible(dc: hdc; const ARect: TRect): Boolean;
var
ACairoRegion: Pcairo_region_t;
ACairoRect: Tcairo_rectangle_int_t;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
// DebugLn('WARNING: TGtk3WidgetSet.RectVisible not implemented ...');
{$ENDIF}
Result := False;
if not IsValidDC(DC) then
exit;
if (TGtk3DeviceContext(DC).Parent <> nil) and
Gtk3IsGdkWindow(TGtk3DeviceContext(DC).Parent^.window) then
begin
if not gdk_window_is_visible(TGtk3DeviceContext(DC).Parent^.window) then
exit;
ACairoRegion := gdk_window_get_visible_region(TGtk3DeviceContext(DC).Parent^.window);
end else
ACairoRegion := gdk_window_get_visible_region(gdk_get_default_root_window);
ACairoRect.x := ARect.Left;
ACairoRect.y := ARect.Top;
ACairoRect.width := ARect.Right - ARect.Left;
ACairoRect.height := ARect.Bottom - ARect.Top;
Result := cairo_region_contains_rectangle(ACairoRegion, @ACairoRect) <> CAIRO_REGION_OVERLAP_OUT;
end;
function TGtk3WidgetSet.RegroupMenuItem(hndMenu: HMENU; GroupIndex: integer
): Boolean;
begin
Result := False;
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.RegroupMenuItem not implemented ...');
{$ENDIF}
// inherited RegroupMenuItem(hndMenu, GroupIndex);
end;
function TGtk3WidgetSet.ReleaseCapture: Boolean;
var
AWidget: TGtk3Widget;
begin
{$IFDEF VerboseGtk3WinApi}
DebugLn('TGtk3WidgetSet.ReleaseCapture');
{$ENDIF}
AWidget := TGtk3Widget(GetCapture);
Result := AWidget <> nil;
if Result then
begin
if AWidget.Widget = nil then exit;
if AWidget.GetContainerWidget^.has_grab then
gtk_grab_remove(AWidget.GetContainerWidget)
else
if AWidget.Widget^.has_grab then
gtk_grab_remove(AWidget.Widget);
end;
end;
function TGtk3WidgetSet.ReleaseDC(hWnd: HWND; DC: HDC): Integer;
begin
Result := 0;
if IsValidDC(DC) then
begin
if TGtk3DeviceContext(DC).CanRelease then
TGtk3DeviceContext(DC).Free;
Result := 1;
end;
end;
function TGtk3WidgetSet.RemoveProp(Handle: hwnd; Str: PChar): THandle;
begin
Result := 0;
if Handle = 0 then
exit;
if Gtk3IsObject(TGtk3Widget(Handle).Widget) then
g_object_set_data(TGtk3Widget(Handle).Widget, Str, nil);
if TGtk3Widget(Handle).GetContainerWidget <> TGtk3Widget(Handle).Widget then
begin
if Gtk3IsObject(TGtk3Widget(Handle).GetContainerWidget) then
g_object_set_data(TGtk3Widget(Handle).GetContainerWidget, Str, nil);
end;
Result := 1;
end;
function TGtk3WidgetSet.RestoreDC(DC: HDC; SavedDC: Integer): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
// DebugLn('WARNING: TGtk3WidgetSet.RestoreDC not implemented ...');
{$ENDIF}
Result := False;
if not IsValidDC(DC) then
exit;
cairo_restore(TGtk3DeviceContext(DC).pcr);
Result := True;
end;
function TGtk3WidgetSet.RoundRect(DC: hDC; X1, Y1, X2, Y2: Integer; RX,
RY: Integer): Boolean;
begin
Result := False;
if not IsValidDC(DC) then
exit;
Result := TGtk3DeviceContext(DC).RoundRect(X1, Y1, X2, Y2, RX, RY);
end;
function TGtk3WidgetSet.SaveDC(DC: HDC): Integer;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
// DebugLn('WARNING: TGtk3WidgetSet.SaveDC not implemented ...');
{$ENDIF}
Result := 0;
if not IsValidDC(DC) then
exit;
cairo_save(TGtk3DeviceContext(DC).pcr);
Result := 1;
end;
function TGtk3WidgetSet.ScreenToClient(Handle: HWND; var P: TPoint): Integer;
begin
Result := 0;
{$ifdef VerboseGtk3WinApi}
DebugLn('Trace:> [TGtk3WidgetSet.ScreenToClient] ',dbgs(P));
{$endif}
if not IsValidHandle(Handle) then
exit;
Result := TGtk3Widget(Handle).ScreenToClient(P);
end;
function TGtk3WidgetSet.ScrollWindowEx(hWnd: HWND; dx, dy: Integer; prcScroll,
prcClip: PRect; hrgnUpdate: HRGN; prcUpdate: PRect; flags: UINT): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.ScrollWindowEx not implemented ...');
{$ENDIF}
Result:=inherited ScrollWindowEx(hWnd, dx, dy, prcScroll, prcClip,
hrgnUpdate, prcUpdate, flags);
end;
function TGtk3WidgetSet.SelectClipRGN(DC: hDC; RGN: HRGN): Longint;
begin
Result := 0;
if IsValidDC(DC) then
begin
if IsValidGDIObject(RGN) then
Result := TGtk3DeviceContext(DC).setClipRegion(TGtk3Region(RGN))
else
Result := TGtk3DeviceContext(DC).ResetClip;
end;
end;
function TGtk3WidgetSet.SelectObject(DC: HDC; GDIObj: HGDIOBJ): HGDIOBJ;
begin
Result := 0;
if not IsValidDC(DC) then
exit;
if IsValidGDIObject(GDIObj) then
begin
Result:=HGDIOBJ(TGtk3ContextObject(GDIOBJ).Select(TGtk3DeviceContext(DC)));
end;
end;
function TGtk3WidgetSet.SelectPalette(DC: HDC; Palette: HPALETTE;
ForceBackground: Boolean): HPALETTE;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.SelectPalette not implemented ...');
{$ENDIF}
Result := inherited SelectPalette(DC, Palette, ForceBackground);
end;
function TGtk3WidgetSet.SendMessage(HandleWnd: HWND; Msg: Cardinal;
wParam: WParam; lParam: LParam): LResult;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.SendMessage not implemented ...');
{$ENDIF}
Result := inherited SendMessage(HandleWnd, Msg, wParam, lParam);
end;
function TGtk3WidgetSet.SetActiveWindow(Handle: HWND): HWND;
begin
Result := GetActiveWindow;
if Handle <> 0 then
begin
if wtWindow in TGtk3Widget(Handle).WidgetType then
PGtkWindow(TGtk3Window(Handle).Widget)^.present;
end;
end;
function TGtk3WidgetSet.SetBkColor(DC: HDC; Color: TColorRef): TColorRef;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
// DebugLn('WARNING: TGtk3WidgetSet.SetBkColor not implemented ...');
{$ENDIF}
Result := clNone;
if not IsValidDC(DC) then
exit;
Result := TGtk3DeviceContext(DC).CurrentBrush.Color;
TGtk3DeviceContext(DC).CurrentBrush.Color := TColor(ColorToRGB(TColor(Color)));
end;
function TGtk3WidgetSet.SetBkMode(DC: HDC; bkMode: Integer): Integer;
begin
{.$IFDEF GTK3DEBUGNOTIMPLEMENTED}
// DebugLn('WARNING: TGtk3WidgetSet.SetBkMode not implemented ...', dbgs(BkMode));
{.$ENDIF}
Result := 0;
if not IsValidDC(DC) then
exit;
Result := TGtk3DeviceContext(DC).BkMode;
TGtk3DeviceContext(DC).BkMode := bkMode;
// if cairo_pattern_get_type(cairo_get_source(TGtk3DeviceContext(DC).Widget)) = CAIRO_PATTERN_TYPE_SURFACE then
// Result := TRANSPARENT;
// we must use TGtk3Brush.Handle = Pcairo_pattern_t
// cairo_pattern_get_type(nil).CAIRO_PATTERN_TYPE_SOLID;
// cairo_get_source();
end;
function TGtk3WidgetSet.SetCapture(AHandle: HWND): HWND;
var
Message: TLMessage;
begin
{$IFDEF VerboseGtk3WinApi}
DebugLn('TGtk3WidgetSet.SetCapture');
{$ENDIF}
Result := GetCapture;
if Result <> AHandle then
begin
if Result <> 0 then
ReleaseCapture;
if IsValidHandle(AHandle) then
begin
TGtk3Widget(AHandle).SetCapture;
Message.Msg := 0;
FillChar(Message, SizeOf(Message), 0);
Message.msg := LM_CAPTURECHANGED;
Message.wParam := 0;
Message.lParam := PtrInt(Result);
LCLMessageGlue.DeliverMessage(TGtk3Widget(AHandle).LCLObject, Message);
end;
end;
end;
function TGtk3WidgetSet.SetCaretPos(X, Y: Integer): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.SetCaretPos not implemented ...');
{$ENDIF}
Result:=inherited SetCaretPos(X, Y);
end;
function TGtk3WidgetSet.SetCaretPosEx(Handle: HWnd; X, Y: Integer): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.SetCaretPosEx not implemented ...');
{$ENDIF}
Result:=inherited SetCaretPosEx(Handle, X, Y);
end;
function TGtk3WidgetSet.SetCaretRespondToFocus(handle: HWND;
ShowHideOnFocus: boolean): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.SetCaretRespondToFocus not implemented ...');
{$ENDIF}
Result:=inherited SetCaretRespondToFocus(handle, ShowHideOnFocus);
end;
function TGtk3WidgetSet.SetCursor(ACursor: HCURSOR): HCURSOR;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
// DebugLn('WARNING: TGtk3WidgetSet.SetCursor not implemented ...');
{$ENDIF}
Result := FGlobalCursor;
if ACursor = FGlobalCursor then Exit;
if ACursor = Screen.Cursors[crDefault]
then SetGlobalCursor(0)
else SetGlobalCursor(ACursor);
FGlobalCursor := ACursor;
end;
function TGtk3WidgetSet.SetCursorPos(X, Y: Integer): Boolean;
var
ADeviceManager: PGdkDeviceManager;
APointer: PGdkDevice;
begin
ADeviceManager := gdk_display_get_device_manager(gdk_display_get_default);
APointer := gdk_device_manager_get_client_pointer(ADeviceManager);
// howto get what screen we are querying on ?
// gdk_display_get_screen(gdk_display_get_default, 0);
gdk_device_warp(APointer, gdk_screen_get_default, X, Y);
Result := True;
end;
function TGtk3WidgetSet.SetFocus(hWnd: HWND): HWND;
begin
Result := GetFocus;
if hWnd <> 0 then
begin
{$IFDEF GTK3DEBUGFOCUS}
if Result <> 0 then
DebugLn('TGtk3WidgetSet.SetFocus: ',dbgsName(TGtk3Widget(HWND).LCLObject),' oldFocus ',dbgsName(TGtk3Widget(Result).LCLObject))
else
DebugLn('TGtk3WidgetSet.SetFocus: ',dbgsName(TGtk3Widget(HWND).LCLObject),' oldFocus 0');
{$ENDIF}
TGtk3Widget(HWND).setFocus;
end;
end;
function TGtk3WidgetSet.SetForegroundWindow(hWnd: HWND): boolean;
var
AWindow: TGtk3Window;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
// DebugLn('WARNING: TGtk3WidgetSet.SetForegroundWindow not implemented ...');
{$ENDIF}
if not IsValidHandle(HWnd) then
exit(False);
Result := wtWindow in TGtk3Widget(HWND).WidgetType;
if Result then
begin
AWindow := TGtk3Window(HWND);
if not AWindow.Visible then
exit(False);
// DebugLn('TGtk3WidgetSet.SetForegroundWindow ',dbgsName(AWindow.LCLObject));
AWindow.Activate;
Result := True;
end;
end;
function TGtk3WidgetSet.SetMapMode(DC: HDC; fnMapMode: Integer): Integer;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.SetMapMode not implemented ...');
{$ENDIF}
Result:=inherited SetMapMode(DC, fnMapMode);
end;
function TGtk3WidgetSet.SetParent(hWndChild: HWND; hWndParent: HWND): HWND;
begin
Result := HWND(TGtk3Widget(hWndChild).getParent);
TGtk3Widget(hWndChild).SetParent(TGtk3Widget(hWndParent),0,0)
end;
function TGtk3WidgetSet.SetProp(Handle: hwnd; Str: PChar; Data: Pointer
): Boolean;
begin
if Handle = 0 then
exit(False);
if Gtk3IsObject(TGtk3Widget(Handle).Widget) then
g_object_set_data(TGtk3Widget(Handle).Widget, Str, Data);
if TGtk3Widget(Handle).GetContainerWidget <> TGtk3Widget(Handle).Widget then
begin
if Gtk3IsObject(TGtk3Widget(Handle).GetContainerWidget) then
g_object_set_data(TGtk3Widget(Handle).GetContainerWidget, Str, Data);
end;
Result := True;
end;
function TGtk3WidgetSet.SetRectRgn(aRGN: HRGN; X1, Y1, X2, Y2: Integer
): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.SetRectRgn not implemented ...');
{$ENDIF}
Result:=inherited SetRectRgn(aRGN, X1, Y1, X2, Y2);
end;
function TGtk3WidgetSet.SetROP2(DC: HDC; Mode: Integer): Integer;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.SetROP2 not implemented ...');
{$ENDIF}
Result:=inherited SetROP2(DC, Mode);
end;
function TGtk3WidgetSet.SetScrollInfo(Handle: HWND; SBStyle: Integer;
ScrollInfo: TScrollInfo; bRedraw: Boolean): Integer;
(*
procedure SetRangeUpdatePolicy(Range: PGtkRange);
var
UpdPolicy: TGTKUpdateType;
begin
case ScrollInfo.nTrackPos of
SB_POLICY_DISCONTINUOUS: UpdPolicy := GTK_UPDATE_DISCONTINUOUS;
SB_POLICY_DELAYED: UpdPolicy := GTK_UPDATE_DELAYED;
else
UpdPolicy := GTK_UPDATE_CONTINUOUS;
end;
!!! update policy for gtkRange does not exist anymore in gtk3
so we must mimic that by using events. !!!
gtk_range_set_update_policy(Range, UpdPolicy);
end;
procedure SetScrolledWindowUpdatePolicy(ScrolledWindow:PGTKScrolledWindow);
var
Range: PGtkRange;
begin
case SBStyle of
SB_VERT: Range := PGtkRange(ScrolledWindow^.vscrollbar);
SB_HORZ: Range := PGtkRange(ScrolledWindow^.hscrollbar);
else exit;
end;
SetRangeUpdatePolicy(Range);
end;
*)
const
POLICY: array[BOOLEAN] of TGTKPolicyType = (2, 0); // GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
var
Adjustment,hadj,vadj: PGtkAdjustment;
AWidget: TGtk3Widget;
ACenter:PGtkWidget;
ARange: PGtkRange;
AScrollWin: PGtkScrolledWindow;
IsScrollbarVis: Boolean;
w,h:gint;
begin
Result := 0;
if not IsValidHandle(Handle) then
exit;
AWidget := TGtk3Widget(Handle);
Adjustment := nil;
ARange := nil;
AScrollWin := nil;
if wtScrollBar in AWidget.WidgetType then
begin
ARange := PGtkRange(AWidget.Widget);
Adjustment := ARange^.adjustment;
end else
if wtScrollingWin in AWidget.WidgetType then
begin
AScrollWin := TGtk3ScrollableWin(Handle).GetScrolledWindow;
if AScrollWin = nil then
exit;
if not Gtk3IsScrolledWindow(AScrollWin) then
begin
DebugLn('ERROR: TGtk3WidgetSet.SetScrollInfo: Wrong class extracted for scrollwin ',dbgsName(TGtk3Widget(Handle).LCLObject));
AScrollWin := nil;
end;
if Assigned(AScrollWin) then
begin
hadj := AScrollWin^.get_hadjustment;
vadj := AScrollWin^.get_vadjustment;
end else
begin
hadj:=nil;
vadj:=nil;
end;
end;
case SBStyle of
SB_Horz:
begin
if not Assigned(Adjustment) and Assigned(AScrollWin) then
begin
Adjustment := hadj;
if (ScrollInfo.fMask and SIF_RANGE) <> 0 then
begin
ACenter:=AWidget.GetContainerWidget;
Acenter^.set_size_request(ScrollInfo.nMax - ScrollInfo.nMin,round(vadj^.upper));
end;
end;
end;
SB_Vert:
begin
if not Assigned(Adjustment) and Assigned(AScrollWin) then
begin
Adjustment := vadj;
if (ScrollInfo.fMask and SIF_RANGE) <> 0 then
begin
ACenter:=AWidget.GetContainerWidget;
Acenter^.set_size_request(round(hadj^.upper),ScrollInfo.nMax - ScrollInfo.nMin);
end;
end;
end;
SB_CTL:
begin
DebugLn('TGtk3WidgetSet.SetScrollInfo SB_CTL error: not implemented ',
dbgsName(AWidget.LCLObject));
end;
SB_BOTH:
begin
DebugLn('TGtk3WidgetSet.SetScrollInfo SB_BOTH error: not implemented ',
dbgsName(AWidget.LCLObject));
end;
end;
if Adjustment = nil then
begin
DebugLn('TGtk3WidgetSet.SetScrollInfo error: cannot get PGtkAdjustment from ',
dbgsName(AWidget.LCLObject));
exit;
end;
if (ScrollInfo.fMask and SIF_RANGE) <> 0 then
begin
Adjustment^.lower := ScrollInfo.nMin;
Adjustment^.upper := ScrollInfo.nMax;
end;
if (ScrollInfo.fMask and SIF_PAGE) <> 0 then
begin
// 0 <= nPage <= nMax-nMin+1
Adjustment^.page_size := ScrollInfo.nPage;
Adjustment^.page_size := Min(Max(Adjustment^.page_size,0),
Adjustment^.upper-Adjustment^.lower+1);
Adjustment^.page_increment := (Adjustment^.page_size/6)+1;
end;
if (ScrollInfo.fMask and SIF_POS) <> 0 then
begin
// nMin <= nPos <= nMax - Max(nPage-1,0)
Adjustment^.value := ScrollInfo.nPos;
Adjustment^.value := Max(Adjustment^.value,Adjustment^.lower);
Adjustment^.value := Min(Adjustment^.value,
Adjustment^.upper-Max(Adjustment^.page_size-1,0));
end;
// check if scrollbar should be hidden
IsScrollbarVis := True;
if ((ScrollInfo.fMask and (SIF_RANGE or SIF_PAGE)) <> 0) and
((SBStyle=SB_HORZ) or (SBStyle=SB_VERT)) then
begin
if (Adjustment^.lower >= (Adjustment^.upper-Max(adjustment^.page_size-1,0)))
then begin
if (ScrollInfo.fMask and SIF_DISABLENOSCROLL) = 0 then
IsScrollbarVis := False
else
;// scrollbar should look disabled (no thumbbar and grayed appearance)
// maybe not possible in gtk
end;
end;
if bRedraw then
begin
if (AScrollWin <> nil) then
begin
// DebugLn('Setting scrollstyle of ',dbgsName(AWidget.LCLObject));
if SBStyle = SB_HORZ then
TGtk3ScrollableWin(AWidget).HScrollBarPolicy := POLICY[IsScrollbarVis]
else
if SBStyle = SB_VERT then
TGtk3ScrollableWin(AWidget).VScrollBarPolicy := POLICY[IsScrollbarVis];
end else
AWidget.Update(nil);
Adjustment^.changed;
end;
Result := Round(Adjustment^.value);
end;
function TGtk3WidgetSet.SetSysColors(cElements: Integer; const lpaElements;
const lpaRgbValues): Boolean;
begin
Result:=inherited SetSysColors(cElements, lpaElements, lpaRgbValues);
end;
function TGtk3WidgetSet.SetTextCharacterExtra(DC: hdc; nCharExtra: Integer
): Integer;
begin
Result:=inherited SetTextCharacterExtra(DC, nCharExtra);
end;
function TGtk3WidgetSet.SetTextColor(DC: HDC; Color: TColorRef): TColorRef;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
// DebugLn('WARNING: TGtk3WidgetSet.SetTextColor not implemented ...');
{$ENDIF}
Result := CLR_INVALID;
if IsValidDC(DC) then
begin
Result := TGtk3DeviceContext(DC).CurrentTextColor;
TGtk3DeviceContext(DC).CurrentTextColor := Color;
end;
end;
function TGtk3WidgetSet.SetViewPortExtEx(DC: HDC; XExtent, YExtent: Integer;
OldSize: PSize): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.SetViewPortExtEx not implemented ...');
{$ENDIF}
Result:=inherited SetViewPortExtEx(DC, XExtent, YExtent, OldSize);
end;
function TGtk3WidgetSet.SetViewPortOrgEx(DC: HDC; NewX, NewY: Integer;
OldPoint: PPoint): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.SetViewPortOrgEx not implemented ...');
{$ENDIF}
Result:=inherited SetViewPortOrgEx(DC, NewX, NewY, OldPoint);
end;
function TGtk3WidgetSet.SetWindowExtEx(DC: HDC; XExtent, YExtent: Integer;
OldSize: PSize): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.SetWindowExtEx not implemented ...');
{$ENDIF}
Result:=inherited SetWindowExtEx(DC, XExtent, YExtent, OldSize);
end;
function TGtk3WidgetSet.SetWindowLong(Handle: HWND; Idx: Integer;
NewLong: PtrInt): PtrInt;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.SetWindowLong not implemented ...');
{$ENDIF}
Result:=inherited SetWindowLong(Handle, Idx, NewLong);
end;
function TGtk3WidgetSet.SetWindowOrgEx(dc: hdc; NewX, NewY: Integer;
OldPoint: PPoint): Boolean;
var
Matrix: cairo_matrix_t;
//dx, dy: Double;
begin
Result := False; // inherited SetWindowOrgEx(dc, NewX, NewY, OldPoint);
if IsValidDC(DC) then
begin
GetWindowOrgEx(dc, OldPoint);
cairo_get_matrix(TGtk3DeviceContext(DC).pcr, @Matrix);
//dx := 0;
//dy := 0;
// cairo_matrix_init_translate(Matrix, -NewX, -NewY);
cairo_matrix_translate(@Matrix,
-NewX - TGtk3DeviceContext(DC).fncOrigin.x,
-NewY - TGtk3DeviceContext(DC).fncOrigin.Y);
cairo_transform(TGtk3DeviceContext(DC).pcr, @Matrix);
// cairo_set_matrix(TGtk3DeviceContext(DC).Widget, Matrix);
// DebugLn('TGtk3WidgetSet.SetWindowOrgEx NewX=',dbgs(NewX),' NewY=',dbgs(NewY));
Result := True;
end;
end;
function TGtk3WidgetSet.SetWindowPos(hWnd: HWND; hWndInsertAfter: HWND; X, Y,
cx, cy: Integer; uFlags: UINT): Boolean;
begin
Result := False;
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.SetWindowPos not implemented Handle=',dbgHex(hWnd),' X=',dbgs(X),' Y=',dbgs(Y));
{$ENDIF}
end;
function TGtk3WidgetSet.SetWindowRgn(hWnd: HWND; hRgn: HRGN; bRedraw: Boolean
): longint;
var
PCR: Pcairo_region_t;
begin
if hRgn = 0 then
PCR := nil
else
PCR := TGtk3Region(hRgn).Handle;
gtk_widget_shape_combine_region(TGtk3Widget(hWnd).Widget, PCR);
if bRedraw then
TGtk3Widget(hWnd).Widget^.realize;
Result:=1;
end;
function TGtk3WidgetSet.ShowCaret(hWnd: HWND): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.ShowCaret not implemented ...');
{$ENDIF}
Result:=inherited ShowCaret(hWnd);
end;
function TGtk3WidgetSet.ShowScrollBar(Handle: HWND; wBar: Integer;
bShow: Boolean): Boolean;
var
AWidget: TGtk3Widget;
// AScrolledWin: PGtkScrolledWindow;
NewPolicy: TGtkPolicyType;
begin
Result := IsValidHandle(Handle);
if not Result then
exit;
AWidget := TGtk3Widget(Handle);
if wtScrollBar in AWidget.WidgetType then
begin
AWidget.Visible := bShow;
end else
(*
if wtWindow in AWidget.WidgetType then
begin
DebugLn('WARNING: TGtk3WidgetSet.ShowScrollBar cannot get scrollbar from ',dbgsName(AWidget.LCLObject),
' bShow ',dbgs(bShow));
end else
*)
if wtScrollingWin in AWidget.WidgetType then
begin
// AScrolledWin :=
if TGtk3ScrollableWin(Handle).GetScrolledWindow = nil then
exit;
if wBar in [SB_BOTH, SB_HORZ] then
begin
if bShow then
NewPolicy := GTK_POLICY_ALWAYS
else
NewPolicy := GTK_POLICY_NEVER;
// bug in gtk3
if (wtWindow in AWidget.WidgetType) and (NewPolicy = GTK_POLICY_NEVER) then
NewPolicy := GTK_POLICY_AUTOMATIC;
TGtk3ScrollableWin(AWidget).HScrollBarPolicy := NewPolicy;
end;
if wBar in [SB_BOTH, SB_VERT] then
begin
if bShow then
NewPolicy := GTK_POLICY_ALWAYS
else
NewPolicy := GTK_POLICY_NEVER;
// bug in gtk3
if (wtWindow in AWidget.WidgetType) and (NewPolicy = GTK_POLICY_NEVER) then
NewPolicy := GTK_POLICY_AUTOMATIC;
TGtk3ScrollableWin(AWidget).VScrollBarPolicy := NewPolicy;
end;
end else
DebugLn('WARNING: TGtk3WidgetSet.ShowScrollBar cannot get scrollbar from ',dbgsName(AWidget.LCLObject));
end;
function TGtk3WidgetSet.ShowWindow(hWnd: HWND; nCmdShow: Integer): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.ShowWindow not implemented ...');
{$ENDIF}
Result := IsValidHandle(Hwnd);
if not result then exit;
if TObject(hWnd) is TGtk3Window then
Result:=TGtk3Window(hWnd).ShowState(nCmdShow)
else
begin
TGtk3Widget(hWnd).Show;
Result:=true;
end;
end;
function TGtk3WidgetSet.StretchBlt(DestDC: HDC; X, Y, Width, Height: Integer;
SrcDC: HDC; XSrc, YSrc, SrcWidth, SrcHeight: Integer; ROp: Cardinal): Boolean;
begin
Result := StretchMaskBlt(DestDC,X,Y,Width,Height,
SrcDC,XSrc,YSrc,SrcWidth,SrcHeight,
0,0,0,
ROp);
end;
function TGtk3WidgetSet.StretchMaskBlt(DestDC: HDC; X, Y, Width,
Height: Integer; SrcDC: HDC; XSrc, YSrc, SrcWidth, SrcHeight: Integer;
Mask: HBITMAP; XMask, YMask: Integer; Rop: DWORD): Boolean;
var
DestContext: TGtk3DeviceContext absolute DestDC;
SrcContext: TGtk3DeviceContext absolute SrcDC;
ATargetRect, ASrcRect: TRect;
begin
Result := False;
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.StretchMaskBlt not implemented ...');
{$ENDIF}
ATargetRect := Rect(X, Y, Width + X, Height + Y);
ASrcRect := Rect(XSrc, YSrc, SrcWidth + XSrc, SrcHeight + YSrc);
if (DestContext.OwnsSurface) and (SrcContext.OwnsSurface) or (mask<>0) then
DestContext.drawImage1(@ATargetRect, PgdkPixbuf(SrcContext.CurrentImage.Handle) , @ASrcRect, nil, nil)
else
DestContext.drawSurface(@ATargetRect,SrcContext.CairoSurface , @ASrcRect, nil, nil);
Result := True;
end;
function TGtk3WidgetSet.SystemParametersInfo(uiAction: DWord; uiParam: DWord;
pvParam: Pointer; fWinIni: DWord): LongBool;
var
wa:TGdkRectangle;
pdisp:PGdkDisplay;
pmon:PgdkMonitor;
pr:PRect;
begin
Result:=True;
Case uiAction of
SPI_GETWHEELSCROLLLINES: PDword(pvParam)^ := 3;
SPI_GETWORKAREA: begin
pdisp:=TGdkDisplay.get_default;
pmon:=pdisp^.get_primary_monitor();
pmon^.get_workarea(@wa);
pr:=PRect(pvParam);
pr^.Left:=wa.x;
pr^.Top:=wa.y;
pr^.Width:=wa.width;
pr^.Height:=wa.height;
end;
else
Result:=False;
end;
end;
function TGtk3WidgetSet.TextOut(DC: HDC; X, Y: Integer; Str: PChar; Count: Integer): Boolean;
begin
{$IFDEF VerboseGtk3DeviceContext}
DebugLn('TGtk3WidgetSet.TextOut X=',dbgs(x),' Y=',dbgs(y),' Text=',dbgs(Str),' Count=',dbgs(Count));
{$ENDIF}
Result := False;
if Count <= 0 then
Exit;
if IsValidDC(DC) then
begin
Result := True;
TGtk3DeviceContext(DC).drawText(X, Y, Str, Count);
end;
end;
function TGtk3WidgetSet.UpdateWindow(Handle: HWND): Boolean;
begin
{$ifdef VerboseGtk3WinAPI}
DebugLn('[Gtk3WinAPI UpdateWindow]');
{$endif}
Result := False;
if IsValidHandle(Handle) then
begin
TGtk3Widget(Handle).Update(nil);
if TGtk3Widget(Handle).GetContainerWidget^.get_has_window then
begin
if Gtk3IsGdkWindow(TGtk3Widget(Handle).GetContainerWidget^.window) then
TGtk3Widget(Handle).GetContainerWidget^.window^.process_updates(True);
end else
if TGtk3Widget(Handle).Widget^.get_has_window then
begin
if Gtk3IsGdkWindow(TGtk3Widget(Handle).Widget^.window) then
TGtk3Widget(Handle).Widget^.window^.process_updates(True);
end;
Result := True;
end;
end;
function TGtk3WidgetSet.WindowFromPoint(APoint: TPoint): HWND;
var
ev: TGdkEvent;
ADeviceManager: PGdkDeviceManager;
APointer: PGdkDevice;
AWindow: PGdkWindow;
AWidget: PGtkWidget;
x: gint;
y: gint;
begin
//TODO: create caching mechanism. window_at_position is pretty expensive call.
Result := 0;
ADeviceManager := gdk_display_get_device_manager(gdk_display_get_default);
APointer := gdk_device_manager_get_client_pointer(ADeviceManager);
APointer^.get_position(nil, @x ,@y);
AWindow := gdk_device_get_window_at_position(APointer, @APoint.X, @APoint.Y);
if AWindow <> nil then
begin
FillChar(ev{%H-}, SizeOf(ev), 0);
ev.any.window := AWindow;
AWidget := gtk_get_event_widget(@ev);
Result := HwndFromGtkWidget(AWidget);
(*
if Result <> 0 then
begin
DebugLn('TGtk3WidgetSet.WindowFromPoint ',dbgsName(TGtk3Widget(Result).LCLObject));
end else
DebugLn('Cannot find window under point ',dbgs(APoint));
*)
end;
end;