Community
Participate
Working Groups
Many widgets like ToolItems are clipped to the height and clipped in the width when you run them with GTK+ 3. The problem is that height/width calculations in GTK+ 3 are different from GTK+2. One of the solutions could be to implement swt_fixed_get_preferred_width/height, which currently assigns minimal and natural sizes to 0, so it calculates minimal and natural sizes for GTK+3 as it is suppose to. Here is the patch I propose: http://fedorapeople.org/cgit/aspektor/public_git/eclipse.platform.swt.git/commit/?h=swt_fixed This patch fixes height-width clippings issues. Couple of side-effects of the calculating height/width is that Preference window cannot be resized and CoolBar is taking more space than it should (see ControlExample -> Coolbar Tab), however, there is possibility that there is problem within calculations of CoolBar itself and regarding Preferences window - it has resizing problem without this patch too. Silenio, when you have time, could you please take a look and tell me what are your thoughts on this issue. Thanks!
SWTFixed is only used on GTK3, so the version check is not necessary. Actually it is already done around the whole class (i.e. #ifndef NO_SwtFixed). Let me get the patch running and I will give more useful feedback...
Anatoly, could you point me to some cases where the widgets are clipped? Either on eclipse or controlexample. Thanks!
(In reply to comment #2) > Anatoly, could you point me to some cases where the widgets are clipped? > Either on eclipse or controlexample. Thanks! Silenio, If you run ControlExample without this patch and go to Toolbar Tab you will see that ToolItems in Toolbar are clipped in height and some of them (like last item in the Toolbar) in width. Please take a look at this screenshot: http://oi47.tinypic.com/axzbwy.jpg In Eclipse + GTK3 these clipping are seen in the Eclipse Toolbar, as every Toolbar button is height clipped.
Hum, I cannot reproduce the problem on Ubuntu 12.04 or Fedora 17. Which distribution and gtk version are you running?
(In reply to comment #4) > Hum, I cannot reproduce the problem on Ubuntu 12.04 or Fedora 17. Which > distribution and gtk version are you running? I am on Fedora 18 (64bit) Gtk 3.6
Finally got a Fedora 18 setup, I can see the problem now. Will investigate...
Here is a simple snippet that shows the problem. It is happening because the toolbar padding changes from (0,0,0,0) to (3,3,3,3) when the toolbar is made visible (after shell.open()). If the call to shell.setSize(400, 300) is comment the toolbar lays out properly, otherwise it does not. I confirmed this by calling gtk_style_context_get_padding() before and after shell.open(). I believe the patch is not fixing this problem, since the computeSize() is still wrong. The patch is only forcing the widget to not size smaller than the preferred size computed in the patch. This is a bad side effect. For example, the line bar.setSize(10, 10) does not work with the patch applied. We need to figure out why the padding is changing. Is the GTK CSS explicitly saying that the padding for invisible toolbars is different than the padding for visible toolbars? import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.*; public class ToolBarTest { public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display); shell.setLayout(new GridLayout(1, false)); Image image = display.getSystemImage(SWT.ICON_ERROR); ToolBar bar = new ToolBar(shell, SWT.NONE); bar.setBackground(display.getSystemColor(SWT.COLOR_GREEN)); for (int i = 0; i < 4; i++) { int style = SWT.PUSH; ToolItem item = new ToolItem(bar, style); item.setImage(image); } Point size; size = bar.computeSize(SWT.DEFAULT, SWT.DEFAULT); System.out.println("size=" + size); //Uncomment to see the problem //shell.setSize(400, 300); shell.open(); size = bar.computeSize(SWT.DEFAULT, SWT.DEFAULT); System.out.println("size=" + size); // This line does not work with the patch //bar.setSize(10, 10); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose(); } }
Looks like it's definetely theme specific as with HighContrast I get: size=Point {240, 60} size=Point {248, 70} aka 5,5, 4, 4 and with Oxygen-gtk it's: size=Point {240, 57} size=Point {240, 57} so no padding added. Hope that helps.
Simple PI code that shows the padding changing before and after the window is made visible. public static void main(String[] args) { OS.gtk_init_check(new long[1], null); long window = OS.gtk_window_new(OS.GTK_WINDOW_TOPLEVEL); long toolbar = OS.gtk_toolbar_new(); OS.gtk_container_add(window, toolbar); long item = OS.gtk_tool_button_new(0, "Item\0".getBytes()); OS.gtk_toolbar_set_style(toolbar, OS.GTK_TOOLBAR_TEXT); OS.gtk_toolbar_insert(toolbar, item, 0); OS.gtk_widget_show(item); OS.gtk_widget_show(toolbar); long context = OS.gtk_widget_get_style_context(toolbar); GtkBorder tmp = new GtkBorder(); OS.gtk_style_context_get_padding(context, 0, tmp); System.out.println("padding b=" + tmp.left + " " + tmp.top + " " + tmp.right + " " + tmp.bottom); OS.gtk_window_resize(window, 300, 300); OS.gtk_widget_show(window); OS.gtk_style_context_get_padding(context, 0, tmp); System.out.println("padding b=" + tmp.left + " " + tmp.top + " " + tmp.right + " " + tmp.bottom); OS.gtk_main(); }
So do you have any plan how can we deal with it? I guess that what we see with the toolbar is the same problem in other clipping issues.
(In reply to comment #10) > So do you have any plan how can we deal with it? I guess that what we see > with the toolbar is the same problem in other clipping issues. I still do not understand why this is happening to toolbars. The padding/border of buttons do not change the same way for example. I am not sure which widgets are affected by this. The only hack I can think right now is to override padding for all SWT toolbars. Add something like this in ToolBar.createHandle(). Of cource without creating a new provider every time. long /*int*/ provider = OS.gtk_css_provider_new(); String css = ".toolbar {padding: 0px;}"; byte[] buffer = Converter.wcsToMbcs(null, css, true); OS.gtk_css_provider_load_from_data(provider, buffer, buffer.length, null); long /*int*/ context = OS.gtk_widget_get_style_context(handle); OS.gtk_style_context_add_provider(context, provider, 800/*OS.GTK_STYLE_PROVIDER_PRIORITY_USER*/); Could you point me to other cases where widgets are clipped? Are they toolbars as well? if not, maybe it could help to explain this problem.
It seems none of the toolbar CSS values are loaded before the window is shown, since other values like color do not match. padding b=0 0 0 0 border b=0 0 0 0 color b=1.0 1.0 1.0 border color b=1.0 1.0 1.0 font b=Cantarell 11 padding a=3 3 3 3 border a=0 0 0 0 color b=0.1803921568627451 0.20392156862745098 0.21176470588235294 border color b=0.6505882352941176 0.6505882352941176 0.6505882352941176 font b=Cantarell 11 public static void main(String[] args) { OS.gtk_init_check(new long[1], null); long window = OS.gtk_window_new(OS.GTK_WINDOW_TOPLEVEL); long toolbar = OS.gtk_toolbar_new(); OS.gtk_container_add(window, toolbar); long item = OS.gtk_tool_button_new(0, "Item\0".getBytes()); OS.gtk_toolbar_set_style(toolbar, OS.GTK_TOOLBAR_TEXT); OS.gtk_toolbar_insert(toolbar, item, 0); OS.gtk_widget_show(item); OS.gtk_widget_show(toolbar); long context = OS.gtk_widget_get_style_context(toolbar); GtkBorder tmp = new GtkBorder(); GdkRGBA color = new GdkRGBA(); OS.gtk_style_context_get_padding(context, 0, tmp); System.out.println("padding b=" + tmp.left + " " + tmp.top + " " + tmp.right + " " + tmp.bottom); OS.gtk_style_context_get_border(context, 0, tmp); System.out.println("border b=" + tmp.left + " " + tmp.top + " " + tmp.right + " " + tmp.bottom); OS.gtk_style_context_get_color(context, 0, color); System.out.println("color b=" + color.red + " " + color.green + " " + color.blue); OS.gtk_style_context_get_border_color(context, 0, color); System.out.println("border color b=" + color.red + " " + color.green + " " + color.blue); long /*int*/ font = OS.gtk_style_context_get_font(context, 0); long /*int*/ name = OS.pango_font_description_to_string(font); byte[] buffer= new byte[OS.strlen(name)]; OS.memmove(buffer, name, buffer.length); System.out.println("font b=" + new String(buffer)); OS.gtk_window_resize(window, 300, 300); OS.gtk_widget_show(window); OS.gtk_style_context_get_padding(context, 0, tmp); System.out.println("padding a=" + tmp.left + " " + tmp.top + " " + tmp.right + " " + tmp.bottom); OS.gtk_style_context_get_border(context, 0, tmp); System.out.println("border a=" + tmp.left + " " + tmp.top + " " + tmp.right + " " + tmp.bottom); OS.gtk_style_context_get_color(context, 0, color); System.out.println("color b=" + color.red + " " + color.green + " " + color.blue); OS.gtk_style_context_get_border_color(context, 0, color); System.out.println("border color b=" + color.red + " " + color.green + " " + color.blue); font = OS.gtk_style_context_get_font(context, 0); name = OS.pango_font_description_to_string(font); buffer= new byte[OS.strlen(name)]; OS.memmove(buffer, name, buffer.length); System.out.println("font b=" + new String(buffer)); OS.gtk_main(); }
Calling gtk_style_context_invalidate() seems to work around the problem. padding b=3 3 3 3 border b=0 0 0 0 color b=0.1803921568627451 0.20392156862745098 0.21176470588235294 border color b=0.6505882352941176 0.6505882352941176 0.6505882352941176 font b=Cantarell 11 padding a=3 3 3 3 border a=0 0 0 0 color b=0.1803921568627451 0.20392156862745098 0.21176470588235294 border color b=0.6505882352941176 0.6505882352941176 0.6505882352941176 font b=Cantarell 11 public static void main(String[] args) { OS.gtk_init_check(new long[1], null); long window = OS.gtk_window_new(OS.GTK_WINDOW_TOPLEVEL); long toolbar = OS.gtk_toolbar_new(); OS.gtk_container_add(window, toolbar); long item = OS.gtk_tool_button_new(0, "Item\0".getBytes()); OS.gtk_toolbar_set_style(toolbar, OS.GTK_TOOLBAR_TEXT); OS.gtk_toolbar_insert(toolbar, item, 0); OS.gtk_widget_show(item); OS.gtk_widget_show(toolbar); long context = OS.gtk_widget_get_style_context(toolbar); //FIX OS.gtk_style_context_invalidate(context); GtkBorder tmp = new GtkBorder(); GdkRGBA color = new GdkRGBA(); OS.gtk_style_context_get_padding(context, 0, tmp); System.out.println("padding b=" + tmp.left + " " + tmp.top + " " + tmp.right + " " + tmp.bottom); OS.gtk_style_context_get_border(context, 0, tmp); System.out.println("border b=" + tmp.left + " " + tmp.top + " " + tmp.right + " " + tmp.bottom); OS.gtk_style_context_get_color(context, 0, color); System.out.println("color b=" + color.red + " " + color.green + " " + color.blue); OS.gtk_style_context_get_border_color(context, 0, color); System.out.println("border color b=" + color.red + " " + color.green + " " + color.blue); long /*int*/ font = OS.gtk_style_context_get_font(context, 0); long /*int*/ name = OS.pango_font_description_to_string(font); byte[] buffer= new byte[OS.strlen(name)]; OS.memmove(buffer, name, buffer.length); System.out.println("font b=" + new String(buffer)); OS.gtk_window_resize(window, 300, 300); OS.gtk_widget_show(window); OS.gtk_style_context_get_padding(context, 0, tmp); System.out.println("padding a=" + tmp.left + " " + tmp.top + " " + tmp.right + " " + tmp.bottom); OS.gtk_style_context_get_border(context, 0, tmp); System.out.println("border a=" + tmp.left + " " + tmp.top + " " + tmp.right + " " + tmp.bottom); OS.gtk_style_context_get_color(context, 0, color); System.out.println("color b=" + color.red + " " + color.green + " " + color.blue); OS.gtk_style_context_get_border_color(context, 0, color); System.out.println("border color b=" + color.red + " " + color.green + " " + color.blue); font = OS.gtk_style_context_get_font(context, 0); name = OS.pango_font_description_to_string(font); buffer= new byte[OS.strlen(name)]; OS.memmove(buffer, name, buffer.length); System.out.println("font b=" + new String(buffer)); OS.gtk_main(); }
Released this work around for now. I still want to investigate other clipped widgets. http://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/?id=84cc272047c4a7bc01c0302a7e0d0d86b563b8f5
Bug 400339 is another clipping issue but it looks different from this one.
Another observation if one runs AllGtkTests there are a number of setForeground/setBackground failures which are fixable by invalidating the style context. This makes me think that the context might need to be invalidated everytime gtk_widget_override* is used and maybe in a number of other cases too.
Anyone objecting to invalidating in setFont/setBackground/setForeground in order to be sure that getters retrieve the correct data. It would be good to finally have a working testsuite with gtk3.
It seems ok. The tests are not failing for me on Fedora 18. Are you running Fedora 17?
(In reply to comment #18) > It seems ok. The tests are not failing for me on Fedora 18. Are you running > Fedora 17? I do run fully uptodate Fedora 18 x86_64.
Using Gnome Shell with Adwaita - this might be important as many times issues appear only with certain themes.
(In reply to comment #18) > It seems ok. The tests are not failing for me on Fedora 18. Are you running > Fedora 17? I swapped the versions above. Tests are not falling for me on Fedora 17. And I just checked that they fail on Fedora 18.
It looks like Fedora 18 introduced a bug. We should not have to call gtk_context_style_invalidate(). Maybe we should open a bug against GTK. In the mean time calling invalidate ourselves is ok.
I believe the clipping problems are gone. Bug#400339 and bug#394583 where not related to this problem, but they are fixed as well. Closing this. Alex, please open a separate bug for the font/foreground/background problem.