LCL-GTK3: Fix TEdit width, show hint when mouse stops. Issues #39036,#39039, patch by Anton Kavalenka.

git-svn-id: trunk@65302 -
This commit is contained in:
juha 2021-06-24 17:40:18 +00:00
parent 3ff7c6b95c
commit 587b7a8582
3 changed files with 83 additions and 20 deletions

View File

@ -82,6 +82,9 @@ type
FGlobalCursor: HCursor; FGlobalCursor: HCursor;
FThemeName: string; FThemeName: string;
FCSSTheme: TStringList; FCSSTheme: TStringList;
// tmp
cssProvider:PGtkCssProvider;
public public
function CreateDCForWidget(AWidget: PGtkWidget; AWindow: PGdkWindow; cr: Pcairo_t): HDC; function CreateDCForWidget(AWidget: PGtkWidget; AWindow: PGdkWindow; cr: Pcairo_t): HDC;
procedure AddWindow(AWindow: PGtkWindow); procedure AddWindow(AWindow: PGtkWindow);

View File

@ -348,6 +348,14 @@ begin
// g_object_set_property(gtk_settings_get_default,'gtk-enable-mnemonics',@AValue); // g_object_set_property(gtk_settings_get_default,'gtk-enable-mnemonics',@AValue);
// g_object_set_property(gtk_settings_get_default,'gtk-auto-mnemonics',@AValue); // g_object_set_property(gtk_settings_get_default,'gtk-auto-mnemonics',@AValue);
cssProvider := gtk_css_provider_new();
gtk_css_provider_load_from_path(cssProvider, 'theme.css', nil);
gtk_style_context_add_provider_for_screen(gdk_screen_get_default(),
PGtkStyleProvider(cssProvider),
GTK_STYLE_PROVIDER_PRIORITY_USER);
end; end;
destructor TGtk3WidgetSet.Destroy; destructor TGtk3WidgetSet.Destroy;
@ -355,6 +363,8 @@ begin
{$IFDEF GTK3DEBUGCORE} {$IFDEF GTK3DEBUGCORE}
DebugLn('** TGtk3WidgetSet.Destroy **'); DebugLn('** TGtk3WidgetSet.Destroy **');
{$ENDIF} {$ENDIF}
if Assigned(cssProvider) then
cssProvider^.unref;
ReleaseAllStyles; ReleaseAllStyles;
Styles.Free; Styles.Free;
Styles := nil; Styles := nil;
@ -682,7 +692,8 @@ begin
{$IFDEF VerboseTimer} {$IFDEF VerboseTimer}
DebugLn(['TGtk3WidgetSet.CreateTimer Interval=',dbgs(Interval)]); DebugLn(['TGtk3WidgetSet.CreateTimer Interval=',dbgs(Interval)]);
{$ENDIF} {$ENDIF}
Result:= g_timeout_add_full(0 {G_PRIORITY_DEFAULT}, Interval, @gtk3TimerProc, TimerInfo, @gtk3TimerDestroyed); //Result:= g_timeout_add_full(0 {G_PRIORITY_DEFAULT}, Interval, @gtk3TimerProc, TimerInfo, @gtk3TimerDestroyed);
Result:=g_timeout_add(Interval, @gtk3TimerProc, TimerInfo);
if Result = 0 then if Result = 0 then
Dispose(TimerInfo) Dispose(TimerInfo)
else begin else begin
@ -707,8 +718,9 @@ begin
if (TimerInfo^.TimerHandle = guint(TimerHandle)) then if (TimerInfo^.TimerHandle = guint(TimerHandle)) then
begin begin
// in gtk3 timeout is automatically removed // in gtk3 timeout is automatically removed
TimerInfo^.TimerHandle := 0;
// g_timeout_remove(TimerInfo^.TimerHandle); // g_timeout_remove(TimerInfo^.TimerHandle);
g_source_remove(TimerInfo^.TimerHandle);
TimerInfo^.TimerHandle := 0;
FTimerData.Delete(n); FTimerData.Delete(n);
Dispose(TimerInfo); Dispose(TimerInfo);
end; end;

