View Issue Details

IDProjectCategoryView StatusLast Update
0018679LazarusLCLpublic2017-07-31 13:03
Reporteru-boot Assigned ToZeljan Rikalo  
PrioritynormalSeveritymajorReproducibilityalways
Status closedResolutionfixed 
Platformi386OSUbuntu 
Product Version0.9.31 (SVN) 
Target Version1.0.0 
Summary0018679: wrong behaviour of TFloatSpinEdit at Keyboard input
DescriptionSelected Numbers are not deleted at keyboard input.
Steps To Reproduceeasiest is to place two FloatSpinEdits on a Form
set increment between 0 and 1
finally run it and try to fill numbers into the FloatSpinEdits via tab and number-keys
TagsNo tags attached.
Fixed in Revision36024,36068,36095
LazTarget1.0
WidgetsetGTK 2
Attached Files

Relationships

related to 0028123 assignedZeljan Rikalo Patches TFloatSpinEdit, TSpinEdit: Cannot enter value as expected 
related to 0031618 closedJuha Manninen Lazarus TSpinEdit.OnChange events in GTk2 

Activities

Zeljan Rikalo

2011-02-03 14:48

developer   ~0045748

Isn't it gtk behaviour ?

u-boot

2011-02-05 05:07

reporter   ~0045802

Floatspinedit and a spinedit have different behaviour. alternate pressing tab and 7 the floatspinedit shows 0.01 the spinedit shows 7 with initial value 0.

in Spinedit it only works because 07 = 7.

0.01 i guess 0.007 rounded.

however ... manually entering numbers should replace existing numbers, especially if the whole old text belongs to selection.

TEdit also replaces text if it is marked at beginning of typing.

Zeljan Rikalo

2011-02-05 09:59

developer   ~0045805

What gtk2 version do you have ?

u-boot

2011-02-05 13:49

reporter   ~0045809

ii | libgtk2.0-0 | 2.18.3-1ubuntu2.2 | The GTK+ graphical user interface library

I hope this is the information you need.

Benito van der Zander

2011-07-24 00:42

reporter   ~0050117

Here are some example of wrong behaviour: (standard floatspinedit, no properties changed from default value, German system so the comma separator is ',')

input 1,23 select 1, press 4, it should become 4,23, but it becomes 40,23
input 1,23 select 2, press 4, it should become 1,43, but it becomes 14,30
input 1,23 select 3, press 4, it should become 1,24, but it becomes 1,20 (if you select from left to right, with the cursor on the right side of selection) or 41,20 (if you select from right to left)
input 1,00 move cursor like 1,0|0, press backspace, it should become 1|,00 or 1,|00, but it becomes |1,00 (cursor moved to front)
input 1,00 move cursor like 1,00, press backspace, it should become 1,0|0, but nothing happens
input 1,00 select first 0 zero, press backspace, wrong behaviour: the cursor jumps to the front like |1,00
input 1,00 select second 0 zero, press backspace, wrong behaviour: the whole number is selected
input 0,30 delete comma, it should become 0|30, or |30,00, (cursor before 3!), but it becomes 3|0,00
input 0,00 place cursor 0|,00, write 5, it should become 5|,00 (to enter a integer), but it becomes 5,|00
input 3,00 delete 3, it should become |,00 (valid decimal number almost everywhere), but it becomes



>Isn't it gtk behaviour ?
No, absolutely not! Check gimp

Bart Broersma

2011-07-24 17:18

developer   ~0050121

Behaves as expected here, typing in it is just like any TEdit.

Lazarus r31567 / fpc 2.4.4
gtk2-2.8.3-4
Suse Linux 10.0

u-boot

2011-10-12 00:05

reporter   ~0052876

Last edited: 2011-10-12 00:48

here it has still same wrong behaviour

lazarus r32825 / fpc 2.4.2
german language
system specifications as reported...

Bart Broersma

2011-10-12 17:21

developer   ~0052908

Maybe related to 0019220?

2012-03-14 12:21

 

gtk2floatspinedit_rework.diff (7,326 bytes)   
Index: lcl/interfaces/gtk2/gtk2callback.inc
===================================================================
--- lcl/interfaces/gtk2/gtk2callback.inc	(revision 35965)
+++ lcl/interfaces/gtk2/gtk2callback.inc	(working copy)
@@ -413,24 +413,29 @@
   NeedCursorCheck := False;
   if GTK_IS_ENTRY(Widget) then
   begin
