mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-30 23:30:30 +02:00
* Cursor patch from Paul Ishenin
* Disabled setting cursors for gtk2, since it is broken git-svn-id: trunk@10544 -
This commit is contained in:
parent
d0214c39e6
commit
92e3d63d75
@ -242,9 +242,10 @@ begin
|
||||
{$IFDEF DebugGDK}EndGDKErrorTrap;{$ENDIF}
|
||||
end;
|
||||
|
||||
if TheWinControl<>nil then begin
|
||||
if TheWinControl<>nil then
|
||||
begin
|
||||
TheWinControl.CNPreferredSizeChanged;
|
||||
SetCursor(TheWinControl, crDefault);
|
||||
SetCursor(TheWinControl, Screen.Cursors[TheWinControl.Cursor]);
|
||||
ConnectInternalWidgetsSignals(MainWidget,TheWinControl);
|
||||
|
||||
if TheWinControl is TCustomPage then
|
||||
|
@ -365,7 +365,6 @@ begin
|
||||
FExtUTF8OutCacheSize:=0;
|
||||
|
||||
FreeAllStyles;
|
||||
FreeGDKCursors;
|
||||
FreeStockItems;
|
||||
|
||||
if FGTKToolTips<>nil then begin
|
||||
@ -3530,7 +3529,7 @@ procedure TGtkWidgetSet.SetDesigning(AComponent: TComponent);
|
||||
begin
|
||||
// change cursor
|
||||
if AComponent is TWinControl then
|
||||
gtkproc.SetCursor(TWinControl(AComponent), TCursor(PtrUInt(nil)));
|
||||
gtkproc.SetCursor(TWinControl(AComponent), Screen.Cursors[TWinControl(AComponent).Cursor]);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
@ -5238,8 +5237,46 @@ begin
|
||||
end;
|
||||
|
||||
function TGTKWidgetSet.CreateStandardCursor(ACursor: SmallInt): hCursor;
|
||||
var
|
||||
CursorValue: Integer;
|
||||
begin
|
||||
Result := GetPredefinedCursor(ACursor);
|
||||
Result := 0;
|
||||
if ACursor < crLow then Exit;
|
||||
if ACursor > crHigh then Exit;
|
||||
|
||||
case TCursor(ACursor) of
|
||||
crDefault: CursorValue := GDK_LEFT_PTR;
|
||||
crNone: CursorValue := GDK_LEFT_PTR;
|
||||
crArrow: CursorValue := GDK_Arrow;
|
||||
crCross: CursorValue := GDK_Cross;
|
||||
crIBeam: CursorValue := GDK_XTerm;
|
||||
// crSize: CursorValue := GDK_FLEUR;
|
||||
crSizeNESW: CursorValue := GDK_BOTTOM_LEFT_CORNER;
|
||||
crSizeNS: CursorValue := GDK_SB_V_DOUBLE_ARROW;
|
||||
crSizeNWSE: CursorValue := GDK_TOP_LEFT_CORNER;
|
||||
crSizeWE: CursorValue := GDK_SB_H_DOUBLE_ARROW;
|
||||
crSizeNW: CursorValue := GDK_TOP_LEFT_CORNER;
|
||||
crSizeN: CursorValue := GDK_TOP_SIDE;
|
||||
crSizeNE: CursorValue := GDK_TOP_RIGHT_CORNER;
|
||||
crSizeW: CursorValue := GDK_LEFT_SIDE;
|
||||
crSizeE: CursorValue := GDK_RIGHT_SIDE;
|
||||
crSizeSW: CursorValue := GDK_BOTTOM_LEFT_CORNER;
|
||||
crSizeS: CursorValue := GDK_BOTTOM_SIDE;
|
||||
crSizeSE: CursorValue := GDK_BOTTOM_RIGHT_CORNER;
|
||||
crUpArrow: CursorValue := GDK_LEFT_PTR;
|
||||
crHourGlass:CursorValue := GDK_CLOCK;
|
||||
crHSplit: CursorValue := GDK_SB_H_DOUBLE_ARROW;
|
||||
crVSplit: CursorValue := GDK_SB_V_DOUBLE_ARROW;
|
||||
crNo: CursorValue := GDK_LEFT_PTR;
|
||||
crAppStart: CursorValue := GDK_LEFT_PTR;
|
||||
crHelp: CursorValue := GDK_QUESTION_ARROW;
|
||||
crHandPoint:CursorValue := GDK_Hand1;
|
||||
crSizeAll: CursorValue := GDK_FLEUR;
|
||||
else
|
||||
CursorValue := -1;
|
||||
end;
|
||||
if CursorValue <> -1 then
|
||||
Result := hCursor(gdk_cursor_new(CursorValue));
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
|
@ -4630,109 +4630,39 @@ var
|
||||
AWindow: PGdkWindow;
|
||||
NewCursor: PGdkCursor;
|
||||
begin
|
||||
{$ifdef gtk2}
|
||||
// MWE:
|
||||
// We seriously need to rethink the way of setting cursors.
|
||||
// for instance a button doesn't have an own xwindow.
|
||||
// so setting the cursor results in a cursor set for the parent (=most times form)
|
||||
// buttons have for instance a event_window, we might be able to set a cursor
|
||||
// for that (if an input only window allows that).
|
||||
// using an overridden Tgtk2WSButtonPrivate.SetCursor might solve it.
|
||||
{$note Rethink gtk2 setcursor}
|
||||
Exit;
|
||||
{$endif}
|
||||
|
||||
if not ((AWinControl is TWinControl) and AWinControl.HandleAllocated)
|
||||
then exit;
|
||||
|
||||
AWidget:= PGtkWidget(AWinControl.Handle);
|
||||
|
||||
{$note Move designcursor to LCL}
|
||||
if csDesigning in AWinControl.ComponentState
|
||||
then begin
|
||||
AWindow:=GetControlWindow(AWidget);
|
||||
if AWindow = nil then exit;
|
||||
if ACursor = crDefault then
|
||||
SetCursorRecursive(AWindow, GetGDKMouseCursor(GetPredefinedCursor(crDefault)))
|
||||
else begin
|
||||
NewCursor:= GetGDKMouseCursor(ACursor);
|
||||
if NewCursor <> nil then SetCursorRecursive(AWindow, NewCursor);
|
||||
end;
|
||||
end
|
||||
else begin
|
||||
|
||||
ACursor := Screen.Cursors[crDefault];
|
||||
end else
|
||||
begin
|
||||
FixWidget:= GetFixedWidget(AWidget);
|
||||
AWindow:= GetControlWindow(FixWidget);
|
||||
if AWindow = nil then exit;
|
||||
|
||||
NewCursor:= GetGDKMouseCursor(AWinControl.Cursor);
|
||||
if NewCursor <> nil then DoSetCursor(AWindow, NewCursor);
|
||||
end;
|
||||
end;
|
||||
if AWindow = nil then exit;
|
||||
|
||||
function GetPredefinedCursor(ACursor: TCursor): HCursor;
|
||||
begin
|
||||
Result := 0;
|
||||
if ACursor > crHigh then Exit;
|
||||
if ACursor < crLow then Exit;
|
||||
NewCursor := PGdkCursor(ACursor);
|
||||
if NewCursor = nil then Exit;
|
||||
|
||||
Result := ACursor - PREDEFINED_CURSOR_OFFSET;
|
||||
end;
|
||||
|
||||
function GetGDKMouseCursor(ACursor: HCursor): PGdkCursor;
|
||||
var
|
||||
CursorValue: Integer;
|
||||
begin
|
||||
Result := nil;
|
||||
if ACursor < Low(SmallInt) then Exit;
|
||||
if ACursor > High(SmallInt) then Exit;
|
||||
|
||||
if MMouseCursorMap.GetData(ACursor, Result) then Exit;
|
||||
// not yet created or illegal value
|
||||
|
||||
if TCursor(ACursor + PREDEFINED_CURSOR_OFFSET) > crHigh then Exit;
|
||||
if TCursor(ACursor + PREDEFINED_CURSOR_OFFSET) < crLow then Exit;
|
||||
|
||||
// add it now
|
||||
case TCursor(ACursor + PREDEFINED_CURSOR_OFFSET) of
|
||||
crDefault: CursorValue := GDK_LEFT_PTR;
|
||||
crNone: CursorValue := GDK_LEFT_PTR;
|
||||
crArrow: CursorValue := GDK_Arrow;
|
||||
crCross: CursorValue := GDK_Cross;
|
||||
crIBeam: CursorValue := GDK_XTerm;
|
||||
// crSize: CursorValue := GDK_FLEUR;
|
||||
crSizeNESW: CursorValue := GDK_BOTTOM_LEFT_CORNER;
|
||||
crSizeNS: CursorValue := GDK_SB_V_DOUBLE_ARROW;
|
||||
crSizeNWSE: CursorValue := GDK_TOP_LEFT_CORNER;
|
||||
crSizeWE: CursorValue := GDK_SB_H_DOUBLE_ARROW;
|
||||
crSizeNW: CursorValue := GDK_TOP_LEFT_CORNER;
|
||||
crSizeN: CursorValue := GDK_TOP_SIDE;
|
||||
crSizeNE: CursorValue := GDK_TOP_RIGHT_CORNER;
|
||||
crSizeW: CursorValue := GDK_LEFT_SIDE;
|
||||
crSizeE: CursorValue := GDK_RIGHT_SIDE;
|
||||
crSizeSW: CursorValue := GDK_BOTTOM_LEFT_CORNER;
|
||||
crSizeS: CursorValue := GDK_BOTTOM_SIDE;
|
||||
crSizeSE: CursorValue := GDK_BOTTOM_RIGHT_CORNER;
|
||||
crUpArrow: CursorValue := GDK_LEFT_PTR;
|
||||
crHourGlass:CursorValue := GDK_CLOCK;
|
||||
crDrag: CursorValue := GDK_SAILBOAT;
|
||||
crNoDrop: CursorValue := GDK_IRON_CROSS;
|
||||
crHSplit: CursorValue := GDK_SB_H_DOUBLE_ARROW;
|
||||
crVSplit: CursorValue := GDK_SB_V_DOUBLE_ARROW;
|
||||
crMultiDrag:CursorValue := GDK_SAILBOAT;
|
||||
crSQLWait: CursorValue := GDK_LEFT_PTR;
|
||||
crNo: CursorValue := GDK_LEFT_PTR;
|
||||
crAppStart: CursorValue := GDK_LEFT_PTR;
|
||||
crHelp: CursorValue := GDK_QUESTION_ARROW;
|
||||
crHandPoint:CursorValue := GDK_Hand1;
|
||||
crSizeAll: CursorValue := GDK_FLEUR;
|
||||
else
|
||||
CursorValue := GDK_LEFT_PTR;
|
||||
end;
|
||||
|
||||
Result := gdk_cursor_new(CursorValue);
|
||||
MMouseCursorMap.Add(ACursor, Result);
|
||||
end;
|
||||
|
||||
procedure FreeGDKCursors;
|
||||
var
|
||||
Iterator: TMapIterator;
|
||||
begin
|
||||
Iterator := TMapIterator.Create(MMouseCursorMap);
|
||||
while not Iterator.EOM do
|
||||
begin
|
||||
gdk_Cursor_destroy(PGdkCursor(Iterator.DataPtr^));
|
||||
Iterator.Next;
|
||||
end;
|
||||
Iterator.Free;
|
||||
MMouseCursorMap.Clear;
|
||||
SetCursorRecursive(AWindow, NewCursor);
|
||||
end;
|
||||
|
||||
{-------------------------------------------------------------------------------
|
||||
|
@ -492,9 +492,6 @@ procedure UpdateMouseCaptureControl;
|
||||
|
||||
// mouse cursor
|
||||
procedure SetCursor(AWinControl: TWinControl; ACursor: HCursor);
|
||||
function GetPredefinedCursor(ACursor: TCursor): HCursor;
|
||||
function GetGDKMouseCursor(ACursor: hCursor): PGdkCursor;
|
||||
procedure FreeGDKCursors;
|
||||
|
||||
const
|
||||
// for now return the same value, in the future we may want to return an
|
||||
|
@ -1256,6 +1256,127 @@ begin
|
||||
Assert(False,Format('trace: [TGtkWidgetSet.CreateCompatibleDC] DC: 0x%x --> 0x%x', [Integer(DC), Integer(Result)]));
|
||||
end;
|
||||
|
||||
|
||||
function TGtkWidgetSet.CreateCursor(ACursorInfo: PIconInfo): hCursor;
|
||||
|
||||
procedure GetColorMask(AImage, AMask: PGDKPixmap; AImgBits, AMskBits: PByte; AWidth, AHeight: integer);
|
||||
var
|
||||
i, j: integer;
|
||||
colormap: PGDKColormap;
|
||||
Image, MaskImage: PGDKImage;
|
||||
GDKColor: TGDKColor;
|
||||
Pixel, MaskPixel: LongWord;
|
||||
offset: byte;
|
||||
|
||||
procedure SetColorAndMask(c: TGDKColor; MaskPixel: LongWord);
|
||||
var
|
||||
c_bit, m_bit: byte;
|
||||
begin
|
||||
c_bit := ord(c.pixel = $FFFFFF);
|
||||
m_bit := ord(MaskPixel = 0);
|
||||
|
||||
AImgBits^ := AImgBits^ or (c_bit shl offset);
|
||||
AMskBits^ := AMskBits^ or (m_bit shl offset);
|
||||
|
||||
inc(offset);
|
||||
if offset > 7 then
|
||||
begin
|
||||
inc(AImgBits);
|
||||
inc(AMskBits);
|
||||
offset := 0;
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
// most of this code was taken from TGtkWidgetSet.DCGetPixel
|
||||
|
||||
Image := gdk_drawable_get_image(AImage, 0, 0, AWidth, AHeight);
|
||||
MaskImage := gdk_drawable_get_image(AMask, 0, 0, AWidth, AHeight);
|
||||
|
||||
{$ifdef Gtk1}
|
||||
// previously gdk_image_get_colormap(image) was used, implementation
|
||||
// was casting GdkImage to GdkWindow which is not valid and cause AVs
|
||||
if gdk_window_get_type(PGdkWindow(AImage))= GDK_WINDOW_PIXMAP then
|
||||
colormap := nil // pixmaps are created with null colormap, get system one instead
|
||||
else
|
||||
colormap := gdk_window_get_colormap(PGdkWindow(AImage));
|
||||
{$else}
|
||||
colormap := gdk_image_get_colormap(image);
|
||||
{$endif}
|
||||
|
||||
if colormap = nil then
|
||||
colormap := gdk_colormap_get_system;
|
||||
|
||||
offset := 0;
|
||||
|
||||
for j := 0 to AHeight - 1 do
|
||||
for i := 0 to AWidth - 1 do
|
||||
begin
|
||||
Pixel := gdk_image_get_pixel(Image, i, j);
|
||||
MaskPixel := gdk_image_get_pixel(MaskImage, i, j);
|
||||
FillChar(GDKColor,SizeOf(GDKColor), 0);
|
||||
// does not work with TBitmap.Canvas
|
||||
gdk_colormap_query_color(colormap, Pixel, @GDKColor);
|
||||
SetColorAndMask(GDKColor, MaskPixel);
|
||||
end;
|
||||
gdk_image_unref(Image);
|
||||
gdk_image_unref(MaskImage);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
var
|
||||
FG, BG: TGDKColor;
|
||||
Img, Msk: PGdkPixmap;
|
||||
srcbitmap, mskbitmap: PGdkPixmap;
|
||||
W, H, bitlen: integer;
|
||||
ImgBits, MskBits: array of byte;
|
||||
begin
|
||||
Result := 0;
|
||||
if not IsValidGDIObject(ACursorInfo^.hbmColor) then Exit;
|
||||
|
||||
Img := PGDIObject(ACursorInfo^.hbmColor)^.GDIBitmapObject;
|
||||
Msk := PGDIObject(ACursorInfo^.hbmColor)^.GDIBitmapMaskObject;
|
||||
|
||||
gdk_drawable_get_size(Img, @W, @H);
|
||||
bitlen := (W * H) shr 3;
|
||||
SetLength(ImgBits, bitlen);
|
||||
SetLength(MskBits, bitlen);
|
||||
FillChar(ImgBits[0], bitlen, 0);
|
||||
FillChar(MskBits[0], bitlen, 0);
|
||||
|
||||
GetColorMask(Img, Msk, @ImgBits[0], @MskBits[0], W, H);
|
||||
|
||||
srcbitmap := gdk_bitmap_create_from_data (nil, @ImgBits[0], W, H);
|
||||
mskbitmap := gdk_bitmap_create_from_data (nil, @MskBits[0], W, H);
|
||||
|
||||
|
||||
// white
|
||||
fg.red := $FFFF;
|
||||
fg.green := $FFFF;
|
||||
fg.blue := $FFFF;
|
||||
fg.pixel := 0;
|
||||
|
||||
// black
|
||||
bg.red := 0;
|
||||
bg.green := 0;
|
||||
bg.blue := 0;
|
||||
bg.pixel := 0;
|
||||
|
||||
// TODO: for gtk2, use gdk_cursor_new_from_pixbuf for colored cursors
|
||||
Result := hCursor(gdk_cursor_new_from_pixmap (srcbitmap, mskbitmap, @fg, @bg,
|
||||
ACursorInfo^.xHotspot, ACursorInfo^.yHotspot));
|
||||
|
||||
gdk_pixmap_unref(srcbitmap);
|
||||
gdk_pixmap_unref(mskbitmap);
|
||||
end;
|
||||
|
||||
function TGtkWidgetSet.DestroyCursor(Handle: hCursor): Boolean;
|
||||
begin
|
||||
if Handle <> 0 then
|
||||
gdk_cursor_destroy(PGdkCursor(Handle));
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
Function: CreateFontIndirect
|
||||
Params: const LogFont: TLogFont
|
||||
|
@ -53,6 +53,7 @@ function CreateBrushIndirect(const LogBrush: TLogBrush): HBRUSH; override;
|
||||
function CreateCaret(Handle : HWND; Bitmap : hBitmap; width, Height : Integer) : Boolean; override;
|
||||
function CreateCompatibleBitmap(DC: HDC; Width, Height: Integer): HBITMAP; override;
|
||||
function CreateCompatibleDC(DC: HDC): HDC; override;
|
||||
function CreateCursor(ACursorInfo: PIconInfo): hCursor; override;
|
||||
function CreateFontIndirect(const LogFont: TLogFont): HFONT; override;
|
||||
function CreateFontIndirectEx(const LogFont: TLogFont; const LongFontName: string): HFONT; override;
|
||||
function CreatePalette(const LogPalette: TLogPalette): HPALETTE; override;
|
||||
@ -65,6 +66,7 @@ procedure DeleteCriticalSection(var CritSection: TCriticalSection); override;
|
||||
function DeleteDC(hDC: HDC): Boolean; override;
|
||||
function DeleteObject(GDIObject: HGDIOBJ): Boolean; override;
|
||||
function DestroyCaret(Handle : HWND): Boolean; override;
|
||||
function DestroyCursor(Handle: hCursor): Boolean; override;
|
||||
Function DrawFrameControl(DC: HDC; var Rect : TRect; uType, uState : Cardinal) : Boolean; override;
|
||||
function DrawFocusRect(DC: HDC; const Rect: TRect): boolean; override;
|
||||
function DrawEdge(DC: HDC; var ARect: TRect; Edge: Cardinal; grfFlags: Cardinal): Boolean; override;
|
||||
|
Loading…
Reference in New Issue
Block a user