View File

@ -114,6 +114,7 @@ type
constructor CreateFrom(const AWinControl: TWinControl; AWidget: PGtkWidget); virtual; constructor CreateFrom(const AWinControl: TWinControl; AWidget: PGtkWidget); virtual;
procedure InitializeWidget; virtual; procedure InitializeWidget; virtual;
procedure UpdateWidgetConstraints;virtual;
procedure DeInitializeWidget; procedure DeInitializeWidget;
procedure RecreateWidget; procedure RecreateWidget;
procedure DestroyNotify({%H-}AWidget: PGtkWidget); virtual; procedure DestroyNotify({%H-}AWidget: PGtkWidget); virtual;
@ -223,12 +224,15 @@ type
procedure setText(const AValue: String); override; procedure setText(const AValue: String); override;
function CreateWidget(const {%H-}Params: TCreateParams):PGtkWidget; override; function CreateWidget(const {%H-}Params: TCreateParams):PGtkWidget; override;
public public
procedure SetBounds(Left,Top,Width,Height:integer);override;
procedure InitializeWidget; override; procedure InitializeWidget; override;
procedure UpdateWidgetConstraints;override;
procedure SetEchoMode(AVisible: Boolean); procedure SetEchoMode(AVisible: Boolean);
procedure SetMaxLength(AMaxLength: Integer); procedure SetMaxLength(AMaxLength: Integer);
procedure SetPasswordChar(APasswordChar: Char); procedure SetPasswordChar(APasswordChar: Char);
procedure SetNumbersOnly(ANumbersOnly:boolean); procedure SetNumbersOnly(ANumbersOnly:boolean);
procedure SetTextHint(const AHint:string); procedure SetTextHint(const AHint:string);
procedure SetFrame(const aborder:boolean);
function GetTextHint:string; function GetTextHint:string;
function IsWidgetOk: Boolean; override; function IsWidgetOk: Boolean; override;
property Alignment: TAlignment read GetAlignment write SetAlignment; property Alignment: TAlignment read GetAlignment write SetAlignment;
@ -1743,14 +1747,11 @@ begin
Result := False; Result := False;
FillChar(Msg{%H-}, SizeOf(Msg), #0); FillChar(Msg{%H-}, SizeOf(Msg), #0);
if Event^.type_ = GDK_ENTER_NOTIFY then if Event^.type_ = GDK_ENTER_NOTIFY then
begin Msg.Msg := LM_MOUSEENTER
Msg.Msg := LM_MOUSEENTER;
NotifyApplicationUserInput(LCLObject, Msg.Msg);
end
else else
Msg.Msg := LM_MOUSELEAVE; Msg.Msg := LM_MOUSELEAVE;
//NotifyApplicationUserInput(LCLObject, Msg.Msg); NotifyApplicationUserInput(LCLObject, Msg.Msg);
Result := DeliverMessage(Msg, True) <> 0; Result := DeliverMessage(Msg, True) <> 0;
{$IFDEF GTK3DEBUGCORE} {$IFDEF GTK3DEBUGCORE}
MousePos.X := Round(Event^.crossing.x); MousePos.X := Round(Event^.crossing.x);
@ -1800,7 +1801,6 @@ begin
Msg.Msg := LM_MOUSEMOVE; Msg.Msg := LM_MOUSEMOVE;
NotifyApplicationUserInput(LCLObject, Msg.Msg); NotifyApplicationUserInput(LCLObject, Msg.Msg);
if Widget^.get_parent <> nil then if Widget^.get_parent <> nil then
Event^.motion.send_event := NO_PROPAGATION_TO_PARENT; Event^.motion.send_event := NO_PROPAGATION_TO_PARENT;
@ -2653,7 +2653,6 @@ var
ARect: TGdkRectangle; ARect: TGdkRectangle;
ARgba: TGdkRGBA; ARgba: TGdkRGBA;
i: TGtkStateType; i: TGtkStateType;
mh,nh,mw,nw:gint;
begin begin
FFocusableByMouse := False; FFocusableByMouse := False;
FCentralWidget := nil; FCentralWidget := nil;
@ -2664,7 +2663,6 @@ begin
FWidgetType := [wtWidget]; FWidgetType := [wtWidget];
FWidget := CreateWidget(FParams); FWidget := CreateWidget(FParams);
// connect events
if not (wtWindow in FWidgetType) then if not (wtWindow in FWidgetType) then
begin begin
FWidget^.show_all; FWidget^.show_all;
@ -2677,16 +2675,11 @@ begin
end; end;
FWidget^.set_allocation(@ARect); FWidget^.set_allocation(@ARect);
fWidget^.get_preferred_height(@mh,@nh); UpdateWidgetConstraints;
fWidget^.get_preferred_width(@mw,@nw);
if mh>LCLObject.Constraints.MinHeight then
LCLObject.Constraints.MinHeight:=mh;
if mw>LCLObject.Constraints.MinWidth then
LCLObject.Constraints.MinWidth:=mw;
end; end;
LCLIntf.SetProp(HWND(Self),'lclwidget',Self); LCLIntf.SetProp(HWND(Self),'lclwidget',Self);
// connect events
// move signal connections into attach events // move signal connections into attach events
if not gtk_widget_get_realized(FWidget) then if not gtk_widget_get_realized(FWidget) then
FWidget^.set_events(GDK_DEFAULT_EVENTS_MASK); FWidget^.set_events(GDK_DEFAULT_EVENTS_MASK);
@ -2738,6 +2731,22 @@ begin
// g_signal_connect_data(FWidget, 'motion_notify_event', TGCallback(@Gtk3MotionNotifyEvent), LCLObject, nil, 0); // g_signal_connect_data(FWidget, 'motion_notify_event', TGCallback(@Gtk3MotionNotifyEvent), LCLObject, nil, 0);
end; end;
procedure TGtk3Widget.UpdateWidgetConstraints;
var mh,nh,mw,nw:gint;
begin
// some GTK3 widgets my report unacceptible for LCL values
// i.e. GtkEntry have 152px minimal and natural width
// this has to be handled in specific classes
fWidget^.get_preferred_height(@mh,@nh);
fWidget^.get_preferred_width(@mw,@nw);
if mh>LCLObject.Constraints.MinHeight then
LCLObject.Constraints.MinHeight:=mh;
if mw>LCLObject.Constraints.MinWidth then
LCLObject.Constraints.MinWidth:=mw;
end;
procedure TGtk3Widget.DeInitializeWidget; procedure TGtk3Widget.DeInitializeWidget;
begin begin
@ -2913,7 +2922,8 @@ function TGtk3Widget.getClientRect: TRect;
var var
AAlloc: TGtkAllocation; AAlloc: TGtkAllocation;
begin begin
Result := Rect(0, 0, 0, 0); //writeln('GetClientRect ',LCLObject.Name,':',LCLObject.Name);
Result := LCLObject.BoundsRect;
if not IsWidgetOK then if not IsWidgetOK then
exit; exit;
if GetContainerWidget^.get_realized then if GetContainerWidget^.get_realized then
@ -2926,7 +2936,6 @@ begin
FWidget^.get_allocation(@AAlloc); FWidget^.get_allocation(@AAlloc);
Result := Rect(AAlloc.x, AAlloc.y, AAlloc.width + AAlloc.x,AAlloc.height + AAlloc.y); Result := Rect(AAlloc.x, AAlloc.y, AAlloc.width + AAlloc.x,AAlloc.height + AAlloc.y);
end; end;
OffsetRect(Result, -Result.Left, -Result.Top); OffsetRect(Result, -Result.Left, -Result.Top);
end; end;
@ -3633,14 +3642,30 @@ function TGtk3Entry.CreateWidget(const Params: TCreateParams): PGtkWidget;
begin begin
Result := PGtkWidget(TGtkEntry.new); Result := PGtkWidget(TGtkEntry.new);
FWidgetType := FWidgetType + [wtEntry]; FWidgetType := FWidgetType + [wtEntry];
fText:=Params.Caption;
PrivateCursorPos := -1; PrivateCursorPos := -1;
PrivateSelection := -1; PrivateSelection := -1;
end; end;
procedure TGtk3Entry.SetBounds(Left, Top, Width, Height: integer);
var val:TGvalue;
begin
val.clear;
val.init(G_TYPE_UINT);
val.set_uint(Width);
inherited SetBounds(Left, Top, Width, Height);
PGtkEntry(FWidget)^.set_property('width-request',@val);
val.unset;
end;
procedure TGtk3Entry.InitializeWidget; procedure TGtk3Entry.InitializeWidget;
begin begin
inherited InitializeWidget; inherited InitializeWidget;
fWidget^.set_size_request(fParams.Width,fParams.Height);
PgtkEntry(fWidget)^.set_text(PgChar(fParams.Caption));
Self.SetTextHint(TCustomEdit(Self.LCLObject).TextHint); Self.SetTextHint(TCustomEdit(Self.LCLObject).TextHint);
Self.SetNumbersOnly(TCustomEdit(Self.LCLObject).NumbersOnly); Self.SetNumbersOnly(TCustomEdit(Self.LCLObject).NumbersOnly);
@ -3651,6 +3676,19 @@ begin
//g_signal_connect_data(PGtkEntry(FWidget)^.get_buffer, 'inserted-text', TGCallback(@Gtk3EntryInsertedText), Self, nil, 0); //g_signal_connect_data(PGtkEntry(FWidget)^.get_buffer, 'inserted-text', TGCallback(@Gtk3EntryInsertedText), Self, nil, 0);
end; end;
procedure TGtk3Entry.UpdateWidgetConstraints;
var mh,nh,mw,nw:gint;
begin
// GtkEntry have 152px minimal and natural width
fWidget^.get_preferred_height(@mh,@nh);
fWidget^.get_preferred_width(@mw,@nw);
if mh>LCLObject.Constraints.MinHeight then
LCLObject.Constraints.MinHeight:=mh;
// LCLObject.Constraints.MinWidth:=0;
end;
procedure TGtk3Entry.SetPasswordChar(APasswordChar: Char); procedure TGtk3Entry.SetPasswordChar(APasswordChar: Char);
var var
PWChar: Integer; PWChar: Integer;
@ -3675,10 +3713,16 @@ end;
procedure TGtk3Entry.SetTextHint(const AHint: string); procedure TGtk3Entry.SetTextHint(const AHint: string);
begin begin
if IsWidgetOK then if IsWidgetOK and (Ahint<>'') then
PGtkEntry(FWidget)^.set_placeholder_text(PgChar(AHint)); PGtkEntry(FWidget)^.set_placeholder_text(PgChar(AHint));
end; end;
procedure TGtk3Entry.SetFrame(const aborder: boolean);
begin
if IsWidgetOk then
PGtkEntry(FWidget)^.set_has_frame(aborder);
end;
function TGtk3Entry.GetTextHint:string; function TGtk3Entry.GetTextHint:string;
begin begin
@ -3697,7 +3741,11 @@ end;
procedure TGtk3Entry.SetMaxLength(AMaxLength: Integer); procedure TGtk3Entry.SetMaxLength(AMaxLength: Integer);
begin begin
if IsWidgetOK then if IsWidgetOK then
begin
PGtkEntry(FWidget)^.set_max_length(AMaxLength); PGtkEntry(FWidget)^.set_max_length(AMaxLength);
PGtkEntry(FWidget)^.set_width_chars(AMaxLength);
end;
end; end;
function TGtk3Entry.IsWidgetOk: Boolean; function TGtk3Entry.IsWidgetOk: Boolean;