-    {cheat GtkEditable to update cursor pos in gtkEntry. issue #7243}
-    gtk_editable_get_selection_bounds(PGtkEditable(Widget), @GStart, @GEnd);
-    EntryText := gtk_entry_get_text(PGtkEntry(Widget));
-    if (GStart = GEnd) and
-      (UTF8Length(EntryText) >= PGtkEntry(Widget)^.text_length) then
+    // lcl-do-not-change-selection comes from gtkKeyPress. issue #18679
+    if g_object_get_data(PGObject(Widget),'lcl-do-not-change-selection') = nil then
     begin
-      Info := GetWidgetInfo(Widget, False);
-      {do not update position if backspace or delete pressed}
-      if wwiInvalidEvent in Info^.Flags then
-        exclude(Info^.Flags, wwiInvalidEvent)
-      else
+      {cheat GtkEditable to update cursor pos in gtkEntry. issue #7243}
+      gtk_editable_get_selection_bounds(PGtkEditable(Widget), @GStart, @GEnd);
+      EntryText := gtk_entry_get_text(PGtkEntry(Widget));
+      if (GStart = GEnd) and
+        (UTF8Length(EntryText) >= PGtkEntry(Widget)^.text_length) then
       begin
-        // if we change selstart in OnChange event new cursor pos need to
-        // be postponed in TGtk2WSCustomEdit.SetSelStart
-        NeedCursorCheck := True;
-        gtk_editable_set_position(PGtkEditable(Widget), GStart+1);
+        Info := GetWidgetInfo(Widget, False);
+        {do not update position if backspace or delete pressed}
+        if wwiInvalidEvent in Info^.Flags then
+          exclude(Info^.Flags, wwiInvalidEvent)
+        else
+        begin
+          // if we change selstart in OnChange event new cursor pos need to
+          // be postponed in TGtk2WSCustomEdit.SetSelStart
+          NeedCursorCheck := True;
+          gtk_editable_set_position(PGtkEditable(Widget), GStart+1);
+        end;
       end;
-    end;
+    end else
+      g_object_set_data(PGObject(Widget),'lcl-do-not-change-selection', nil);
   end;
 
   if NeedCursorCheck then
@@ -443,13 +448,29 @@
 end;
 
 function gtkchanged_spinbox(widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
+var
+  SText: String;
+  SValue: String;
 begin
   Result := CallBackDefaultReturn;
   if LockOnChange(PgtkObject(Widget),0) > 0 then exit;
   // prior to gtk2-2.12 there's bug with signalling of spin button
   // which leads to crash.See issue #18554
   if GTK_IS_SPIN_BUTTON(Widget) and (gtk_minor_version >= 12) then
-    gtk_spin_button_update(PGtkSpinButton(Widget));
+  begin
+    SText := '';
+    // do not call gtk_spin_button_update for no reason in floatspinedit.
+    if gtk_spin_button_get_digits(PGtkSpinButton(Widget)) > 0 then
+    begin
+      SText := StrPas(gtk_entry_get_text(PGtkEntry(@PGtkSpinButton(Widget)^.entry)));
+      SValue := FloatToStrF(gtk_spin_button_get_value(PGtkSpinButton(Widget)), ffFixed,
+        12, gtk_spin_button_get_digits(PGtkSpinButton(Widget)));
+    end else
+      SValue := '1';
+
+    if SText <> SValue then
+      gtk_spin_button_update(PGtkSpinButton(Widget));
+  end;
 end;
 
 function gtkchanged_editbox_backspace(widget: PGtkWidget;
@@ -741,8 +762,95 @@
   EventTrace('map', data);
 end;
 
+
+procedure HandleFloatSpinEditKeyPress(Widget: PGtkWidget; Event: PGdkEventKey; Data: gPointer);
+var
+  Entry: PGtkEntry;
+  AChar: Array [0..0] of Char;
+  ACurPos: Integer;
+  ASelLen: Integer;
+  FL: Double;
+  S: String;
+  SSel: String;
+  P: PChar;
+begin
+  Entry := @PGtkSpinButton(Widget)^.entry;
+  if (ABS(Entry^.current_pos - Entry^.selection_bound) >= 0) and
+    (Event^.keyval > 31) and (Event^.keyval < 256) then
+  begin
+    FL := gtk_spin_button_get_value(PGtkSpinButton(Widget));
+    ACurPos := Min(Entry^.current_pos, Entry^.selection_bound);
+    ASelLen := ABS(Entry^.current_pos - Entry^.selection_bound);
+    S := StrPas(gtk_entry_get_text(Entry));
+    // writeln(Format('Value %12.2n text %s start %d len %d',[FL, StrPas(gtk_entry_get_text(Entry)), ACurPos, ASelLen]));
+    if ASelLen > 0 then
+    begin
+      if ASelLen = length(S) then
+      begin
+        gtk_spin_button_set_value(PGtkSpinButton(Widget), 0);
+        gtk_editable_set_position(Entry, 1);
+      end else
+      begin
+        SSel := Copy(S, ACurPos + 1, ASelLen);
+        if Pos(DecimalSeparator, SSel) > 0 then
+          SSel := Copy(S,ACurPos + 1, ASelLen + 1);
+
+        Delete(S, ACurPos + 1, ASelLen);
+        Insert(Chr(Event^.keyVal), S, ACurPos + 1);
+
+        // if clocale isn't included in our project we are in trouble !
+        S := StringReplace(S,',',DecimalSeparator,[rfReplaceAll]);
+        TryStrToFloat(S, FL);
+
+        g_object_set_data(PGObject(Widget),'lcl-do-not-change-selection', Data);
+        gtk_spin_button_set_value(PGtkSpinButton(Widget), FL);
+        gtk_entry_set_text(Entry, PChar(S));
+        gtk_editable_set_position(Entry, ACurPos);
+        gtk_spin_button_update(PGtkSpinButton(Widget));
+
+        // do not trigger OnChange in keyrelease !
+        LockOnChange(PGtkObject(Widget), 1);
+        S := FloatToStr(FL);
+        P := StrNew(PChar(S));
+        g_object_set_data(PGObject(Widget),'lcl-eat-next-key-release', P);
+        g_object_set_data(PGObject(Widget),'lcl-eat-next-key-release-pos', TObject(ACurPos));
+      end;
+    end;
+  end;
+end;
+
+function HandleFloatSpinEditKeyRelease(Widget: PGtkWidget; Event: PGdkEventKey; Data: gPointer): GBoolean;
+var
+  AData: PChar;
+  FL: Double;
+  APos: Integer;
+begin
+  Result := False;
+  if g_object_get_data(PGObject(Widget),'lcl-eat-next-key-release') <> nil then
+  begin
+    AData := g_object_get_data(PGObject(Widget),'lcl-eat-next-key-release');
+    FL := StrToFloat(StrPas(AData));
+    if g_object_get_data(PGObject(Widget),'lcl-eat-next-key-release-pos') <> nil then
+      APos := PtrInt(g_object_get_data(PGObject(Widget),'lcl-eat-next-key-release-pos'))
+    else
+      APos := 0;
+    gtk_spin_button_set_value(PGtkSpinButton(Widget), FL);
+    if APos >= 0 then
+      gtk_editable_set_position(PGtkEditable(Widget), APos + 1);
+    StrDispose(AData);
+    g_object_set_data(PGObject(Widget),'lcl-eat-next-key-release', nil);
+    Result := True;
+    LockOnChange(PGtkObject(Widget), -1);
+  end;
+end;
+
 function GTKKeyPress(Widget: PGtkWidget; Event: PGdkEventKey; Data: gPointer) : GBoolean; cdecl;
 begin
+  // we intercept ugly floatspinedit selection behaviour here. issue #18679
+  if GTK_IS_SPIN_BUTTON(Widget) and
+    (gtk_spin_button_get_digits(PGtkSpinButton(Widget)) > 0) then
+      HandleFloatSpinEditKeyPress(Widget, Event, Data);
+
   Result := HandleGtkKeyUpDown(Widget,Event,Data,true,True,'key-press-event');
 end;
 
@@ -753,6 +861,10 @@
 
 function GTKKeyRelease(Widget: PGtkWidget; Event: PGdkEventKey; Data: gPointer) : GBoolean; cdecl;
 begin
+  // we intercept ugly floatspinedit selection behaviour here. issue #18679
+  if GTK_IS_SPIN_BUTTON(Widget) and
+    (gtk_spin_button_get_digits(PGtkSpinButton(Widget)) > 0) then
+    Result := HandleFloatSpinEditKeyRelease(Widget, Event, Data);
   Result := HandleGtkKeyUpDown(Widget,Event,Data,true,False,'key-release-event');
 end;
 
gtk2floatspinedit_rework.diff (7,326 bytes)   

Zeljan Rikalo

2012-03-14 12:21

developer   ~0057625

Please guys test with attached patch. It's maded against gtk2-2.24 (no time to test with others) @Bart, please give feedback for your gtk2 2.8

Bart Broersma

2012-03-14 13:12

developer   ~0057632

@Zeljan: see note 0050121:
> Behaves as expected here, typing in it is just like any TEdit.

Applied your patch.
Still behaves as expected.
Lazarus r35947
Fpc 2.6.0
gtk2-2.8.3-4
Suse Linux 10.0 (Kernel 2.6.13-15)

Zeljan Rikalo

2012-03-14 13:14

developer   ~0057633

@Benito ? Can you test ?
@Bart: so with or without patch it works on 2.8 ?
Here it does not work correctly without patch.

Zeljan Rikalo

2012-03-14 18:47

developer   ~0057651

Very ugly, setting target to 1.0 since patch is ready.

Bart Broersma

2012-03-14 21:35

developer   ~0057656

> @Bart: so with or without patch it works on 2.8 ?

Yes.

Zeljan Rikalo

2012-03-15 07:56

developer   ~0057664

ufff...with 2.8.15 it does not work, so seem that you have special 2.8

Bart Broersma

2012-03-15 10:34

developer   ~0057671

> ufff...with 2.8.15 it does not work,
Does not work with, or without the patch?

> so seem that you have special 2.8
;-)

Zeljan Rikalo

2012-03-15 11:35

developer   ~0057672

Please test and close if ok.

u-boot

2012-03-15 17:53

reporter   ~0057685

Not working here. I provide example project.
Maybe my Computer is special case....

2012-03-15 17:54

 

bug18679.zip (193,103 bytes)

u-boot

2012-03-15 23:27

reporter   ~0057693

Last edited: 2012-03-16 01:45

I hope nobody read before i edited this. :)

Thing is that for ordinary keyboard the bug is fixed here. But trying to do the input with numeric pad (which i use often) still fails here at the moment.

Zeljan Rikalo

2012-03-16 08:04

developer   ~0057696

@u-boot, you didn't tell me that part ;) ... anyway I'm installing ubuntu 9.10 with gtk2 2.18 to see if it differs from 2.24.

Zeljan Rikalo

2012-03-16 08:05

developer   ~0057697

Ok, 2.24 have same problem with input from numeric part of kbd.

Zeljan Rikalo

2012-03-16 08:58

developer   ~0057699

Now it works, please test and close if ok.

u-boot

2012-03-16 19:27

reporter   ~0057734

Testing with rev 36094:

For whole numbers between 0 and 9 it is working fine right now
Numbers between 0 and 1 are working fine too, as far as i start typing with ","


tab into floatspinedit and type "6""7"",""8""9" -> result number in floatspinedit is 6,72

additional i think negative numbers should be supported
(pay attention to min value)

Zeljan Rikalo

2012-03-16 20:02

developer   ~0057735

1. That's behaviour of gtkspinbutton
2. Yes, I forgot about - sign.

Zeljan Rikalo

2012-03-16 21:17

developer   ~0057737

I've rewritten validator part, so we are validating our input, not gtk2 ...it works same as in qt now.
Please test and close if ok.

u-boot

2012-03-16 21:27

reporter   ~0057738

Great work! Works fine now. Thanks a lot.

Issue History

Date Modified Username Field Change
2011-02-03 13:54 u-boot New Issue
2011-02-03 13:54 u-boot Widgetset => GTK 2
2011-02-03 14:48 Zeljan Rikalo LazTarget => -
2011-02-03 14:48 Zeljan Rikalo Note Added: 0045748
2011-02-03 14:48 Zeljan Rikalo Status new => feedback
2011-02-05 05:07 u-boot Note Added: 0045802
2011-02-05 09:59 Zeljan Rikalo Note Added: 0045805
2011-02-05 13:49 u-boot Note Added: 0045809
2011-07-24 00:42 Benito van der Zander Note Added: 0050117
2011-07-24 17:18 Bart Broersma Note Added: 0050121
2011-10-12 00:05 u-boot Note Added: 0052876
2011-10-12 00:48 u-boot Note Edited: 0052876
2011-10-12 17:21 Bart Broersma Note Added: 0052908
2012-03-13 18:44 Vincent Snijders Status feedback => acknowledged
2012-03-14 07:44 Zeljan Rikalo Status acknowledged => assigned
2012-03-14 07:44 Zeljan Rikalo Assigned To => Zeljan Rikalo
2012-03-14 12:21 Zeljan Rikalo File Added: gtk2floatspinedit_rework.diff
2012-03-14 12:21 Zeljan Rikalo Note Added: 0057625
2012-03-14 12:21 Zeljan Rikalo Status assigned => feedback
2012-03-14 13:12 Bart Broersma Note Added: 0057632
2012-03-14 13:14 Zeljan Rikalo Note Added: 0057633
2012-03-14 18:47 Zeljan Rikalo LazTarget - => 1.0
2012-03-14 18:47 Zeljan Rikalo Note Added: 0057651
2012-03-14 18:47 Zeljan Rikalo Status feedback => confirmed
2012-03-14 18:47 Zeljan Rikalo Target Version => 1.0.0
2012-03-14 21:35 Bart Broersma Note Added: 0057656
2012-03-15 07:56 Zeljan Rikalo Note Added: 0057664
2012-03-15 10:34 Bart Broersma Note Added: 0057671
2012-03-15 11:35 Zeljan Rikalo Fixed in Revision => 36024
2012-03-15 11:35 Zeljan Rikalo Status confirmed => resolved
2012-03-15 11:35 Zeljan Rikalo Resolution open => fixed
2012-03-15 11:35 Zeljan Rikalo Note Added: 0057672
2012-03-15 17:53 u-boot Status resolved => assigned
2012-03-15 17:53 u-boot Resolution fixed => reopened
2012-03-15 17:53 u-boot Note Added: 0057685
2012-03-15 17:54 u-boot File Added: bug18679.zip
2012-03-15 23:27 u-boot Note Added: 0057693
2012-03-16 01:29 u-boot Note Edited: 0057693
2012-03-16 01:45 u-boot Note Edited: 0057693
2012-03-16 08:04 Zeljan Rikalo Note Added: 0057696
2012-03-16 08:05 Zeljan Rikalo Note Added: 0057697
2012-03-16 08:05 Zeljan Rikalo Status assigned => confirmed
2012-03-16 08:58 Zeljan Rikalo Fixed in Revision 36024 => 36024,36068
2012-03-16 08:58 Zeljan Rikalo Status confirmed => resolved
2012-03-16 08:58 Zeljan Rikalo Resolution reopened => fixed
2012-03-16 08:58 Zeljan Rikalo Note Added: 0057699
2012-03-16 19:27 u-boot Status resolved => assigned
2012-03-16 19:27 u-boot Resolution fixed => reopened
2012-03-16 19:27 u-boot Note Added: 0057734
2012-03-16 20:02 Zeljan Rikalo Note Added: 0057735
2012-03-16 21:17 Zeljan Rikalo Fixed in Revision 36024,36068 => 36024,36068,36095
2012-03-16 21:17 Zeljan Rikalo Status assigned => resolved
2012-03-16 21:17 Zeljan Rikalo Resolution reopened => fixed
2012-03-16 21:17 Zeljan Rikalo Note Added: 0057737
2012-03-16 21:27 u-boot Status resolved => closed
2012-03-16 21:27 u-boot Note Added: 0057738
2015-06-24 14:30 Zeljan Rikalo Relationship added related to 0028123
2017-07-31 13:03 Bart Broersma Relationship added related to 0031618