* Cursor patch from Paul Ishenin

* Disabled setting cursors for gtk2, since it is broken

git-svn-id: trunk@10544 -
This commit is contained in:
marc 2007-01-31 01:11:00 +00:00
parent d0214c39e6
commit 92e3d63d75
6 changed files with 186 additions and 98 deletions

View File

@ -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

View File

@ -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;
{------------------------------------------------------------------------------

View File

@ -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;
{-------------------------------------------------------------------------------

View File

@ -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

View File

@ -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

View File

@ -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;