Recent

Author Topic: TEdit background color and gtkrc experiements (is it worth it?)  (Read 1258 times)

maxerist

  • New Member
  • *
  • Posts: 28
TEdit background color and gtkrc experiements (is it worth it?)
« on: November 02, 2022, 05:10:19 pm »
Hi,
I recently met a well-known problem that gtk sometimes ignores different styling customizations for particular widgets, the posts about it can be found not only in lazarus-related communities, but many others as well. In my case it was about TEdit background color (in current Almalinux 9). I tried to play with gtkrc file for my application and nothing seemed to work except one peculiar case.

The following gtkrc file (the trick with disabling engine was borrowed from https://github.com/picoe/Eto/issues/382)

Quote
style "noengine" {
  engine "" {}
}
widget_class "*" style "noengine"

freed the TEdit from the "always while" life and started coloring it. But with caveats. So it basically became
  • blue for the active state (no blue in any color-related properties of the control)
  • the color from the TEdit.Color property I chose when the edit is in the inactive state.

I felt lucky because at least the chosen color reveal itself in some circumstances (inactive). So  is it worth it trying to make some additional calls for custom colors in order for it to accept the Color property as a whole? Sure I try to solve my problem, but who knows, maybe this trick will allow managing linux gtk-based controls for other cases.

Thanks

maxerist

  • New Member
  • *
  • Posts: 28
Re: TEdit background color and gtkrc experiements (is it worth it?)
« Reply #1 on: November 11, 2022, 09:00:42 pm »
Replying to myself after some experiments

It looks like the trick with disabling gtk engine is really working and helps overcome TEdit background color limitation. 
The syntax to apply it only to GtkEntry is a little modified fragment I posted earlier

Quote
style "noengine" {
  engine "" {}
}
widget_class "*.GtkEntry" style "noengine"

The different colors I mentioned previously that unexpectedly reveal after such a change is actually correspond to each of the known widget states (in lazarus constants GTK_STATE_NORMAL, GTK_STATE_ACTIVE,GTK_STATE_PRELIGHT,GTK_STATE_SELECTED). I suspect that the gtk+ developers intentionally made them different to be noticed when the engine is off but it's just a guess. The problem with lcl is that  the code only tries to affect a single state, the code fragment below shows it
(lcl\interfaces\gtk2\gtk2wsstdctrls.pp)
Code: [Select]
class procedure TGtk2WSCustomEdit.SetColor(const AWinControl: TWinControl);
var
  AWidget: PGTKWidget;
begin
  if not WSCheckHandleAllocated(AWinControl, 'SetColor') then Exit;
  AWidget := {%H-}PGtkWidget(AWinControl.Handle);
  // don't change selected state
  Gtk2WidgetSet.SetWidgetColor(AWidget, clNone, AWinControl.Color,
    [GTK_STATE_NORMAL, GTK_STYLE_BASE]);
end;
probably for some reason (the comment is very scary in this respect),but changing the set to

[GTK_STATE_NORMAL, GTK_STATE_ACTIVE,GTK_STATE_PRELIGHT,GTK_STATE_SELECTED, GTK_STYLE_BASE] allows TEdit fully obey the color set. Also the same can be achieved by creating a style in gtkrc file when all four base colors are chosen, but this will be applied to all edits in the project. 

The first trick (with engine disabling and patching) was used in my project with plenty of light on dark edits and it works at least for now.

But I should mention that for controls that has clNone for Color the rainbow effect of noengine colors will be persistent since TGtk2WidgetSet.SetWidgetColor just ignores calling gtk routines in this case. When engine is on, the default theme colors working so no negative visible change exist. In my case I was sure that no default color edits exist in the project so this wasn't a problem


I noticed that TComboBox with editable field seems like also behaves similar to TEdit and the code about setting color also lacks three other states. This fix seems like also working, but I didn't test it carefully. But there's another problem with TComboBox. This time the TComboBox in drop down only mode (without editable field) doesn't listen to background color changes no matter what. I thought that it may be due to the fact that GTK_STYLE_BASE also passed unconditionally so gtk_widget_modify_base is called instead of (more logical) gtk_widget_modify_bg, but this change didn't help. Googling probably shows different examples of "always gray" combobox, but I'm not sure

MarkMLl

  • Hero Member
  • *****
  • Posts: 6812
Re: TEdit background color and gtkrc experiements (is it worth it?)
« Reply #2 on: November 12, 2022, 10:26:53 pm »
Even if nobody's commenting, that doesn't mean that nobody's reading :-)

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

codeninja

  • New member
  • *
  • Posts: 7
Re: TEdit background color and gtkrc experiements (is it worth it?)
« Reply #3 on: May 16, 2024, 12:58:40 pm »
maxerist, I ran into the same issue. Your topic helped me a lot.

I solved the problem this way
https://gitlab.com/freepascal.org/lazarus/lazarus/-/issues/38516#note_1898936686

You can turn off theme engine for you control by using api. The same can be done using gtkrc file. But you need to call gtk_widget_set_name to set a name to your control

Code: Pascal  [Select][+][-]
  1. {$IFDEF LCLGTK2}uses gtk2, WSProc{$ENDIF};
  2. ...
  3. {$IFDEF LCLGTK2}
  4. // parse gtkrc from string
  5. gtk_rc_parse_string(PChar('style "noengine" {' + LineEnding +
  6.   'engine "" {}' + LineEnding +
  7.   '}' + LineEnding +
  8.   'widget "*.your-edit" style "noengine"'));
  9.  
  10. if WSCheckHandleAllocated(Edit, 'SetColor') then
  11. begin
  12.   // set gtk name to our component
  13.   gtk_widget_set_name({%H-}PGtkWidget(YorEdit.Handle), 'your-edit');
  14. end;
  15. {$ENDIF}
  16.  

Hope this will help somebody

maxerist

  • New Member
  • *
  • Posts: 28
Re: TEdit background color and gtkrc experiements (is it worth it?)
« Reply #4 on: May 17, 2024, 01:50:53 pm »
maxerist, I ran into the same issue. Your topic helped me a lot.
codeninja, glad to hear. Interesting that I remember that I visited the issue tracker page you mentioned while trying to solve this, but the problem is niche so no surprise.

Also I should correct my previous info, probably because it was posted in relaxed form, so even I myself have trouble recalling exactly what I thought :) Anyway, the TGtk2WSCustomEdit.SetColor fragment and the suggestion to extend the set was not about solving with this single change, but as an additional action to the gtk engine disabling. So in my case without this the colors of the states that correspond to [GTK_STATE_ACTIVE,GTK_STATE_PRELIGHT,GTK_STATE_SELECTED] were changing uncontrollably.

So, no question about disabling the engine, with the gtkrc file or programmatically as you have found. But are your color in different states are ok without this change? I see in the current source  that the TGtk2WSCustomEdit.SetColor body looks like it it was then. Maybe some other change allowed avoiding this fix?

 

TinyPortal © 2005-2018