Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 403191 - [GTK+3] Implement SwtFixed preferred height/width methods
Summary: [GTK+3] Implement SwtFixed preferred height/width methods
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 4.3   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: 4.3 M6   Edit
Assignee: Silenio Quarti CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 340067
  Show dependency tree
 
Reported: 2013-03-13 09:53 EDT by Anatoly Spektor CLA
Modified: 2013-07-22 07:35 EDT (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Anatoly Spektor CLA 2013-03-13 09:53:48 EDT
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!
Comment 1 Silenio Quarti CLA 2013-03-13 15:31:55 EDT
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...
Comment 2 Silenio Quarti CLA 2013-03-14 13:46:11 EDT
Anatoly, could you point me to some cases where the widgets are clipped? Either on eclipse or controlexample. Thanks!
Comment 3 Anatoly Spektor CLA 2013-03-14 14:02:16 EDT
(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.
Comment 4 Silenio Quarti CLA 2013-03-14 14:25:22 EDT
Hum, I cannot reproduce the problem on Ubuntu 12.04 or Fedora 17. Which distribution and gtk version are you running?
Comment 5 Anatoly Spektor CLA 2013-03-14 14:39:51 EDT
(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
Comment 6 Silenio Quarti CLA 2013-03-18 11:30:16 EDT
Finally got a Fedora 18 setup, I can see the problem now. Will investigate...
Comment 7 Silenio Quarti CLA 2013-03-18 15:24:14 EDT
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();
}
}
Comment 8 Alexander Kurtakov CLA 2013-03-18 17:13:54 EDT
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.
Comment 9 Silenio Quarti CLA 2013-03-19 13:08:59 EDT
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();
}
Comment 10 Alexander Kurtakov CLA 2013-03-19 13:13:51 EDT
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.
Comment 11 Silenio Quarti CLA 2013-03-19 14:09:11 EDT
(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.
Comment 12 Silenio Quarti CLA 2013-03-19 14:27:22 EDT
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();
}
Comment 13 Silenio Quarti CLA 2013-03-19 14:37:11 EDT
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();
}
Comment 14 Silenio Quarti CLA 2013-03-19 14:52:22 EDT
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
Comment 15 Alexander Kurtakov CLA 2013-03-19 15:19:47 EDT
Bug 400339 is another clipping issue but it looks different from this one.
Comment 16 Alexander Kurtakov CLA 2013-03-19 15:35:27 EDT
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.
Comment 17 Alexander Kurtakov CLA 2013-03-20 11:13:06 EDT
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.
Comment 18 Silenio Quarti CLA 2013-03-20 12:10:17 EDT
It seems ok. The tests are not failing for me on Fedora 18. Are you running Fedora 17?
Comment 19 Alexander Kurtakov CLA 2013-03-20 12:11:11 EDT
(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.
Comment 20 Alexander Kurtakov CLA 2013-03-20 12:12:05 EDT
Using Gnome Shell with Adwaita - this might be important as many times issues appear only with certain themes.
Comment 21 Silenio Quarti CLA 2013-03-20 12:26:06 EDT
(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.
Comment 22 Silenio Quarti CLA 2013-03-20 12:29:20 EDT
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.
Comment 23 Silenio Quarti CLA 2013-03-20 12:46:18 EDT
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.