--- old/make/lib/Awt2dLibraries.gmk 2018-09-05 12:09:24.239360000 +0530 +++ new/make/lib/Awt2dLibraries.gmk 2018-09-05 12:09:23.943212000 +0530 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -606,7 +606,9 @@ debug_trace.c \ debug_util.c \ gnome_interface.c \ + gtk_interface.c \ gtk2_interface.c \ + gtk3_interface.c \ swing_GTKEngine.c \ swing_GTKStyle.c \ rect.c \ --- old/make/mapfiles/libawt_xawt/mapfile-vers 2018-09-05 12:09:25.115798000 +0530 +++ new/make/mapfiles/libawt_xawt/mapfile-vers 2018-09-05 12:09:24.771626000 +0530 @@ -1,5 +1,5 @@ # -# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -174,6 +174,7 @@ Java_sun_awt_UNIXToolkit_load_1gtk_1icon; Java_sun_awt_UNIXToolkit_nativeSync; Java_sun_awt_UNIXToolkit_gtkCheckVersionImpl; + Java_sun_awt_UNIXToolkit_get_1gtk_1version; Java_java_awt_AWTEvent_initIDs; Java_java_awt_event_InputEvent_initIDs; Java_java_awt_event_KeyEvent_initIDs; --- old/src/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java 2018-09-05 12:09:25.940210000 +0530 +++ new/src/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java 2018-09-05 12:09:25.636057999 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -158,8 +158,8 @@ int widgetType, int state, int shadowType, String detail, int x, int y, int width, int height, int synthState, int dir); private native void native_paint_slider( - int widgetType, int state, int shadowType, String detail, - int x, int y, int width, int height, int orientation); + int widgetType, int state, int shadowType, String detail, int x, + int y, int width, int height, int orientation, boolean hasFocus); private native void native_paint_vline( int widgetType, int state, String detail, int x, int y, int width, int height); @@ -491,6 +491,14 @@ int gtkState = GTKLookAndFeel.synthStateToGTKStateType(state).ordinal(); int synthState = context.getComponentState(); + Container parent = context.getComponent().getParent(); + if(GTKLookAndFeel.is3()) { + if (parent != null && parent.getParent() instanceof JComboBox) { + if (parent.getParent().hasFocus()) { + synthState |= SynthConstants.FOCUSED; + } + } + } int dir = getTextDirection(context); int widget = getWidgetType(context.getComponent(), id).ordinal(); native_paint_shadow(widget, gtkState, shadowType.ordinal(), detail, @@ -498,13 +506,13 @@ } public void paintSlider(Graphics g, SynthContext context, - Region id, int state, ShadowType shadowType, String detail, - int x, int y, int w, int h, Orientation orientation) { + Region id, int state, ShadowType shadowType, String detail, int x, + int y, int w, int h, Orientation orientation, boolean hasFocus) { state = GTKLookAndFeel.synthStateToGTKStateType(state).ordinal(); int widget = getWidgetType(context.getComponent(), id).ordinal(); native_paint_slider(widget, state, shadowType.ordinal(), detail, - x - x0, y - y0, w, h, orientation.ordinal()); + x - x0, y - y0, w, h, orientation.ordinal(), hasFocus); } public void paintVline(Graphics g, SynthContext context, @@ -578,8 +586,8 @@ * Convenience method that delegates to finishPainting() with * caching enabled. */ - public void finishPainting() { - finishPainting(true); + public BufferedImage finishPainting() { + return finishPainting(true); } /** @@ -587,7 +595,7 @@ * BufferedImage from the offscreen buffer, (optionally) cache it, * and paint it. */ - public void finishPainting(boolean useCache) { + public BufferedImage finishPainting(boolean useCache) { DataBufferInt dataBuffer = new DataBufferInt(w0 * h0); // Note that stealData() requires a markDirty() afterwards // since we modify the data in it. @@ -601,11 +609,12 @@ dataBuffer, w0, h0, w0, bands, null); ColorModel cm = COLOR_MODELS[transparency - 1]; - Image img = new BufferedImage(cm, raster, false, null); + BufferedImage img = new BufferedImage(cm, raster, false, null); if (useCache) { cache.setImage(getClass(), null, w0, h0, cacheArgs, img); } graphics.drawImage(img, x0, y0, null); + return img; } /** --- old/src/share/classes/com/sun/java/swing/plaf/gtk/GTKGraphicsUtils.java 2018-09-05 12:09:27.028754000 +0530 +++ new/src/share/classes/com/sun/java/swing/plaf/gtk/GTKGraphicsUtils.java 2018-09-05 12:09:26.644561999 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,32 +47,15 @@ return; } int componentState = context.getComponentState(); - if ((componentState & SynthConstants.DISABLED) == - SynthConstants.DISABLED){ - Color orgColor = g.getColor(); - g.setColor(context.getStyle().getColor(context, - GTKColorType.WHITE)); - x += 1; - y += 1; - super.paintText(context, g, text, x, y, mnemonicIndex); - - g.setColor(orgColor); - x -= 1; - y -= 1; - super.paintText(context, g, text, x, y, mnemonicIndex); - } - else { - String themeName = GTKLookAndFeel.getGtkThemeName(); - if (themeName != null && themeName.startsWith("blueprint") && - shouldShadowText(context.getRegion(), componentState)) { - - g.setColor(Color.BLACK); - super.paintText(context, g, text, x+1, y+1, mnemonicIndex); - g.setColor(Color.WHITE); - } - - super.paintText(context, g, text, x, y, mnemonicIndex); + String themeName = GTKLookAndFeel.getGtkThemeName(); + if (themeName != null && themeName.startsWith("blueprint") && + shouldShadowText(context.getRegion(), componentState)) { + + g.setColor(Color.BLACK); + super.paintText(context, g, text, x+1, y+1, mnemonicIndex); + g.setColor(Color.WHITE); } + super.paintText(context, g, text, x, y, mnemonicIndex); } /** --- old/src/share/classes/com/sun/java/swing/plaf/gtk/GTKIconFactory.java 2018-09-05 12:09:28.289384000 +0530 +++ new/src/share/classes/com/sun/java/swing/plaf/gtk/GTKIconFactory.java 2018-09-05 12:09:27.809144000 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -214,6 +214,18 @@ Region region = context.getRegion(); GTKStyle style = (GTKStyle) context.getStyle(); + if (GTKLookAndFeel.is3() && region == Region.MENU) { + Object value = style.getClassSpecificValue("arrow-scaling"); + if (value instanceof Number) { + iconDimension = (int)(((Number) value).floatValue() * + (style.getFont(context).getSize2D() + + 2 * style.getClassSpecificIntValue(context, + "indicator-spacing", DEFAULT_ICON_SPACING))); + if (iconDimension > 0) { + return iconDimension; + } + } + } iconDimension = style.getClassSpecificIntValue(context, "indicator-size", (region == Region.CHECK_BOX_MENU_ITEM || --- old/src/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java 2018-09-05 12:09:29.449964000 +0530 +++ new/src/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java 2018-09-05 12:09:29.025752000 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,8 @@ * @author Scott Violet */ public class GTKLookAndFeel extends SynthLookAndFeel { - private static final boolean IS_22; + private static boolean IS_22; + private static boolean IS_3; /** * Whether or not text is drawn antialiased. This keys off the @@ -105,16 +106,6 @@ private static String gtkThemeName = "Default"; static { - // Backup for specifying the version, this isn't currently documented. - // If you pass in anything but 2.2 you got the 2.0 colors/look. - String version = AccessController.doPrivileged( - new GetPropertyAction("swing.gtk.version")); - if (version != null) { - IS_22 = version.equals("2.2"); - } - else { - IS_22 = true; - } String language = Locale.getDefault().getLanguage(); boolean cjkLocale = @@ -156,6 +147,10 @@ return IS_22; } + static boolean is3() { + return IS_3; + } + /** * Maps a swing constant to a GTK constant. */ @@ -545,7 +540,7 @@ public Object createValue(UIDefaults table) { GTKStyleFactory factory = (GTKStyleFactory)getStyleFactory(); GTKStyle style = (GTKStyle)factory.getStyle(null, region); - return style.getFontForState(null); + return style.getDefaultFont(); } } @@ -1457,6 +1452,19 @@ throw new InternalError("Unable to load native GTK libraries"); } + if (UNIXToolkit.getGtkVersion() == UNIXToolkit.GtkVersions.GTK2) { + String version = AccessController.doPrivileged( + new GetPropertyAction("jdk.gtk.version")); + if (version != null) { + IS_22 = version.equals("2.2"); + } else { + IS_22 = true; + } + } else if (UNIXToolkit.getGtkVersion() == + UNIXToolkit.GtkVersions.GTK3) { + IS_3 = true; + } + super.initialize(); inInitialize = true; loadStyles(); --- old/src/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java 2018-09-05 12:09:30.698587999 +0530 +++ new/src/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java 2018-09-05 12:09:30.214345999 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,8 @@ import sun.awt.UNIXToolkit; +import sun.awt.ModalExclude; +import sun.awt.SunToolkit; import javax.swing.plaf.synth.*; import java.awt.*; import javax.swing.*; @@ -36,6 +38,7 @@ import com.sun.java.swing.plaf.gtk.GTKConstants.Orientation; import com.sun.java.swing.plaf.gtk.GTKConstants.PositionType; import com.sun.java.swing.plaf.gtk.GTKConstants.ShadowType; +import java.awt.image.BufferedImage; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -567,8 +570,10 @@ Region id = context.getRegion(); int gtkState = GTKLookAndFeel.synthStateToGTKState( id, context.getComponentState()); + boolean isHW = SunToolkit.getHeavyweightComponent( + context.getComponent()) instanceof ModalExclude; synchronized (UNIXToolkit.GTK_LOCK) { - if (ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState)) { + if (ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState, isHW)) { return; } ENGINE.startPainting(g, x, y, w, h, id, gtkState); @@ -582,7 +587,25 @@ style.getGTKColor(context, gtkState, GTKColorType.BACKGROUND), x + xThickness, y + yThickness, w - xThickness - xThickness, h - yThickness - yThickness); - ENGINE.finishPainting(); + BufferedImage img = ENGINE.finishPainting(); + if(!isHW) { + int border = img.getRGB(0, h / 2); + if (img != null && border == img.getRGB(w / 2, h / 2)) { + // fix no menu borders in Adwaita theme + Graphics g2 = img.getGraphics(); + Color c = new Color(border); + g2.setColor(new Color(Math.max((int) (c.getRed() * 0.8), 0), + Math.max((int) (c.getGreen() * 0.8), 0), + Math.max((int) (c.getBlue() * 0.8), 0))); + g2.drawLine(0, 0, w - 1, 0); + g2.drawLine(w - 1, 0, w - 1, h - 1); + g2.drawLine(0, h - 1, 0, 1); + g2.setColor(c.darker()); + g2.drawLine(w - 1, h - 1, 0, h - 1); + g2.dispose(); + g.drawImage(img, x, y, null); + } + } } } @@ -699,6 +722,17 @@ } else { h -= (insets.top + insets.bottom); } + if (GTKLookAndFeel.is3()) { + if (id == Region.POPUP_MENU_SEPARATOR) { + detail = "menuitem"; + h -= (insets.top + insets.bottom); + } else { + detail = "separator"; + } + } else { + detail = orientation == JSeparator.HORIZONTAL ? + "hseparator" : "vseparator"; + } } synchronized (UNIXToolkit.GTK_LOCK) { @@ -743,6 +777,15 @@ // The ubuntulooks engine paints slider troughs differently depending // on the current slider value and its component orientation. JSlider slider = (JSlider)context.getComponent(); + if (GTKLookAndFeel.is3()) { + if (slider.getOrientation() == JSlider.VERTICAL) { + y += 1; + h -= 2; + } else { + x += 1; + w -= 2; + } + } double value = slider.getValue(); double min = slider.getMinimum(); double max = slider.getMaximum(); @@ -776,15 +819,17 @@ Region id = context.getRegion(); int gtkState = GTKLookAndFeel.synthStateToGTKState( id, context.getComponentState()); + boolean hasFocus = GTKLookAndFeel.is3() && + ((context.getComponentState() & SynthConstants.FOCUSED) != 0); synchronized (UNIXToolkit.GTK_LOCK) { - if (! ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState, dir)) { + if (! ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState, dir, hasFocus)) { Orientation orientation = (dir == JSlider.HORIZONTAL ? Orientation.HORIZONTAL : Orientation.VERTICAL); String detail = (dir == JSlider.HORIZONTAL ? "hscale" : "vscale"); ENGINE.startPainting(g, x, y, w, h, id, gtkState, dir); ENGINE.paintSlider(g, context, id, gtkState, - ShadowType.OUT, detail, x, y, w, h, orientation); + ShadowType.OUT, detail, x, y, w, h, orientation, hasFocus); ENGINE.finishPainting(); } } @@ -963,15 +1008,21 @@ int yThickness = style.getYThickness(); ENGINE.startPainting(g, x, y, w, h, id, state); + if (GTKLookAndFeel.is3()) { + ENGINE.paintBackground(g, context, id, gtkState, null, + x, y, w, h); + } ENGINE.paintShadow(g, context, id, gtkState, ShadowType.IN, "entry", x, y, w, h); - ENGINE.paintFlatBox(g, context, id, - gtkState, ShadowType.NONE, "entry_bg", - x + xThickness, - y + yThickness, - w - (2 * xThickness), - h - (2 * yThickness), - ColorType.TEXT_BACKGROUND); + if (!GTKLookAndFeel.is3()) { + ENGINE.paintFlatBox(g, context, id, + gtkState, ShadowType.NONE, "entry_bg", + x + xThickness, + y + yThickness, + w - (2 * xThickness), + h - (2 * yThickness), + ColorType.TEXT_BACKGROUND); + } if (focusSize > 0 && (state & SynthConstants.FOCUSED) != 0) { if (!interiorFocus) { @@ -982,14 +1033,14 @@ } else { if (containerParent instanceof JComboBox) { x += (focusSize + 2); - y += (focusSize + 1); - w -= (2 * focusSize + 1); - h -= (2 * focusSize + 2); + y += focusSize + (GTKLookAndFeel.is3() ? 3 : 1); + w -= 2 * focusSize + (GTKLookAndFeel.is3() ? 4 : 1); + h -= 2 * focusSize + (GTKLookAndFeel.is3() ? 6 : 2); } else { - x += focusSize; - y += focusSize; - w -= 2 * focusSize; - h -= 2 * focusSize; + x += focusSize + (GTKLookAndFeel.is3() ? 2 : 0); + y += focusSize + (GTKLookAndFeel.is3() ? 2 :0 ); + w -= 2 * focusSize + (GTKLookAndFeel.is3() ? 4 : 0); + h -= 2 * focusSize + (GTKLookAndFeel.is3() ? 4 : 0); } } ENGINE.paintFocus(g, context, id, gtkState, @@ -1139,7 +1190,7 @@ Orientation.HORIZONTAL : Orientation.VERTICAL); ENGINE.setRangeValue(context, id, value, min, max, visible); ENGINE.paintSlider(g, context, id, gtkState, - ShadowType.OUT, "slider", x, y, w, h, orientation); + ShadowType.OUT, "slider", x, y, w, h, orientation, false); ENGINE.finishPainting(); } } @@ -1295,14 +1346,14 @@ Graphics g, int state, int x, int y, int w, int h) { ENGINE.paintExpander(g, context, Region.TREE, GTKLookAndFeel.synthStateToGTKState(context.getRegion(), state), - ExpanderStyle.EXPANDED, "treeview", x, y, w, h); + ExpanderStyle.EXPANDED, "expander", x, y, w, h); } public void paintTreeCollapsedIcon(SynthContext context, Graphics g, int state, int x, int y, int w, int h) { ENGINE.paintExpander(g, context, Region.TREE, GTKLookAndFeel.synthStateToGTKState(context.getRegion(), state), - ExpanderStyle.COLLAPSED, "treeview", x, y, w, h); + ExpanderStyle.COLLAPSED, "expander", x, y, w, h); } public void paintCheckBoxIcon(SynthContext context, @@ -1337,8 +1388,13 @@ if (gtkState == SynthConstants.MOUSE_OVER) { shadow = ShadowType.IN; } + if (!GTKLookAndFeel.is3()) { + x += 3; + y += 3; + w = h = 7; + } ENGINE.paintArrow(g, context, Region.MENU_ITEM, gtkState, shadow, - dir, "menuitem", x + 3, y + 3, 7, 7); + dir, "menuitem", x, y, w, h); } public void paintCheckBoxMenuItemCheckIcon(SynthContext context, --- old/src/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java 2018-09-05 12:09:31.791133999 +0530 +++ new/src/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java 2018-09-05 12:09:31.442960000 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -278,7 +278,17 @@ return getColorForState(context, type); } + Font getDefaultFont() { + return font; + } + protected Font getFontForState(SynthContext context) { + Font propFont = UIManager + .getFont(context.getRegion().getName() + ".font"); + if (propFont != null) { + // if font property got a value then return it + return propFont; + } return font; } @@ -711,29 +721,33 @@ if (region == Region.COMBO_BOX || region == Region.DESKTOP_PANE || region == Region.DESKTOP_ICON || - region == Region.EDITOR_PANE || - region == Region.FORMATTED_TEXT_FIELD || region == Region.INTERNAL_FRAME || region == Region.LIST || region == Region.MENU_BAR || region == Region.PANEL || - region == Region.PASSWORD_FIELD || region == Region.POPUP_MENU || region == Region.PROGRESS_BAR || region == Region.ROOT_PANE || region == Region.SCROLL_PANE || - region == Region.SPINNER || region == Region.SPLIT_PANE_DIVIDER || region == Region.TABLE || region == Region.TEXT_AREA || - region == Region.TEXT_FIELD || - region == Region.TEXT_PANE || region == Region.TOOL_BAR_DRAG_WINDOW || region == Region.TOOL_TIP || region == Region.TREE || region == Region.VIEWPORT) { return true; } + if (!GTKLookAndFeel.is3()) { + if (region == Region.EDITOR_PANE || + region == Region.FORMATTED_TEXT_FIELD || + region == Region.PASSWORD_FIELD || + region == Region.SPINNER || + region == Region.TEXT_FIELD || + region == Region.TEXT_PANE) { + return true; + } + } Component c = context.getComponent(); String name = c.getName(); if (name == "ComboBox.renderer" || name == "ComboBox.listRenderer") { @@ -829,6 +843,14 @@ int focusPad = getClassSpecificIntValue(context, "focus-padding", 1); return indicatorSpacing + focusSize + focusPad; + } else if (GTKLookAndFeel.is3() && "ComboBox.forceOpaque".equals(key)) { + return true; + } else if ("Tree.expanderSize".equals(key)) { + Object value = getClassSpecificValue("expander-size"); + if (value instanceof Integer) { + return (Integer)value + 4; + } + return null; } // Is it a stock icon ? @@ -1108,9 +1130,9 @@ static { CLASS_SPECIFIC_MAP = new HashMap(); CLASS_SPECIFIC_MAP.put("Slider.thumbHeight", "slider-width"); + CLASS_SPECIFIC_MAP.put("Slider.thumbWidth", "slider-length"); CLASS_SPECIFIC_MAP.put("Slider.trackBorder", "trough-border"); CLASS_SPECIFIC_MAP.put("SplitPane.size", "handle-size"); - CLASS_SPECIFIC_MAP.put("Tree.expanderSize", "expander-size"); CLASS_SPECIFIC_MAP.put("ScrollBar.thumbHeight", "slider-width"); CLASS_SPECIFIC_MAP.put("ScrollBar.width", "slider-width"); CLASS_SPECIFIC_MAP.put("TextArea.caretForeground", "cursor-color"); --- old/src/solaris/classes/sun/awt/UNIXToolkit.java 2018-09-05 12:09:32.683580000 +0530 +++ new/src/solaris/classes/sun/awt/UNIXToolkit.java 2018-09-05 12:09:32.375425999 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,9 +29,11 @@ import java.awt.color.ColorSpace; import java.awt.image.*; import java.security.AccessController; +import java.security.PrivilegedAction; import sun.security.action.GetIntegerAction; import com.sun.java.swing.plaf.gtk.GTKConstants.TextDirection; import sun.java2d.opengl.OGLRenderQueue; +import sun.security.action.GetPropertyAction; public abstract class UNIXToolkit extends SunToolkit { @@ -42,6 +44,40 @@ private static final int[] BAND_OFFSETS_ALPHA = { 0, 1, 2, 3 }; private static final int DEFAULT_DATATRANSFER_TIMEOUT = 10000; + // Allowed GTK versions + public enum GtkVersions { + ANY(0), + GTK2(Constants.GTK2_MAJOR_NUMBER), + GTK3(Constants.GTK3_MAJOR_NUMBER); + + static class Constants { + static final int GTK2_MAJOR_NUMBER = 2; + static final int GTK3_MAJOR_NUMBER = 3; + } + + final int number; + + GtkVersions(int number) { + this.number = number; + } + + public static GtkVersions getVersion(int number) { + switch (number) { + case Constants.GTK2_MAJOR_NUMBER: + return GTK2; + case Constants.GTK3_MAJOR_NUMBER: + return GTK3; + default: + return ANY; + } + } + + // major GTK version number + public int getNumber() { + return number; + } + }; + private Boolean nativeGTKAvailable; private Boolean nativeGTKLoaded; private BufferedImage tmpImage = null; @@ -79,7 +115,7 @@ return nativeGTKAvailable; } else { - boolean success = check_gtk(); + boolean success = check_gtk(getEnabledGtkVersion().getNumber()); nativeGTKAvailable = success; return success; } @@ -97,7 +133,8 @@ public boolean loadGTK() { synchronized (GTK_LOCK) { if (nativeGTKLoaded == null) { - nativeGTKLoaded = load_gtk(); + nativeGTKLoaded = load_gtk(getEnabledGtkVersion().getNumber(), + isGtkVerbose()); } } return nativeGTKLoaded; @@ -240,14 +277,15 @@ tmpImage = new BufferedImage(colorModel, raster, false, null); } - private static native boolean check_gtk(); - private static native boolean load_gtk(); + private static native boolean check_gtk(int version); + private static native boolean load_gtk(int version, boolean verbose); private static native boolean unload_gtk(); private native boolean load_gtk_icon(String filename); private native boolean load_stock_icon(int widget_type, String stock_id, int iconSize, int textDirection, String detail); private native void nativeSync(); + private static native int get_gtk_version(); @Override public void sync() { @@ -337,4 +375,26 @@ } return false; } + + public static GtkVersions getEnabledGtkVersion() { + String version = AccessController.doPrivileged( + new GetPropertyAction("jdk.gtk.version")); + if (version == null) { + return GtkVersions.ANY; + } else if (version.startsWith("2")) { + return GtkVersions.GTK2; + } else if("3".equals(version) ){ + return GtkVersions.GTK3; + } + return GtkVersions.ANY; + } + + public static GtkVersions getGtkVersion() { + return GtkVersions.getVersion(get_gtk_version()); + } + + public static boolean isGtkVerbose() { + return AccessController.doPrivileged((PrivilegedAction)() + -> Boolean.getBoolean("jdk.gtk.verbose")); + } } --- old/src/solaris/classes/sun/awt/X11/XDesktopPeer.java 2018-09-05 12:09:33.612043999 +0530 +++ new/src/solaris/classes/sun/awt/X11/XDesktopPeer.java 2018-09-05 12:09:33.279878000 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package sun.awt.X11; +import sun.awt.UNIXToolkit; import java.io.File; import java.io.IOException; @@ -57,7 +58,8 @@ XToolkit.awtLock(); try { if (!initExecuted) { - nativeLibraryLoaded = init(); + nativeLibraryLoaded = init(UNIXToolkit.getEnabledGtkVersion() + .getNumber(), UNIXToolkit.isGtkVerbose()); } } finally { initExecuted = true; @@ -123,5 +125,5 @@ } private native boolean gnome_url_show(byte[] url); - private static native boolean init(); + private static native boolean init(int gtkVersion, boolean verbose); } --- old/src/solaris/classes/sun/awt/X11/XToolkit.java 2018-09-05 12:09:34.576526000 +0530 +++ new/src/solaris/classes/sun/awt/X11/XToolkit.java 2018-09-05 12:09:34.232353999 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1079,7 +1079,8 @@ public FileDialogPeer createFileDialog(FileDialog target) { FileDialogPeer peer = null; // The current GtkFileChooser is available from GTK+ 2.4 - if (!getSunAwtDisableGtkFileDialogs() && checkGtkVersion(2, 4, 0)) { + if (!getSunAwtDisableGtkFileDialogs() && + (checkGtkVersion(2, 4, 0) || checkGtkVersion(3, 0, 0))) { peer = new GtkFileDialogPeer(target); } else { peer = new XFileDialogPeer(target); --- old/src/solaris/native/sun/awt/awt_InputMethod.c 2018-09-05 12:09:35.561017999 +0530 +++ new/src/solaris/native/sun/awt/awt_InputMethod.c 2018-09-05 12:09:35.212844000 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "awt.h" --- old/src/solaris/native/sun/awt/awt_UNIXToolkit.c 2018-09-05 12:09:36.789632000 +0530 +++ new/src/solaris/native/sun/awt/awt_UNIXToolkit.c 2018-09-05 12:09:36.369422000 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,7 @@ #ifndef HEADLESS #include "awt.h" -#include "gtk2_interface.h" +#include "gtk_interface.h" #endif /* !HEADLESS */ @@ -45,13 +45,12 @@ /* * Class: sun_awt_UNIXToolkit * Method: check_gtk - * Signature: ()Z + * Signature: (I)Z */ JNIEXPORT jboolean JNICALL -Java_sun_awt_UNIXToolkit_check_1gtk(JNIEnv *env, jclass klass) -{ +Java_sun_awt_UNIXToolkit_check_1gtk(JNIEnv *env, jclass klass, jint version) { #ifndef HEADLESS - return (jboolean)gtk2_check_version(); + return (jboolean)gtk_check_version(version); #else return JNI_FALSE; #endif /* !HEADLESS */ @@ -61,13 +60,13 @@ /* * Class: sun_awt_UNIXToolkit * Method: load_gtk - * Signature: ()Z + * Signature: (I)Z */ JNIEXPORT jboolean JNICALL -Java_sun_awt_UNIXToolkit_load_1gtk(JNIEnv *env, jclass klass) -{ +Java_sun_awt_UNIXToolkit_load_1gtk(JNIEnv *env, jclass klass, jint version, + jboolean verbose) { #ifndef HEADLESS - return (jboolean)gtk2_load(env); + return (jboolean)gtk_load(env, version, verbose); #else return JNI_FALSE; #endif /* !HEADLESS */ @@ -83,16 +82,14 @@ Java_sun_awt_UNIXToolkit_unload_1gtk(JNIEnv *env, jclass klass) { #ifndef HEADLESS - return (jboolean)gtk2_unload(); + return (jboolean)gtk->unload(); #else return JNI_FALSE; #endif /* !HEADLESS */ } -jboolean _icon_upcall(JNIEnv *env, jobject this, GdkPixbuf *pixbuf) +jboolean init_method(JNIEnv *env, jobject this) { - jboolean result = JNI_FALSE; - if (this_class == NULL) { this_class = (*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, this)); @@ -101,32 +98,7 @@ CHECK_NULL_RETURN(icon_upcall_method, JNI_FALSE); } - if (pixbuf != NULL) - { - guchar *pixbuf_data = (*fp_gdk_pixbuf_get_pixels)(pixbuf); - int row_stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf); - int width = (*fp_gdk_pixbuf_get_width)(pixbuf); - int height = (*fp_gdk_pixbuf_get_height)(pixbuf); - int bps = (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf); - int channels = (*fp_gdk_pixbuf_get_n_channels)(pixbuf); - gboolean alpha = (*fp_gdk_pixbuf_get_has_alpha)(pixbuf); - - /* Copy the data array into a Java structure so we can pass it back. */ - jbyteArray data = (*env)->NewByteArray(env, (row_stride * height)); - JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); - - (*env)->SetByteArrayRegion(env, data, 0, (row_stride * height), - (jbyte *)pixbuf_data); - - /* Release the pixbuf. */ - (*fp_g_object_unref)(pixbuf); - - /* Call the callback method to create the image on the Java side. */ - (*env)->CallVoidMethod(env, this, icon_upcall_method, data, - width, height, row_stride, bps, channels, alpha); - result = JNI_TRUE; - } - return result; + return JNI_TRUE; } /* @@ -144,7 +116,6 @@ int len; char *filename_str = NULL; GError **error = NULL; - GdkPixbuf *pixbuf; if (filename == NULL) { @@ -158,13 +129,18 @@ JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); return JNI_FALSE; } + if (!init_method(env, this) ) { + free(filename_str); + return JNI_FALSE; + } (*env)->GetStringUTFRegion(env, filename, 0, len, filename_str); - pixbuf = (*fp_gdk_pixbuf_new_from_file)(filename_str, error); + jboolean result = gtk->get_file_icon_data(env, filename_str, error, + icon_upcall_method, this); /* Release the strings we've allocated. */ free(filename_str); - return _icon_upcall(env, this, pixbuf); + return result; #else /* HEADLESS */ return JNI_FALSE; #endif /* !HEADLESS */ @@ -186,7 +162,6 @@ int len; char *stock_id_str = NULL; char *detail_str = NULL; - GdkPixbuf *pixbuf; if (stock_id == NULL) { @@ -215,8 +190,12 @@ (*env)->GetStringUTFRegion(env, detail, 0, len, detail_str); } - pixbuf = gtk2_get_stock_icon(widget_type, stock_id_str, icon_size, - text_direction, detail_str); + if (!init_method(env, this) ) { + return JNI_FALSE; + } + jboolean result = gtk->get_icon_data(env, widget_type, stock_id_str, + icon_size, text_direction, detail_str, + icon_upcall_method, this); /* Release the strings we've allocated. */ free(stock_id_str); @@ -225,7 +204,7 @@ free(detail_str); } - return _icon_upcall(env, this, pixbuf); + return result; #else /* HEADLESS */ return JNI_FALSE; #endif /* !HEADLESS */ @@ -279,11 +258,25 @@ { char *ret; - ret = fp_gtk_check_version(major, minor, micro); + ret = gtk->gtk_check_version(major, minor, micro); if (ret == NULL) { return TRUE; } - free(ret); return FALSE; } + +/* + * Class: sun_awt_UNIXToolkit + * Method: get_gtk_version + * Signature: ()I + */ +JNIEXPORT jint JNICALL +Java_sun_awt_UNIXToolkit_get_1gtk_1version(JNIEnv *env, jclass klass) +{ +#ifndef HEADLESS + return gtk ? gtk->version : GTK_ANY; +#else + return GTK_ANY; +#endif /* !HEADLESS */ +} --- old/src/solaris/native/sun/awt/gtk2_interface.c 2018-09-05 12:09:37.686079999 +0530 +++ new/src/solaris/native/sun/awt/gtk2_interface.c 2018-09-05 12:09:37.357916000 +0530 @@ -35,52 +35,15 @@ #include #include "awt.h" -#define GTK2_LIB_VERSIONED VERSIONED_JNI_LIB_NAME("gtk-x11-2.0", "0") -#define GTK2_LIB JNI_LIB_NAME("gtk-x11-2.0") -#define GTHREAD_LIB_VERSIONED VERSIONED_JNI_LIB_NAME("gthread-2.0", "0") -#define GTHREAD_LIB JNI_LIB_NAME("gthread-2.0") - -#define G_TYPE_INVALID G_TYPE_MAKE_FUNDAMENTAL (0) -#define G_TYPE_NONE G_TYPE_MAKE_FUNDAMENTAL (1) -#define G_TYPE_INTERFACE G_TYPE_MAKE_FUNDAMENTAL (2) -#define G_TYPE_CHAR G_TYPE_MAKE_FUNDAMENTAL (3) -#define G_TYPE_UCHAR G_TYPE_MAKE_FUNDAMENTAL (4) -#define G_TYPE_BOOLEAN G_TYPE_MAKE_FUNDAMENTAL (5) -#define G_TYPE_INT G_TYPE_MAKE_FUNDAMENTAL (6) -#define G_TYPE_UINT G_TYPE_MAKE_FUNDAMENTAL (7) -#define G_TYPE_LONG G_TYPE_MAKE_FUNDAMENTAL (8) -#define G_TYPE_ULONG G_TYPE_MAKE_FUNDAMENTAL (9) -#define G_TYPE_INT64 G_TYPE_MAKE_FUNDAMENTAL (10) -#define G_TYPE_UINT64 G_TYPE_MAKE_FUNDAMENTAL (11) -#define G_TYPE_ENUM G_TYPE_MAKE_FUNDAMENTAL (12) -#define G_TYPE_FLAGS G_TYPE_MAKE_FUNDAMENTAL (13) -#define G_TYPE_FLOAT G_TYPE_MAKE_FUNDAMENTAL (14) -#define G_TYPE_DOUBLE G_TYPE_MAKE_FUNDAMENTAL (15) -#define G_TYPE_STRING G_TYPE_MAKE_FUNDAMENTAL (16) -#define G_TYPE_POINTER G_TYPE_MAKE_FUNDAMENTAL (17) -#define G_TYPE_BOXED G_TYPE_MAKE_FUNDAMENTAL (18) -#define G_TYPE_PARAM G_TYPE_MAKE_FUNDAMENTAL (19) -#define G_TYPE_OBJECT G_TYPE_MAKE_FUNDAMENTAL (20) - #define GTK_TYPE_BORDER ((*fp_gtk_border_get_type)()) #define G_TYPE_FUNDAMENTAL_SHIFT (2) #define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT)) -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define CONV_BUFFER_SIZE 128 #define NO_SYMBOL_EXCEPTION 1 -/* SynthConstants */ -const gint ENABLED = 1 << 0; -const gint MOUSE_OVER = 1 << 1; -const gint PRESSED = 1 << 2; -const gint DISABLED = 1 << 3; -const gint FOCUSED = 1 << 8; -const gint SELECTED = 1 << 9; -const gint DEFAULT = 1 << 10; - static void *gtk2_libhandle = NULL; static void *gthread_libhandle = NULL; @@ -105,55 +68,6 @@ static gboolean new_combo = TRUE; const char ENV_PREFIX[] = "GTK_MODULES="; -/*******************/ -enum GtkWidgetType -{ - _GTK_ARROW_TYPE, - _GTK_BUTTON_TYPE, - _GTK_CHECK_BUTTON_TYPE, - _GTK_CHECK_MENU_ITEM_TYPE, - _GTK_COLOR_SELECTION_DIALOG_TYPE, - _GTK_COMBO_BOX_TYPE, - _GTK_COMBO_BOX_ARROW_BUTTON_TYPE, - _GTK_COMBO_BOX_TEXT_FIELD_TYPE, - _GTK_CONTAINER_TYPE, - _GTK_ENTRY_TYPE, - _GTK_FRAME_TYPE, - _GTK_HANDLE_BOX_TYPE, - _GTK_HPANED_TYPE, - _GTK_HPROGRESS_BAR_TYPE, - _GTK_HSCALE_TYPE, - _GTK_HSCROLLBAR_TYPE, - _GTK_HSEPARATOR_TYPE, - _GTK_IMAGE_TYPE, - _GTK_MENU_TYPE, - _GTK_MENU_BAR_TYPE, - _GTK_MENU_ITEM_TYPE, - _GTK_NOTEBOOK_TYPE, - _GTK_LABEL_TYPE, - _GTK_RADIO_BUTTON_TYPE, - _GTK_RADIO_MENU_ITEM_TYPE, - _GTK_SCROLLED_WINDOW_TYPE, - _GTK_SEPARATOR_MENU_ITEM_TYPE, - _GTK_SEPARATOR_TOOL_ITEM_TYPE, - _GTK_SPIN_BUTTON_TYPE, - _GTK_TEXT_VIEW_TYPE, - _GTK_TOGGLE_BUTTON_TYPE, - _GTK_TOOLBAR_TYPE, - _GTK_TOOLTIP_TYPE, - _GTK_TREE_VIEW_TYPE, - _GTK_VIEWPORT_TYPE, - _GTK_VPANED_TYPE, - _GTK_VPROGRESS_BAR_TYPE, - _GTK_VSCALE_TYPE, - _GTK_VSCROLLBAR_TYPE, - _GTK_VSEPARATOR_TYPE, - _GTK_WINDOW_TYPE, - _GTK_DIALOG_TYPE, - _GTK_WIDGET_TYPE_SIZE -}; - - static GtkWidget *gtk2_widgets[_GTK_WIDGET_TYPE_SIZE]; /************************* @@ -362,20 +276,6 @@ static GtkAdjustment* (*fp_gtk_range_get_adjustment)(GtkRange* range); /* Method bodies */ -const char *getStrFor(JNIEnv *env, jstring val) -{ - int length = (*env)->GetStringLength(env, val); - if (length > CONV_BUFFER_SIZE-1) - { - length = CONV_BUFFER_SIZE-1; -#ifdef INTERNAL_BUILD - fprintf(stderr, "Note: Detail is too long: %d chars\n", length); -#endif /* INTERNAL_BUILD */ - } - - (*env)->GetStringUTFRegion(env, val, 0, length, convertionBuffer); - return convertionBuffer; -} static void throw_exception(JNIEnv *env, const char* name, const char* message) { @@ -411,33 +311,43 @@ return result; } -gboolean gtk2_check_version() +gboolean gtk2_check(const char* lib_name, gboolean load) { if (gtk2_libhandle != NULL) { /* We've already successfully opened the GTK libs, so return true. */ return TRUE; } else { void *lib = NULL; - gboolean result = FALSE; + #ifdef RTLD_NOLOAD + /* Just check if gtk libs are already in the process space */ + lib = dlopen(lib_name, RTLD_LAZY | RTLD_NOLOAD); + if (!load || lib != NULL) { + return lib != NULL; + } +#else +#ifdef _AIX + /* On AIX we could implement this with the help of loadquery(L_GETINFO, ..) */ + /* (see reload_table() in hotspot/src/os/aix/vm/loadlib_aix.cpp) but it is */ + /* probably not worth it because most AIX servers don't have GTK libs anyway */ +#endif +#endif + + lib = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL); - lib = dlopen(GTK2_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL); if (lib == NULL) { - lib = dlopen(GTK2_LIB, RTLD_LAZY | RTLD_LOCAL); - if (lib == NULL) { - return FALSE; - } + return FALSE; } fp_gtk_check_version = dlsym(lib, "gtk_check_version"); /* Check for GTK 2.2+ */ if (!fp_gtk_check_version(2, 2, 0)) { - result = TRUE; + return TRUE; } // 8048289: workaround for https://bugzilla.gnome.org/show_bug.cgi?id=733065 // dlclose(lib); - return result; + return FALSE; } } @@ -453,7 +363,7 @@ } while(0); -void update_supported_actions(JNIEnv *env) { +static void update_supported_actions(JNIEnv *env) { GVfs * (*fp_g_vfs_get_default) (void); const gchar * const * (*fp_g_vfs_get_supported_uri_schemes) (GVfs * vfs); const gchar * const * schemes = NULL; @@ -516,7 +426,7 @@ /** * Functions for awt_Desktop.c */ -gboolean gtk2_show_uri_load(JNIEnv *env) { +static gboolean gtk2_show_uri_load(JNIEnv *env) { gboolean success = FALSE; dlerror(); const char *gtk_version = fp_gtk_check_version(2, 14, 0); @@ -540,6 +450,7 @@ fprintf(stderr, "dlsym(gtk_show_uri) returned NULL\n"); #endif /* INTERNAL_BUILD */ } else { + gtk->gtk_show_uri = fp_gtk_show_uri; update_supported_actions(env); success = TRUE; } @@ -550,7 +461,7 @@ /** * Functions for sun_awt_X11_GtkFileDialogPeer.c */ -void gtk2_file_chooser_load() +static void gtk2_file_chooser_load() { fp_gtk_file_chooser_get_filename = dl_symbol( "gtk_file_chooser_get_filename"); @@ -578,7 +489,7 @@ fp_gtk_g_slist_length = dl_symbol("g_slist_length"); } -gboolean gtk2_load(JNIEnv *env) +GtkApi* gtk2_load(JNIEnv *env, const char* lib_name) { gboolean result; int i; @@ -586,11 +497,9 @@ int (*io_handler)(); char *gtk_modules_env; - gtk2_libhandle = dlopen(GTK2_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL); + gtk2_libhandle = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL); if (gtk2_libhandle == NULL) { - gtk2_libhandle = dlopen(GTK2_LIB, RTLD_LAZY | RTLD_LOCAL); - if (gtk2_libhandle == NULL) - return FALSE; + return FALSE; } gthread_libhandle = dlopen(GTHREAD_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL); @@ -891,33 +800,19 @@ io_handler = XSetIOErrorHandler(NULL); if (fp_gtk_check_version(2, 2, 0) == NULL) { - jclass clazz = (*env)->FindClass(env, "sun/misc/GThreadHelper"); - jmethodID mid_getAndSetInitializationNeededFlag = - (*env)->GetStaticMethodID(env, clazz, "getAndSetInitializationNeededFlag", "()Z"); - jmethodID mid_lock = (*env)->GetStaticMethodID(env, clazz, "lock", "()V"); - jmethodID mid_unlock = (*env)->GetStaticMethodID(env, clazz, "unlock", "()V"); - - // Init the thread system to use GLib in a thread-safe mode - (*env)->CallStaticVoidMethod(env, clazz, mid_lock); - // Calling g_thread_init() multiple times leads to crash on GLib < 2.24 // We can use g_thread_get_initialized () but it is available only for - // GLib >= 2.20. We rely on GThreadHelper for GLib < 2.20. + // GLib >= 2.20. gboolean is_g_thread_get_initialized = FALSE; if (GLIB_CHECK_VERSION(2, 20, 0)) { is_g_thread_get_initialized = fp_g_thread_get_initialized(); } - - if (!(*env)->CallStaticBooleanMethod(env, clazz, mid_getAndSetInitializationNeededFlag)) { - if (!is_g_thread_get_initialized) { - fp_g_thread_init(NULL); - } - - //According the GTK documentation, gdk_threads_init() should be - //called before gtk_init() or gtk_init_check() - fp_gdk_threads_init(); + if (!is_g_thread_get_initialized) { + fp_g_thread_init(NULL); } - (*env)->CallStaticVoidMethod(env, clazz, mid_unlock); + //According the GTK documentation, gdk_threads_init() should be + //called before gtk_init() or gtk_init_check() + fp_gdk_threads_init(); } result = (*fp_gtk_init_check)(NULL, NULL); @@ -931,7 +826,13 @@ gtk2_widgets[i] = NULL; } - return result; + + if (result) { + GtkApi* gtk = (GtkApi*)malloc(sizeof(GtkApi)); + gtk2_init(gtk); + return gtk; + } + return NULL; } int gtk2_unload() @@ -975,7 +876,7 @@ /* Dispatch all pending events from the GTK event loop. * This is needed to catch theme change and update widgets' style. */ -void flush_gtk_event_loop() +static void flush_gtk_event_loop() { while( (*fp_g_main_context_iteration)(NULL, FALSE)); } @@ -1024,7 +925,7 @@ * comparing results. This can be optimized by using subclassed pixmap and * doing the second drawing only if necessary. */ -void gtk2_init_painting(JNIEnv *env, gint width, gint height) +static void gtk2_init_painting(JNIEnv *env, gint width, gint height) { GdkGC *gc; GdkPixbuf *white, *black; @@ -1084,7 +985,7 @@ * one of java_awt_Transparency_OPAQUE, java_awt_Transparency_BITMASK, and * java_awt_Transparency_TRANSLUCENT. */ -gint gtk2_copy_image(gint *dst, gint width, gint height) +static gint gtk2_copy_image(gint *dst, gint width, gint height) { gint i, j, r, g, b; guchar *white, *black; @@ -1746,7 +1647,7 @@ x, y, w, h); } -void gtk2_paint_box(WidgetType widget_type, GtkStateType state_type, +static void gtk2_paint_box(WidgetType widget_type, GtkStateType state_type, GtkShadowType shadow_type, const gchar *detail, gint x, gint y, gint width, gint height, gint synth_state, GtkTextDirection dir) @@ -1916,7 +1817,7 @@ x, y, width, height, gap_side, gap_x, gap_width); } -void gtk2_paint_check(WidgetType widget_type, gint synth_state, +static void gtk2_paint_check(WidgetType widget_type, gint synth_state, const gchar *detail, gint x, gint y, gint width, gint height) { GtkStateType state_type = get_gtk_state_type(widget_type, synth_state); @@ -1933,7 +1834,7 @@ x, y, width, height); } -void gtk2_paint_diamond(WidgetType widget_type, GtkStateType state_type, +static void gtk2_paint_diamond(WidgetType widget_type, GtkStateType state_type, GtkShadowType shadow_type, const gchar *detail, gint x, gint y, gint width, gint height) { @@ -1946,7 +1847,7 @@ x, y, width, height); } -void gtk2_paint_expander(WidgetType widget_type, GtkStateType state_type, +static void gtk2_paint_expander(WidgetType widget_type, GtkStateType state_type, const gchar *detail, gint x, gint y, gint width, gint height, GtkExpanderStyle expander_style) { @@ -1959,7 +1860,7 @@ x + width / 2, y + height / 2, expander_style); } -void gtk2_paint_extension(WidgetType widget_type, GtkStateType state_type, +static void gtk2_paint_extension(WidgetType widget_type, GtkStateType state_type, GtkShadowType shadow_type, const gchar *detail, gint x, gint y, gint width, gint height, GtkPositionType gap_side) { @@ -1972,7 +1873,7 @@ x, y, width, height, gap_side); } -void gtk2_paint_flat_box(WidgetType widget_type, GtkStateType state_type, +static void gtk2_paint_flat_box(WidgetType widget_type, GtkStateType state_type, GtkShadowType shadow_type, const gchar *detail, gint x, gint y, gint width, gint height, gboolean has_focus) { @@ -1991,7 +1892,7 @@ x, y, width, height); } -void gtk2_paint_focus(WidgetType widget_type, GtkStateType state_type, +static void gtk2_paint_focus(WidgetType widget_type, GtkStateType state_type, const char *detail, gint x, gint y, gint width, gint height) { gtk2_widget = gtk2_get_widget(widget_type); @@ -2001,7 +1902,7 @@ NULL, gtk2_widget, detail, x, y, width, height); } -void gtk2_paint_handle(WidgetType widget_type, GtkStateType state_type, +static void gtk2_paint_handle(WidgetType widget_type, GtkStateType state_type, GtkShadowType shadow_type, const gchar *detail, gint x, gint y, gint width, gint height, GtkOrientation orientation) { @@ -2014,7 +1915,7 @@ x, y, width, height, orientation); } -void gtk2_paint_hline(WidgetType widget_type, GtkStateType state_type, +static void gtk2_paint_hline(WidgetType widget_type, GtkStateType state_type, const gchar *detail, gint x, gint y, gint width, gint height) { gtk2_widget = gtk2_get_widget(widget_type); @@ -2024,7 +1925,7 @@ NULL, gtk2_widget, detail, x, x + width, y); } -void gtk2_paint_option(WidgetType widget_type, gint synth_state, +static void gtk2_paint_option(WidgetType widget_type, gint synth_state, const gchar *detail, gint x, gint y, gint width, gint height) { GtkStateType state_type = get_gtk_state_type(widget_type, synth_state); @@ -2041,7 +1942,7 @@ x, y, width, height); } -void gtk2_paint_shadow(WidgetType widget_type, GtkStateType state_type, +static void gtk2_paint_shadow(WidgetType widget_type, GtkStateType state_type, GtkShadowType shadow_type, const gchar *detail, gint x, gint y, gint width, gint height, gint synth_state, GtkTextDirection dir) @@ -2091,9 +1992,10 @@ gtk2_set_direction(gtk2_widget, GTK_TEXT_DIR_LTR); } -void gtk2_paint_slider(WidgetType widget_type, GtkStateType state_type, +static void gtk2_paint_slider(WidgetType widget_type, GtkStateType state_type, GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, GtkOrientation orientation) + gint x, gint y, gint width, gint height, GtkOrientation orientation, + gboolean has_focus) { gtk2_widget = gtk2_get_widget(widget_type); (*fp_gtk_paint_slider)(gtk2_widget->style, gtk2_white_pixmap, state_type, @@ -2104,7 +2006,7 @@ x, y, width, height, orientation); } -void gtk2_paint_vline(WidgetType widget_type, GtkStateType state_type, +static void gtk2_paint_vline(WidgetType widget_type, GtkStateType state_type, const gchar *detail, gint x, gint y, gint width, gint height) { gtk2_widget = gtk2_get_widget(widget_type); @@ -2114,7 +2016,7 @@ NULL, gtk2_widget, detail, y, y + height, x); } -void gtk_paint_background(WidgetType widget_type, GtkStateType state_type, +static void gtk_paint_background(WidgetType widget_type, GtkStateType state_type, gint x, gint y, gint width, gint height) { gtk2_widget = gtk2_get_widget(widget_type); @@ -2124,7 +2026,7 @@ gtk2_black_pixmap, TRUE, state_type, NULL, x, y, width, height); } -GdkPixbuf *gtk2_get_stock_icon(gint widget_type, const gchar *stock_id, +static GdkPixbuf *gtk2_get_stock_icon(gint widget_type, const gchar *stock_id, GtkIconSize size, GtkTextDirection direction, const char *detail) { init_containers(); @@ -2134,8 +2036,52 @@ return (*fp_gtk_widget_render_icon)(gtk2_widget, stock_id, size, detail); } +static jboolean gtk2_get_pixbuf_data(JNIEnv *env, GdkPixbuf* pixbuf, + jmethodID icon_upcall_method, jobject this) { + if (!pixbuf) { + return JNI_FALSE; + } + guchar *pixbuf_data = (*fp_gdk_pixbuf_get_pixels)(pixbuf); + if (pixbuf_data) { + int row_stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf); + int width = (*fp_gdk_pixbuf_get_width)(pixbuf); + int height = (*fp_gdk_pixbuf_get_height)(pixbuf); + int bps = (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf); + int channels = (*fp_gdk_pixbuf_get_n_channels)(pixbuf); + gboolean alpha = (*fp_gdk_pixbuf_get_has_alpha)(pixbuf); + + jbyteArray data = (*env)->NewByteArray(env, (row_stride * height)); + JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); + + (*env)->SetByteArrayRegion(env, data, 0, (row_stride * height), + (jbyte *)pixbuf_data); + (*fp_g_object_unref)(pixbuf); + + /* Call the callback method to create the image on the Java side. */ + (*env)->CallVoidMethod(env, this, icon_upcall_method, data, + width, height, row_stride, bps, channels, alpha); + return JNI_TRUE; + } + return JNI_FALSE; +} + +static jboolean gtk2_get_file_icon_data(JNIEnv *env, const char *filename, + GError **error, jmethodID icon_upcall_method, jobject this) { + GdkPixbuf* pixbuf = fp_gdk_pixbuf_new_from_file(filename, error); + return gtk2_get_pixbuf_data(env, pixbuf, icon_upcall_method, this); +} + +static jboolean gtk2_get_icon_data(JNIEnv *env, gint widget_type, + const gchar *stock_id, GtkIconSize size, + GtkTextDirection direction, const char *detail, + jmethodID icon_upcall_method, jobject this) { + GdkPixbuf* pixbuf = gtk2_get_stock_icon(widget_type, stock_id, size, + direction, detail); + return gtk2_get_pixbuf_data(env, pixbuf, icon_upcall_method, this); +} + /*************************************************/ -gint gtk2_get_xthickness(JNIEnv *env, WidgetType widget_type) +static gint gtk2_get_xthickness(JNIEnv *env, WidgetType widget_type) { init_containers(); @@ -2144,7 +2090,7 @@ return style->xthickness; } -gint gtk2_get_ythickness(JNIEnv *env, WidgetType widget_type) +static gint gtk2_get_ythickness(JNIEnv *env, WidgetType widget_type) { init_containers(); @@ -2154,12 +2100,12 @@ } /*************************************************/ -guint8 recode_color(guint16 channel) +static guint8 recode_color(guint16 channel) { return (guint8)(channel>>8); } -gint gtk2_get_color_for_state(JNIEnv *env, WidgetType widget_type, +static gint gtk2_get_color_for_state(JNIEnv *env, WidgetType widget_type, GtkStateType state_type, ColorType color_type) { gint result = 0; @@ -2211,19 +2157,19 @@ } /*************************************************/ -jobject create_Boolean(JNIEnv *env, jboolean boolean_value); -jobject create_Integer(JNIEnv *env, jint int_value); -jobject create_Long(JNIEnv *env, jlong long_value); -jobject create_Float(JNIEnv *env, jfloat float_value); -jobject create_Double(JNIEnv *env, jdouble double_value); -jobject create_Character(JNIEnv *env, jchar char_value); -jobject create_Insets(JNIEnv *env, GtkBorder *border); +static jobject create_Boolean(JNIEnv *env, jboolean boolean_value); +static jobject create_Integer(JNIEnv *env, jint int_value); +static jobject create_Long(JNIEnv *env, jlong long_value); +static jobject create_Float(JNIEnv *env, jfloat float_value); +static jobject create_Double(JNIEnv *env, jdouble double_value); +static jobject create_Character(JNIEnv *env, jchar char_value); +static jobject create_Insets(JNIEnv *env, GtkBorder *border); -jobject gtk2_get_class_value(JNIEnv *env, WidgetType widget_type, jstring jkey) +static jobject gtk2_get_class_value(JNIEnv *env, WidgetType widget_type, + const char* key) { init_containers(); - const char* key = getStrFor(env, jkey); gtk2_widget = gtk2_get_widget(widget_type); GValue value; @@ -2344,7 +2290,7 @@ return NULL; } -void gtk2_set_range_value(WidgetType widget_type, jdouble value, +static void gtk2_set_range_value(WidgetType widget_type, jdouble value, jdouble min, jdouble max, jdouble visible) { GtkAdjustment *adj; @@ -2359,7 +2305,7 @@ } /*************************************************/ -jobject create_Object(JNIEnv *env, jmethodID *cid, +static jobject create_Object(JNIEnv *env, jmethodID *cid, const char* class_name, const char* signature, jvalue* value) @@ -2462,7 +2408,7 @@ } /*********************************************/ -jstring gtk2_get_pango_font_name(JNIEnv *env, WidgetType widget_type) +static jstring gtk2_get_pango_font_name(JNIEnv *env, WidgetType widget_type) { init_containers(); @@ -2481,7 +2427,7 @@ } /***********************************************/ -jobject get_string_property(JNIEnv *env, GtkSettings* settings, const gchar* key) +static jobject get_string_property(JNIEnv *env, GtkSettings* settings, const gchar* key) { jobject result = NULL; gchar* strval = NULL; @@ -2493,21 +2439,21 @@ return result; } -jobject get_integer_property(JNIEnv *env, GtkSettings* settings, const gchar* key) +static jobject get_integer_property(JNIEnv *env, GtkSettings* settings, const gchar* key) { - gint intval = NULL; + gint intval = 0; (*fp_g_object_get)(settings, key, &intval, NULL); return create_Integer(env, intval); } -jobject get_boolean_property(JNIEnv *env, GtkSettings* settings, const gchar* key) +static jobject get_boolean_property(JNIEnv *env, GtkSettings* settings, const gchar* key) { - gint intval = NULL; + gint intval = 0; (*fp_g_object_get)(settings, key, &intval, NULL); return create_Boolean(env, intval); } -jobject gtk2_get_setting(JNIEnv *env, Setting property) +static jobject gtk2_get_setting(JNIEnv *env, Setting property) { GtkSettings* settings = (*fp_gtk_settings_get_default)(); @@ -2525,3 +2471,87 @@ return NULL; } + +static GdkWindow* gtk2_get_window(void *widget) { + return ((GtkWidget*)widget)->window; +} + +void gtk2_init(GtkApi* gtk) { + gtk->version = GTK_2; + + gtk->show_uri_load = >k2_show_uri_load; + gtk->unload = >k2_unload; + gtk->flush_event_loop = &flush_gtk_event_loop; + gtk->gtk_check_version = fp_gtk_check_version; + gtk->get_setting = >k2_get_setting; + + gtk->paint_arrow = >k2_paint_arrow; + gtk->paint_box = >k2_paint_box; + gtk->paint_box_gap = >k2_paint_box_gap; + gtk->paint_expander = >k2_paint_expander; + gtk->paint_extension = >k2_paint_extension; + gtk->paint_flat_box = >k2_paint_flat_box; + gtk->paint_focus = >k2_paint_focus; + gtk->paint_handle = >k2_paint_handle; + gtk->paint_hline = >k2_paint_hline; + gtk->paint_vline = >k2_paint_vline; + gtk->paint_option = >k2_paint_option; + gtk->paint_shadow = >k2_paint_shadow; + gtk->paint_slider = >k2_paint_slider; + gtk->paint_background = >k_paint_background; + gtk->paint_check = >k2_paint_check; + gtk->set_range_value = >k2_set_range_value; + + gtk->init_painting = >k2_init_painting; + gtk->copy_image = >k2_copy_image; + + gtk->get_xthickness = >k2_get_xthickness; + gtk->get_ythickness = >k2_get_ythickness; + gtk->get_color_for_state = >k2_get_color_for_state; + gtk->get_class_value = >k2_get_class_value; + + gtk->get_pango_font_name = >k2_get_pango_font_name; + gtk->get_icon_data = >k2_get_icon_data; + gtk->get_file_icon_data = >k2_get_file_icon_data; + gtk->gdk_threads_enter = fp_gdk_threads_enter; + gtk->gdk_threads_leave = fp_gdk_threads_leave; + gtk->gtk_show_uri = fp_gtk_show_uri; + gtk->g_free = fp_g_free; + + gtk->gtk_file_chooser_get_filename = fp_gtk_file_chooser_get_filename; + gtk->gtk_widget_hide = fp_gtk_widget_hide; + gtk->gtk_main_quit = fp_gtk_main_quit; + gtk->gtk_file_chooser_dialog_new = fp_gtk_file_chooser_dialog_new; + gtk->gtk_file_chooser_set_current_folder = + fp_gtk_file_chooser_set_current_folder; + gtk->gtk_file_chooser_set_filename = fp_gtk_file_chooser_set_filename; + gtk->gtk_file_chooser_set_current_name = + fp_gtk_file_chooser_set_current_name; + gtk->gtk_file_filter_add_custom = fp_gtk_file_filter_add_custom; + gtk->gtk_file_chooser_set_filter = fp_gtk_file_chooser_set_filter; + gtk->gtk_file_chooser_get_type = fp_gtk_file_chooser_get_type; + gtk->gtk_file_filter_new = fp_gtk_file_filter_new; + gtk->gtk_file_chooser_set_do_overwrite_confirmation = + fp_gtk_file_chooser_set_do_overwrite_confirmation; + gtk->gtk_file_chooser_set_select_multiple = + fp_gtk_file_chooser_set_select_multiple; + gtk->gtk_file_chooser_get_current_folder = + fp_gtk_file_chooser_get_current_folder; + gtk->gtk_file_chooser_get_filenames = fp_gtk_file_chooser_get_filenames; + gtk->gtk_g_slist_length = fp_gtk_g_slist_length; + gtk->g_signal_connect_data = fp_g_signal_connect_data; + gtk->gtk_widget_show = fp_gtk_widget_show; + gtk->gtk_main = fp_gtk_main; + gtk->gtk_main_level = fp_gtk_main_level; + gtk->g_path_get_dirname = fp_g_path_get_dirname; + gtk->gtk_widget_destroy = fp_gtk_widget_destroy; + gtk->gtk_window_present = fp_gtk_window_present; + gtk->gtk_window_move = fp_gtk_window_move; + gtk->gtk_window_resize = fp_gtk_window_resize; + gtk->get_window = >k2_get_window; + + gtk->g_object_unref = fp_g_object_unref; + gtk->g_list_append = fp_g_list_append; + gtk->g_list_free = fp_g_list_free; + gtk->g_list_free_full = fp_g_list_free_full; +} --- old/src/solaris/native/sun/awt/gtk2_interface.h 2018-09-05 12:09:38.866670000 +0530 +++ new/src/solaris/native/sun/awt/gtk2_interface.h 2018-09-05 12:09:38.446460000 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,232 +27,11 @@ #include #include - -#define _G_TYPE_CIC(ip, gt, ct) ((ct*) ip) -#define G_TYPE_CHECK_INSTANCE_CAST(instance, g_type, c_type) (_G_TYPE_CIC ((instance), (g_type), c_type)) -#define GTK_TYPE_FILE_CHOOSER (fp_gtk_file_chooser_get_type ()) -#define GTK_FILE_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_CHOOSER, GtkFileChooser)) -#define fp_g_signal_connect(instance, detailed_signal, c_handler, data) \ - fp_g_signal_connect_data ((instance), (detailed_signal), (c_handler), (data), NULL, (GConnectFlags) 0) -#define G_CALLBACK(f) ((GCallback) (f)) -#define G_TYPE_FUNDAMENTAL_SHIFT (2) -#define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT)) -#define G_TYPE_OBJECT G_TYPE_MAKE_FUNDAMENTAL (20) -#define G_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), G_TYPE_OBJECT, GObject)) -#define GTK_STOCK_CANCEL "gtk-cancel" -#define GTK_STOCK_SAVE "gtk-save" -#define GTK_STOCK_OPEN "gtk-open" -#define GDK_CURRENT_TIME 0L - -typedef enum _WidgetType -{ - BUTTON, /* GtkButton */ - CHECK_BOX, /* GtkCheckButton */ - CHECK_BOX_MENU_ITEM, /* GtkCheckMenuItem */ - COLOR_CHOOSER, /* GtkColorSelectionDialog */ - COMBO_BOX, /* GtkComboBox */ - COMBO_BOX_ARROW_BUTTON, /* GtkComboBoxEntry */ - COMBO_BOX_TEXT_FIELD, /* GtkComboBoxEntry */ - DESKTOP_ICON, /* GtkLabel */ - DESKTOP_PANE, /* GtkContainer */ - EDITOR_PANE, /* GtkTextView */ - FORMATTED_TEXT_FIELD, /* GtkEntry */ - HANDLE_BOX, /* GtkHandleBox */ - HPROGRESS_BAR, /* GtkProgressBar */ - HSCROLL_BAR, /* GtkHScrollbar */ - HSCROLL_BAR_BUTTON_LEFT, /* GtkHScrollbar */ - HSCROLL_BAR_BUTTON_RIGHT, /* GtkHScrollbar */ - HSCROLL_BAR_TRACK, /* GtkHScrollbar */ - HSCROLL_BAR_THUMB, /* GtkHScrollbar */ - HSEPARATOR, /* GtkHSeparator */ - HSLIDER, /* GtkHScale */ - HSLIDER_TRACK, /* GtkHScale */ - HSLIDER_THUMB, /* GtkHScale */ - HSPLIT_PANE_DIVIDER, /* GtkHPaned */ - INTERNAL_FRAME, /* GtkWindow */ - INTERNAL_FRAME_TITLE_PANE, /* GtkLabel */ - IMAGE, /* GtkImage */ - LABEL, /* GtkLabel */ - LIST, /* GtkTreeView */ - MENU, /* GtkMenu */ - MENU_BAR, /* GtkMenuBar */ - MENU_ITEM, /* GtkMenuItem */ - MENU_ITEM_ACCELERATOR, /* GtkLabel */ - OPTION_PANE, /* GtkMessageDialog */ - PANEL, /* GtkContainer */ - PASSWORD_FIELD, /* GtkEntry */ - POPUP_MENU, /* GtkMenu */ - POPUP_MENU_SEPARATOR, /* GtkSeparatorMenuItem */ - RADIO_BUTTON, /* GtkRadioButton */ - RADIO_BUTTON_MENU_ITEM, /* GtkRadioMenuItem */ - ROOT_PANE, /* GtkContainer */ - SCROLL_PANE, /* GtkScrolledWindow */ - SPINNER, /* GtkSpinButton */ - SPINNER_ARROW_BUTTON, /* GtkSpinButton */ - SPINNER_TEXT_FIELD, /* GtkSpinButton */ - SPLIT_PANE, /* GtkPaned */ - TABBED_PANE, /* GtkNotebook */ - TABBED_PANE_TAB_AREA, /* GtkNotebook */ - TABBED_PANE_CONTENT, /* GtkNotebook */ - TABBED_PANE_TAB, /* GtkNotebook */ - TABLE, /* GtkTreeView */ - TABLE_HEADER, /* GtkButton */ - TEXT_AREA, /* GtkTextView */ - TEXT_FIELD, /* GtkEntry */ - TEXT_PANE, /* GtkTextView */ - TITLED_BORDER, /* GtkFrame */ - TOGGLE_BUTTON, /* GtkToggleButton */ - TOOL_BAR, /* GtkToolbar */ - TOOL_BAR_DRAG_WINDOW, /* GtkToolbar */ - TOOL_BAR_SEPARATOR, /* GtkSeparatorToolItem */ - TOOL_TIP, /* GtkWindow */ - TREE, /* GtkTreeView */ - TREE_CELL, /* GtkTreeView */ - VIEWPORT, /* GtkViewport */ - VPROGRESS_BAR, /* GtkProgressBar */ - VSCROLL_BAR, /* GtkVScrollbar */ - VSCROLL_BAR_BUTTON_UP, /* GtkVScrollbar */ - VSCROLL_BAR_BUTTON_DOWN, /* GtkVScrollbar */ - VSCROLL_BAR_TRACK, /* GtkVScrollbar */ - VSCROLL_BAR_THUMB, /* GtkVScrollbar */ - VSEPARATOR, /* GtkVSeparator */ - VSLIDER, /* GtkVScale */ - VSLIDER_TRACK, /* GtkVScale */ - VSLIDER_THUMB, /* GtkVScale */ - VSPLIT_PANE_DIVIDER, /* GtkVPaned */ - WIDGET_TYPE_SIZE -} WidgetType; - -typedef enum _ColorType -{ - FOREGROUND, - BACKGROUND, - TEXT_FOREGROUND, - TEXT_BACKGROUND, - FOCUS, - LIGHT, - DARK, - MID, - BLACK, - WHITE -} ColorType; - -typedef enum _Setting -{ - GTK_FONT_NAME, - GTK_ICON_SIZES, - GTK_CURSOR_BLINK, - GTK_CURSOR_BLINK_TIME -} Setting; - -/* GTK types, here to eliminate need for GTK headers at compile time */ - -#ifndef FALSE -#define FALSE (0) -#define TRUE (!FALSE) -#endif +#include "gtk_interface.h" #define GTK_HAS_FOCUS (1 << 12) #define GTK_HAS_DEFAULT (1 << 14) - -/* basic types */ -typedef char gchar; -typedef short gshort; -typedef int gint; -typedef long glong; -typedef float gfloat; -typedef double gdouble; -typedef void* gpointer; -typedef gint gboolean; - -typedef signed char gint8; -typedef signed short gint16; -typedef signed int gint32; - -typedef unsigned char guchar; -typedef unsigned char guint8; -typedef unsigned short gushort; -typedef unsigned short guint16; -typedef unsigned int guint; -typedef unsigned int guint32; -typedef unsigned int gsize; -typedef unsigned long gulong; - -typedef signed long long gint64; -typedef unsigned long long guint64; - -/* enumerated constants */ -typedef enum -{ - GTK_ARROW_UP, - GTK_ARROW_DOWN, - GTK_ARROW_LEFT, - GTK_ARROW_RIGHT -} GtkArrowType; - -typedef enum { - GDK_COLORSPACE_RGB -} GdkColorspace; - -typedef enum -{ - GTK_EXPANDER_COLLAPSED, - GTK_EXPANDER_SEMI_COLLAPSED, - GTK_EXPANDER_SEMI_EXPANDED, - GTK_EXPANDER_EXPANDED -} GtkExpanderStyle; - -typedef enum -{ - GTK_ICON_SIZE_INVALID, - GTK_ICON_SIZE_MENU, - GTK_ICON_SIZE_SMALL_TOOLBAR, - GTK_ICON_SIZE_LARGE_TOOLBAR, - GTK_ICON_SIZE_BUTTON, - GTK_ICON_SIZE_DND, - GTK_ICON_SIZE_DIALOG -} GtkIconSize; - -typedef enum -{ - GTK_ORIENTATION_HORIZONTAL, - GTK_ORIENTATION_VERTICAL -} GtkOrientation; - -typedef enum -{ - GTK_POS_LEFT, - GTK_POS_RIGHT, - GTK_POS_TOP, - GTK_POS_BOTTOM -} GtkPositionType; - -typedef enum -{ - GTK_SHADOW_NONE, - GTK_SHADOW_IN, - GTK_SHADOW_OUT, - GTK_SHADOW_ETCHED_IN, - GTK_SHADOW_ETCHED_OUT -} GtkShadowType; - -typedef enum -{ - GTK_STATE_NORMAL, - GTK_STATE_ACTIVE, - GTK_STATE_PRELIGHT, - GTK_STATE_SELECTED, - GTK_STATE_INSENSITIVE -} GtkStateType; - -typedef enum -{ - GTK_TEXT_DIR_NONE, - GTK_TEXT_DIR_LTR, - GTK_TEXT_DIR_RTL -} GtkTextDirection; - typedef enum { GTK_WINDOW_TOPLEVEL, @@ -270,24 +49,14 @@ } GParamFlags; /* We define all structure pointers to be void* */ -typedef void GError; typedef void GMainContext; typedef void GVfs; -typedef struct _GSList GSList; -struct _GSList -{ - gpointer data; - GSList *next; -}; - typedef void GdkColormap; typedef void GdkDrawable; typedef void GdkGC; -typedef void GdkScreen; typedef void GdkPixbuf; typedef void GdkPixmap; -typedef void GdkWindow; typedef void GtkFixed; typedef void GtkMenuItem; @@ -347,7 +116,6 @@ * structures. This is a place where getting rid of gtk * headers may be dangerous. ******************************************************/ -typedef gulong GType; typedef struct { @@ -582,70 +350,6 @@ guint ellipsize : 3; }; -typedef enum { - GTK_RESPONSE_NONE = -1, - GTK_RESPONSE_REJECT = -2, - GTK_RESPONSE_ACCEPT = -3, - GTK_RESPONSE_DELETE_EVENT = -4, - GTK_RESPONSE_OK = -5, - GTK_RESPONSE_CANCEL = -6, - GTK_RESPONSE_CLOSE = -7, - GTK_RESPONSE_YES = -8, - GTK_RESPONSE_NO = -9, - GTK_RESPONSE_APPLY = -10, - GTK_RESPONSE_HELP = -11 -} GtkResponseType; - -typedef struct _GtkWindow GtkWindow; - -typedef struct _GtkFileChooser GtkFileChooser; - -typedef enum { - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_FILE_CHOOSER_ACTION_SAVE, - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, - GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER -} GtkFileChooserAction; - -typedef struct _GtkFileFilter GtkFileFilter; - -typedef enum { - GTK_FILE_FILTER_FILENAME = 1 << 0, - GTK_FILE_FILTER_URI = 1 << 1, - GTK_FILE_FILTER_DISPLAY_NAME = 1 << 2, - GTK_FILE_FILTER_MIME_TYPE = 1 << 3 -} GtkFileFilterFlags; - -typedef struct { - GtkFileFilterFlags contains; - const gchar *filename; - const gchar *uri; - const gchar *display_name; - const gchar *mime_type; -} GtkFileFilterInfo; - -typedef gboolean (*GtkFileFilterFunc)(const GtkFileFilterInfo *filter_info, - gpointer data); - -typedef void (*GDestroyNotify)(gpointer data); - -typedef void (*GCallback)(void); - -typedef struct _GClosure GClosure; - -typedef void (*GClosureNotify)(gpointer data, GClosure *closure); - -typedef enum { - G_CONNECT_AFTER = 1 << 0, G_CONNECT_SWAPPED = 1 << 1 -} GConnectFlags; - -typedef struct _GThreadFunctions GThreadFunctions; - -/* - * Converts java.lang.String object to UTF-8 character string. - */ -const char *getStrFor(JNIEnv *env, jstring value); - /** * Returns : * NULL if the GLib library is compatible with the given version, or a string @@ -653,8 +357,8 @@ * Please note that the glib_check_version() is available since 2.6, * so you should use GLIB_CHECK_VERSION macro instead. */ -gchar* (*fp_glib_check_version)(guint required_major, guint required_minor, - guint required_micro); +static gchar* (*fp_glib_check_version)(guint required_major, guint required_minor, + guint required_micro); /** * Returns : @@ -663,176 +367,74 @@ #define GLIB_CHECK_VERSION(major, minor, micro) \ (fp_glib_check_version && fp_glib_check_version(major, minor, micro) == NULL) -/* - * Check whether the gtk2 library is available and meets the minimum - * version requirement. If the library is already loaded this method has no - * effect and returns success. - * Returns FALSE on failure and TRUE on success. - */ -gboolean gtk2_check_version(); - /** * Returns : * NULL if the GTK+ library is compatible with the given version, or a string * describing the version mismatch. */ -gchar* (*fp_gtk_check_version)(guint required_major, guint required_minor, - guint required_micro); -/* - * Load the gtk2 library. If the library is already loaded this method has no - * effect and returns success. - * Returns FALSE on failure and TRUE on success. - */ -gboolean gtk2_load(JNIEnv *env); - -/* - * Loads fp_gtk_show_uri function pointer. This initialization is - * separated because the function is required only - * for java.awt.Desktop API. The function relies on initialization in - * gtk2_load, so it must be invoked only after a successful gtk2_load - * invocation - */ -gboolean gtk2_show_uri_load(JNIEnv *env); - -/* - * Unload the gtk2 library. If the library is already unloaded this method has - * no effect and returns success. - * Returns FALSE on failure and TRUE on success. - */ -gboolean gtk2_unload(); +static gchar* (*fp_gtk_check_version)(guint required_major, guint required_minor, + guint required_micro); -void gtk2_paint_arrow(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, - GtkArrowType arrow_type, gboolean fill); -void gtk2_paint_box(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, - gint synth_state, GtkTextDirection dir); -void gtk2_paint_box_gap(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, - GtkPositionType gap_side, gint gap_x, gint gap_width); -void gtk2_paint_check(WidgetType widget_type, gint synth_state, - const gchar *detail, gint x, gint y, gint width, gint height); -void gtk2_paint_diamond(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height); -void gtk2_paint_expander(WidgetType widget_type, GtkStateType state_type, - const gchar *detail, gint x, gint y, gint width, gint height, - GtkExpanderStyle expander_style); -void gtk2_paint_extension(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, GtkPositionType gap_side); -void gtk2_paint_flat_box(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, gboolean has_focus); -void gtk2_paint_focus(WidgetType widget_type, GtkStateType state_type, - const char *detail, gint x, gint y, gint width, gint height); -void gtk2_paint_handle(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, GtkOrientation orientation); -void gtk2_paint_hline(WidgetType widget_type, GtkStateType state_type, - const gchar *detail, gint x, gint y, gint width, gint height); -void gtk2_paint_option(WidgetType widget_type, gint synth_state, - const gchar *detail, gint x, gint y, gint width, gint height); -void gtk2_paint_shadow(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, - gint synth_state, GtkTextDirection dir); -void gtk2_paint_slider(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, GtkOrientation orientation); -void gtk2_paint_vline(WidgetType widget_type, GtkStateType state_type, - const gchar *detail, gint x, gint y, gint width, gint height); -void gtk_paint_background(WidgetType widget_type, GtkStateType state_type, - gint x, gint y, gint width, gint height); - -void gtk2_init_painting(JNIEnv *env, gint w, gint h); -gint gtk2_copy_image(gint *dest, gint width, gint height); - -gint gtk2_get_xthickness(JNIEnv *env, WidgetType widget_type); -gint gtk2_get_ythickness(JNIEnv *env, WidgetType widget_type); -gint gtk2_get_color_for_state(JNIEnv *env, WidgetType widget_type, - GtkStateType state_type, ColorType color_type); -jobject gtk2_get_class_value(JNIEnv *env, WidgetType widget_type, jstring key); - -GdkPixbuf *gtk2_get_stock_icon(gint widget_type, const gchar *stock_id, - GtkIconSize size, GtkTextDirection direction, const char *detail); -GdkPixbuf *gtk2_get_icon(const gchar *filename, gint size); -jstring gtk2_get_pango_font_name(JNIEnv *env, WidgetType widget_type); - -void flush_gtk_event_loop(); - -jobject gtk2_get_setting(JNIEnv *env, Setting property); - -void gtk2_set_range_value(WidgetType widget_type, jdouble value, - jdouble min, jdouble max, jdouble visible); - -void (*fp_g_free)(gpointer mem); -void (*fp_g_object_unref)(gpointer object); -int (*fp_gdk_pixbuf_get_bits_per_sample)(const GdkPixbuf *pixbuf); -guchar *(*fp_gdk_pixbuf_get_pixels)(const GdkPixbuf *pixbuf); -gboolean (*fp_gdk_pixbuf_get_has_alpha)(const GdkPixbuf *pixbuf); -int (*fp_gdk_pixbuf_get_height)(const GdkPixbuf *pixbuf); -int (*fp_gdk_pixbuf_get_n_channels)(const GdkPixbuf *pixbuf); -int (*fp_gdk_pixbuf_get_rowstride)(const GdkPixbuf *pixbuf); -int (*fp_gdk_pixbuf_get_width)(const GdkPixbuf *pixbuf); -GdkPixbuf *(*fp_gdk_pixbuf_new_from_file)(const char *filename, GError **error); -void (*fp_gtk_widget_destroy)(GtkWidget *widget); -void (*fp_gtk_window_present)(GtkWindow *window); -void (*fp_gtk_window_move)(GtkWindow *window, gint x, gint y); -void (*fp_gtk_window_resize)(GtkWindow *window, gint width, gint height); +static void gtk2_init(GtkApi* gtk); +static void (*fp_g_free)(gpointer mem); +static void (*fp_g_object_unref)(gpointer object); + +static int (*fp_gdk_pixbuf_get_bits_per_sample)(const GdkPixbuf *pixbuf); +static guchar *(*fp_gdk_pixbuf_get_pixels)(const GdkPixbuf *pixbuf); +static gboolean (*fp_gdk_pixbuf_get_has_alpha)(const GdkPixbuf *pixbuf); +static int (*fp_gdk_pixbuf_get_height)(const GdkPixbuf *pixbuf); +static int (*fp_gdk_pixbuf_get_n_channels)(const GdkPixbuf *pixbuf); +static int (*fp_gdk_pixbuf_get_rowstride)(const GdkPixbuf *pixbuf); +static int (*fp_gdk_pixbuf_get_width)(const GdkPixbuf *pixbuf); +static GdkPixbuf *(*fp_gdk_pixbuf_new_from_file)(const char *filename, GError **error); + +static void (*fp_gtk_widget_destroy)(void *widget); +static void (*fp_gtk_window_present)(GtkWindow *window); +static void (*fp_gtk_window_move)(GtkWindow *window, gint x, gint y); +static void (*fp_gtk_window_resize)(GtkWindow *window, gint width, gint height); /** * Function Pointers for GtkFileChooser */ -gchar* (*fp_gtk_file_chooser_get_filename)(GtkFileChooser *chooser); -void (*fp_gtk_widget_hide)(GtkWidget *widget); -void (*fp_gtk_main_quit)(void); -GtkWidget* (*fp_gtk_file_chooser_dialog_new)(const gchar *title, +static gchar* (*fp_gtk_file_chooser_get_filename)(GtkFileChooser *chooser); +static void (*fp_gtk_widget_hide)(void *widget); +static void (*fp_gtk_main_quit)(void); +static void* (*fp_gtk_file_chooser_dialog_new)(const gchar *title, GtkWindow *parent, GtkFileChooserAction action, const gchar *first_button_text, ...); -gboolean (*fp_gtk_file_chooser_set_current_folder)(GtkFileChooser *chooser, +static gboolean (*fp_gtk_file_chooser_set_current_folder)(GtkFileChooser *chooser, const gchar *filename); -gboolean (*fp_gtk_file_chooser_set_filename)(GtkFileChooser *chooser, +static gboolean (*fp_gtk_file_chooser_set_filename)(GtkFileChooser *chooser, const char *filename); -void (*fp_gtk_file_chooser_set_current_name)(GtkFileChooser *chooser, +static void (*fp_gtk_file_chooser_set_current_name)(GtkFileChooser *chooser, const gchar *name); -void (*fp_gtk_file_filter_add_custom)(GtkFileFilter *filter, +static void (*fp_gtk_file_filter_add_custom)(GtkFileFilter *filter, GtkFileFilterFlags needed, GtkFileFilterFunc func, gpointer data, GDestroyNotify notify); -void (*fp_gtk_file_chooser_set_filter)(GtkFileChooser *chooser, +static void (*fp_gtk_file_chooser_set_filter)(GtkFileChooser *chooser, GtkFileFilter *filter); -GType (*fp_gtk_file_chooser_get_type)(void); -GtkFileFilter* (*fp_gtk_file_filter_new)(void); -void (*fp_gtk_file_chooser_set_do_overwrite_confirmation)( +static GType (*fp_gtk_file_chooser_get_type)(void); +static GtkFileFilter* (*fp_gtk_file_filter_new)(void); +static void (*fp_gtk_file_chooser_set_do_overwrite_confirmation)( GtkFileChooser *chooser, gboolean do_overwrite_confirmation); -void (*fp_gtk_file_chooser_set_select_multiple)( +static void (*fp_gtk_file_chooser_set_select_multiple)( GtkFileChooser *chooser, gboolean select_multiple); -gchar* (*fp_gtk_file_chooser_get_current_folder)(GtkFileChooser *chooser); -GSList* (*fp_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser); -guint (*fp_gtk_g_slist_length)(GSList *list); -gulong (*fp_g_signal_connect_data)(gpointer instance, +static gchar* (*fp_gtk_file_chooser_get_current_folder)(GtkFileChooser *chooser); +static GSList* (*fp_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser); +static guint (*fp_gtk_g_slist_length)(GSList *list); +static gulong (*fp_g_signal_connect_data)(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags); -void (*fp_gtk_widget_show)(GtkWidget *widget); -void (*fp_gtk_main)(void); -guint (*fp_gtk_main_level)(void); -gchar* (*fp_g_path_get_dirname) (const gchar *file_name); - -/** - * This function is available for GLIB > 2.20, so it MUST be - * called within GLIB_CHECK_VERSION(2, 20, 0) check. - */ -gboolean (*fp_g_thread_get_initialized)(void); - -void (*fp_g_thread_init)(GThreadFunctions *vtable); -void (*fp_gdk_threads_init)(void); -void (*fp_gdk_threads_enter)(void); -void (*fp_gdk_threads_leave)(void); +static void (*fp_gtk_widget_show)(void *widget); +static void (*fp_gtk_main)(void); +static guint (*fp_gtk_main_level)(void); +static gchar* (*fp_g_path_get_dirname) (const gchar *file_name); + +static GList* (*fp_g_list_append) (GList *list, gpointer data); +static void (*fp_g_list_free) (GList *list); +static void (*fp_g_list_free_full) (GList *list, GDestroyNotify free_func); -gboolean (*fp_gtk_show_uri)(GdkScreen *screen, const gchar *uri, +static gboolean (*fp_gtk_show_uri)(GdkScreen *screen, const gchar *uri, guint32 timestamp, GError **error); #endif /* !_GTK2_INTERFACE_H */ --- old/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c 2018-09-05 12:09:39.787129999 +0530 +++ new/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c 2018-09-05 12:09:39.482978000 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,11 +27,12 @@ #include #include #include -#include "gtk2_interface.h" +#include "gtk_interface.h" #include "sun_awt_X11_GtkFileDialogPeer.h" #include "java_awt_FileDialog.h" #include "debug_assert.h" +typedef void GtkWidget; static JavaVM *jvm; /* To cache some method IDs */ @@ -84,20 +85,20 @@ { // Callbacks from GTK signals are made within the GTK lock // So, within a signal handler there is no need to call - // gdk_threads_enter() / fp_gdk_threads_leave() + // gdk_threads_enter() / gtk->gdk_threads_leave() if (!isSignalHandler) { - fp_gdk_threads_enter(); + gtk->gdk_threads_enter(); } - fp_gtk_widget_hide (dialog); - fp_gtk_widget_destroy (dialog); + gtk->gtk_widget_hide (dialog); + gtk->gtk_widget_destroy (dialog); - fp_gtk_main_quit (); + gtk->gtk_main_quit (); (*env)->SetLongField(env, jpeer, widgetFieldID, 0); if (!isSignalHandler) { - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } } @@ -127,16 +128,16 @@ { GtkWidget * dialog; - fp_gdk_threads_enter(); + gtk->gdk_threads_enter(); dialog = (GtkWidget*)jlong_to_ptr( (*env)->GetLongField(env, jpeer, widgetFieldID)); if (dialog != NULL) { - fp_gtk_window_present((GtkWindow*)dialog); + gtk->gtk_window_present((GtkWindow*)dialog); } - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -149,21 +150,21 @@ { GtkWindow* dialog; - fp_gdk_threads_enter(); + gtk->gdk_threads_enter(); dialog = (GtkWindow*)jlong_to_ptr( (*env)->GetLongField(env, jpeer, widgetFieldID)); if (dialog != NULL) { if (x >= 0 && y >= 0) { - fp_gtk_window_move(dialog, (gint)x, (gint)y); + gtk->gtk_window_move(dialog, (gint)x, (gint)y); } if (width > 0 && height > 0) { - fp_gtk_window_resize(dialog, (gint)width, (gint)height); + gtk->gtk_window_resize(dialog, (gint)width, (gint)height); } } - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -176,18 +177,18 @@ gboolean isAllDirsSame = TRUE; while (it) { - gchar* dir = fp_g_path_get_dirname((gchar*) it->data); + gchar* dir = gtk->g_path_get_dirname((gchar*) it->data); if (prevDir && strcmp(prevDir, dir) != 0) { isAllDirsSame = FALSE; - fp_g_free(dir); + gtk->g_free(dir); break; } if (!prevDir) { prevDir = strdup(dir); } - fp_g_free(dir); + gtk->g_free(dir); it = it->next; } @@ -227,7 +228,7 @@ return NULL; } - array = (*env)->NewObjectArray(env, fp_gtk_g_slist_length(list), stringCls, NULL); + array = (*env)->NewObjectArray(env, gtk->gtk_g_slist_length(list), stringCls, NULL); if (array == NULL) { (*env)->ExceptionClear(env); JNU_ThrowInternalError(env, "Could not instantiate array files array"); @@ -281,7 +282,7 @@ filenames = NULL; if (responseId == GTK_RESPONSE_ACCEPT) { - filenames = fp_gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(aDialog)); + filenames = gtk->gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(aDialog)); } jfilenames = toFilenamesArray(env, filenames, &jcurrent_folder); @@ -312,7 +313,7 @@ JNU_CHECK_EXCEPTION(env); } - fp_gdk_threads_enter(); + gtk->gdk_threads_enter(); const char *title = jtitle == NULL? "": (*env)->GetStringUTFChars(env, jtitle, 0); if (title == NULL) { @@ -323,19 +324,19 @@ if (mode == java_awt_FileDialog_SAVE) { /* Save action */ - dialog = fp_gtk_file_chooser_dialog_new(title, NULL, + dialog = gtk->gtk_file_chooser_dialog_new(title, NULL, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); } else { /* Default action OPEN */ - dialog = fp_gtk_file_chooser_dialog_new(title, NULL, + dialog = gtk->gtk_file_chooser_dialog_new(title, NULL, GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); /* Set multiple selection mode, that is allowed only in OPEN action */ if (multiple) { - fp_gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), + gtk->gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), multiple); } } @@ -352,7 +353,7 @@ JNU_ThrowOutOfMemoryError(env, "Could not get dir"); return; } - fp_gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir); + gtk->gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir); (*env)->ReleaseStringUTFChars(env, jdir, dir); } @@ -365,43 +366,44 @@ return; } if (mode == java_awt_FileDialog_SAVE) { - fp_gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), filename); + gtk->gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), filename); } else { - fp_gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), filename); + gtk->gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), filename); } (*env)->ReleaseStringUTFChars(env, jfile, filename); } /* Set the file filter */ if (jfilter != NULL) { - filter = fp_gtk_file_filter_new(); - fp_gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, + filter = gtk->gtk_file_filter_new(); + gtk->gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, filenameFilterCallback, jpeer, NULL); - fp_gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); + gtk->gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); } /* Other Properties */ - if (fp_gtk_check_version(2, 8, 0) == NULL) { - fp_gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER( + if (gtk->gtk_check_version(2, 8, 0) == NULL || + gtk->gtk_check_version(3, 0, 0) == NULL) { + gtk->gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER( dialog), TRUE); } /* Set the initial location */ if (x >= 0 && y >= 0) { - fp_gtk_window_move((GtkWindow*)dialog, (gint)x, (gint)y); + gtk->gtk_window_move((GtkWindow*)dialog, (gint)x, (gint)y); // NOTE: it doesn't set the initial size for the file chooser // as it seems like the file chooser overrides the size internally } - fp_g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK( - handle_response), jpeer); + gtk->g_signal_connect_data(dialog, "response", G_CALLBACK( + handle_response), jpeer, 0, 0); (*env)->SetLongField(env, jpeer, widgetFieldID, ptr_to_jlong(dialog)); - fp_gtk_widget_show(dialog); + gtk->gtk_widget_show(dialog); - fp_gtk_main(); - fp_gdk_threads_leave(); + gtk->gtk_main(); + gtk->gdk_threads_leave(); } --- old/src/solaris/native/sun/awt/swing_GTKEngine.c 2018-09-05 12:09:40.871671999 +0530 +++ new/src/solaris/native/sun/awt/swing_GTKEngine.c 2018-09-05 12:09:40.551512000 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,24 @@ */ #include -#include "gtk2_interface.h" +#include "gtk_interface.h" #include "com_sun_java_swing_plaf_gtk_GTKEngine.h" +/* Static buffer for conversion from java.lang.String to UTF-8 */ +static char conversionBuffer[CONV_BUFFER_SIZE]; + +const char *getStrFor(JNIEnv *env, jstring val) +{ + int length = (*env)->GetStringLength(env, val); + if (length > CONV_BUFFER_SIZE-1) + { + length = CONV_BUFFER_SIZE-1; + } + + (*env)->GetStringUTFRegion(env, val, 0, length, conversionBuffer); + return conversionBuffer; +} + /* * Class: com_sun_java_swing_plaf_gtk_GTKEngine * Method: native_paint_arrow @@ -38,10 +53,10 @@ jint widget_type, jint state, jint shadow_type, jstring detail, jint x, jint y, jint w, jint h, jint arrow_type) { - fp_gdk_threads_enter(); - gtk2_paint_arrow(widget_type, state, shadow_type, getStrFor(env, detail), + gtk->gdk_threads_enter(); + gtk->paint_arrow(widget_type, state, shadow_type, getStrFor(env, detail), x, y, w, h, arrow_type, TRUE); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -56,10 +71,10 @@ jint x, jint y, jint w, jint h, jint synth_state, jint dir) { - fp_gdk_threads_enter(); - gtk2_paint_box(widget_type, state, shadow_type, getStrFor(env, detail), + gtk->gdk_threads_enter(); + gtk->paint_box(widget_type, state, shadow_type, getStrFor(env, detail), x, y, w, h, synth_state, dir); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -74,10 +89,10 @@ jint x, jint y, jint w, jint h, jint gap_side, jint gap_x, jint gap_w) { - fp_gdk_threads_enter(); - gtk2_paint_box_gap(widget_type, state, shadow_type, getStrFor(env, detail), + gtk->gdk_threads_enter(); + gtk->paint_box_gap(widget_type, state, shadow_type, getStrFor(env, detail), x, y, w, h, gap_side, gap_x, gap_w); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -91,10 +106,10 @@ jint widget_type, jint synth_state, jstring detail, jint x, jint y, jint w, jint h) { - fp_gdk_threads_enter(); - gtk2_paint_check(widget_type, synth_state, getStrFor(env, detail), + gtk->gdk_threads_enter(); + gtk->paint_check(widget_type, synth_state, getStrFor(env, detail), x, y, w, h); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -108,10 +123,10 @@ jint widget_type, jint state, jstring detail, jint x, jint y, jint w, jint h, jint expander_style) { - fp_gdk_threads_enter(); - gtk2_paint_expander(widget_type, state, getStrFor(env, detail), + gtk->gdk_threads_enter(); + gtk->paint_expander(widget_type, state, getStrFor(env, detail), x, y, w, h, expander_style); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -125,10 +140,10 @@ jint widget_type, jint state, jint shadow_type, jstring detail, jint x, jint y, jint w, jint h, jint placement) { - fp_gdk_threads_enter(); - gtk2_paint_extension(widget_type, state, shadow_type, + gtk->gdk_threads_enter(); + gtk->paint_extension(widget_type, state, shadow_type, getStrFor(env, detail), x, y, w, h, placement); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -142,10 +157,10 @@ jint widget_type, jint state, jint shadow_type, jstring detail, jint x, jint y, jint w, jint h, jboolean has_focus) { - fp_gdk_threads_enter(); - gtk2_paint_flat_box(widget_type, state, shadow_type, + gtk->gdk_threads_enter(); + gtk->paint_flat_box(widget_type, state, shadow_type, getStrFor(env, detail), x, y, w, h, has_focus); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -159,10 +174,10 @@ jint widget_type, jint state, jstring detail, jint x, jint y, jint w, jint h) { - fp_gdk_threads_enter(); - gtk2_paint_focus(widget_type, state, getStrFor(env, detail), + gtk->gdk_threads_enter(); + gtk->paint_focus(widget_type, state, getStrFor(env, detail), x, y, w, h); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -176,10 +191,10 @@ jint widget_type, jint state, jint shadow_type, jstring detail, jint x, jint y, jint w, jint h, jint orientation) { - fp_gdk_threads_enter(); - gtk2_paint_handle(widget_type, state, shadow_type, getStrFor(env, detail), + gtk->gdk_threads_enter(); + gtk->paint_handle(widget_type, state, shadow_type, getStrFor(env, detail), x, y, w, h, orientation); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -193,10 +208,10 @@ jint widget_type, jint state, jstring detail, jint x, jint y, jint w, jint h) { - fp_gdk_threads_enter(); - gtk2_paint_hline(widget_type, state, getStrFor(env, detail), + gtk->gdk_threads_enter(); + gtk->paint_hline(widget_type, state, getStrFor(env, detail), x, y, w, h); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -210,10 +225,10 @@ jint widget_type, jint synth_state, jstring detail, jint x, jint y, jint w, jint h) { - fp_gdk_threads_enter(); - gtk2_paint_option(widget_type, synth_state, getStrFor(env, detail), + gtk->gdk_threads_enter(); + gtk->paint_option(widget_type, synth_state, getStrFor(env, detail), x, y, w, h); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -228,10 +243,10 @@ jint x, jint y, jint w, jint h, jint synth_state, jint dir) { - fp_gdk_threads_enter(); - gtk2_paint_shadow(widget_type, state, shadow_type, getStrFor(env, detail), + gtk->gdk_threads_enter(); + gtk->paint_shadow(widget_type, state, shadow_type, getStrFor(env, detail), x, y, w, h, synth_state, dir); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -243,12 +258,12 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1slider( JNIEnv *env, jobject this, jint widget_type, jint state, jint shadow_type, jstring detail, - jint x, jint y, jint w, jint h, jint orientation) + jint x, jint y, jint w, jint h, jint orientation, jboolean has_focus) { - fp_gdk_threads_enter(); - gtk2_paint_slider(widget_type, state, shadow_type, getStrFor(env, detail), - x, y, w, h, orientation); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + gtk->paint_slider(widget_type, state, shadow_type, getStrFor(env, detail), + x, y, w, h, orientation, has_focus); + gtk->gdk_threads_leave(); } /* @@ -262,10 +277,10 @@ jint widget_type, jint state, jstring detail, jint x, jint y, jint w, jint h) { - fp_gdk_threads_enter(); - gtk2_paint_vline(widget_type, state, getStrFor(env, detail), + gtk->gdk_threads_enter(); + gtk->paint_vline(widget_type, state, getStrFor(env, detail), x, y, w, h); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -278,9 +293,9 @@ JNIEnv *env, jobject this, jint widget_type, jint state, jint x, jint y, jint w, jint h) { - fp_gdk_threads_enter(); - gtk_paint_background(widget_type, state, x, y, w, h); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + gtk->paint_background(widget_type, state, x, y, w, h); + gtk->gdk_threads_leave(); } /* @@ -292,9 +307,9 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_nativeStartPainting( JNIEnv *env, jobject this, jint w, jint h) { - fp_gdk_threads_enter(); - gtk2_init_painting(env, w, h); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + gtk->init_painting(env, w, h); + gtk->gdk_threads_leave(); } /* @@ -308,9 +323,9 @@ { jint transparency; gint *buffer = (gint*) (*env)->GetPrimitiveArrayCritical(env, dest, 0); - fp_gdk_threads_enter(); - transparency = gtk2_copy_image(buffer, width, height); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + transparency = gtk->copy_image(buffer, width, height); + gtk->gdk_threads_leave(); (*env)->ReleasePrimitiveArrayCritical(env, dest, buffer, 0); return transparency; } @@ -324,7 +339,9 @@ JNIEnv *env, jobject this) { // Note that flush_gtk_event_loop takes care of locks (7053002) - flush_gtk_event_loop(); + gtk->gdk_threads_enter(); + gtk->flush_event_loop(); + gtk->gdk_threads_leave(); } /* @@ -336,9 +353,9 @@ JNIEnv *env, jobject this, jint property) { jobject obj; - fp_gdk_threads_enter(); - obj = gtk2_get_setting(env, property); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + obj = gtk->get_setting(env, property); + gtk->gdk_threads_leave(); return obj; } @@ -352,7 +369,7 @@ JNIEnv *env, jobject this, jint widget_type, jdouble value, jdouble min, jdouble max, jdouble visible) { - fp_gdk_threads_enter(); - gtk2_set_range_value(widget_type, value, min, max, visible); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + gtk->set_range_value(widget_type, value, min, max, visible); + gtk->gdk_threads_leave(); } --- old/src/solaris/native/sun/awt/swing_GTKStyle.c 2018-09-05 12:09:41.912192000 +0530 +++ new/src/solaris/native/sun/awt/swing_GTKStyle.c 2018-09-05 12:09:41.584028000 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,12 @@ */ #include -#include "gtk2_interface.h" +#include +#include "gtk_interface.h" #include "com_sun_java_swing_plaf_gtk_GTKStyle.h" +const char *getStrFor(JNIEnv *env, jstring val); + /* * Class: com_sun_java_swing_plaf_gtk_GTKStyle * Method: nativeGetXThickness @@ -37,9 +40,9 @@ JNIEnv *env, jclass klass, jint widget_type) { jint ret; - fp_gdk_threads_enter(); - ret = gtk2_get_xthickness(env, widget_type); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + ret = gtk->get_xthickness(env, widget_type); + gtk->gdk_threads_leave(); return ret; } @@ -53,9 +56,9 @@ JNIEnv *env, jclass klass, jint widget_type) { jint ret; - fp_gdk_threads_enter(); - ret = gtk2_get_ythickness(env, widget_type); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + ret = gtk->get_ythickness(env, widget_type); + gtk->gdk_threads_leave(); return ret; } @@ -70,9 +73,9 @@ jint state_type, jint type_id) { jint ret; - fp_gdk_threads_enter(); - ret = gtk2_get_color_for_state(env, widget_type, state_type, type_id); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + ret = gtk->get_color_for_state(env, widget_type, state_type, type_id); + gtk->gdk_threads_leave(); return ret; } @@ -86,9 +89,9 @@ JNIEnv *env, jclass klass, jint widget_type, jstring key) { jobject ret; - fp_gdk_threads_enter(); - ret = gtk2_get_class_value(env, widget_type, key); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + ret = gtk->get_class_value(env, widget_type, getStrFor(env, key)); + gtk->gdk_threads_leave(); return ret; } @@ -102,8 +105,8 @@ JNIEnv *env, jclass klass, jint widget_type) { jstring ret; - fp_gdk_threads_enter(); - ret = gtk2_get_pango_font_name(env, widget_type); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + ret = gtk->get_pango_font_name(env, widget_type); + gtk->gdk_threads_leave(); return ret; } --- old/src/solaris/native/sun/xawt/XToolkit.c 2018-09-05 12:09:42.880675999 +0530 +++ new/src/solaris/native/sun/xawt/XToolkit.c 2018-09-05 12:09:42.560516000 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -579,7 +579,7 @@ */ static uint32_t get_poll_timeout(jlong nextTaskTime) { - uint32_t ret_timeout; + uint32_t ret_timeout = 0; uint32_t timeout; uint32_t taskTimeout; uint32_t flushTimeout; --- old/src/solaris/native/sun/xawt/awt_Desktop.c 2018-09-05 12:09:43.785128000 +0530 +++ new/src/solaris/native/sun/xawt/awt_Desktop.c 2018-09-05 12:09:43.488980000 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ */ #include "jni_util.h" -#include "gtk2_interface.h" +#include "gtk_interface.h" #include "gnome_interface.h" static gboolean gtk_has_been_loaded = FALSE; @@ -36,14 +36,14 @@ * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XDesktopPeer_init - (JNIEnv *env, jclass cls) + (JNIEnv *env, jclass cls, jint version, jboolean verbose) { if (gtk_has_been_loaded || gnome_has_been_loaded) { return JNI_TRUE; } - if (gtk2_load(env) && gtk2_show_uri_load(env)) { + if (gtk_load(env, version, verbose) && gtk->show_uri_load(env)) { gtk_has_been_loaded = TRUE; return JNI_TRUE; } else if (gnome_load()) { @@ -74,9 +74,9 @@ } if (gtk_has_been_loaded) { - fp_gdk_threads_enter(); - success = fp_gtk_show_uri(NULL, url_c, GDK_CURRENT_TIME, NULL); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + success = gtk->gtk_show_uri(NULL, url_c, GDK_CURRENT_TIME, NULL); + gtk->gdk_threads_leave(); } else if (gnome_has_been_loaded) { success = (*gnome_url_show)(url_c, NULL); } --- old/src/solaris/native/sun/xawt/gnome_interface.h 2018-09-05 12:09:44.605538000 +0530 +++ new/src/solaris/native/sun/xawt/gnome_interface.h 2018-09-05 12:09:44.273372000 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ #ifndef _GNOME_INTERFACE_H #define _GNOME_INTERFACE_H -#include "gtk2_interface.h" +#include "gtk_interface.h" #include #include #include --- /dev/null 2018-09-04 17:27:28.996000000 +0530 +++ new/src/solaris/native/sun/awt/gtk3_interface.c 2018-09-05 12:09:45.041756000 +0530 @@ -0,0 +1,2863 @@ +/* + * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +#include +#include +#include +#include +#include +#include "gtk3_interface.h" +#include "java_awt_Transparency.h" +#include "sizecalc.h" +#include +#include +#include "awt.h" + +static void *gtk3_libhandle = NULL; +static void *gthread_libhandle = NULL; + +static jmp_buf j; + +/* Widgets */ +static GtkWidget *gtk3_widget = NULL; +static GtkWidget *gtk3_window = NULL; +static GtkFixed *gtk3_fixed = NULL; +static GtkStyleProvider *gtk3_css = NULL; + +/* Paint system */ +static cairo_surface_t *surface = NULL; +static cairo_t *cr = NULL; + +static const char ENV_PREFIX[] = "GTK_MODULES="; + +static GtkWidget *gtk3_widgets[_GTK_WIDGET_TYPE_SIZE]; + +static void throw_exception(JNIEnv *env, const char* name, const char* message) +{ + jclass class = (*env)->FindClass(env, name); + + if (class != NULL) + (*env)->ThrowNew(env, class, message); + + (*env)->DeleteLocalRef(env, class); +} + +static void gtk3_add_state(GtkWidget *widget, GtkStateType state) { + GtkStateType old_state = fp_gtk_widget_get_state(widget); + fp_gtk_widget_set_state(widget, old_state | state); +} + +static void gtk3_remove_state(GtkWidget *widget, GtkStateType state) { + GtkStateType old_state = fp_gtk_widget_get_state(widget); + fp_gtk_widget_set_state(widget, old_state & ~state); +} + +/* This is a workaround for the bug: + * http://sourceware.org/bugzilla/show_bug.cgi?id=1814 + * (dlsym/dlopen clears dlerror state) + * This bug is specific to Linux, but there is no harm in + * applying this workaround on Solaris as well. + */ +static void* dl_symbol(const char* name) +{ + void* result = dlsym(gtk3_libhandle, name); + if (!result) + longjmp(j, NO_SYMBOL_EXCEPTION); + + return result; +} + +static void* dl_symbol_gthread(const char* name) +{ + void* result = dlsym(gthread_libhandle, name); + if (!result) + longjmp(j, NO_SYMBOL_EXCEPTION); + + return result; +} + +gboolean gtk3_check(const char* lib_name, gboolean load) +{ + if (gtk3_libhandle != NULL) { + /* We've already successfully opened the GTK libs, so return true. */ + return TRUE; + } else { +#ifdef RTLD_NOLOAD + void *lib = dlopen(lib_name, RTLD_LAZY | RTLD_NOLOAD); + if (!load || lib != NULL) { + return lib != NULL; + } +#else +#ifdef _AIX + /* On AIX we could implement this with the help of loadquery(L_GETINFO, ..) */ + /* (see reload_table() in hotspot/src/os/aix/vm/loadlib_aix.cpp) but it is */ + /* probably not worth it because most AIX servers don't have GTK libs anyway */ +#endif +#endif + return dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL) != NULL; + } +} + +#define ADD_SUPPORTED_ACTION(actionStr) \ +do { \ + jfieldID fld_action = (*env)->GetStaticFieldID(env, cls_action, actionStr, \ + "Ljava/awt/Desktop$Action;"); \ + if (!(*env)->ExceptionCheck(env)) { \ + jobject action = (*env)->GetStaticObjectField(env, cls_action, \ + fld_action); \ + (*env)->CallBooleanMethod(env, supportedActions, mid_arrayListAdd, \ + action); \ + } else { \ + (*env)->ExceptionClear(env); \ + } \ +} while(0); + + +static void update_supported_actions(JNIEnv *env) { + GVfs * (*fp_g_vfs_get_default) (void); + const gchar * const * (*fp_g_vfs_get_supported_uri_schemes) (GVfs * vfs); + const gchar * const * schemes = NULL; + + jclass cls_action = (*env)->FindClass(env, "java/awt/Desktop$Action"); + CHECK_NULL(cls_action); + jclass cls_xDesktopPeer = (*env)-> + FindClass(env, "sun/awt/X11/XDesktopPeer"); + CHECK_NULL(cls_xDesktopPeer); + jfieldID fld_supportedActions = (*env)->GetStaticFieldID(env, + cls_xDesktopPeer, "supportedActions", "Ljava/util/List;"); + CHECK_NULL(fld_supportedActions); + jobject supportedActions = (*env)->GetStaticObjectField(env, + cls_xDesktopPeer, fld_supportedActions); + + jclass cls_arrayList = (*env)->FindClass(env, "java/util/ArrayList"); + CHECK_NULL(cls_arrayList); + jmethodID mid_arrayListAdd = (*env)->GetMethodID(env, cls_arrayList, "add", + "(Ljava/lang/Object;)Z"); + CHECK_NULL(mid_arrayListAdd); + jmethodID mid_arrayListClear = (*env)->GetMethodID(env, cls_arrayList, + "clear", "()V"); + CHECK_NULL(mid_arrayListClear); + + (*env)->CallVoidMethod(env, supportedActions, mid_arrayListClear); + + ADD_SUPPORTED_ACTION("OPEN"); + + /** + * gtk_show_uri() documentation says: + * + * > you need to install gvfs to get support for uri schemes such as http:// + * > or ftp://, as only local files are handled by GIO itself. + * + * So OPEN action was safely added here. + * However, it looks like Solaris 11 have gvfs support only for 32-bit + * applications only by default. + */ + + fp_g_vfs_get_default = dl_symbol("g_vfs_get_default"); + fp_g_vfs_get_supported_uri_schemes = + dl_symbol("g_vfs_get_supported_uri_schemes"); + dlerror(); + + if (fp_g_vfs_get_default && fp_g_vfs_get_supported_uri_schemes) { + GVfs * vfs = fp_g_vfs_get_default(); + schemes = vfs ? fp_g_vfs_get_supported_uri_schemes(vfs) : NULL; + if (schemes) { + int i = 0; + while (schemes[i]) { + if (strcmp(schemes[i], "http") == 0) { + ADD_SUPPORTED_ACTION("BROWSE"); + ADD_SUPPORTED_ACTION("MAIL"); + break; + } + i++; + } + } + } else { +#ifdef DEBUG + fprintf(stderr, "Cannot load g_vfs_get_supported_uri_schemes\n"); +#endif /* DEBUG */ + } + +} +/** + * Functions for awt_Desktop.c + */ +static gboolean gtk3_show_uri_load(JNIEnv *env) { + gboolean success = FALSE; + dlerror(); + fp_gtk_show_uri = dl_symbol("gtk_show_uri"); + const char *dlsym_error = dlerror(); + if (dlsym_error) { +#ifdef DEBUG + fprintf (stderr, "Cannot load symbol: %s \n", dlsym_error); +#endif /* DEBUG */ + } else if (fp_gtk_show_uri == NULL) { +#ifdef DEBUG + fprintf(stderr, "dlsym(gtk_show_uri) returned NULL\n"); +#endif /* DEBUG */ + } else { + gtk->gtk_show_uri = fp_gtk_show_uri; + update_supported_actions(env); + success = TRUE; + } + return success; +} + +/** + * Functions for sun_awt_X11_GtkFileDialogPeer.c + */ +static void gtk3_file_chooser_load() +{ + fp_gtk_file_chooser_get_filename = dl_symbol( + "gtk_file_chooser_get_filename"); + fp_gtk_file_chooser_dialog_new = dl_symbol("gtk_file_chooser_dialog_new"); + fp_gtk_file_chooser_set_current_folder = dl_symbol( + "gtk_file_chooser_set_current_folder"); + fp_gtk_file_chooser_set_filename = dl_symbol( + "gtk_file_chooser_set_filename"); + fp_gtk_file_chooser_set_current_name = dl_symbol( + "gtk_file_chooser_set_current_name"); + fp_gtk_file_filter_add_custom = dl_symbol("gtk_file_filter_add_custom"); + fp_gtk_file_chooser_set_filter = dl_symbol("gtk_file_chooser_set_filter"); + fp_gtk_file_chooser_get_type = dl_symbol("gtk_file_chooser_get_type"); + fp_gtk_file_filter_new = dl_symbol("gtk_file_filter_new"); + fp_gtk_file_chooser_set_do_overwrite_confirmation = dl_symbol( + "gtk_file_chooser_set_do_overwrite_confirmation"); + fp_gtk_file_chooser_set_select_multiple = dl_symbol( + "gtk_file_chooser_set_select_multiple"); + fp_gtk_file_chooser_get_current_folder = dl_symbol( + "gtk_file_chooser_get_current_folder"); + fp_gtk_file_chooser_get_filenames = dl_symbol( + "gtk_file_chooser_get_filenames"); + fp_gtk_g_slist_length = dl_symbol("g_slist_length"); + fp_gdk_x11_drawable_get_xid = dl_symbol("gdk_x11_window_get_xid"); +} + +static void empty() {} + +static gboolean gtk3_version_3_10 = TRUE; +static gboolean gtk3_version_3_14 = FALSE; + +GtkApi* gtk3_load(JNIEnv *env, const char* lib_name) +{ + gboolean result; + int i; + int (*handler)(); + int (*io_handler)(); + char *gtk_modules_env; + gtk3_libhandle = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL); + if (gtk3_libhandle == NULL) { + return FALSE; + } + + gthread_libhandle = dlopen(GTHREAD_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL); + if (gthread_libhandle == NULL) { + gthread_libhandle = dlopen(GTHREAD_LIB, RTLD_LAZY | RTLD_LOCAL); + if (gthread_libhandle == NULL) + return FALSE; + } + + if (setjmp(j) == 0) + { + fp_gtk_check_version = dl_symbol("gtk_check_version"); + + /* GLib */ + fp_glib_check_version = dlsym(gtk3_libhandle, "glib_check_version"); + if (!fp_glib_check_version) { + dlerror(); + } + fp_g_free = dl_symbol("g_free"); + fp_g_object_unref = dl_symbol("g_object_unref"); + + fp_g_main_context_iteration = + dl_symbol("g_main_context_iteration"); + + fp_g_value_init = dl_symbol("g_value_init"); + fp_g_type_is_a = dl_symbol("g_type_is_a"); + fp_g_value_get_boolean = dl_symbol("g_value_get_boolean"); + fp_g_value_get_char = dl_symbol("g_value_get_char"); + fp_g_value_get_uchar = dl_symbol("g_value_get_uchar"); + fp_g_value_get_int = dl_symbol("g_value_get_int"); + fp_g_value_get_uint = dl_symbol("g_value_get_uint"); + fp_g_value_get_long = dl_symbol("g_value_get_long"); + fp_g_value_get_ulong = dl_symbol("g_value_get_ulong"); + fp_g_value_get_int64 = dl_symbol("g_value_get_int64"); + fp_g_value_get_uint64 = dl_symbol("g_value_get_uint64"); + fp_g_value_get_float = dl_symbol("g_value_get_float"); + fp_g_value_get_double = dl_symbol("g_value_get_double"); + fp_g_value_get_string = dl_symbol("g_value_get_string"); + fp_g_value_get_enum = dl_symbol("g_value_get_enum"); + fp_g_value_get_flags = dl_symbol("g_value_get_flags"); + fp_g_value_get_param = dl_symbol("g_value_get_param"); + fp_g_value_get_boxed = dl_symbol("g_value_get_boxed"); + fp_g_value_get_pointer = dl_symbol("g_value_get_pointer"); + + fp_g_object_get = dl_symbol("g_object_get"); + fp_g_object_set = dl_symbol("g_object_set"); + + fp_g_str_has_prefix = dl_symbol("g_str_has_prefix"); + fp_g_strsplit = dl_symbol("g_strsplit"); + fp_g_strfreev = dl_symbol("g_strfreev"); + + /* GDK */ + fp_gdk_get_default_root_window = + dl_symbol("gdk_get_default_root_window"); + + /* Pixbuf */ + fp_gdk_pixbuf_new = dl_symbol("gdk_pixbuf_new"); + fp_gdk_pixbuf_new_from_file = + dl_symbol("gdk_pixbuf_new_from_file"); + fp_gdk_pixbuf_get_from_drawable = + dl_symbol("gdk_pixbuf_get_from_window"); + fp_gdk_pixbuf_get_width = dl_symbol("gdk_pixbuf_get_width"); + fp_gdk_pixbuf_get_height = dl_symbol("gdk_pixbuf_get_height"); + fp_gdk_pixbuf_get_pixels = dl_symbol("gdk_pixbuf_get_pixels"); + fp_gdk_pixbuf_get_rowstride = + dl_symbol("gdk_pixbuf_get_rowstride"); + fp_gdk_pixbuf_get_has_alpha = + dl_symbol("gdk_pixbuf_get_has_alpha"); + fp_gdk_pixbuf_get_bits_per_sample = + dl_symbol("gdk_pixbuf_get_bits_per_sample"); + fp_gdk_pixbuf_get_n_channels = + dl_symbol("gdk_pixbuf_get_n_channels"); + fp_gdk_pixbuf_get_colorspace = + dl_symbol("gdk_pixbuf_get_colorspace"); + + fp_cairo_image_surface_create = dl_symbol("cairo_image_surface_create"); + fp_cairo_surface_destroy = dl_symbol("cairo_surface_destroy"); + fp_cairo_create = dl_symbol("cairo_create"); + fp_cairo_destroy = dl_symbol("cairo_destroy"); + fp_cairo_fill = dl_symbol("cairo_fill"); + fp_cairo_rectangle = dl_symbol("cairo_rectangle"); + fp_cairo_set_source_rgb = dl_symbol("cairo_set_source_rgb"); + fp_cairo_set_source_rgba = dl_symbol("cairo_set_source_rgba"); + fp_cairo_surface_flush = dl_symbol("cairo_surface_flush"); + fp_cairo_paint = dl_symbol("cairo_paint"); + fp_cairo_clip = dl_symbol("cairo_clip"); + fp_cairo_image_surface_get_data = + dl_symbol("cairo_image_surface_get_data"); + fp_cairo_image_surface_get_stride = + dl_symbol("cairo_image_surface_get_stride"); + + fp_gdk_pixbuf_get_from_surface = + dl_symbol("gdk_pixbuf_get_from_surface"); + + fp_gtk_widget_get_state = dl_symbol("gtk_widget_get_state"); + fp_gtk_widget_set_state = dl_symbol("gtk_widget_set_state"); + + fp_gtk_widget_is_focus = dl_symbol("gtk_widget_is_focus"); + fp_gtk_widget_set_allocation = dl_symbol("gtk_widget_set_allocation"); + fp_gtk_widget_get_parent = dl_symbol("gtk_widget_get_parent"); + fp_gtk_widget_get_window = dl_symbol("gtk_widget_get_window"); + + fp_gtk_widget_get_style_context = + dl_symbol("gtk_widget_get_style_context"); + fp_gtk_style_context_get_color = + dl_symbol("gtk_style_context_get_color"); + fp_gtk_style_context_get_background_color = + dl_symbol("gtk_style_context_get_background_color"); + fp_gtk_widget_get_state_flags = dl_symbol("gtk_widget_get_state_flags"); + fp_gtk_style_context_set_state = + dl_symbol("gtk_style_context_set_state"); + fp_gtk_style_context_add_class = + dl_symbol("gtk_style_context_add_class"); + fp_gtk_style_context_save = dl_symbol("gtk_style_context_save"); + fp_gtk_style_context_restore = dl_symbol("gtk_style_context_restore"); + fp_gtk_render_check = dl_symbol("gtk_render_check"); + fp_gtk_render_option = dl_symbol("gtk_render_option"); + fp_gtk_render_extension = dl_symbol("gtk_render_extension"); + fp_gtk_render_expander = dl_symbol("gtk_render_expander"); + fp_gtk_render_frame_gap = dl_symbol("gtk_render_frame_gap"); + fp_gtk_render_line = dl_symbol("gtk_render_line"); + fp_gtk_widget_render_icon_pixbuf = + dl_symbol("gtk_widget_render_icon_pixbuf"); + if (fp_gtk_check_version(3, 10, 0)) { + gtk3_version_3_10 = FALSE; + } else { + fp_gdk_window_create_similar_image_surface = + dl_symbol("gdk_window_create_similar_image_surface"); + } + gtk3_version_3_14 = !fp_gtk_check_version(3, 14, 0); + + fp_gdk_window_create_similar_surface = + dl_symbol("gdk_window_create_similar_surface"); + fp_gtk_settings_get_for_screen = + dl_symbol("gtk_settings_get_for_screen"); + fp_gtk_widget_get_screen = dl_symbol("gtk_widget_get_screen"); + fp_gtk_css_provider_get_named = dl_symbol("gtk_css_provider_get_named"); + fp_gtk_style_context_add_provider = + dl_symbol("gtk_style_context_add_provider"); + fp_gtk_render_frame = dl_symbol("gtk_render_frame"); + fp_gtk_render_focus = dl_symbol("gtk_render_focus"); + fp_gtk_render_handle = dl_symbol("gtk_render_handle"); + fp_gtk_render_arrow = dl_symbol("gtk_render_arrow"); + + fp_gtk_style_context_get_property = + dl_symbol("gtk_style_context_get_property"); + fp_gtk_scrolled_window_set_shadow_type = + dl_symbol("gtk_scrolled_window_set_shadow_type"); + fp_gtk_render_slider = dl_symbol("gtk_render_slider"); + fp_gtk_style_context_get_padding = + dl_symbol("gtk_style_context_get_padding"); + fp_gtk_range_set_inverted = dl_symbol("gtk_range_set_inverted"); + fp_gtk_style_context_get_font = dl_symbol("gtk_style_context_get_font"); + fp_gtk_widget_get_allocated_width = + dl_symbol("gtk_widget_get_allocated_width"); + fp_gtk_widget_get_allocated_height = + dl_symbol("gtk_widget_get_allocated_height"); + fp_gtk_icon_theme_get_default = dl_symbol("gtk_icon_theme_get_default"); + fp_gtk_icon_theme_load_icon = dl_symbol("gtk_icon_theme_load_icon"); + + fp_gtk_adjustment_set_lower = dl_symbol("gtk_adjustment_set_lower"); + fp_gtk_adjustment_set_page_increment = + dl_symbol("gtk_adjustment_set_page_increment"); + fp_gtk_adjustment_set_page_size = + dl_symbol("gtk_adjustment_set_page_size"); + fp_gtk_adjustment_set_step_increment = + dl_symbol("gtk_adjustment_set_step_increment"); + fp_gtk_adjustment_set_upper = dl_symbol("gtk_adjustment_set_upper"); + fp_gtk_adjustment_set_value = dl_symbol("gtk_adjustment_set_value"); + + fp_gtk_render_activity = dl_symbol("gtk_render_activity"); + fp_gtk_render_background = dl_symbol("gtk_render_background"); + fp_gtk_style_context_has_class = + dl_symbol("gtk_style_context_has_class"); + + fp_gtk_style_context_set_junction_sides = + dl_symbol("gtk_style_context_set_junction_sides"); + fp_gtk_style_context_add_region = + dl_symbol("gtk_style_context_add_region"); + + fp_gtk_init_check = dl_symbol("gtk_init_check"); + + /* GTK widgets */ + fp_gtk_arrow_new = dl_symbol("gtk_arrow_new"); + fp_gtk_button_new = dl_symbol("gtk_button_new"); + fp_gtk_spin_button_new = dl_symbol("gtk_spin_button_new"); + fp_gtk_check_button_new = dl_symbol("gtk_check_button_new"); + fp_gtk_check_menu_item_new = + dl_symbol("gtk_check_menu_item_new"); + fp_gtk_color_selection_dialog_new = + dl_symbol("gtk_color_selection_dialog_new"); + fp_gtk_entry_new = dl_symbol("gtk_entry_new"); + fp_gtk_fixed_new = dl_symbol("gtk_fixed_new"); + fp_gtk_handle_box_new = dl_symbol("gtk_handle_box_new"); + fp_gtk_image_new = dl_symbol("gtk_image_new"); + fp_gtk_hpaned_new = dl_symbol("gtk_hpaned_new"); + fp_gtk_vpaned_new = dl_symbol("gtk_vpaned_new"); + fp_gtk_scale_new = dl_symbol("gtk_scale_new"); + fp_gtk_hscrollbar_new = dl_symbol("gtk_hscrollbar_new"); + fp_gtk_vscrollbar_new = dl_symbol("gtk_vscrollbar_new"); + fp_gtk_hseparator_new = dl_symbol("gtk_hseparator_new"); + fp_gtk_vseparator_new = dl_symbol("gtk_vseparator_new"); + fp_gtk_label_new = dl_symbol("gtk_label_new"); + fp_gtk_menu_new = dl_symbol("gtk_menu_new"); + fp_gtk_menu_bar_new = dl_symbol("gtk_menu_bar_new"); + fp_gtk_menu_item_new = dl_symbol("gtk_menu_item_new"); + fp_gtk_menu_item_set_submenu = + dl_symbol("gtk_menu_item_set_submenu"); + fp_gtk_notebook_new = dl_symbol("gtk_notebook_new"); + fp_gtk_progress_bar_new = + dl_symbol("gtk_progress_bar_new"); + fp_gtk_progress_bar_set_orientation = + dl_symbol("gtk_orientable_set_orientation"); + fp_gtk_radio_button_new = + dl_symbol("gtk_radio_button_new"); + fp_gtk_radio_menu_item_new = + dl_symbol("gtk_radio_menu_item_new"); + fp_gtk_scrolled_window_new = + dl_symbol("gtk_scrolled_window_new"); + fp_gtk_separator_menu_item_new = + dl_symbol("gtk_separator_menu_item_new"); + fp_gtk_text_view_new = dl_symbol("gtk_text_view_new"); + fp_gtk_toggle_button_new = + dl_symbol("gtk_toggle_button_new"); + fp_gtk_toolbar_new = dl_symbol("gtk_toolbar_new"); + fp_gtk_tree_view_new = dl_symbol("gtk_tree_view_new"); + fp_gtk_viewport_new = dl_symbol("gtk_viewport_new"); + fp_gtk_window_new = dl_symbol("gtk_window_new"); + fp_gtk_window_present = dl_symbol("gtk_window_present"); + fp_gtk_window_move = dl_symbol("gtk_window_move"); + fp_gtk_window_resize = dl_symbol("gtk_window_resize"); + + fp_gtk_dialog_new = dl_symbol("gtk_dialog_new"); + fp_gtk_frame_new = dl_symbol("gtk_frame_new"); + + fp_gtk_adjustment_new = dl_symbol("gtk_adjustment_new"); + fp_gtk_container_add = dl_symbol("gtk_container_add"); + fp_gtk_menu_shell_append = + dl_symbol("gtk_menu_shell_append"); + fp_gtk_widget_realize = dl_symbol("gtk_widget_realize"); + fp_gtk_widget_destroy = dl_symbol("gtk_widget_destroy"); + fp_gtk_widget_render_icon = + dl_symbol("gtk_widget_render_icon"); + fp_gtk_widget_set_name = + dl_symbol("gtk_widget_set_name"); + fp_gtk_widget_set_parent = + dl_symbol("gtk_widget_set_parent"); + fp_gtk_widget_set_direction = + dl_symbol("gtk_widget_set_direction"); + fp_gtk_widget_style_get = + dl_symbol("gtk_widget_style_get"); + fp_gtk_widget_class_install_style_property = + dl_symbol("gtk_widget_class_install_style_property"); + fp_gtk_widget_class_find_style_property = + dl_symbol("gtk_widget_class_find_style_property"); + fp_gtk_widget_style_get_property = + dl_symbol("gtk_widget_style_get_property"); + fp_pango_font_description_to_string = + dl_symbol("pango_font_description_to_string"); + fp_gtk_settings_get_default = + dl_symbol("gtk_settings_get_default"); + fp_gtk_widget_get_settings = + dl_symbol("gtk_widget_get_settings"); + fp_gtk_border_get_type = dl_symbol("gtk_border_get_type"); + fp_gtk_arrow_set = dl_symbol("gtk_arrow_set"); + fp_gtk_widget_size_request = + dl_symbol("gtk_widget_size_request"); + fp_gtk_range_get_adjustment = + dl_symbol("gtk_range_get_adjustment"); + + fp_gtk_widget_hide = dl_symbol("gtk_widget_hide"); + fp_gtk_main_quit = dl_symbol("gtk_main_quit"); + fp_g_signal_connect_data = dl_symbol("g_signal_connect_data"); + fp_gtk_widget_show = dl_symbol("gtk_widget_show"); + fp_gtk_main = dl_symbol("gtk_main"); + + fp_g_path_get_dirname = dl_symbol("g_path_get_dirname"); + + fp_gdk_threads_init = dl_symbol("gdk_threads_init"); + fp_gdk_threads_enter = dl_symbol("gdk_threads_enter"); + fp_gdk_threads_leave = dl_symbol("gdk_threads_leave"); + + /** + * Functions for sun_awt_X11_GtkFileDialogPeer.c + */ + gtk3_file_chooser_load(); + + fp_gtk_combo_box_new = dlsym(gtk3_libhandle, "gtk_combo_box_new"); + fp_gtk_combo_box_entry_new = dlsym(gtk3_libhandle, + "gtk_combo_box_new_with_entry"); + fp_gtk_separator_tool_item_new = dlsym(gtk3_libhandle, + "gtk_separator_tool_item_new"); + + fp_g_list_append = dl_symbol("g_list_append"); + fp_g_list_free = dl_symbol("g_list_free"); + fp_g_list_free_full = dl_symbol("g_list_free_full"); + } + /* Now we have only one kind of exceptions: NO_SYMBOL_EXCEPTION + * Otherwise we can check the return value of setjmp method. + */ + else + { + dlclose(gtk3_libhandle); + gtk3_libhandle = NULL; + + dlclose(gthread_libhandle); + gthread_libhandle = NULL; + + return NULL; + } + + /* + * Strip the AT-SPI GTK_MODULES if present + */ + gtk_modules_env = getenv ("GTK_MODULES"); + if ((gtk_modules_env && strstr(gtk_modules_env, "atk-bridge")) || + (gtk_modules_env && strstr(gtk_modules_env, "gail"))) { + /* careful, strtok modifies its args */ + gchar *tmp_env = strdup(gtk_modules_env); + if (tmp_env) { + /* the new env will be smaller than the old one */ + gchar *s, *new_env = SAFE_SIZE_STRUCT_ALLOC(malloc, + sizeof(ENV_PREFIX), 1, strlen (gtk_modules_env)); + + if (new_env) { + strcpy(new_env, ENV_PREFIX); + + /* strip out 'atk-bridge' and 'gail' */ + size_t PREFIX_LENGTH = strlen(ENV_PREFIX); + gchar *tmp_ptr = NULL; + for (s = strtok_r(tmp_env, ":", &tmp_ptr); s; + s = strtok_r(NULL, ":", &tmp_ptr)) { + if ((!strstr(s, "atk-bridge")) && (!strstr(s, "gail"))) { + if (strlen(new_env) > PREFIX_LENGTH) { + new_env = strcat(new_env, ":"); + } + new_env = strcat(new_env, s); + } + } + if (putenv(new_env) != 0) { + /* no free() on success, putenv() doesn't copy string */ + free(new_env); + } + } + free (tmp_env); + } + } + /* + * GTK should be initialized with gtk_init_check() before use. + * + * gtk_init_check installs its own error handlers. It is critical that + * we preserve error handler set from AWT. Otherwise we'll crash on + * BadMatch errors which we would normally ignore. The IO error handler + * is preserved here, too, just for consistency. + */ + AWT_LOCK(); + handler = XSetErrorHandler(NULL); + io_handler = XSetIOErrorHandler(NULL); + + //According the GTK documentation, gdk_threads_init() should be + //called before gtk_init() or gtk_init_check() + fp_gdk_threads_init(); + result = (*fp_gtk_init_check)(NULL, NULL); + + XSetErrorHandler(handler); + XSetIOErrorHandler(io_handler); + AWT_UNLOCK(); + + /* Initialize widget array. */ + for (i = 0; i < _GTK_WIDGET_TYPE_SIZE; i++) + { + gtk3_widgets[i] = NULL; + } + if (result) { + GtkApi* gtk = (GtkApi*)malloc(sizeof(GtkApi)); + gtk3_init(gtk); + return gtk; + } + return NULL; +} + +static int gtk3_unload() +{ + int i; + char *gtk3_error; + + if (!gtk3_libhandle) + return TRUE; + + /* Release painting objects */ + if (surface != NULL) { + fp_cairo_destroy(cr); + fp_cairo_surface_destroy(surface); + surface = NULL; + } + + if (gtk3_window != NULL) { + /* Destroying toplevel widget will destroy all contained widgets */ + (*fp_gtk_widget_destroy)(gtk3_window); + + /* Unset some static data so they get reinitialized on next load */ + gtk3_window = NULL; + } + + dlerror(); + dlclose(gtk3_libhandle); + dlclose(gthread_libhandle); + if ((gtk3_error = dlerror()) != NULL) + { + return FALSE; + } + return TRUE; +} + +/* Dispatch all pending events from the GTK event loop. + * This is needed to catch theme change and update widgets' style. + */ +static void flush_gtk_event_loop() +{ + while((*fp_g_main_context_iteration)(NULL)); +} + +/* + * Initialize components of containment hierarchy. This creates a GtkFixed + * inside a GtkWindow. All widgets get realized. + */ +static void init_containers() +{ + if (gtk3_window == NULL) + { + gtk3_window = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL); + gtk3_fixed = (GtkFixed *)(*fp_gtk_fixed_new)(); + (*fp_gtk_container_add)((GtkContainer*)gtk3_window, + (GtkWidget *)gtk3_fixed); + (*fp_gtk_widget_realize)(gtk3_window); + (*fp_gtk_widget_realize)((GtkWidget *)gtk3_fixed); + + GtkSettings* settings = fp_gtk_settings_get_for_screen( + fp_gtk_widget_get_screen(gtk3_window)); + gchar* strval = NULL; + fp_g_object_get(settings, "gtk-theme-name", &strval, NULL); + gtk3_css = fp_gtk_css_provider_get_named(strval, NULL); + } +} + +/* + * Ensure everything is ready for drawing an element of the specified width + * and height. + * + * We should somehow handle translucent images. GTK can draw to X Drawables + * only, which don't support alpha. When we retrieve the image back from + * the server, translucency information is lost. There're several ways to + * work around this: + * 1) Subclass GdkPixmap and cache translucent objects on client side. This + * requires us to implement parts of X server drawing logic on client side. + * Many X requests can potentially be "translucent"; e.g. XDrawLine with + * fill=tile and a translucent tile is a "translucent" operation, whereas + * XDrawLine with fill=solid is an "opaque" one. Moreover themes can (and some + * do) intermix transparent and opaque operations which makes caching even + * more problematic. + * 2) Use Xorg 32bit ARGB visual when available. GDK has no native support + * for it (as of version 2.6). Also even in JDS 3 Xorg does not support + * these visuals by default, which makes optimizing for them pointless. + * We can consider doing this at a later point when ARGB visuals become more + * popular. + * 3') GTK has plans to use Cairo as its graphical backend (presumably in + * 2.8), and Cairo supports alpha. With it we could also get rid of the + * unnecessary round trip to server and do all the drawing on client side. + * 4) For now we draw to two different pixmaps and restore alpha channel by + * comparing results. This can be optimized by using subclassed pixmap and +*/ +static void gtk3_init_painting(JNIEnv *env, gint width, gint height) +{ + init_containers(); + + if (cr) { + fp_cairo_destroy(cr); + } + + if (surface != NULL) { + /* free old stuff */ + fp_cairo_surface_destroy(surface); + + } + + if (gtk3_version_3_10) { + surface = fp_gdk_window_create_similar_image_surface( + fp_gtk_widget_get_window(gtk3_window), + CAIRO_FORMAT_ARGB32, width, height, 1); + } else { + surface = fp_cairo_image_surface_create(CAIRO_FORMAT_ARGB32, + width, height); + } + + cr = fp_cairo_create(surface); +} + +/* + * Restore image from white and black pixmaps and copy it into destination + * buffer. This method compares two pixbufs taken from white and black + * pixmaps and decodes color and alpha components. Pixbufs are RGB without + * alpha, destination buffer is ABGR. + * + * The return value is the transparency type of the resulting image, either + * one of java_awt_Transparency_OPAQUE, java_awt_Transparency_BITMASK, and + * java_awt_Transparency_TRANSLUCENT. + */ +static gint gtk3_copy_image(gint *dst, gint width, gint height) +{ + gint i, j, r, g, b; + guchar *data; + gint stride, padding; + + fp_cairo_surface_flush(surface); + data = (*fp_cairo_image_surface_get_data)(surface); + stride = (*fp_cairo_image_surface_get_stride)(surface); + padding = stride - width * 4; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) { + int r = *data++; + int g = *data++; + int b = *data++; + int a = *data++; + *dst++ = (a << 24 | b << 16 | g << 8 | r); + } + data += padding; + } + return java_awt_Transparency_TRANSLUCENT; +} + +static void gtk3_set_direction(GtkWidget *widget, GtkTextDirection dir) +{ + /* + * Some engines (inexplicably) look at the direction of the widget's + * parent, so we need to set the direction of both the widget and its + * parent. + */ + (*fp_gtk_widget_set_direction)(widget, dir); + GtkWidget* parent = fp_gtk_widget_get_parent(widget); + if (parent != NULL) { + fp_gtk_widget_set_direction(parent, dir); + } +} + +/* GTK state_type filter */ +static GtkStateType get_gtk_state_type(WidgetType widget_type, gint synth_state) +{ + GtkStateType result = GTK_STATE_NORMAL; + + if ((synth_state & DISABLED) != 0) { + result = GTK_STATE_INSENSITIVE; + } else if ((synth_state & PRESSED) != 0) { + result = GTK_STATE_ACTIVE; + } else if ((synth_state & MOUSE_OVER) != 0) { + result = GTK_STATE_PRELIGHT; + } + return result; +} + +static GtkStateFlags get_gtk_state_flags(gint synth_state) +{ + GtkStateFlags flags = 0; + + if ((synth_state & DISABLED) != 0) { + flags |= GTK_STATE_FLAG_INSENSITIVE; + } + if (((synth_state & PRESSED) != 0 || (synth_state & SELECTED) != 0)) { + flags |= GTK_STATE_FLAG_ACTIVE; + } + if ((synth_state & MOUSE_OVER) != 0) { + flags |= GTK_STATE_FLAG_PRELIGHT; + } + if ((synth_state & FOCUSED) != 0) { + flags |= GTK_STATE_FLAG_FOCUSED; + } + return flags; +} + +static GtkStateFlags get_gtk_flags(GtkStateType state_type) { + GtkStateFlags flags = 0; + switch (state_type) + { + case GTK_STATE_PRELIGHT: + flags |= GTK_STATE_FLAG_PRELIGHT; + break; + case GTK_STATE_SELECTED: + flags |= GTK_STATE_FLAG_SELECTED; + break; + case GTK_STATE_INSENSITIVE: + flags |= GTK_STATE_FLAG_INSENSITIVE; + break; + case GTK_STATE_ACTIVE: + flags |= GTK_STATE_FLAG_ACTIVE; + break; + case GTK_STATE_FOCUSED: + flags |= GTK_STATE_FLAG_FOCUSED; + break; + default: + break; + } + return flags; +} + +/* GTK shadow_type filter */ +static GtkShadowType get_gtk_shadow_type(WidgetType widget_type, + gint synth_state) +{ + GtkShadowType result = GTK_SHADOW_OUT; + + if ((synth_state & SELECTED) != 0) { + result = GTK_SHADOW_IN; + } + return result; +} + + +static GtkWidget* gtk3_get_arrow(GtkArrowType arrow_type, + GtkShadowType shadow_type) +{ + GtkWidget *arrow = NULL; + if (NULL == gtk3_widgets[_GTK_ARROW_TYPE]) + { + gtk3_widgets[_GTK_ARROW_TYPE] = (*fp_gtk_arrow_new)(arrow_type, + shadow_type); + (*fp_gtk_container_add)((GtkContainer *)gtk3_fixed, + gtk3_widgets[_GTK_ARROW_TYPE]); + (*fp_gtk_widget_realize)(gtk3_widgets[_GTK_ARROW_TYPE]); + } + arrow = gtk3_widgets[_GTK_ARROW_TYPE]; + + (*fp_gtk_arrow_set)(arrow, arrow_type, shadow_type); + return arrow; +} + +static GtkAdjustment* create_adjustment() +{ + return (GtkAdjustment *) + (*fp_gtk_adjustment_new)(50.0, 0.0, 100.0, 10.0, 20.0, 20.0); +} + +/** + * Returns a pointer to the cached native widget for the specified widget + * type. + */ +static GtkWidget *gtk3_get_widget(WidgetType widget_type) +{ + gboolean init_result = FALSE; + GtkWidget *result = NULL; + switch (widget_type) + { + case BUTTON: + case TABLE_HEADER: + if (init_result = (NULL == gtk3_widgets[_GTK_BUTTON_TYPE])) + { + gtk3_widgets[_GTK_BUTTON_TYPE] = (*fp_gtk_button_new)(); + } + result = gtk3_widgets[_GTK_BUTTON_TYPE]; + break; + case CHECK_BOX: + if (init_result = (NULL == gtk3_widgets[_GTK_CHECK_BUTTON_TYPE])) + { + gtk3_widgets[_GTK_CHECK_BUTTON_TYPE] = + (*fp_gtk_check_button_new)(); + } + result = gtk3_widgets[_GTK_CHECK_BUTTON_TYPE]; + break; + case CHECK_BOX_MENU_ITEM: + if (init_result = (NULL == gtk3_widgets[_GTK_CHECK_MENU_ITEM_TYPE])) + { + gtk3_widgets[_GTK_CHECK_MENU_ITEM_TYPE] = + (*fp_gtk_check_menu_item_new)(); + } + result = gtk3_widgets[_GTK_CHECK_MENU_ITEM_TYPE]; + break; + /************************************************************ + * Creation a dedicated color chooser is dangerous because + * it deadlocks the EDT + ************************************************************/ +/* case COLOR_CHOOSER: + if (init_result = + (NULL == gtk3_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE])) + { + gtk3_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE] = + (*fp_gtk_color_selection_dialog_new)(NULL); + } + result = gtk3_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE]; + break;*/ + case COMBO_BOX: + if (init_result = (NULL == gtk3_widgets[_GTK_COMBO_BOX_TYPE])) + { + gtk3_widgets[_GTK_COMBO_BOX_TYPE] = + (*fp_gtk_combo_box_new)(); + } + result = gtk3_widgets[_GTK_COMBO_BOX_TYPE]; + break; + case COMBO_BOX_ARROW_BUTTON: + if (init_result = + (NULL == gtk3_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE])) + { + gtk3_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE] = + (*fp_gtk_toggle_button_new)(); + } + result = gtk3_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE]; + break; + case COMBO_BOX_TEXT_FIELD: + if (init_result = + (NULL == gtk3_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE])) + { + result = gtk3_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE] = + (*fp_gtk_entry_new)(); + } + result = gtk3_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE]; + break; + case DESKTOP_ICON: + case INTERNAL_FRAME_TITLE_PANE: + case LABEL: + if (init_result = (NULL == gtk3_widgets[_GTK_LABEL_TYPE])) + { + gtk3_widgets[_GTK_LABEL_TYPE] = + (*fp_gtk_label_new)(NULL); + } + result = gtk3_widgets[_GTK_LABEL_TYPE]; + break; + case DESKTOP_PANE: + case PANEL: + case ROOT_PANE: + if (init_result = (NULL == gtk3_widgets[_GTK_CONTAINER_TYPE])) + { + /* There is no constructor for a container type. I've + * chosen GtkFixed container since it has a default + * constructor. + */ + gtk3_widgets[_GTK_CONTAINER_TYPE] = + (*fp_gtk_fixed_new)(); + } + result = gtk3_widgets[_GTK_CONTAINER_TYPE]; + break; + case EDITOR_PANE: + case TEXT_AREA: + case TEXT_PANE: + if (init_result = (NULL == gtk3_widgets[_GTK_TEXT_VIEW_TYPE])) + { + gtk3_widgets[_GTK_TEXT_VIEW_TYPE] = + (*fp_gtk_text_view_new)(); + } + result = gtk3_widgets[_GTK_TEXT_VIEW_TYPE]; + break; + case FORMATTED_TEXT_FIELD: + case PASSWORD_FIELD: + case TEXT_FIELD: + if (init_result = (NULL == gtk3_widgets[_GTK_ENTRY_TYPE])) + { + gtk3_widgets[_GTK_ENTRY_TYPE] = + (*fp_gtk_entry_new)(); + } + result = gtk3_widgets[_GTK_ENTRY_TYPE]; + break; + case HANDLE_BOX: + if (init_result = (NULL == gtk3_widgets[_GTK_HANDLE_BOX_TYPE])) + { + gtk3_widgets[_GTK_HANDLE_BOX_TYPE] = + (*fp_gtk_handle_box_new)(); + } + result = gtk3_widgets[_GTK_HANDLE_BOX_TYPE]; + break; + case HSCROLL_BAR: + case HSCROLL_BAR_BUTTON_LEFT: + case HSCROLL_BAR_BUTTON_RIGHT: + case HSCROLL_BAR_TRACK: + case HSCROLL_BAR_THUMB: + if (init_result = (NULL == gtk3_widgets[_GTK_HSCROLLBAR_TYPE])) + { + gtk3_widgets[_GTK_HSCROLLBAR_TYPE] = + (*fp_gtk_hscrollbar_new)(create_adjustment()); + } + result = gtk3_widgets[_GTK_HSCROLLBAR_TYPE]; + break; + case HSEPARATOR: + if (init_result = (NULL == gtk3_widgets[_GTK_HSEPARATOR_TYPE])) + { + gtk3_widgets[_GTK_HSEPARATOR_TYPE] = + (*fp_gtk_hseparator_new)(); + } + result = gtk3_widgets[_GTK_HSEPARATOR_TYPE]; + break; + case HSLIDER: + case HSLIDER_THUMB: + case HSLIDER_TRACK: + if (init_result = (NULL == gtk3_widgets[_GTK_HSCALE_TYPE])) + { + gtk3_widgets[_GTK_HSCALE_TYPE] = + (*fp_gtk_scale_new)(GTK_ORIENTATION_HORIZONTAL, NULL); + } + result = gtk3_widgets[_GTK_HSCALE_TYPE]; + break; + case HSPLIT_PANE_DIVIDER: + case SPLIT_PANE: + if (init_result = (NULL == gtk3_widgets[_GTK_HPANED_TYPE])) + { + gtk3_widgets[_GTK_HPANED_TYPE] = (*fp_gtk_hpaned_new)(); + } + result = gtk3_widgets[_GTK_HPANED_TYPE]; + break; + case IMAGE: + if (init_result = (NULL == gtk3_widgets[_GTK_IMAGE_TYPE])) + { + gtk3_widgets[_GTK_IMAGE_TYPE] = (*fp_gtk_image_new)(); + } + result = gtk3_widgets[_GTK_IMAGE_TYPE]; + break; + case INTERNAL_FRAME: + if (init_result = (NULL == gtk3_widgets[_GTK_WINDOW_TYPE])) + { + gtk3_widgets[_GTK_WINDOW_TYPE] = + (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL); + } + result = gtk3_widgets[_GTK_WINDOW_TYPE]; + break; + case TOOL_TIP: + if (init_result = (NULL == gtk3_widgets[_GTK_TOOLTIP_TYPE])) + { + result = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL); + gtk3_widgets[_GTK_TOOLTIP_TYPE] = result; + } + result = gtk3_widgets[_GTK_TOOLTIP_TYPE]; + break; + case LIST: + case TABLE: + case TREE: + case TREE_CELL: + if (init_result = (NULL == gtk3_widgets[_GTK_TREE_VIEW_TYPE])) + { + gtk3_widgets[_GTK_TREE_VIEW_TYPE] = + (*fp_gtk_tree_view_new)(); + } + result = gtk3_widgets[_GTK_TREE_VIEW_TYPE]; + break; + case TITLED_BORDER: + if (init_result = (NULL == gtk3_widgets[_GTK_FRAME_TYPE])) + { + gtk3_widgets[_GTK_FRAME_TYPE] = fp_gtk_frame_new(NULL); + } + result = gtk3_widgets[_GTK_FRAME_TYPE]; + break; + case POPUP_MENU: + if (init_result = (NULL == gtk3_widgets[_GTK_MENU_TYPE])) + { + gtk3_widgets[_GTK_MENU_TYPE] = + (*fp_gtk_menu_new)(); + } + result = gtk3_widgets[_GTK_MENU_TYPE]; + break; + case MENU: + case MENU_ITEM: + case MENU_ITEM_ACCELERATOR: + if (init_result = (NULL == gtk3_widgets[_GTK_MENU_ITEM_TYPE])) + { + gtk3_widgets[_GTK_MENU_ITEM_TYPE] = + (*fp_gtk_menu_item_new)(); + } + result = gtk3_widgets[_GTK_MENU_ITEM_TYPE]; + break; + case MENU_BAR: + if (init_result = (NULL == gtk3_widgets[_GTK_MENU_BAR_TYPE])) + { + gtk3_widgets[_GTK_MENU_BAR_TYPE] = + (*fp_gtk_menu_bar_new)(); + } + result = gtk3_widgets[_GTK_MENU_BAR_TYPE]; + break; + case COLOR_CHOOSER: + case OPTION_PANE: + if (init_result = (NULL == gtk3_widgets[_GTK_DIALOG_TYPE])) + { + gtk3_widgets[_GTK_DIALOG_TYPE] = + (*fp_gtk_dialog_new)(); + } + result = gtk3_widgets[_GTK_DIALOG_TYPE]; + break; + case POPUP_MENU_SEPARATOR: + if (init_result = + (NULL == gtk3_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE])) + { + gtk3_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE] = + (*fp_gtk_separator_menu_item_new)(); + } + result = gtk3_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE]; + break; + case HPROGRESS_BAR: + if (init_result = (NULL == gtk3_widgets[_GTK_HPROGRESS_BAR_TYPE])) + { + gtk3_widgets[_GTK_HPROGRESS_BAR_TYPE] = + (*fp_gtk_progress_bar_new)(); + } + result = gtk3_widgets[_GTK_HPROGRESS_BAR_TYPE]; + break; + case VPROGRESS_BAR: + if (init_result = (NULL == gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE])) + { + gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE] = + (*fp_gtk_progress_bar_new)(); + /* + * Vertical JProgressBars always go bottom-to-top, + * regardless of the ComponentOrientation. + */ + (*fp_gtk_progress_bar_set_orientation)( + (GtkProgressBar *)gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE], + GTK_PROGRESS_BOTTOM_TO_TOP); + } + result = gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE]; + break; + case RADIO_BUTTON: + if (init_result = (NULL == gtk3_widgets[_GTK_RADIO_BUTTON_TYPE])) + { + gtk3_widgets[_GTK_RADIO_BUTTON_TYPE] = + (*fp_gtk_radio_button_new)(NULL); + } + result = gtk3_widgets[_GTK_RADIO_BUTTON_TYPE]; + break; + case RADIO_BUTTON_MENU_ITEM: + if (init_result = + (NULL == gtk3_widgets[_GTK_RADIO_MENU_ITEM_TYPE])) + { + gtk3_widgets[_GTK_RADIO_MENU_ITEM_TYPE] = + (*fp_gtk_radio_menu_item_new)(NULL); + } + result = gtk3_widgets[_GTK_RADIO_MENU_ITEM_TYPE]; + break; + case SCROLL_PANE: + if (init_result = + (NULL == gtk3_widgets[_GTK_SCROLLED_WINDOW_TYPE])) + { + gtk3_widgets[_GTK_SCROLLED_WINDOW_TYPE] = + (*fp_gtk_scrolled_window_new)(NULL, NULL); + } + result = gtk3_widgets[_GTK_SCROLLED_WINDOW_TYPE]; + break; + case SPINNER: + case SPINNER_ARROW_BUTTON: + case SPINNER_TEXT_FIELD: + if (init_result = (NULL == gtk3_widgets[_GTK_SPIN_BUTTON_TYPE])) + { + result = gtk3_widgets[_GTK_SPIN_BUTTON_TYPE] = + (*fp_gtk_spin_button_new)(NULL, 0, 0); + } + result = gtk3_widgets[_GTK_SPIN_BUTTON_TYPE]; + break; + case TABBED_PANE: + case TABBED_PANE_TAB_AREA: + case TABBED_PANE_CONTENT: + case TABBED_PANE_TAB: + if (init_result = (NULL == gtk3_widgets[_GTK_NOTEBOOK_TYPE])) + { + gtk3_widgets[_GTK_NOTEBOOK_TYPE] = + (*fp_gtk_notebook_new)(NULL); + } + result = gtk3_widgets[_GTK_NOTEBOOK_TYPE]; + break; + case TOGGLE_BUTTON: + if (init_result = (NULL == gtk3_widgets[_GTK_TOGGLE_BUTTON_TYPE])) + { + gtk3_widgets[_GTK_TOGGLE_BUTTON_TYPE] = + (*fp_gtk_toggle_button_new)(NULL); + } + result = gtk3_widgets[_GTK_TOGGLE_BUTTON_TYPE]; + break; + case TOOL_BAR: + case TOOL_BAR_DRAG_WINDOW: + if (init_result = (NULL == gtk3_widgets[_GTK_TOOLBAR_TYPE])) + { + gtk3_widgets[_GTK_TOOLBAR_TYPE] = + (*fp_gtk_toolbar_new)(NULL); + } + result = gtk3_widgets[_GTK_TOOLBAR_TYPE]; + break; + case TOOL_BAR_SEPARATOR: + if (init_result = + (NULL == gtk3_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE])) + { + gtk3_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE] = + (*fp_gtk_separator_tool_item_new)(); + } + result = gtk3_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE]; + break; + case VIEWPORT: + if (init_result = (NULL == gtk3_widgets[_GTK_VIEWPORT_TYPE])) + { + GtkAdjustment *adjustment = create_adjustment(); + gtk3_widgets[_GTK_VIEWPORT_TYPE] = + (*fp_gtk_viewport_new)(adjustment, adjustment); + } + result = gtk3_widgets[_GTK_VIEWPORT_TYPE]; + break; + case VSCROLL_BAR: + case VSCROLL_BAR_BUTTON_UP: + case VSCROLL_BAR_BUTTON_DOWN: + case VSCROLL_BAR_TRACK: + case VSCROLL_BAR_THUMB: + if (init_result = (NULL == gtk3_widgets[_GTK_VSCROLLBAR_TYPE])) + { + gtk3_widgets[_GTK_VSCROLLBAR_TYPE] = + (*fp_gtk_vscrollbar_new)(create_adjustment()); + } + result = gtk3_widgets[_GTK_VSCROLLBAR_TYPE]; + break; + case VSEPARATOR: + if (init_result = (NULL == gtk3_widgets[_GTK_VSEPARATOR_TYPE])) + { + gtk3_widgets[_GTK_VSEPARATOR_TYPE] = + (*fp_gtk_vseparator_new)(); + } + result = gtk3_widgets[_GTK_VSEPARATOR_TYPE]; + break; + case VSLIDER: + case VSLIDER_THUMB: + case VSLIDER_TRACK: + if (init_result = (NULL == gtk3_widgets[_GTK_VSCALE_TYPE])) + { + gtk3_widgets[_GTK_VSCALE_TYPE] = + (*fp_gtk_scale_new)(GTK_ORIENTATION_VERTICAL, NULL); + } + result = gtk3_widgets[_GTK_VSCALE_TYPE]; + /* + * Vertical JSliders start at the bottom, while vertical + * GtkVScale widgets start at the top (by default), so to fix + * this we set the "inverted" flag to get the Swing behavior. + */ + fp_gtk_range_set_inverted((GtkRange*)result, TRUE); + break; + case VSPLIT_PANE_DIVIDER: + if (init_result = (NULL == gtk3_widgets[_GTK_VPANED_TYPE])) + { + gtk3_widgets[_GTK_VPANED_TYPE] = (*fp_gtk_vpaned_new)(); + } + result = gtk3_widgets[_GTK_VPANED_TYPE]; + break; + default: + result = NULL; + break; + } + + if (result != NULL && init_result) + { + if (widget_type == RADIO_BUTTON_MENU_ITEM || + widget_type == CHECK_BOX_MENU_ITEM || + widget_type == MENU_ITEM || + widget_type == MENU || + widget_type == POPUP_MENU_SEPARATOR) + { + GtkWidget *menu = gtk3_get_widget(POPUP_MENU); + (*fp_gtk_menu_shell_append)((GtkMenuShell *)menu, result); + } + else if (widget_type == POPUP_MENU) + { + GtkWidget *menu_bar = gtk3_get_widget(MENU_BAR); + GtkWidget *root_menu = (*fp_gtk_menu_item_new)(); + (*fp_gtk_menu_item_set_submenu)((GtkMenuItem*)root_menu, result); + (*fp_gtk_menu_shell_append)((GtkMenuShell *)menu_bar, root_menu); + } + else if (widget_type == COMBO_BOX_TEXT_FIELD ) + { + GtkWidget* combo = gtk3_get_widget(COMBO_BOX); + + /* + * We add a regular GtkButton/GtkEntry to a GtkComboBoxEntry + * in order to trick engines into thinking it's a real combobox + * arrow button/text field. + */ + + fp_gtk_container_add ((GtkContainer*)(combo), result); + GtkStyleContext* context = fp_gtk_widget_get_style_context (combo); + fp_gtk_style_context_add_class (context, "combobox-entry"); + context = fp_gtk_widget_get_style_context (result); + fp_gtk_style_context_add_class (context, "combobox"); + fp_gtk_style_context_add_class (context, "entry"); + } + else if (widget_type == COMBO_BOX_ARROW_BUTTON ) + { + GtkWidget* combo = gtk3_get_widget(COMBO_BOX); + fp_gtk_widget_set_parent(result, combo); + } + else if (widget_type != TOOL_TIP && + widget_type != INTERNAL_FRAME && + widget_type != OPTION_PANE) + { + (*fp_gtk_container_add)((GtkContainer *)gtk3_fixed, result); + } + (*fp_gtk_widget_realize)(result); + } + return result; +} + +static void gtk3_paint_arrow(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, + GtkArrowType arrow_type, gboolean fill) +{ + gdouble xx, yy, a = G_PI; + int s = width; + gtk3_widget = gtk3_get_arrow(arrow_type, shadow_type); + + switch (widget_type) + { + case SPINNER_ARROW_BUTTON: + s = (int)(0.4 * width + 0.5) + 1; + if (arrow_type == GTK_ARROW_UP) { + a = 0; + } else if (arrow_type == GTK_ARROW_DOWN) { + a = G_PI; + } + break; + + case HSCROLL_BAR_BUTTON_LEFT: + s = (int)(0.5 * MIN(height, width * 2) + 0.5) + 1; + a = 3 * G_PI / 2; + break; + + case HSCROLL_BAR_BUTTON_RIGHT: + s = (int)(0.5 * MIN(height, width * 2) + 0.5) + 1; + a = G_PI / 2; + break; + + case VSCROLL_BAR_BUTTON_UP: + s = (int)(0.5 * MIN(height * 2, width) + 0.5) + 1; + a = 0; + break; + + case VSCROLL_BAR_BUTTON_DOWN: + s = (int)(0.5 * MIN(height * 2, width) + 0.5) + 1; + a = G_PI; + break; + + case COMBO_BOX_ARROW_BUTTON: + s = (int)(0.3 * height + 0.5) + 1; + a = G_PI; + break; + + case TABLE: + s = (int)(0.8 * height + 0.5) + 1; + if (arrow_type == GTK_ARROW_UP) { + a = G_PI; + } else if (arrow_type == GTK_ARROW_DOWN) { + a = 0; + } + break; + + case MENU_ITEM: + if (arrow_type == GTK_ARROW_UP) { + a = G_PI; + } else if (arrow_type == GTK_ARROW_DOWN) { + a = 0; + } else if (arrow_type == GTK_ARROW_RIGHT) { + a = G_PI / 2; + } else if (arrow_type == GTK_ARROW_LEFT) { + a = 3 * G_PI / 2; + } + break; + + default: + if (arrow_type == GTK_ARROW_UP) { + a = G_PI; + } else if (arrow_type == GTK_ARROW_DOWN) { + a = 0; + } else if (arrow_type == GTK_ARROW_RIGHT) { + a = G_PI / 2; + } else if (arrow_type == GTK_ARROW_LEFT) { + a = 3 * G_PI / 2; + } + break; + } + + if (s < width && s < height) { + xx = x + (0.5 * (width - s) + 0.5); + yy = y + (0.5 * (height - s) + 0.5); + } else { + xx = x; + yy = y; + } + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + fp_gtk_style_context_save (context); + + + if (detail != NULL) { + transform_detail_string(detail, context); + } + + GtkStateFlags flags = get_gtk_flags(state_type); + + fp_gtk_style_context_set_state (context, flags); + + (*fp_gtk_render_arrow)(context, cr, a, xx, yy, s); + + fp_gtk_style_context_restore (context); +} + +static void gtk3_paint_box(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, + gint synth_state, GtkTextDirection dir) +{ + gtk3_widget = gtk3_get_widget(widget_type); + + if (widget_type == HSLIDER_TRACK) { + /* + * For horizontal JSliders with right-to-left orientation, we need + * to set the "inverted" flag to match the native GTK behavior where + * the foreground highlight is on the right side of the slider thumb. + * This is needed especially for the ubuntulooks engine, which looks + * exclusively at the "inverted" flag to determine on which side of + * the thumb to paint the highlight... + */ + fp_gtk_range_set_inverted((GtkRange*)gtk3_widget, dir == + GTK_TEXT_DIR_RTL); + + /* + * Note however that other engines like clearlooks will look at both + * the "inverted" field and the text direction to determine how + * the foreground highlight is painted: + * !inverted && ltr --> paint highlight on left side + * !inverted && rtl --> paint highlight on right side + * inverted && ltr --> paint highlight on right side + * inverted && rtl --> paint highlight on left side + * So the only way to reliably get the desired results for horizontal + * JSlider (i.e., highlight on left side for LTR ComponentOrientation + * and highlight on right side for RTL ComponentOrientation) is to + * always override text direction as LTR, and then set the "inverted" + * flag accordingly (as we have done above). + */ + dir = GTK_TEXT_DIR_LTR; + } + + /* + * Some engines (e.g. clearlooks) will paint the shadow of certain + * widgets (e.g. COMBO_BOX_ARROW_BUTTON) differently depending on the + * the text direction. + */ + gtk3_set_direction(gtk3_widget, dir); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + fp_gtk_style_context_save (context); + + transform_detail_string(detail, context); + + GtkStateFlags flags = get_gtk_flags(state_type); + + if (shadow_type == GTK_SHADOW_IN && widget_type != COMBO_BOX_ARROW_BUTTON) { + flags |= GTK_STATE_FLAG_ACTIVE; + } + + if (synth_state & MOUSE_OVER) { + flags |= GTK_STATE_FLAG_PRELIGHT; + } + + if (synth_state & FOCUSED) { + flags |= GTK_STATE_FLAG_FOCUSED; + } + + if (synth_state & DEFAULT) { + fp_gtk_style_context_add_class (context, "default"); + } + + fp_gtk_style_context_set_state (context, flags); + + if (fp_gtk_style_context_has_class(context, "progressbar")) { + fp_gtk_render_activity (context, cr, x, y, width, height); + } else { + fp_gtk_render_background (context, cr, x, y, width, height); + if (shadow_type != GTK_SHADOW_NONE) { + fp_gtk_render_frame(context, cr, x, y, width, height); + } + } + + fp_gtk_style_context_restore (context); + /* + * Reset the text direction to the default value so that we don't + * accidentally affect other operations and widgets. + */ + gtk3_set_direction(gtk3_widget, GTK_TEXT_DIR_LTR); +} + +static void gtk3_paint_box_gap(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, + GtkPositionType gap_side, gint gap_x, gint gap_width) +{ + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + + fp_gtk_style_context_save (context); + + GtkStateFlags flags = get_gtk_flags(state_type); + fp_gtk_style_context_set_state(context, flags); + + if (detail != 0) { + transform_detail_string(detail, context); + } + fp_gtk_render_background(context, cr, x, y, width, height); + + if (shadow_type != GTK_SHADOW_NONE) { + fp_gtk_render_frame_gap(context, cr, x, y, width, height, gap_side, + (gdouble)gap_x, (gdouble)gap_x + gap_width); + } + fp_gtk_style_context_restore (context); +} + +static void gtk3_paint_check(WidgetType widget_type, gint synth_state, + const gchar *detail, gint x, gint y, gint width, gint height) +{ + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + + fp_gtk_style_context_save (context); + + GtkStateFlags flags = get_gtk_state_flags(synth_state); + if (gtk3_version_3_14 && (synth_state & SELECTED)) { + flags = GTK_STATE_FLAG_CHECKED; + } + fp_gtk_style_context_set_state(context, flags); + + fp_gtk_style_context_add_class (context, "check"); + + fp_gtk_render_check (context, cr, x, y, width, height); + + fp_gtk_style_context_restore (context); +} + + +static void gtk3_paint_expander(WidgetType widget_type, GtkStateType state_type, + const gchar *detail, gint x, gint y, gint width, gint height, + GtkExpanderStyle expander_style) +{ + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + + fp_gtk_style_context_save (context); + + GtkStateFlags flags = get_gtk_flags(state_type); + if (expander_style == GTK_EXPANDER_EXPANDED) { + flags |= GTK_STATE_FLAG_ACTIVE; + } + + fp_gtk_style_context_set_state(context, flags); + + if (detail != 0) { + transform_detail_string(detail, context); + } + + fp_gtk_render_expander (context, cr, x + 2, y + 2, width - 4, height - 4); + + fp_gtk_style_context_restore (context); +} + +static void gtk3_paint_extension(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, GtkPositionType gap_side) +{ + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + + fp_gtk_style_context_save (context); + + GtkStateFlags flags = GTK_STATE_FLAG_NORMAL; + + if (state_type == 0) { + flags = GTK_STATE_FLAG_ACTIVE; + } + + fp_gtk_style_context_set_state(context, flags); + + if (detail != 0) { + transform_detail_string(detail, context); + } + switch(gap_side) { + case GTK_POS_LEFT: + fp_gtk_style_context_add_class(context, "right"); + break; + case GTK_POS_RIGHT: + fp_gtk_style_context_add_class(context, "left"); + break; + case GTK_POS_TOP: + fp_gtk_style_context_add_class(context, "bottom"); + break; + case GTK_POS_BOTTOM: + fp_gtk_style_context_add_class(context, "top"); + break; + default: + break; + } + + fp_gtk_render_extension(context, cr, x, y, width, height, gap_side); + + fp_gtk_style_context_restore (context); +} + +static void gtk3_paint_flat_box(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, gboolean has_focus) +{ + if (state_type == GTK_STATE_PRELIGHT && + (widget_type == CHECK_BOX || widget_type == RADIO_BUTTON)) { + return; + } + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + + fp_gtk_style_context_save (context); + + if (detail != 0) { + transform_detail_string(detail, context); + } + + GtkStateFlags flags = get_gtk_flags(state_type); + + if (has_focus) { + flags |= GTK_STATE_FLAG_FOCUSED; + } + + fp_gtk_style_context_set_state (context, flags); + + if (widget_type == COMBO_BOX_TEXT_FIELD) { + width += height /2; + } + + fp_gtk_render_background (context, cr, x, y, width, height); + + fp_gtk_style_context_restore (context); +} + +static void gtk3_paint_focus(WidgetType widget_type, GtkStateType state_type, + const char *detail, gint x, gint y, gint width, gint height) +{ + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + fp_gtk_style_context_save (context); + + transform_detail_string(detail, context); + fp_gtk_render_focus (context, cr, x, y, width, height); + + fp_gtk_style_context_restore (context); + +} + +static void gtk3_paint_handle(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, GtkOrientation orientation) +{ + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + + fp_gtk_style_context_save (context); + + GtkStateFlags flags = get_gtk_flags(state_type); + fp_gtk_style_context_set_state(context, GTK_STATE_FLAG_PRELIGHT); + + if (detail != 0) { + transform_detail_string(detail, context); + fp_gtk_style_context_add_class (context, "handlebox_bin"); + } + + fp_gtk_render_handle(context, cr, x, y, width, height); + fp_gtk_render_background(context, cr, x, y, width, height); + + fp_gtk_style_context_restore (context); +} + +static void gtk3_paint_hline(WidgetType widget_type, GtkStateType state_type, + const gchar *detail, gint x, gint y, gint width, gint height) +{ + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + + fp_gtk_style_context_save (context); + + if (detail != 0) { + transform_detail_string(detail, context); + } + + fp_gtk_render_line(context, cr, x, y, x + width, y); + + fp_gtk_style_context_restore (context); +} + +static void gtk3_paint_vline(WidgetType widget_type, GtkStateType state_type, + const gchar *detail, gint x, gint y, gint width, gint height) +{ + gtk3_widget = gtk3_get_widget(widget_type); + + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + + fp_gtk_style_context_save (context); + + if (detail != 0) { + transform_detail_string(detail, context); + } + + fp_gtk_render_line(context, cr, x, y, x, y + height); + + fp_gtk_style_context_restore (context); +} + +static void gtk3_paint_option(WidgetType widget_type, gint synth_state, + const gchar *detail, gint x, gint y, gint width, gint height) +{ + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + + fp_gtk_style_context_save (context); + + GtkStateFlags flags = get_gtk_state_flags(synth_state); + if (gtk3_version_3_14 && (synth_state & SELECTED)) { + flags = GTK_STATE_FLAG_CHECKED; + } + fp_gtk_style_context_set_state(context, flags); + + if (detail != 0) { + transform_detail_string(detail, context); + } + + fp_gtk_render_option(context, cr, x, y, width, height); + + fp_gtk_style_context_restore (context); +} + +static void gtk3_paint_shadow(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, + gint synth_state, GtkTextDirection dir) +{ + if (shadow_type == GTK_SHADOW_NONE) { + return; + } + gtk3_widget = gtk3_get_widget(widget_type); + + /* + * Some engines (e.g. clearlooks) will paint the shadow of certain + * widgets (e.g. COMBO_BOX_TEXT_FIELD) differently depending on the + * the text direction. + */ + gtk3_set_direction(gtk3_widget, dir); + + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + fp_gtk_style_context_save (context); + + if (detail) { + transform_detail_string(detail, context); + } + + GtkStateFlags flags = get_gtk_flags(state_type); + + if (synth_state & MOUSE_OVER) { + flags |= GTK_STATE_FLAG_PRELIGHT; + } + + if (synth_state & FOCUSED) { + flags |= GTK_STATE_FLAG_FOCUSED; + } + + fp_gtk_style_context_set_state (context, flags); + + if (widget_type == COMBO_BOX_TEXT_FIELD) { + width += height / 2; + } + fp_gtk_render_frame(context, cr, x, y, width, height); + + fp_gtk_style_context_restore (context); + + /* + * Reset the text direction to the default value so that we don't + * accidentally affect other operations and widgets. + */ + gtk3_set_direction(gtk3_widget, GTK_TEXT_DIR_LTR); +} + +static void gtk3_paint_slider(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, GtkOrientation orientation, + gboolean has_focus) +{ + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + + fp_gtk_style_context_save (context); + + if (detail) { + transform_detail_string(detail, context); + } + + GtkStateFlags flags = get_gtk_flags(state_type); + + if (state_type == GTK_STATE_ACTIVE) { + flags |= GTK_STATE_FLAG_PRELIGHT; + } + + if (has_focus) { + flags |= GTK_STATE_FLAG_FOCUSED; + } + + fp_gtk_style_context_set_state (context, flags); + + (*fp_gtk_render_slider)(context, cr, x, y, width, height, orientation); + + fp_gtk_style_context_restore (context); +} + +static void gtk3_paint_background(WidgetType widget_type, + GtkStateType state_type, gint x, gint y, gint width, gint height) { + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + fp_gtk_style_context_save (context); + + GtkStateFlags flags = get_gtk_flags(state_type); + + fp_gtk_style_context_set_state (context, flags); + + fp_gtk_render_background (context, cr, x, y, width, height); + + fp_gtk_style_context_restore (context); +} + +static GdkPixbuf *gtk3_get_stock_icon(gint widget_type, const gchar *stock_id, + GtkIconSize size, GtkTextDirection direction, const char *detail) +{ + int sz; + + switch(size) { + case GTK_ICON_SIZE_MENU: + sz = 16; + break; + case GTK_ICON_SIZE_SMALL_TOOLBAR: + sz = 18; + break; + case GTK_ICON_SIZE_LARGE_TOOLBAR: + sz = 24; + break; + case GTK_ICON_SIZE_BUTTON: + sz = 20; + break; + case GTK_ICON_SIZE_DND: + sz = 32; + break; + case GTK_ICON_SIZE_DIALOG: + sz = 48; + break; + default: + sz = 0; + break; + } + + init_containers(); + gtk3_widget = gtk3_get_widget((widget_type < 0) ? IMAGE : widget_type); + (*fp_gtk_widget_set_direction)(gtk3_widget, direction); + GtkIconTheme *icon_theme = fp_gtk_icon_theme_get_default(); + GdkPixbuf *result = fp_gtk_icon_theme_load_icon(icon_theme, stock_id, sz, + GTK_ICON_LOOKUP_USE_BUILTIN, NULL); + return result; +} + +static jboolean gtk3_get_pixbuf_data(JNIEnv *env, GdkPixbuf* pixbuf, + jmethodID icon_upcall_method, jobject this) { + if (!pixbuf) { + return JNI_FALSE; + } + guchar *pixbuf_data = (*fp_gdk_pixbuf_get_pixels)(pixbuf); + if (pixbuf_data) { + int row_stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf); + int width = (*fp_gdk_pixbuf_get_width)(pixbuf); + int height = (*fp_gdk_pixbuf_get_height)(pixbuf); + int bps = (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf); + int channels = (*fp_gdk_pixbuf_get_n_channels)(pixbuf); + gboolean alpha = (*fp_gdk_pixbuf_get_has_alpha)(pixbuf); + + jbyteArray data = (*env)->NewByteArray(env, (row_stride * height)); + JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); + + (*env)->SetByteArrayRegion(env, data, 0, (row_stride * height), + (jbyte *)pixbuf_data); + (*fp_g_object_unref)(pixbuf); + + /* Call the callback method to create the image on the Java side. */ + (*env)->CallVoidMethod(env, this, icon_upcall_method, data, + width, height, row_stride, bps, channels, alpha); + return JNI_TRUE; + } + return JNI_FALSE; +} + +static jboolean gtk3_get_file_icon_data(JNIEnv *env, const char *filename, + GError **error, jmethodID icon_upcall_method, jobject this) { + GdkPixbuf* pixbuf = fp_gdk_pixbuf_new_from_file(filename, error); + return gtk3_get_pixbuf_data(env, pixbuf, icon_upcall_method, this); +} + +static jboolean gtk3_get_icon_data(JNIEnv *env, gint widget_type, + const gchar *stock_id, GtkIconSize size, + GtkTextDirection direction, const char *detail, + jmethodID icon_upcall_method, jobject this) { + GdkPixbuf* pixbuf = gtk3_get_stock_icon(widget_type, stock_id, size, + direction, detail); + return gtk3_get_pixbuf_data(env, pixbuf, icon_upcall_method, this); +} + +/*************************************************/ +static gint gtk3_get_xthickness(JNIEnv *env, WidgetType widget_type) +{ + init_containers(); + + gtk3_widget = gtk3_get_widget(widget_type); + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + if (context) { + GtkBorder padding; + fp_gtk_style_context_get_padding(context, 0, &padding); + return padding.left + 1; + } + return 0; +} + +static gint gtk3_get_ythickness(JNIEnv *env, WidgetType widget_type) +{ + init_containers(); + + gtk3_widget = gtk3_get_widget(widget_type); + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + if (context) { + GtkBorder padding; + fp_gtk_style_context_get_padding(context, 0, &padding); + return padding.top + 1; + } + return 0; +} + +/*************************************************/ +static guint8 recode_color(gdouble channel) +{ + guint16 result = (guint16)(channel * 65535); + if (result > 65535) { + result = 65535; + } + return (guint8)( result >> 8); +} + +static GtkStateFlags gtk3_get_state_flags(GtkStateType state_type) { + switch (state_type) + { + case GTK_STATE_NORMAL: + return GTK_STATE_FLAG_NORMAL; + case GTK_STATE_ACTIVE: + return GTK_STATE_FLAG_ACTIVE; + case GTK_STATE_PRELIGHT: + return GTK_STATE_FLAG_PRELIGHT; + case GTK_STATE_SELECTED: + return GTK_STATE_FLAG_SELECTED; + case GTK_STATE_INSENSITIVE: + return GTK_STATE_FLAG_INSENSITIVE; + case GTK_STATE_INCONSISTENT: + return GTK_STATE_FLAG_INCONSISTENT; + case GTK_STATE_FOCUSED: + return GTK_STATE_FLAG_FOCUSED; + } + return 0; +} + + +static void rgb_to_hls (gdouble *r, gdouble *g, gdouble *b) { + gdouble min; + gdouble max; + gdouble red; + gdouble green; + gdouble blue; + gdouble h, l, s; + gdouble delta; + + red = *r; + green = *g; + blue = *b; + + if (red > green) + { + if (red > blue) + max = red; + else + max = blue; + + if (green < blue) + min = green; + else + min = blue; + } + else + { + if (green > blue) + max = green; + else + max = blue; + + if (red < blue) + min = red; + else + min = blue; + } + + l = (max + min) / 2; + s = 0; + h = 0; + + if (max != min) + { + if (l <= 0.5) + s = (max - min) / (max + min); + else + s = (max - min) / (2 - max - min); + + delta = max -min; + if (red == max) + h = (green - blue) / delta; + else if (green == max) + h = 2 + (blue - red) / delta; + else if (blue == max) + h = 4 + (red - green) / delta; + + h *= 60; + if (h < 0.0) + h += 360; + } + + *r = h; + *g = l; + *b = s; +} + +static void hls_to_rgb (gdouble *h, gdouble *l, gdouble *s) +{ + gdouble hue; + gdouble lightness; + gdouble saturation; + gdouble m1, m2; + gdouble r, g, b; + + lightness = *l; + saturation = *s; + + if (lightness <= 0.5) + m2 = lightness * (1 + saturation); + else + m2 = lightness + saturation - lightness * saturation; + m1 = 2 * lightness - m2; + + if (saturation == 0) + { + *h = lightness; + *l = lightness; + *s = lightness; + } + else + { + hue = *h + 120; + while (hue > 360) + hue -= 360; + while (hue < 0) + hue += 360; + + if (hue < 60) + r = m1 + (m2 - m1) * hue / 60; + else if (hue < 180) + r = m2; + else if (hue < 240) + r = m1 + (m2 - m1) * (240 - hue) / 60; + else + r = m1; + + hue = *h; + while (hue > 360) + hue -= 360; + while (hue < 0) + hue += 360; + + if (hue < 60) + g = m1 + (m2 - m1) * hue / 60; + else if (hue < 180) + g = m2; + else if (hue < 240) + g = m1 + (m2 - m1) * (240 - hue) / 60; + else + g = m1; + + hue = *h - 120; + while (hue > 360) + hue -= 360; + while (hue < 0) + hue += 360; + + if (hue < 60) + b = m1 + (m2 - m1) * hue / 60; + else if (hue < 180) + b = m2; + else if (hue < 240) + b = m1 + (m2 - m1) * (240 - hue) / 60; + else + b = m1; + + *h = r; + *l = g; + *s = b; + } +} + + + +static void gtk3_style_shade (const GdkRGBA *a, GdkRGBA *b, gdouble k) { + gdouble red = a->red; + gdouble green = a->green; + gdouble blue = a->blue; + + rgb_to_hls (&red, &green, &blue); + + green *= k; + if (green > 1.0) + green = 1.0; + else if (green < 0.0) + green = 0.0; + + blue *= k; + if (blue > 1.0) + blue = 1.0; + else if (blue < 0.0) + blue = 0.0; + + hls_to_rgb (&red, &green, &blue); + + b->red = red; + b->green = green; + b->blue = blue; +} + +static GdkRGBA gtk3_get_color_for_flags(GtkStyleContext* context, + GtkStateFlags flags, ColorType color_type) { + GdkRGBA c, color; + color.alpha = 1; + + switch (color_type) + { + case FOREGROUND: + case TEXT_FOREGROUND: + fp_gtk_style_context_get_color(context, flags, &color); + break; + case BACKGROUND: + case TEXT_BACKGROUND: + fp_gtk_style_context_get_background_color(context, flags, &color); + break; + case LIGHT: + c = gtk3_get_color_for_flags(context, flags, BACKGROUND); + gtk3_style_shade(&c, &color, LIGHTNESS_MULT); + break; + case DARK: + c = gtk3_get_color_for_flags(context, flags, BACKGROUND); + gtk3_style_shade (&c, &color, DARKNESS_MULT); + break; + case MID: + { + GdkRGBA c1 = gtk3_get_color_for_flags(context, flags, LIGHT); + GdkRGBA c2 = gtk3_get_color_for_flags(context, flags, DARK); + color.red = (c1.red + c2.red) / 2; + color.green = (c1.green + c2.green) / 2; + color.blue = (c1.blue + c2.blue) / 2; + } + break; + case FOCUS: + case BLACK: + color.red = 0; + color.green = 0; + color.blue = 0; + break; + case WHITE: + color.red = 1; + color.green = 1; + color.blue = 1; + break; + } + return color; +} + +static gint gtk3_get_color_for_state(JNIEnv *env, WidgetType widget_type, + GtkStateType state_type, ColorType color_type) +{ + + gint result = 0; + + GtkStateFlags flags = gtk3_get_state_flags(state_type); + + init_containers(); + + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context(gtk3_widget); + + if (widget_type == TOOL_TIP) { + fp_gtk_style_context_add_class(context, "tooltip"); + } + if (widget_type == CHECK_BOX_MENU_ITEM + || widget_type == RADIO_BUTTON_MENU_ITEM) { + flags &= GTK_STATE_FLAG_NORMAL | GTK_STATE_FLAG_SELECTED + | GTK_STATE_FLAG_INSENSITIVE | GTK_STATE_FLAG_FOCUSED; + } + + GdkRGBA color = gtk3_get_color_for_flags(context, flags, color_type); + + if (recode_color(color.alpha) == 0) { + color = gtk3_get_color_for_flags( + fp_gtk_widget_get_style_context(gtk3_get_widget(INTERNAL_FRAME)), + 0, BACKGROUND); + } + + result = recode_color(color.alpha) << 24 | recode_color(color.red) << 16 | + recode_color(color.green) << 8 | recode_color(color.blue); + + return result; +} + +/*************************************************/ +static jobject create_Boolean(JNIEnv *env, jboolean boolean_value); +static jobject create_Integer(JNIEnv *env, jint int_value); +static jobject create_Long(JNIEnv *env, jlong long_value); +static jobject create_Float(JNIEnv *env, jfloat float_value); +static jobject create_Double(JNIEnv *env, jdouble double_value); +static jobject create_Character(JNIEnv *env, jchar char_value); +static jobject create_Insets(JNIEnv *env, GtkBorder *border); + +static jobject gtk3_get_class_value(JNIEnv *env, WidgetType widget_type, + const char* key) +{ + init_containers(); + + gtk3_widget = gtk3_get_widget(widget_type); + + GValue value = { 0, { { 0 } } }; + + GParamSpec* param = (*fp_gtk_widget_class_find_style_property)( + ((GTypeInstance*)gtk3_widget)->g_class, key); + if ( param ) + { + (*fp_g_value_init)( &value, param->value_type ); + (*fp_gtk_widget_style_get_property)(gtk3_widget, key, &value); + + if ((*fp_g_type_is_a)( param->value_type, G_TYPE_BOOLEAN )) + { + gboolean val = (*fp_g_value_get_boolean)(&value); + return create_Boolean(env, (jboolean)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_CHAR )) + { + gchar val = (*fp_g_value_get_char)(&value); + return create_Character(env, (jchar)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_UCHAR )) + { + guchar val = (*fp_g_value_get_uchar)(&value); + return create_Character(env, (jchar)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_INT )) + { + gint val = (*fp_g_value_get_int)(&value); + return create_Integer(env, (jint)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_UINT )) + { + guint val = (*fp_g_value_get_uint)(&value); + return create_Integer(env, (jint)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_LONG )) + { + glong val = (*fp_g_value_get_long)(&value); + return create_Long(env, (jlong)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_ULONG )) + { + gulong val = (*fp_g_value_get_ulong)(&value); + return create_Long(env, (jlong)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_INT64 )) + { + gint64 val = (*fp_g_value_get_int64)(&value); + return create_Long(env, (jlong)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_UINT64 )) + { + guint64 val = (*fp_g_value_get_uint64)(&value); + return create_Long(env, (jlong)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_FLOAT )) + { + gfloat val = (*fp_g_value_get_float)(&value); + return create_Float(env, (jfloat)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_DOUBLE )) + { + gdouble val = (*fp_g_value_get_double)(&value); + return create_Double(env, (jdouble)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_ENUM )) + { + gint val = (*fp_g_value_get_enum)(&value); + return create_Integer(env, (jint)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_FLAGS )) + { + guint val = (*fp_g_value_get_flags)(&value); + return create_Integer(env, (jint)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_STRING )) + { + const gchar* val = (*fp_g_value_get_string)(&value); + + /* We suppose that all values come in C locale and + * utf-8 representation of a string is the same as + * the string itself. If this isn't so we should + * use g_convert. + */ + return (*env)->NewStringUTF(env, val); + } + else if ((*fp_g_type_is_a)( param->value_type, GTK_TYPE_BORDER )) + { + GtkBorder *border = (GtkBorder*)(*fp_g_value_get_boxed)(&value); + return border ? create_Insets(env, border) : NULL; + } + + /* TODO: Other types are not supported yet.*/ +/* else if((*fp_g_type_is_a)( param->value_type, G_TYPE_PARAM )) + { + GParamSpec* val = (*fp_g_value_get_param)(&value); + printf( "Param: %p\n", val ); + } + else if((*fp_g_type_is_a)( param->value_type, G_TYPE_BOXED )) + { + gpointer* val = (*fp_g_value_get_boxed)(&value); + printf( "Boxed: %p\n", val ); + } + else if((*fp_g_type_is_a)( param->value_type, G_TYPE_POINTER )) + { + gpointer* val = (*fp_g_value_get_pointer)(&value); + printf( "Pointer: %p\n", val ); + } + else if((*fp_g_type_is_a)( param->value_type, G_TYPE_OBJECT )) + { + GObject* val = (GObject*)(*fp_g_value_get_object)(&value); + printf( "Object: %p\n", val ); + }*/ + } + + return NULL; +} + +static void gtk3_set_range_value(WidgetType widget_type, jdouble value, + jdouble min, jdouble max, jdouble visible) +{ + GtkAdjustment *adj; + + gtk3_widget = gtk3_get_widget(widget_type); + + adj = (*fp_gtk_range_get_adjustment)((GtkRange *)gtk3_widget); + + fp_gtk_adjustment_set_value(adj, value); + fp_gtk_adjustment_set_lower(adj, min); + fp_gtk_adjustment_set_upper(adj, max); + fp_gtk_adjustment_set_page_size(adj, visible); +} + +/*************************************************/ +static jobject create_Object(JNIEnv *env, jmethodID *cid, + const char* class_name, + const char* signature, + jvalue* value) +{ + jclass class; + jobject result; + + class = (*env)->FindClass(env, class_name); + if (class == NULL) + return NULL; /* can't find/load the class, exception thrown */ + + if (*cid == NULL) + { + *cid = (*env)->GetMethodID(env, class, "", signature); + if (*cid == NULL) + { + (*env)->DeleteLocalRef(env, class); + return NULL; /* can't find/get the method, exception thrown */ + } + } + + result = (*env)->NewObjectA(env, class, *cid, value); + + (*env)->DeleteLocalRef(env, class); + return result; +} + +jobject create_Boolean(JNIEnv *env, jboolean boolean_value) +{ + static jmethodID cid = NULL; + jvalue value; + + value.z = boolean_value; + + return create_Object(env, &cid, "java/lang/Boolean", "(Z)V", &value); +} + +jobject create_Integer(JNIEnv *env, jint int_value) +{ + static jmethodID cid = NULL; + jvalue value; + + value.i = int_value; + + return create_Object(env, &cid, "java/lang/Integer", "(I)V", &value); +} + +jobject create_Long(JNIEnv *env, jlong long_value) +{ + static jmethodID cid = NULL; + jvalue value; + + value.j = long_value; + + return create_Object(env, &cid, "java/lang/Long", "(J)V", &value); +} + +jobject create_Float(JNIEnv *env, jfloat float_value) +{ + static jmethodID cid = NULL; + jvalue value; + + value.f = float_value; + + return create_Object(env, &cid, "java/lang/Float", "(F)V", &value); +} + +jobject create_Double(JNIEnv *env, jdouble double_value) +{ + static jmethodID cid = NULL; + jvalue value; + + value.d = double_value; + + return create_Object(env, &cid, "java/lang/Double", "(D)V", &value); +} + +jobject create_Character(JNIEnv *env, jchar char_value) +{ + static jmethodID cid = NULL; + jvalue value; + + value.c = char_value; + + return create_Object(env, &cid, "java/lang/Character", "(C)V", &value); +} + + +jobject create_Insets(JNIEnv *env, GtkBorder *border) +{ + static jmethodID cid = NULL; + jvalue values[4]; + + values[0].i = border->top; + values[1].i = border->left; + values[2].i = border->bottom; + values[3].i = border->right; + + return create_Object(env, &cid, "java/awt/Insets", "(IIII)V", values); +} + +/*********************************************/ +static jstring gtk3_get_pango_font_name(JNIEnv *env, WidgetType widget_type) +{ + init_containers(); + + gtk3_widget = gtk3_get_widget(widget_type); + jstring result = NULL; + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + if (context) + { + PangoFontDescription* fd = fp_gtk_style_context_get_font(context, 0); + gchar* val = (*fp_pango_font_description_to_string)(fd); + result = (*env)->NewStringUTF(env, val); + (*fp_g_free)( val ); + } + + return result; +} + +/***********************************************/ +static jobject get_string_property(JNIEnv *env, GtkSettings* settings, + const gchar* key) { + jobject result = NULL; + gchar* strval = NULL; + + (*fp_g_object_get)(settings, key, &strval, NULL); + result = (*env)->NewStringUTF(env, strval); + (*fp_g_free)(strval); + + return result; +} + +static jobject get_integer_property(JNIEnv *env, GtkSettings* settings, + const gchar* key) { + gint intval = 0; + (*fp_g_object_get)(settings, key, &intval, NULL); + return create_Integer(env, intval); +} + +static jobject get_boolean_property(JNIEnv *env, GtkSettings* settings, + const gchar* key) { + gint intval = 0; + (*fp_g_object_get)(settings, key, &intval, NULL); + return create_Boolean(env, intval); +} + +static jobject gtk3_get_setting(JNIEnv *env, Setting property) +{ + GtkSettings* settings = (*fp_gtk_settings_get_default)(); + + switch (property) + { + case GTK_FONT_NAME: + return get_string_property(env, settings, "gtk-font-name"); + case GTK_ICON_SIZES: + return get_string_property(env, settings, "gtk-icon-sizes"); + case GTK_CURSOR_BLINK: + return get_boolean_property(env, settings, "gtk-cursor-blink"); + case GTK_CURSOR_BLINK_TIME: + return get_integer_property(env, settings, "gtk-cursor-blink-time"); + } + + return NULL; +} + +static void transform_detail_string (const gchar *detail, + GtkStyleContext *context) { + if (!detail) + return; + + if (strcmp (detail, "arrow") == 0) + fp_gtk_style_context_add_class (context, "arrow"); + else if (strcmp (detail, "button") == 0) + fp_gtk_style_context_add_class (context, "button"); + else if (strcmp (detail, "buttondefault") == 0) + { + fp_gtk_style_context_add_class (context, "button"); + fp_gtk_style_context_add_class (context, "default"); + } + else if (strcmp (detail, "calendar") == 0) + fp_gtk_style_context_add_class (context, "calendar"); + else if (strcmp (detail, "cellcheck") == 0) + { + fp_gtk_style_context_add_class (context, "cell"); + fp_gtk_style_context_add_class (context, "check"); + } + else if (strcmp (detail, "cellradio") == 0) + { + fp_gtk_style_context_add_class (context, "cell"); + fp_gtk_style_context_add_class (context, "radio"); + } + else if (strcmp (detail, "checkbutton") == 0) + fp_gtk_style_context_add_class (context, "check"); + else if (strcmp (detail, "check") == 0) + { + fp_gtk_style_context_add_class (context, "check"); + fp_gtk_style_context_add_class (context, "menu"); + } + else if (strcmp (detail, "radiobutton") == 0) + { + fp_gtk_style_context_add_class (context, "radio"); + } + else if (strcmp (detail, "option") == 0) + { + fp_gtk_style_context_add_class (context, "radio"); + fp_gtk_style_context_add_class (context, "menu"); + } + else if (strcmp (detail, "entry") == 0 || + strcmp (detail, "entry_bg") == 0) + fp_gtk_style_context_add_class (context, "entry"); + else if (strcmp (detail, "expander") == 0) + fp_gtk_style_context_add_class (context, "expander"); + else if (strcmp (detail, "tooltip") == 0) + fp_gtk_style_context_add_class (context, "tooltip"); + else if (strcmp (detail, "frame") == 0) + fp_gtk_style_context_add_class (context, "frame"); + else if (strcmp (detail, "scrolled_window") == 0) + fp_gtk_style_context_add_class (context, "scrolled-window"); + else if (strcmp (detail, "viewport") == 0 || + strcmp (detail, "viewportbin") == 0) + fp_gtk_style_context_add_class (context, "viewport"); + else if (strncmp (detail, "trough", 6) == 0) + fp_gtk_style_context_add_class (context, "trough"); + else if (strcmp (detail, "spinbutton") == 0) + fp_gtk_style_context_add_class (context, "spinbutton"); + else if (strcmp (detail, "spinbutton_up") == 0) + { + fp_gtk_style_context_add_class (context, "spinbutton"); + fp_gtk_style_context_add_class (context, "button"); + fp_gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM); + } + else if (strcmp (detail, "spinbutton_down") == 0) + { + fp_gtk_style_context_add_class (context, "spinbutton"); + fp_gtk_style_context_add_class (context, "button"); + fp_gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP); + } + else if ((detail[0] == 'h' || detail[0] == 'v') && + strncmp (&detail[1], "scrollbar_", 9) == 0) + { + fp_gtk_style_context_add_class (context, "button"); + fp_gtk_style_context_add_class (context, "scrollbar"); + } + else if (strcmp (detail, "slider") == 0) + { + fp_gtk_style_context_add_class (context, "slider"); + fp_gtk_style_context_add_class (context, "scrollbar"); + } + else if (strcmp (detail, "vscale") == 0 || + strcmp (detail, "hscale") == 0) + { + fp_gtk_style_context_add_class (context, "slider"); + fp_gtk_style_context_add_class (context, "scale"); + } + else if (strcmp (detail, "menuitem") == 0) + { + fp_gtk_style_context_add_class (context, "menuitem"); + fp_gtk_style_context_add_class (context, "menu"); + } + else if (strcmp (detail, "menu") == 0) + { + fp_gtk_style_context_add_class (context, "popup"); + fp_gtk_style_context_add_class (context, "menu"); + } + else if (strcmp (detail, "accellabel") == 0) + fp_gtk_style_context_add_class (context, "accelerator"); + else if (strcmp (detail, "menubar") == 0) + fp_gtk_style_context_add_class (context, "menubar"); + else if (strcmp (detail, "base") == 0) + fp_gtk_style_context_add_class (context, "background"); + else if (strcmp (detail, "bar") == 0 || + strcmp (detail, "progressbar") == 0) + fp_gtk_style_context_add_class (context, "progressbar"); + else if (strcmp (detail, "toolbar") == 0) + fp_gtk_style_context_add_class (context, "toolbar"); + else if (strcmp (detail, "handlebox_bin") == 0) + fp_gtk_style_context_add_class (context, "dock"); + else if (strcmp (detail, "notebook") == 0) + fp_gtk_style_context_add_class (context, "notebook"); + else if (strcmp (detail, "tab") == 0) + { + fp_gtk_style_context_add_class (context, "notebook"); + fp_gtk_style_context_add_region (context, "tab", 0); + } else if (strcmp (detail, "paned") == 0) { + fp_gtk_style_context_add_class (context, "pane-separator"); + } + else if (fp_g_str_has_prefix (detail, "cell")) + { + GtkRegionFlags row, col; + gboolean ruled = FALSE; + gchar** tokens; + guint i; + + tokens = fp_g_strsplit (detail, "_", -1); + row = col = 0; + i = 0; + + while (tokens[i]) + { + if (strcmp (tokens[i], "even") == 0) + row |= GTK_REGION_EVEN; + else if (strcmp (tokens[i], "odd") == 0) + row |= GTK_REGION_ODD; + else if (strcmp (tokens[i], "start") == 0) + col |= GTK_REGION_FIRST; + else if (strcmp (tokens[i], "end") == 0) + col |= GTK_REGION_LAST; + else if (strcmp (tokens[i], "ruled") == 0) + ruled = TRUE; + else if (strcmp (tokens[i], "sorted") == 0) + col |= GTK_REGION_SORTED; + + i++; + } + + if (!ruled) + row &= ~(GTK_REGION_EVEN | GTK_REGION_ODD); + + fp_gtk_style_context_add_class (context, "cell"); + fp_gtk_style_context_add_region (context, "row", row); + fp_gtk_style_context_add_region (context, "column", col); + + fp_g_strfreev (tokens); + } +} + +static GdkWindow* gtk3_get_window(void *widget) { + return fp_gtk_widget_get_window((GtkWidget*)widget); +} + +static void gtk3_init(GtkApi* gtk) { + gtk->version = GTK_3; + + gtk->show_uri_load = >k3_show_uri_load; + gtk->unload = >k3_unload; + gtk->flush_event_loop = &flush_gtk_event_loop; + gtk->gtk_check_version = fp_gtk_check_version; + gtk->get_setting = >k3_get_setting; + + gtk->paint_arrow = >k3_paint_arrow; + gtk->paint_box = >k3_paint_box; + gtk->paint_box_gap = >k3_paint_box_gap; + gtk->paint_expander = >k3_paint_expander; + gtk->paint_extension = >k3_paint_extension; + gtk->paint_flat_box = >k3_paint_flat_box; + gtk->paint_focus = >k3_paint_focus; + gtk->paint_handle = >k3_paint_handle; + gtk->paint_hline = >k3_paint_hline; + gtk->paint_vline = >k3_paint_vline; + gtk->paint_option = >k3_paint_option; + gtk->paint_shadow = >k3_paint_shadow; + gtk->paint_slider = >k3_paint_slider; + gtk->paint_background = >k3_paint_background; + gtk->paint_check = >k3_paint_check; + gtk->set_range_value = >k3_set_range_value; + + gtk->init_painting = >k3_init_painting; + gtk->copy_image = >k3_copy_image; + + gtk->get_xthickness = >k3_get_xthickness; + gtk->get_ythickness = >k3_get_ythickness; + gtk->get_color_for_state = >k3_get_color_for_state; + gtk->get_class_value = >k3_get_class_value; + + gtk->get_pango_font_name = >k3_get_pango_font_name; + gtk->get_icon_data = >k3_get_icon_data; + gtk->get_file_icon_data = >k3_get_file_icon_data; + gtk->gdk_threads_enter = fp_gdk_threads_enter; + gtk->gdk_threads_leave = fp_gdk_threads_leave; + gtk->gtk_show_uri = fp_gtk_show_uri; + gtk->g_free = fp_g_free; + + gtk->gtk_file_chooser_get_filename = fp_gtk_file_chooser_get_filename; + gtk->gtk_widget_hide = fp_gtk_widget_hide; + gtk->gtk_main_quit = fp_gtk_main_quit; + gtk->gtk_file_chooser_dialog_new = fp_gtk_file_chooser_dialog_new; + gtk->gtk_file_chooser_set_current_folder = + fp_gtk_file_chooser_set_current_folder; + gtk->gtk_file_chooser_set_filename = fp_gtk_file_chooser_set_filename; + gtk->gtk_file_chooser_set_current_name = + fp_gtk_file_chooser_set_current_name; + gtk->gtk_file_filter_add_custom = fp_gtk_file_filter_add_custom; + gtk->gtk_file_chooser_set_filter = fp_gtk_file_chooser_set_filter; + gtk->gtk_file_chooser_get_type = fp_gtk_file_chooser_get_type; + gtk->gtk_file_filter_new = fp_gtk_file_filter_new; + gtk->gtk_file_chooser_set_do_overwrite_confirmation = + fp_gtk_file_chooser_set_do_overwrite_confirmation; + gtk->gtk_file_chooser_set_select_multiple = + fp_gtk_file_chooser_set_select_multiple; + gtk->gtk_file_chooser_get_current_folder = + fp_gtk_file_chooser_get_current_folder; + gtk->gtk_file_chooser_get_filenames = fp_gtk_file_chooser_get_filenames; + gtk->gtk_g_slist_length = fp_gtk_g_slist_length; + gtk->g_signal_connect_data = fp_g_signal_connect_data; + gtk->gtk_widget_show = fp_gtk_widget_show; + gtk->gtk_main = fp_gtk_main; + gtk->gtk_main_level = fp_gtk_main_level; + gtk->g_path_get_dirname = fp_g_path_get_dirname; + gtk->gtk_widget_destroy = fp_gtk_widget_destroy; + gtk->gtk_window_present = fp_gtk_window_present; + gtk->gtk_window_move = fp_gtk_window_move; + gtk->gtk_window_resize = fp_gtk_window_resize; + gtk->get_window = >k3_get_window; + + gtk->g_object_unref = fp_g_object_unref; + gtk->g_list_append = fp_g_list_append; + gtk->g_list_free = fp_g_list_free; + gtk->g_list_free_full = fp_g_list_free_full; +} --- /dev/null 2018-09-04 17:27:28.996000000 +0530 +++ new/src/solaris/native/sun/awt/gtk3_interface.h 2018-09-05 12:09:45.746107999 +0530 @@ -0,0 +1,577 @@ +/* + * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +#ifndef _GTK3_INTERFACE_H +#define _GTK3_INTERFACE_H + +#include +#include +#include +#include "gtk_interface.h" + +#define LIGHTNESS_MULT 1.3 +#define DARKNESS_MULT 0.7 + +#define G_PI 3.1415926535897932384626433832795028841971693993751 + +typedef enum +{ + GTK_STATE_FLAG_NORMAL = 0, + GTK_STATE_FLAG_ACTIVE = 1 << 0, + GTK_STATE_FLAG_PRELIGHT = 1 << 1, + GTK_STATE_FLAG_SELECTED = 1 << 2, + GTK_STATE_FLAG_INSENSITIVE = 1 << 3, + GTK_STATE_FLAG_INCONSISTENT = 1 << 4, + GTK_STATE_FLAG_FOCUSED = 1 << 5, + GTK_STATE_FLAG_BACKDROP = 1 << 6, + GTK_STATE_FLAG_DIR_LTR = 1 << 7, + GTK_STATE_FLAG_DIR_RTL = 1 << 8, + GTK_STATE_FLAG_LINK = 1 << 9, + GTK_STATE_FLAG_VISITED = 1 << 10, + GTK_STATE_FLAG_CHECKED = 1 << 11 +} GtkStateFlags; + +typedef enum { + GTK_JUNCTION_NONE = 0, + GTK_JUNCTION_CORNER_TOPLEFT = 1 << 0, + GTK_JUNCTION_CORNER_TOPRIGHT = 1 << 1, + GTK_JUNCTION_CORNER_BOTTOMLEFT = 1 << 2, + GTK_JUNCTION_CORNER_BOTTOMRIGHT = 1 << 3, + GTK_JUNCTION_TOP = + (GTK_JUNCTION_CORNER_TOPLEFT | GTK_JUNCTION_CORNER_TOPRIGHT), + GTK_JUNCTION_BOTTOM = + (GTK_JUNCTION_CORNER_BOTTOMLEFT | GTK_JUNCTION_CORNER_BOTTOMRIGHT), + GTK_JUNCTION_LEFT = + (GTK_JUNCTION_CORNER_TOPLEFT | GTK_JUNCTION_CORNER_BOTTOMLEFT), + GTK_JUNCTION_RIGHT = + (GTK_JUNCTION_CORNER_TOPRIGHT | GTK_JUNCTION_CORNER_BOTTOMRIGHT) +} GtkJunctionSides; + +typedef enum { + GTK_REGION_EVEN = 1 << 0, + GTK_REGION_ODD = 1 << 1, + GTK_REGION_FIRST = 1 << 2, + GTK_REGION_LAST = 1 << 3, + GTK_REGION_ONLY = 1 << 4, + GTK_REGION_SORTED = 1 << 5 +} GtkRegionFlags; + +typedef enum +{ + GTK_WINDOW_TOPLEVEL, + GTK_WINDOW_POPUP +} GtkWindowType; + +typedef enum +{ + G_PARAM_READABLE = 1 << 0, + G_PARAM_WRITABLE = 1 << 1, + G_PARAM_CONSTRUCT = 1 << 2, + G_PARAM_CONSTRUCT_ONLY = 1 << 3, + G_PARAM_LAX_VALIDATION = 1 << 4, + G_PARAM_STATIC_NAME = 1 << 5 +} GParamFlags; + +typedef enum +{ + GTK_ICON_LOOKUP_NO_SVG = 1 << 0, + GTK_ICON_LOOKUP_FORCE_SVG = 1 << 1, + GTK_ICON_LOOKUP_USE_BUILTIN = 1 << 2, + GTK_ICON_LOOKUP_GENERIC_FALLBACK = 1 << 3, + GTK_ICON_LOOKUP_FORCE_SIZE = 1 << 4 +} GtkIconLookupFlags; + +typedef enum +{ + GTK_UPDATE_CONTINUOUS, + GTK_UPDATE_DISCONTINUOUS, + GTK_UPDATE_DELAYED +} GtkUpdateType; + +typedef enum +{ + GTK_PROGRESS_CONTINUOUS, + GTK_PROGRESS_DISCRETE +} GtkProgressBarStyle; + +typedef enum +{ + GTK_PROGRESS_LEFT_TO_RIGHT, + GTK_PROGRESS_RIGHT_TO_LEFT, + GTK_PROGRESS_BOTTOM_TO_TOP, + GTK_PROGRESS_TOP_TO_BOTTOM +} GtkProgressBarOrientation; + +typedef enum { + CAIRO_FORMAT_INVALID = -1, + CAIRO_FORMAT_ARGB32 = 0, + CAIRO_FORMAT_RGB24 = 1, + CAIRO_FORMAT_A8 = 2, + CAIRO_FORMAT_A1 = 3, + CAIRO_FORMAT_RGB16_565 = 4 +} cairo_format_t; + +/* We define all structure pointers to be void* */ +typedef void GdkPixbuf; +typedef void GMainContext; +typedef void GVfs; + +typedef void GdkColormap; +typedef void GdkDrawable; +typedef void GdkGC; +typedef void GdkPixmap; +typedef void GtkStyleContext; +typedef void GtkFixed; +typedef void GtkMenuItem; +typedef void GtkMenuShell; +typedef void GtkWidgetClass; +typedef void PangoFontDescription; +typedef void GtkSettings; +typedef void GtkStyleProvider; +typedef void cairo_pattern_t; +typedef void cairo_t; +typedef void cairo_surface_t; +typedef void GtkScrolledWindow; +typedef void GtkIconTheme; +typedef void GtkWidget; +typedef void GtkMisc; +typedef void GtkContainer; +typedef void GtkBin; +typedef void GtkAdjustment; +typedef void GtkRange; +typedef void GtkProgressBar; +typedef void GtkProgress; + +/* Some real structures */ +typedef struct +{ + guint32 pixel; + guint16 red; + guint16 green; + guint16 blue; +} GdkColor; + +typedef struct +{ + gdouble red; + gdouble green; + gdouble blue; + gdouble alpha; +} GdkRGBA; + +typedef struct { + gint fd; + gushort events; + gushort revents; +} GPollFD; + +typedef struct { + gint x; + gint y; + gint width; + gint height; +} GdkRectangle; + +typedef struct { + int x, y; + int width, height; +} GtkAllocation; + +typedef struct { + gint width; + gint height; +} GtkRequisition; + +typedef struct { + GtkWidgetClass *g_class; +} GTypeInstance; + +typedef struct { + gint16 left; + gint16 right; + gint16 top; + gint16 bottom; +} GtkBorder; + +typedef struct +{ + GType g_type; + union { + gint v_int; + guint v_uint; + glong v_long; + gulong v_ulong; + gint64 v_int64; + guint64 v_uint64; + gfloat v_float; + gdouble v_double; + gpointer v_pointer; + } data[2]; +} GValue; + +typedef struct { + GTypeInstance g_type_instance; + const gchar *name; + GParamFlags flags; + GType value_type; + GType owner_type; +} GParamSpec; + + +static gchar* (*fp_glib_check_version)(guint required_major, + guint required_minor, guint required_micro); + +/** + * Returns : + * NULL if the GTK+ library is compatible with the given version, or a string + * describing the version mismatch. + */ +static gchar* (*fp_gtk_check_version)(guint required_major, guint + required_minor, guint required_micro); + +static void (*fp_g_free)(gpointer mem); +static void (*fp_g_object_unref)(gpointer object); +static GdkWindow *(*fp_gdk_get_default_root_window) (void); + +static int (*fp_gdk_pixbuf_get_bits_per_sample)(const GdkPixbuf *pixbuf); +static guchar *(*fp_gdk_pixbuf_get_pixels)(const GdkPixbuf *pixbuf); +static gboolean (*fp_gdk_pixbuf_get_has_alpha)(const GdkPixbuf *pixbuf); +static int (*fp_gdk_pixbuf_get_height)(const GdkPixbuf *pixbuf); +static int (*fp_gdk_pixbuf_get_n_channels)(const GdkPixbuf *pixbuf); +static int (*fp_gdk_pixbuf_get_rowstride)(const GdkPixbuf *pixbuf); +static int (*fp_gdk_pixbuf_get_width)(const GdkPixbuf *pixbuf); +static GdkPixbuf *(*fp_gdk_pixbuf_new_from_file)(const char *filename, + GError **error); +static GdkColorspace (*fp_gdk_pixbuf_get_colorspace)(const GdkPixbuf *pixbuf); + +static GdkPixbuf *(*fp_gdk_pixbuf_get_from_drawable)(GdkWindow *window, + int src_x, int src_y, int width, int height); +static GdkPixbuf *(*fp_gdk_pixbuf_scale_simple)(GdkPixbuf *src, + int dest_width, int dest_heigh, GdkInterpType interp_type); + + +static void (*fp_gtk_widget_destroy)(void *widget); +static void (*fp_gtk_window_present)(GtkWindow *window); +static void (*fp_gtk_window_move)(GtkWindow *window, gint x, gint y); +static void (*fp_gtk_window_resize)(GtkWindow *window, gint width, gint height); + +/** + * Function Pointers for GtkFileChooser + */ +static gchar* (*fp_gtk_file_chooser_get_filename)(GtkFileChooser *chooser); +static void (*fp_gtk_widget_hide)(void *widget); +static void (*fp_gtk_main_quit)(void); +static void* (*fp_gtk_file_chooser_dialog_new)(const gchar *title, + GtkWindow *parent, GtkFileChooserAction action, + const gchar *first_button_text, ...); +static gboolean (*fp_gtk_file_chooser_set_current_folder) + (GtkFileChooser *chooser, const gchar *filename); +static gboolean (*fp_gtk_file_chooser_set_filename)(GtkFileChooser *chooser, + const char *filename); +static void (*fp_gtk_file_chooser_set_current_name)(GtkFileChooser *chooser, + const gchar *name); +static void (*fp_gtk_file_filter_add_custom)(GtkFileFilter *filter, + GtkFileFilterFlags needed, GtkFileFilterFunc func, gpointer data, + GDestroyNotify notify); +static void (*fp_gtk_file_chooser_set_filter)(GtkFileChooser *chooser, + GtkFileFilter *filter); +static GType (*fp_gtk_file_chooser_get_type)(void); +static GtkFileFilter* (*fp_gtk_file_filter_new)(void); +static void (*fp_gtk_file_chooser_set_do_overwrite_confirmation)( + GtkFileChooser *chooser, gboolean do_overwrite_confirmation); +static void (*fp_gtk_file_chooser_set_select_multiple)( + GtkFileChooser *chooser, gboolean select_multiple); +static gchar* (*fp_gtk_file_chooser_get_current_folder) + (GtkFileChooser *chooser); +static GSList* (*fp_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser); +static guint (*fp_gtk_g_slist_length)(GSList *list); +static gulong (*fp_g_signal_connect_data)(gpointer instance, + const gchar *detailed_signal, GCallback c_handler, gpointer data, + GClosureNotify destroy_data, GConnectFlags connect_flags); +static void (*fp_gtk_widget_show)(void *widget); +static void (*fp_gtk_main)(void); +static guint (*fp_gtk_main_level)(void); +static gchar* (*fp_g_path_get_dirname) (const gchar *file_name); +static XID (*fp_gdk_x11_drawable_get_xid) (GdkWindow *drawable); + +static GList* (*fp_g_list_append) (GList *list, gpointer data); +static void (*fp_g_list_free) (GList *list); +static void (*fp_g_list_free_full) (GList *list, GDestroyNotify free_func); + +static void (*fp_gdk_threads_enter)(void); +static void (*fp_gdk_threads_leave)(void); + +static gboolean (*fp_gtk_show_uri)(GdkScreen *screen, const gchar *uri, + guint32 timestamp, GError **error); + +// Implementation functions prototypes +static void gtk3_init(GtkApi* gtk); +static GValue* (*fp_g_value_init)(GValue *value, GType g_type); +static gboolean (*fp_g_type_is_a)(GType type, GType is_a_type); +static gboolean (*fp_g_value_get_boolean)(const GValue *value); +static gchar (*fp_g_value_get_char)(const GValue *value); +static guchar (*fp_g_value_get_uchar)(const GValue *value); +static gint (*fp_g_value_get_int)(const GValue *value); +static guint (*fp_g_value_get_uint)(const GValue *value); +static glong (*fp_g_value_get_long)(const GValue *value); +static gulong (*fp_g_value_get_ulong)(const GValue *value); +static gint64 (*fp_g_value_get_int64)(const GValue *value); +static guint64 (*fp_g_value_get_uint64)(const GValue *value); +static gfloat (*fp_g_value_get_float)(const GValue *value); +static gdouble (*fp_g_value_get_double)(const GValue *value); +static const gchar* (*fp_g_value_get_string)(const GValue *value); +static gint (*fp_g_value_get_enum)(const GValue *value); +static guint (*fp_g_value_get_flags)(const GValue *value); +static GParamSpec* (*fp_g_value_get_param)(const GValue *value); +static gpointer* (*fp_g_value_get_boxed)(const GValue *value); +static gpointer* (*fp_g_value_get_pointer)(const GValue *value); +static void (*fp_g_object_get)(gpointer object, + const gchar* fpn, ...); +static void (*fp_g_object_set)(gpointer object, + const gchar *first_property_name, + ...); + +static gboolean (*fp_g_main_context_iteration)(GMainContext *context); +static gboolean (*fp_g_str_has_prefix)(const gchar *str, const gchar *prefix); +static gchar** (*fp_g_strsplit)(const gchar *string, const gchar *delimiter, + gint max_tokens); +static void (*fp_g_strfreev)(gchar **str_array); + + +static cairo_surface_t* (*fp_cairo_image_surface_create)(cairo_format_t format, + int width, int height); +static void (*fp_cairo_surface_destroy)(cairo_surface_t *surface); +static cairo_t* (*fp_cairo_create)(cairo_surface_t *target); +static void (*fp_cairo_destroy)(cairo_t *cr); +static void (*fp_cairo_fill)(cairo_t *cr); +static void (*fp_cairo_surface_flush)(cairo_surface_t *surface); +static void (*fp_cairo_rectangle)(cairo_t *cr, double x, double y, double width, + double height); +static void (*fp_cairo_set_source_rgb)(cairo_t *cr, double red, double green, + double blue); +static void (*fp_cairo_set_source_rgba)(cairo_t *cr, double red, double green, + double blue, double alpha); +static void (*fp_cairo_paint)(cairo_t *cr); +static void (*fp_cairo_clip)(cairo_t *cr); +static unsigned char* (*fp_cairo_image_surface_get_data)( + cairo_surface_t *surface); +static int (*fp_cairo_image_surface_get_stride) (cairo_surface_t *surface); +static GdkPixbuf* (*fp_gdk_pixbuf_get_from_surface)(cairo_surface_t *surface, + gint src_x, gint src_y, gint width, gint height); +static GtkStateType (*fp_gtk_widget_get_state)(GtkWidget *widget); +static void (*fp_gtk_widget_set_state)(GtkWidget *widget, GtkStateType state); +static gboolean (*fp_gtk_widget_is_focus)(GtkWidget *widget); +static void (*fp_gtk_widget_set_allocation)(GtkWidget *widget, + const GtkAllocation *allocation); +static GtkWidget* (*fp_gtk_widget_get_parent)(GtkWidget *widget); +static GtkStyleContext* (*fp_gtk_widget_get_style_context)(GtkWidget *widget); +static void (*fp_gtk_style_context_get_color)(GtkStyleContext *context, + GtkStateFlags state, GdkRGBA *color); +static void (*fp_gtk_style_context_get_background_color) + (GtkStyleContext *context, GtkStateFlags state, GdkRGBA *color); +static void (*fp_gtk_style_context_get)(GtkStyleContext *context, + GtkStateFlags state, ...); +static GtkStateFlags (*fp_gtk_widget_get_state_flags)(GtkWidget* widget); +static void (*fp_gtk_style_context_set_state)(GtkStyleContext* style, + GtkStateFlags flags); +static void (*fp_gtk_style_context_add_class)(GtkStyleContext *context, + const gchar *class_name); +static void (*fp_gtk_style_context_save)(GtkStyleContext *context); +static void (*fp_gtk_style_context_restore)(GtkStyleContext *context); +static void (*fp_gtk_render_check)(GtkStyleContext *context, cairo_t *cr, + gdouble x, gdouble y, gdouble width, gdouble height); +static void (*fp_gtk_render_option)(GtkStyleContext *context, cairo_t *cr, + gdouble x, gdouble y, gdouble width, gdouble height); +static void (*fp_gtk_render_extension)(GtkStyleContext *context, cairo_t *cr, + gdouble x, gdouble y, gdouble width, gdouble height, + GtkPositionType gap_side); +static void (*fp_gtk_render_expander)(GtkStyleContext *context, cairo_t *cr, + gdouble x, gdouble y, gdouble width, gdouble height); +static void (*fp_gtk_render_frame_gap)(GtkStyleContext *context, cairo_t *cr, + gdouble x, gdouble y, gdouble width, gdouble height, + GtkPositionType gap_side, gdouble xy0_gap, + gdouble xy1_gap); +static void (*fp_gtk_render_line)(GtkStyleContext *context, cairo_t *cr, + gdouble x0, gdouble y0, gdouble x1, gdouble y1); +static GdkPixbuf* (*fp_gtk_widget_render_icon_pixbuf)(GtkWidget *widget, + const gchar *stock_id, GtkIconSize size); +static cairo_surface_t* (*fp_gdk_window_create_similar_image_surface)( + GdkWindow *window, cairo_format_t format, int width, + int height, int scale); +static cairo_surface_t* (*fp_gdk_window_create_similar_surface)( + GdkWindow *window, cairo_format_t format, + int width, int height); +static GdkWindow* (*fp_gtk_widget_get_window)(GtkWidget *widget); +static GtkSettings *(*fp_gtk_settings_get_for_screen)(GdkScreen *screen); +static GdkScreen *(*fp_gtk_widget_get_screen)(GtkWidget *widget); +static GtkStyleProvider* (*fp_gtk_css_provider_get_named)(const gchar *name, + const gchar *variant); +static void (*fp_gtk_style_context_add_provider)(GtkStyleContext *context, + GtkStyleProvider *provider, guint priority); +static void (*fp_gtk_render_frame)(GtkStyleContext *context,cairo_t *cr, + gdouble x, gdouble y, gdouble width, gdouble height); +static void (*fp_gtk_render_focus)(GtkStyleContext *context,cairo_t *cr, + gdouble x, gdouble y, gdouble width, gdouble height); +static void (*fp_gtk_render_handle)(GtkStyleContext *context,cairo_t *cr, + gdouble x, gdouble y, gdouble width, gdouble height); +static void (*fp_gtk_style_context_get_property)(GtkStyleContext *context, + const gchar *property, GtkStateFlags state, GValue *value); +static void (*fp_gtk_render_activity)(GtkStyleContext *context, cairo_t *cr, + gdouble x, gdouble y, gdouble width, gdouble height); +static void (*fp_gtk_render_background)(GtkStyleContext *context, cairo_t *cr, + gdouble x, gdouble y, gdouble width, gdouble height); +static gboolean (*fp_gtk_style_context_has_class)(GtkStyleContext *context, + const gchar *class_name); +static void transform_detail_string (const gchar *detail, + GtkStyleContext *context); +void (*fp_gtk_style_context_set_junction_sides)(GtkStyleContext *context, + GtkJunctionSides sides); +void (*fp_gtk_style_context_add_region)(GtkStyleContext *context, + const gchar *region_name, GtkRegionFlags flags); +void (*fp_gtk_render_arrow)(GtkStyleContext *context, cairo_t *cr, + gdouble angle, gdouble x, gdouble y, gdouble size); +void (*fp_gtk_bin_set_child)(GtkBin *bin, GtkWidget *widget); +void (*fp_gtk_scrolled_window_set_shadow_type)( + GtkScrolledWindow *scrolled_window, GtkShadowType type); +static void (*fp_gtk_render_slider)(GtkStyleContext *context, cairo_t *cr, + gdouble x, gdouble y, gdouble width, gdouble height, + GtkOrientation orientation); +static void (*fp_gtk_style_context_get_padding)(GtkStyleContext *self, + GtkStateFlags state, GtkBorder* padding); +static void (*fp_gtk_range_set_inverted)(GtkRange *range, gboolean setting); +static PangoFontDescription* (*fp_gtk_style_context_get_font)( + GtkStyleContext *context, GtkStateFlags state); +static int (*fp_gtk_widget_get_allocated_width)(GtkWidget *widget); +static int (*fp_gtk_widget_get_allocated_height)(GtkWidget *widget); +static GtkIconTheme* (*fp_gtk_icon_theme_get_default)(void); +static GdkPixbuf* (*fp_gtk_icon_theme_load_icon)(GtkIconTheme *icon_theme, + const gchar *icon_name, gint size, + GtkIconLookupFlags flags, GError **error); +static void (*fp_gtk_adjustment_set_lower)(GtkAdjustment *adjustment, + gdouble lower); +static void (*fp_gtk_adjustment_set_page_increment)(GtkAdjustment *adjustment, + gdouble page_increment); +static void (*fp_gtk_adjustment_set_page_size)(GtkAdjustment *adjustment, + gdouble page_size); +static void (*fp_gtk_adjustment_set_step_increment)(GtkAdjustment *adjustment, + gdouble step_increment); +static void (*fp_gtk_adjustment_set_upper)(GtkAdjustment *adjustment, + gdouble upper); +static void (*fp_gtk_adjustment_set_value)(GtkAdjustment *adjustment, + gdouble value); +static GdkGC *(*fp_gdk_gc_new)(GdkDrawable*); +static void (*fp_gdk_rgb_gc_set_foreground)(GdkGC*, guint32); +static void (*fp_gdk_draw_rectangle)(GdkDrawable*, GdkGC*, gboolean, + gint, gint, gint, gint); +static GdkPixbuf *(*fp_gdk_pixbuf_new)(GdkColorspace colorspace, + gboolean has_alpha, int bits_per_sample, int width, int height); +static void (*fp_gdk_drawable_get_size)(GdkDrawable *drawable, + gint* width, gint* height); +static gboolean (*fp_gtk_init_check)(int* argc, char** argv); + +/* Widget creation */ +static GtkWidget* (*fp_gtk_arrow_new)(GtkArrowType arrow_type, + GtkShadowType shadow_type); +static GtkWidget* (*fp_gtk_button_new)(); +static GtkWidget* (*fp_gtk_check_button_new)(); +static GtkWidget* (*fp_gtk_check_menu_item_new)(); +static GtkWidget* (*fp_gtk_color_selection_dialog_new)(const gchar* title); +static GtkWidget* (*fp_gtk_combo_box_new)(); +static GtkWidget* (*fp_gtk_combo_box_entry_new)(); +static GtkWidget* (*fp_gtk_entry_new)(); +static GtkWidget* (*fp_gtk_fixed_new)(); +static GtkWidget* (*fp_gtk_handle_box_new)(); +static GtkWidget* (*fp_gtk_hpaned_new)(); +static GtkWidget* (*fp_gtk_vpaned_new)(); +static GtkWidget* (*fp_gtk_scale_new)(GtkOrientation orientation, + GtkAdjustment* adjustment); +static GtkWidget* (*fp_gtk_hscrollbar_new)(GtkAdjustment* adjustment); +static GtkWidget* (*fp_gtk_vscrollbar_new)(GtkAdjustment* adjustment); +static GtkWidget* (*fp_gtk_hseparator_new)(); +static GtkWidget* (*fp_gtk_vseparator_new)(); +static GtkWidget* (*fp_gtk_image_new)(); +static GtkWidget* (*fp_gtk_label_new)(const gchar* str); +static GtkWidget* (*fp_gtk_menu_new)(); +static GtkWidget* (*fp_gtk_menu_bar_new)(); +static GtkWidget* (*fp_gtk_menu_item_new)(); +static GtkWidget* (*fp_gtk_notebook_new)(); +static GtkWidget* (*fp_gtk_progress_bar_new)(); +static GtkWidget* (*fp_gtk_progress_bar_set_orientation)( + GtkProgressBar *pbar, + GtkProgressBarOrientation orientation); +static GtkWidget* (*fp_gtk_radio_button_new)(GSList *group); +static GtkWidget* (*fp_gtk_radio_menu_item_new)(GSList *group); +static GtkWidget* (*fp_gtk_scrolled_window_new)(GtkAdjustment *hadjustment, + GtkAdjustment *vadjustment); +static GtkWidget* (*fp_gtk_separator_menu_item_new)(); +static GtkWidget* (*fp_gtk_separator_tool_item_new)(); +static GtkWidget* (*fp_gtk_text_view_new)(); +static GtkWidget* (*fp_gtk_toggle_button_new)(); +static GtkWidget* (*fp_gtk_toolbar_new)(); +static GtkWidget* (*fp_gtk_tree_view_new)(); +static GtkWidget* (*fp_gtk_viewport_new)(GtkAdjustment *hadjustment, + GtkAdjustment *vadjustment); +static GtkWidget* (*fp_gtk_window_new)(GtkWindowType type); +static GtkWidget* (*fp_gtk_dialog_new)(); +static GtkWidget* (*fp_gtk_spin_button_new)(GtkAdjustment *adjustment, + gdouble climb_rate, guint digits); +static GtkWidget* (*fp_gtk_frame_new)(const gchar *label); + +/* Other widget operations */ +static GtkAdjustment* (*fp_gtk_adjustment_new)(gdouble value, + gdouble lower, gdouble upper, gdouble step_increment, + gdouble page_increment, gdouble page_size); +static void (*fp_gtk_container_add)(GtkContainer *window, GtkWidget *widget); +static void (*fp_gtk_menu_shell_append)(GtkMenuShell *menu_shell, + GtkWidget *child); +static void (*fp_gtk_menu_item_set_submenu)(GtkMenuItem *menu_item, + GtkWidget *submenu); +static void (*fp_gtk_widget_realize)(GtkWidget *widget); +static GdkPixbuf* (*fp_gtk_widget_render_icon)(GtkWidget *widget, + const gchar *stock_id, GtkIconSize size, const gchar *detail); +static void (*fp_gtk_widget_set_name)(GtkWidget *widget, const gchar *name); +static void (*fp_gtk_widget_set_parent)(GtkWidget *widget, GtkWidget *parent); +static void (*fp_gtk_widget_set_direction)(GtkWidget *widget, + GtkTextDirection direction); +static void (*fp_gtk_widget_style_get)(GtkWidget *widget, + const gchar *first_property_name, ...); +static void (*fp_gtk_widget_class_install_style_property)( + GtkWidgetClass* class, GParamSpec *pspec); +static GParamSpec* (*fp_gtk_widget_class_find_style_property)( + GtkWidgetClass* class, const gchar* property_name); +static void (*fp_gtk_widget_style_get_property)(GtkWidget* widget, + const gchar* property_name, GValue* value); +static char* (*fp_pango_font_description_to_string)( + const PangoFontDescription* fd); +static GtkSettings* (*fp_gtk_settings_get_default)(); +static GtkSettings* (*fp_gtk_widget_get_settings)(GtkWidget *widget); +static GType (*fp_gtk_border_get_type)(); +static void (*fp_gtk_arrow_set)(GtkWidget* arrow, + GtkArrowType arrow_type, + GtkShadowType shadow_type); +static void (*fp_gtk_widget_size_request)(GtkWidget *widget, + GtkRequisition *requisition); +static GtkAdjustment* (*fp_gtk_range_get_adjustment)(GtkRange* range); + +#endif /* !_GTK3_INTERFACE_H */ --- /dev/null 2018-09-04 17:27:28.996000000 +0530 +++ new/src/solaris/native/sun/awt/gtk_interface.c 2018-09-05 12:09:46.498483999 +0530 @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +#include +#include +#include "jvm_md.h" +#include "gtk_interface.h" + +GtkApi* gtk2_load(JNIEnv *env, const char* lib_name); +GtkApi* gtk3_load(JNIEnv *env, const char* lib_name); + +gboolean gtk2_check(const char* lib_name, gboolean load); +gboolean gtk3_check(const char* lib_name, gboolean load); + +GtkApi *gtk; + +typedef struct { + GtkVersion version; + const char* name; + const char* vname; + GtkApi* (*load)(JNIEnv *env, const char* lib_name); + gboolean (*check)(const char* lib_name, gboolean load); +} GtkLib; + +static GtkLib gtk_libs[] = { + { + GTK_2, + JNI_LIB_NAME("gtk-x11-2.0"), + VERSIONED_JNI_LIB_NAME("gtk-x11-2.0", "0"), + >k2_load, + >k2_check + }, + { + GTK_3, + JNI_LIB_NAME("r432rr"), + VERSIONED_JNI_LIB_NAME("gtk-3", "0"), + >k3_load, + >k3_check + } +}; + +static GtkLib** get_libs_order(GtkVersion version) { + static GtkLib** load_order; + static int n_libs = 0; + if (!n_libs) { + n_libs = sizeof(gtk_libs) / sizeof(GtkLib); + load_order = calloc(n_libs + 1, sizeof(GtkLib *)); + } + int i, first = 0; + for (i = 0; i < n_libs; i++) { + load_order[i] = >k_libs[i]; + if (load_order[i]->version == version) { + first = i; + } + } + if (first) { + for (i = first; i > 0; i--) { + load_order[i] = load_order[i - 1]; + } + load_order[0] = >k_libs[first]; + } + return load_order; +} + +static GtkLib* get_loaded() { + GtkLib** libs = get_libs_order(GTK_ANY); + while(!gtk && *libs) { + GtkLib* lib = *libs++; + if (lib->check(lib->vname, /* load = */FALSE)) { + return lib; + } + if (lib->check(lib->name, /* load = */FALSE)) { + return lib; + } + } + return NULL; +} + +gboolean gtk_load(JNIEnv *env, GtkVersion version, gboolean verbose) { + if (gtk == NULL) { + GtkLib* lib = get_loaded(); + if (lib) { + if (verbose) { + fprintf(stderr, "Looking for GTK%d library...\n", + lib->version); + } + gtk = lib->load(env, lib->vname); + if (!gtk) { + gtk = lib->load(env, lib->name); + } + } else { + GtkLib** libs = get_libs_order(version); + while (!gtk && *libs) { + lib = *libs++; + if (version == GTK_ANY || lib->version == version) { + if (verbose) { + fprintf(stderr, "Looking for GTK%d library...\n", + lib->version); + } + gtk = lib->load(env, lib->vname); + if (!gtk) { + gtk = lib->load(env, lib->name); + } + if (verbose && !gtk) { + fprintf(stderr, "Not found.\n"); + } + } + } + } + if (verbose) { + if (gtk) { + fprintf(stderr, "GTK%d library loaded.\n", lib->version); + } else { + fprintf(stderr, "Failed to load GTK library.\n"); + } + } + } + return gtk != NULL; +} + +static gboolean check_version(GtkVersion version) { + GtkLib** libs = get_libs_order(version); + while (*libs) { + GtkLib* lib = *libs++; + if (lib->check(lib->vname, /* load = */TRUE)) { + return TRUE; + } + if (lib->check(lib->name, /* load = */TRUE)) { + return TRUE; + } + } + return FALSE; +} + +gboolean gtk_check_version(GtkVersion version) { + if (gtk || get_loaded()) { + return TRUE; + } + return check_version(version); +} --- /dev/null 2018-09-04 17:27:28.996000000 +0530 +++ new/src/solaris/native/sun/awt/gtk_interface.h 2018-09-05 12:09:47.478973999 +0530 @@ -0,0 +1,567 @@ +/* + * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +#ifndef _GTK_INTERFACE_H +#define _GTK_INTERFACE_H + +#include +#include + +#ifndef FALSE +#define FALSE (0) +#define TRUE (!FALSE) +#endif + +#define GTHREAD_LIB_VERSIONED VERSIONED_JNI_LIB_NAME("gthread-2.0", "0") +#define GTHREAD_LIB JNI_LIB_NAME("gthread-2.0") + +#define _G_TYPE_CIC(ip, gt, ct) ((ct*) ip) +#define G_TYPE_CHECK_INSTANCE_CAST(instance, g_type, c_type) \ + (_G_TYPE_CIC ((instance), (g_type), c_type)) +#define GTK_TYPE_FILE_CHOOSER (fp_gtk_file_chooser_get_type ()) +#define GTK_FILE_CHOOSER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_CHOOSER, GtkFileChooser)) +#define G_CALLBACK(f) ((GCallback) (f)) +#define G_TYPE_FUNDAMENTAL_SHIFT (2) +#define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT)) +#define G_TYPE_OBJECT G_TYPE_MAKE_FUNDAMENTAL (20) +#define GTK_STOCK_CANCEL "gtk-cancel" +#define GTK_STOCK_SAVE "gtk-save" +#define GTK_STOCK_OPEN "gtk-open" +#define GDK_CURRENT_TIME 0L + +#define G_TYPE_INVALID G_TYPE_MAKE_FUNDAMENTAL (0) +#define G_TYPE_NONE G_TYPE_MAKE_FUNDAMENTAL (1) +#define G_TYPE_INTERFACE G_TYPE_MAKE_FUNDAMENTAL (2) +#define G_TYPE_CHAR G_TYPE_MAKE_FUNDAMENTAL (3) +#define G_TYPE_UCHAR G_TYPE_MAKE_FUNDAMENTAL (4) +#define G_TYPE_BOOLEAN G_TYPE_MAKE_FUNDAMENTAL (5) +#define G_TYPE_INT G_TYPE_MAKE_FUNDAMENTAL (6) +#define G_TYPE_UINT G_TYPE_MAKE_FUNDAMENTAL (7) +#define G_TYPE_LONG G_TYPE_MAKE_FUNDAMENTAL (8) +#define G_TYPE_ULONG G_TYPE_MAKE_FUNDAMENTAL (9) +#define G_TYPE_INT64 G_TYPE_MAKE_FUNDAMENTAL (10) +#define G_TYPE_UINT64 G_TYPE_MAKE_FUNDAMENTAL (11) +#define G_TYPE_ENUM G_TYPE_MAKE_FUNDAMENTAL (12) +#define G_TYPE_FLAGS G_TYPE_MAKE_FUNDAMENTAL (13) +#define G_TYPE_FLOAT G_TYPE_MAKE_FUNDAMENTAL (14) +#define G_TYPE_DOUBLE G_TYPE_MAKE_FUNDAMENTAL (15) +#define G_TYPE_STRING G_TYPE_MAKE_FUNDAMENTAL (16) +#define G_TYPE_POINTER G_TYPE_MAKE_FUNDAMENTAL (17) +#define G_TYPE_BOXED G_TYPE_MAKE_FUNDAMENTAL (18) +#define G_TYPE_PARAM G_TYPE_MAKE_FUNDAMENTAL (19) +#define G_TYPE_OBJECT G_TYPE_MAKE_FUNDAMENTAL (20) + +#define GTK_TYPE_BORDER ((*fp_gtk_border_get_type)()) + +#define G_TYPE_FUNDAMENTAL_SHIFT (2) +#define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT)) + +#ifndef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#define CONV_BUFFER_SIZE 128 +#define NO_SYMBOL_EXCEPTION 1 + +/* basic types */ +typedef char gchar; +typedef short gshort; +typedef int gint; +typedef long glong; +typedef float gfloat; +typedef double gdouble; +typedef void* gpointer; +typedef gint gboolean; +typedef signed char gint8; +typedef signed short gint16; +typedef signed int gint32; +typedef unsigned char guchar; +typedef unsigned char guint8; +typedef unsigned short gushort; +typedef unsigned short guint16; +typedef unsigned int guint; +typedef unsigned int guint32; +typedef unsigned int gsize; +typedef unsigned long gulong; +typedef signed long long gint64; +typedef unsigned long long guint64; +typedef gulong GType; + +typedef struct _GList GList; +struct _GList +{ + gpointer data; + GList *next; + GList *prev; +}; + +typedef struct _GSList GSList; +struct _GSList { + gpointer data; + GSList *next; +}; + +typedef enum { + BUTTON, /* GtkButton */ + CHECK_BOX, /* GtkCheckButton */ + CHECK_BOX_MENU_ITEM, /* GtkCheckMenuItem */ + COLOR_CHOOSER, /* GtkColorSelectionDialog */ + COMBO_BOX, /* GtkComboBox */ + COMBO_BOX_ARROW_BUTTON, /* GtkComboBoxEntry */ + COMBO_BOX_TEXT_FIELD, /* GtkComboBoxEntry */ + DESKTOP_ICON, /* GtkLabel */ + DESKTOP_PANE, /* GtkContainer */ + EDITOR_PANE, /* GtkTextView */ + FORMATTED_TEXT_FIELD, /* GtkEntry */ + HANDLE_BOX, /* GtkHandleBox */ + HPROGRESS_BAR, /* GtkProgressBar */ + HSCROLL_BAR, /* GtkHScrollbar */ + HSCROLL_BAR_BUTTON_LEFT, /* GtkHScrollbar */ + HSCROLL_BAR_BUTTON_RIGHT, /* GtkHScrollbar */ + HSCROLL_BAR_TRACK, /* GtkHScrollbar */ + HSCROLL_BAR_THUMB, /* GtkHScrollbar */ + HSEPARATOR, /* GtkHSeparator */ + HSLIDER, /* GtkHScale */ + HSLIDER_TRACK, /* GtkHScale */ + HSLIDER_THUMB, /* GtkHScale */ + HSPLIT_PANE_DIVIDER, /* GtkHPaned */ + INTERNAL_FRAME, /* GtkWindow */ + INTERNAL_FRAME_TITLE_PANE, /* GtkLabel */ + IMAGE, /* GtkImage */ + LABEL, /* GtkLabel */ + LIST, /* GtkTreeView */ + MENU, /* GtkMenu */ + MENU_BAR, /* GtkMenuBar */ + MENU_ITEM, /* GtkMenuItem */ + MENU_ITEM_ACCELERATOR, /* GtkLabel */ + OPTION_PANE, /* GtkMessageDialog */ + PANEL, /* GtkContainer */ + PASSWORD_FIELD, /* GtkEntry */ + POPUP_MENU, /* GtkMenu */ + POPUP_MENU_SEPARATOR, /* GtkSeparatorMenuItem */ + RADIO_BUTTON, /* GtkRadioButton */ + RADIO_BUTTON_MENU_ITEM, /* GtkRadioMenuItem */ + ROOT_PANE, /* GtkContainer */ + SCROLL_PANE, /* GtkScrolledWindow */ + SPINNER, /* GtkSpinButton */ + SPINNER_ARROW_BUTTON, /* GtkSpinButton */ + SPINNER_TEXT_FIELD, /* GtkSpinButton */ + SPLIT_PANE, /* GtkPaned */ + TABBED_PANE, /* GtkNotebook */ + TABBED_PANE_TAB_AREA, /* GtkNotebook */ + TABBED_PANE_CONTENT, /* GtkNotebook */ + TABBED_PANE_TAB, /* GtkNotebook */ + TABLE, /* GtkTreeView */ + TABLE_HEADER, /* GtkButton */ + TEXT_AREA, /* GtkTextView */ + TEXT_FIELD, /* GtkEntry */ + TEXT_PANE, /* GtkTextView */ + TITLED_BORDER, /* GtkFrame */ + TOGGLE_BUTTON, /* GtkToggleButton */ + TOOL_BAR, /* GtkToolbar */ + TOOL_BAR_DRAG_WINDOW, /* GtkToolbar */ + TOOL_BAR_SEPARATOR, /* GtkSeparatorToolItem */ + TOOL_TIP, /* GtkWindow */ + TREE, /* GtkTreeView */ + TREE_CELL, /* GtkTreeView */ + VIEWPORT, /* GtkViewport */ + VPROGRESS_BAR, /* GtkProgressBar */ + VSCROLL_BAR, /* GtkVScrollbar */ + VSCROLL_BAR_BUTTON_UP, /* GtkVScrollbar */ + VSCROLL_BAR_BUTTON_DOWN, /* GtkVScrollbar */ + VSCROLL_BAR_TRACK, /* GtkVScrollbar */ + VSCROLL_BAR_THUMB, /* GtkVScrollbar */ + VSEPARATOR, /* GtkVSeparator */ + VSLIDER, /* GtkVScale */ + VSLIDER_TRACK, /* GtkVScale */ + VSLIDER_THUMB, /* GtkVScale */ + VSPLIT_PANE_DIVIDER, /* GtkVPaned */ + WIDGET_TYPE_SIZE +} WidgetType; + +typedef enum +{ + _GTK_ARROW_TYPE, + _GTK_BUTTON_TYPE, + _GTK_CHECK_BUTTON_TYPE, + _GTK_CHECK_MENU_ITEM_TYPE, + _GTK_COLOR_SELECTION_DIALOG_TYPE, + _GTK_COMBO_BOX_TYPE, + _GTK_COMBO_BOX_ARROW_BUTTON_TYPE, + _GTK_COMBO_BOX_TEXT_FIELD_TYPE, + _GTK_CONTAINER_TYPE, + _GTK_ENTRY_TYPE, + _GTK_FRAME_TYPE, + _GTK_HANDLE_BOX_TYPE, + _GTK_HPANED_TYPE, + _GTK_HPROGRESS_BAR_TYPE, + _GTK_HSCALE_TYPE, + _GTK_HSCROLLBAR_TYPE, + _GTK_HSEPARATOR_TYPE, + _GTK_IMAGE_TYPE, + _GTK_MENU_TYPE, + _GTK_MENU_BAR_TYPE, + _GTK_MENU_ITEM_TYPE, + _GTK_NOTEBOOK_TYPE, + _GTK_LABEL_TYPE, + _GTK_RADIO_BUTTON_TYPE, + _GTK_RADIO_MENU_ITEM_TYPE, + _GTK_SCROLLED_WINDOW_TYPE, + _GTK_SEPARATOR_MENU_ITEM_TYPE, + _GTK_SEPARATOR_TOOL_ITEM_TYPE, + _GTK_SPIN_BUTTON_TYPE, + _GTK_TEXT_VIEW_TYPE, + _GTK_TOGGLE_BUTTON_TYPE, + _GTK_TOOLBAR_TYPE, + _GTK_TOOLTIP_TYPE, + _GTK_TREE_VIEW_TYPE, + _GTK_VIEWPORT_TYPE, + _GTK_VPANED_TYPE, + _GTK_VPROGRESS_BAR_TYPE, + _GTK_VSCALE_TYPE, + _GTK_VSCROLLBAR_TYPE, + _GTK_VSEPARATOR_TYPE, + _GTK_WINDOW_TYPE, + _GTK_DIALOG_TYPE, + _GTK_WIDGET_TYPE_SIZE +} GtkWidgetType; + +typedef enum +{ + GTK_STATE_NORMAL, + GTK_STATE_ACTIVE, + GTK_STATE_PRELIGHT, + GTK_STATE_SELECTED, + GTK_STATE_INSENSITIVE, + GTK_STATE_INCONSISTENT, + GTK_STATE_FOCUSED +} GtkStateType; + +typedef enum +{ + GTK_SHADOW_NONE, + GTK_SHADOW_IN, + GTK_SHADOW_OUT, + GTK_SHADOW_ETCHED_IN, + GTK_SHADOW_ETCHED_OUT +} GtkShadowType; + +typedef enum +{ + GTK_EXPANDER_COLLAPSED, + GTK_EXPANDER_SEMI_COLLAPSED, + GTK_EXPANDER_SEMI_EXPANDED, + GTK_EXPANDER_EXPANDED +} GtkExpanderStyle; + +typedef enum +{ + GTK_ICON_SIZE_INVALID, + GTK_ICON_SIZE_MENU, + GTK_ICON_SIZE_SMALL_TOOLBAR, + GTK_ICON_SIZE_LARGE_TOOLBAR, + GTK_ICON_SIZE_BUTTON, + GTK_ICON_SIZE_DND, + GTK_ICON_SIZE_DIALOG +} GtkIconSize; + +typedef enum +{ + GTK_ORIENTATION_HORIZONTAL, + GTK_ORIENTATION_VERTICAL +} GtkOrientation; + +typedef enum +{ + FOREGROUND, + BACKGROUND, + TEXT_FOREGROUND, + TEXT_BACKGROUND, + FOCUS, + LIGHT, + DARK, + MID, + BLACK, + WHITE +} ColorType; + +typedef enum +{ + GTK_FONT_NAME, + GTK_ICON_SIZES, + GTK_CURSOR_BLINK, + GTK_CURSOR_BLINK_TIME +} Setting; + +typedef enum +{ + GTK_ARROW_UP, + GTK_ARROW_DOWN, + GTK_ARROW_LEFT, + GTK_ARROW_RIGHT, + GTK_ARROW_NONE +} GtkArrowType; + +typedef enum +{ + GTK_TEXT_DIR_NONE, + GTK_TEXT_DIR_LTR, + GTK_TEXT_DIR_RTL +} GtkTextDirection; + +typedef enum +{ + GTK_POS_LEFT, + GTK_POS_RIGHT, + GTK_POS_TOP, + GTK_POS_BOTTOM +} GtkPositionType; + +/* SynthConstants */ +static const gint ENABLED = 1 << 0; +static const gint MOUSE_OVER = 1 << 1; +static const gint PRESSED = 1 << 2; +static const gint DISABLED = 1 << 3; +static const gint FOCUSED = 1 << 8; +static const gint SELECTED = 1 << 9; +static const gint DEFAULT = 1 << 10; + +typedef enum +{ + GTK_ANY, + GTK_1, + GTK_2, + GTK_3 +} GtkVersion; + +//------------------------------ + + + +typedef enum { + GTK_RESPONSE_NONE = -1, + GTK_RESPONSE_REJECT = -2, + GTK_RESPONSE_ACCEPT = -3, + GTK_RESPONSE_DELETE_EVENT = -4, + GTK_RESPONSE_OK = -5, + GTK_RESPONSE_CANCEL = -6, + GTK_RESPONSE_CLOSE = -7, + GTK_RESPONSE_YES = -8, + GTK_RESPONSE_NO = -9, + GTK_RESPONSE_APPLY = -10, + GTK_RESPONSE_HELP = -11 +} GtkResponseType; + +typedef enum { + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, + GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER +} GtkFileChooserAction; + +typedef enum { + GTK_FILE_FILTER_FILENAME = 1 << 0, + GTK_FILE_FILTER_URI = 1 << 1, + GTK_FILE_FILTER_DISPLAY_NAME = 1 << 2, + GTK_FILE_FILTER_MIME_TYPE = 1 << 3 +} GtkFileFilterFlags; + +typedef enum { + GDK_COLORSPACE_RGB +} GdkColorspace; + +typedef enum { + GDK_INTERP_NEAREST, + GDK_INTERP_TILES, + GDK_INTERP_BILINEAR, + GDK_INTERP_HYPER +} GdkInterpType; + +typedef enum { + G_CONNECT_AFTER = 1 << 0, G_CONNECT_SWAPPED = 1 << 1 +} GConnectFlags; +//------------------------------ + + +typedef void GError; +typedef void GdkScreen; +typedef void GtkWindow; +typedef void GdkWindow; +typedef void GClosure; +typedef void GtkFileChooser; +typedef void GtkFileFilter; +typedef struct { + GtkFileFilterFlags contains; + const gchar *filename; + const gchar *uri; + const gchar *display_name; + const gchar *mime_type; +} GtkFileFilterInfo; +typedef gboolean (*GtkFileFilterFunc)(const GtkFileFilterInfo *filter_info, + gpointer data); +typedef void (*GClosureNotify)(gpointer data, GClosure *closure); +typedef void (*GDestroyNotify)(gpointer data); +typedef void (*GCallback)(void); + + +typedef struct GtkApi { + int version; + gboolean (*show_uri_load)(JNIEnv *env); + gboolean (*unload)(); + void (*flush_event_loop)(); + gchar* (*gtk_check_version)(guint required_major, guint required_minor, + guint required_micro); + jobject (*get_setting)(JNIEnv *env, Setting property); + + void (*paint_arrow)(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, + GtkArrowType arrow_type, gboolean fill); + void (*paint_box)(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, + gint synth_state, GtkTextDirection dir); + void (*paint_box_gap)(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, + GtkPositionType gap_side, gint gap_x, gint gap_width); + void (*paint_expander)(WidgetType widget_type, GtkStateType state_type, + const gchar *detail, gint x, gint y, gint width, gint height, + GtkExpanderStyle expander_style); + void (*paint_extension)(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, GtkPositionType gap_side); + void (*paint_flat_box)(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, gboolean has_focus); + void (*paint_focus)(WidgetType widget_type, GtkStateType state_type, + const char *detail, gint x, gint y, gint width, gint height); + void (*paint_handle)(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, GtkOrientation orientation); + void (*paint_hline)(WidgetType widget_type, GtkStateType state_type, + const gchar *detail, gint x, gint y, gint width, gint height); + void (*paint_vline)(WidgetType widget_type, GtkStateType state_type, + const gchar *detail, gint x, gint y, gint width, gint height); + void (*paint_option)(WidgetType widget_type, gint synth_state, + const gchar *detail, gint x, gint y, gint width, gint height); + void (*paint_shadow)(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, + gint synth_state, GtkTextDirection dir); + void (*paint_slider)(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, GtkOrientation orientation, + gboolean has_focus); + void (*paint_background)(WidgetType widget_type, GtkStateType state_type, + gint x, gint y, gint width, gint height); + void (*paint_check)(WidgetType widget_type, gint synth_state, + const gchar *detail, gint x, gint y, gint width, gint height); + void (*set_range_value)(WidgetType widget_type, jdouble value, + jdouble min, jdouble max, jdouble visible); + + void (*init_painting)(JNIEnv *env, gint w, gint h); + gint (*copy_image)(gint *dest, gint width, gint height); + + gint (*get_xthickness)(JNIEnv *env, WidgetType widget_type); + gint (*get_ythickness)(JNIEnv *env, WidgetType widget_type); + gint (*get_color_for_state)(JNIEnv *env, WidgetType widget_type, + GtkStateType state_type, ColorType color_type); + jobject (*get_class_value)(JNIEnv *env, WidgetType widget_type, + const char* key); + + jstring (*get_pango_font_name)(JNIEnv *env, WidgetType widget_type); + jboolean (*get_icon_data)(JNIEnv *env, gint widget_type, + const gchar *stock_id, GtkIconSize size, + GtkTextDirection direction, const char *detail, + jmethodID icon_upcall_method, jobject this); + jboolean (*get_file_icon_data)(JNIEnv *env, const char *filename, + GError **error, jmethodID icon_upcall_method, jobject this); + void (*gdk_threads_enter)(void); + void (*gdk_threads_leave)(void); + gboolean (*gtk_show_uri)(GdkScreen *screen, const gchar *uri, + guint32 timestamp, GError **error); + void (*g_free)(gpointer mem); + + + gchar* (*gtk_file_chooser_get_filename)(GtkFileChooser *chooser); + void (*gtk_widget_hide)(void* widget); + void (*gtk_main_quit)(void); + void* (*gtk_file_chooser_dialog_new)(const gchar *title, + GtkWindow *parent, GtkFileChooserAction action, + const gchar *first_button_text, ...); + gboolean (*gtk_file_chooser_set_current_folder)(GtkFileChooser *chooser, + const gchar *filename); + gboolean (*gtk_file_chooser_set_filename)(GtkFileChooser *chooser, + const char *filename); + void (*gtk_file_chooser_set_current_name)(GtkFileChooser *chooser, + const gchar *name); + void (*gtk_file_filter_add_custom)(GtkFileFilter *filter, + GtkFileFilterFlags needed, GtkFileFilterFunc func, gpointer data, + GDestroyNotify notify); + void (*gtk_file_chooser_set_filter)(GtkFileChooser *chooser, + GtkFileFilter *filter); + GType (*gtk_file_chooser_get_type)(void); + GtkFileFilter* (*gtk_file_filter_new)(void); + void (*gtk_file_chooser_set_do_overwrite_confirmation)( + GtkFileChooser *chooser, gboolean do_overwrite_confirmation); + void (*gtk_file_chooser_set_select_multiple)( + GtkFileChooser *chooser, gboolean select_multiple); + gchar* (*gtk_file_chooser_get_current_folder)(GtkFileChooser *chooser); + GSList* (*gtk_file_chooser_get_filenames)(GtkFileChooser *chooser); + guint (*gtk_g_slist_length)(GSList *list); + gulong (*g_signal_connect_data)(gpointer instance, + const gchar *detailed_signal, GCallback c_handler, gpointer data, + GClosureNotify destroy_data, GConnectFlags connect_flags); + void (*gtk_widget_show)(void *widget); + void (*gtk_main)(void); + guint (*gtk_main_level)(void); + gchar* (*g_path_get_dirname) (const gchar *file_name); + XID (*gdk_x11_drawable_get_xid) (void *drawable); + void (*gtk_widget_destroy)(void *widget); + void (*gtk_window_present)(void *window); + void (*gtk_window_move)(void *window, gint x, gint y); + void (*gtk_window_resize)(void *window, gint width, gint height); + GdkWindow *(*get_window)(void *widget); + + void (*g_object_unref)(gpointer object); + GList* (*g_list_append) (GList *list, gpointer data); + void (*g_list_free) (GList *list); + void (*g_list_free_full) (GList *list, GDestroyNotify free_func); +} GtkApi; + +gboolean gtk_load(JNIEnv *env, GtkVersion version, gboolean verbose); +gboolean gtk_check_version(GtkVersion version); + +typedef struct _GThreadFunctions GThreadFunctions; +static gboolean (*fp_g_thread_get_initialized)(void); +static void (*fp_g_thread_init)(GThreadFunctions *vtable); +static void (*fp_gdk_threads_init)(void); +static void (*fp_gdk_threads_enter)(void); +static void (*fp_gdk_threads_leave)(void); + +extern GtkApi* gtk; + +#endif /* !_GTK_INTERFACE_H */ --- /dev/null 2018-09-04 17:27:28.996000000 +0530 +++ new/test/java/awt/Desktop/DesktopGtkLoadTest/DesktopGtkLoadTest.java 2018-09-05 12:09:48.535501999 +0530 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8157827 + * @summary AWT_Desktop/Automated/Exceptions/BasicTest loads incorrect GTK + * version when jdk.gtk.version=3 + * @requires (os.family == "linux") + * @run main DesktopGtkLoadTest + */ + + +import java.awt.*; +import java.io.*; + +public class DesktopGtkLoadTest { + public static class RunDesktop { + public static void main(String[] args) { + Desktop.getDesktop(); + } + } + + public static void main(String[] args) throws Exception { + Process p = Runtime.getRuntime().exec(System.getProperty("java.home") + + "/bin/java -Djdk.gtk.version=3 -Djdk.gtk.verbose=true " + + "-cp " + System.getProperty("java.class.path", ".") + + " DesktopGtkLoadTest$RunDesktop"); + p.waitFor(); + try (BufferedReader br = new BufferedReader( + new InputStreamReader(p.getErrorStream()))) { + String line; + while ((line = br.readLine()) != null) { + System.out.println(line); + if (line.contains("Looking for GTK2 library")) { + break; + } + if (line.contains("Looking for GTK3 library")) { + return; + } + } + throw new RuntimeException("Wrong GTK library version: \n" + line); + } + + } +} + --- /dev/null 2018-09-04 17:27:28.996000000 +0530 +++ new/test/java/awt/Gtk/GtkVersionTest/GtkVersionTest.java 2018-09-05 12:09:49.552010000 +0530 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8156121 + * @summary "Fail forward" fails for GTK3 if no GTK2 available + * @modules java.desktop/sun.awt + * @requires (os.family == "linux") + * @run main GtkVersionTest + */ + +import sun.awt.UNIXToolkit; + +import java.awt.*; +import java.io.*; + +public class GtkVersionTest { + public static class LoadGtk { + public static void main(String[] args) { + ((UNIXToolkit)Toolkit.getDefaultToolkit()).loadGTK(); + } + } + + public static void main(String[] args) throws Exception { + test(null, "2"); + test("2", "2"); + test("2.2", "2"); + test("3", "3"); + } + + private static void test(String version, String expect) throws Exception { + System.out.println( "Test " + + (version == null ? "no" : " GTK" + version) + " preference."); + System.out.println("java home "+System.getProperty("java.home")); + Process p = Runtime.getRuntime().exec(System.getProperty("java.home") + + "/bin/java " + + (version == null ? "" : "-Djdk.gtk.version=" + version) + + " -Djdk.gtk.verbose=true " + + "-cp " + System.getProperty("java.class.path", ".") + + " GtkVersionTest$LoadGtk"); + p.waitFor(); + + try (BufferedReader br = new BufferedReader( + new InputStreamReader(p.getErrorStream()))) { + String line; + while ((line = br.readLine()) != null) { + System.out.println(line); + if (line.contains("Looking for GTK" + expect + " library")) { + return; + } else if (line.contains("Looking for GTK")) { + break; + } + } + throw new RuntimeException("Wrong GTK library version: expected: " + expect + " actual: " + line + " version: " + version); + } + } + +} --- /dev/null 2018-09-04 17:27:28.996000000 +0530 +++ new/test/javax/swing/LookAndFeel/8145547/DemandGTK.java 2018-09-05 12:09:50.468468000 +0530 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @summary Tests that GTK LaF is supported on solaris + regardless of jdk.gtk.version flag values. + @bug 8156121 + @requires (os.name == "linux" | os.name == "solaris") + @run main/othervm -Djdk.gtk.version=2 DemandGTK + @run main/othervm -Djdk.gtk.version=3 DemandGTK +*/ + +import javax.swing.JFrame; +import javax.swing.UIManager; +import javax.swing.SwingUtilities; +import java.awt.Robot; + +public class DemandGTK { + + static JFrame frame; + public static void createAndShow() { + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); + } catch(Exception cnf) { + cnf.printStackTrace(); + throw new RuntimeException("GTK LaF must be supported"); + } + frame = new JFrame("JFrame"); + frame.setSize(200, 200); + + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + } + + /** + * @param args the command line arguments + */ + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(DemandGTK::createAndShow); + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(1000); + SwingUtilities.invokeAndWait( () -> { + frame.setVisible(false); + frame.dispose(); + }); + + } +} --- /dev/null 2018-09-04 17:27:28.996000000 +0530 +++ new/test/javax/swing/LookAndFeel/8145547/DemandGTK2.sh 2018-09-05 12:09:51.440954000 +0530 @@ -0,0 +1,87 @@ +#!/bin/ksh -p + +# +# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# @test +# @summary Try to force GTK2. We must bail out to GTK3 (if any) if no 2 available. +# +# @compile ProvokeGTK.java +# @requires os.family == "linux" +# @run shell/timeout=400 DemandGTK2.sh + +# +# Note that we depend on +# strace in the PATH +# /sbin/ldconfig (which may be not in PATH) +# It is true for OEL 7 and Ubuntu 14, 16 +# but may fail in future. Save tomorrow for tomorrow. +# +# Read DemandGTK2.txt how to prepare GTK2-less machine. +# + +which strace +if [ $? -ne 0 ] +then + echo "Please provide strace: \"which strace\" failed." + exit 1 +fi + +HAVE_2=`/sbin/ldconfig -v 2>/dev/null | grep libgtk-x11-2 | wc -l` +HAVE_3=`/sbin/ldconfig -v 2>/dev/null | grep libgtk-3.so | wc -l` + + +if [ "${HAVE_2}" = "0" ] +then + + if [ "${HAVE_3}" = "0" ] + then + echo "Neither GTK2 nor GTK3 found: system misconfiguration. Exit." + exit 1 + fi + echo "No GTK 2 library found: we should bail out to 3" + strace -o strace.log -fe open ${TESTJAVA}/bin/java -cp ${TESTCLASSPATH} -Djdk.gtk.version=2 ProvokeGTK + EXECRES=$? + grep 'libgtk-3.*=\ *[0-9]*$' strace.log > logg +else + echo "There is GTK 2 library: we should use it" + strace -o strace.log -fe open ${TESTJAVA}/bin/java -cp ${TESTCLASSPATH} -Djdk.gtk.version=2 ProvokeGTK + EXECRES=$? + grep 'libgtk-x11.*=\ *[0-9]*$' strace.log > logg +fi + +if [ ${EXECRES} -ne 0 ] +then + echo "java execution failed for unknown reason, see logs" + exit 2 +fi + +cat logg +if [ -s logg ] +then + echo "Success." + exit 0 +else + echo "Failed. Examine logs." + exit 3 +fi --- /dev/null 2018-09-04 17:27:28.996000000 +0530 +++ new/test/javax/swing/LookAndFeel/8145547/DemandGTK2.txt 2018-09-05 12:09:52.265366000 +0530 @@ -0,0 +1,37 @@ +How to prepare an Ubuntu machine for GTK-2-less test run. + +The test DemandGTK2.sh should work well without GTK-2 switching to version 3 +if there's no GTK-2 library available. +At the moment, it's not easy to find a system with GTK-3 and without GTK-2: +many programs still depend on version 2. +We can, however, rename GTK-2 library for a single test run and then restore +it back. + +(1) Find GTK2 library: run + /sbin/ldconfig -v 2>/dev/null | grep libgtk-x11-2 + +It will output one or two lines like +libgtk-x11-2.0.so.0 -> libgtk-x11-2.0.so.0.2400.23 +Search for the target of that symlink for instance with locate: +locate libgtk-x11-2.0.so.0.2400.23 +Finally, you'll find the libraries. On my current machine they are +/usr/lib/i386-linux-gnu/libgtk-x11-2.0.so.0.2400.23 +/usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.23 + +I'm running 64-bit JDK and need to tamper with x86_64 copy only. + +(2) Find running programs depending on this library. They probably would crash +if you rename it. Stop them for this test run. +That said, I'm afraid it would be impossible to do on a system older than Ubuntu 16.04. +On my Ubuntu 16.04 I have only hud-service using this library, and that's OK, it will restart +after a crash, if any. +To find these programs, run +lsof /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.23 + +(3) Now, +sudo mv /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.23 /usr/lib/x86_64-linux-gnu/bak.libgtk-x11-2.0.so.0.2400.23 +jtreg DemandGTK2.sh +sudo mv /usr/lib/x86_64-linux-gnu/bak.libgtk-x11-2.0.so.0.2400.23 /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.23 + +Needless to say, you should substitute your own library path and however you run jtreg. + --- /dev/null 2018-09-04 17:27:28.996000000 +0530 +++ new/test/javax/swing/LookAndFeel/8145547/DemandGTK3.sh 2018-09-05 12:09:53.177822000 +0530 @@ -0,0 +1,80 @@ +#!/bin/ksh -p + +# +# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + + +# @test +# @summary Try to force GTK3. We must bail out to GTK2 if no 3 available. +# +# @compile ProvokeGTK.java +# @requires os.family == "linux" +# @run shell/timeout=400 DemandGTK3.sh + +# +# Note that we depend on +# strace in the PATH +# /sbin/ldconfig (which may be is not in PATH) +# It is true for OEL 7 and Ubuntu 14, 16 +# but may fail in future. Save tomorrow for tomorrow. +# + +which strace +if [ $? -ne 0 ] +then + echo "Please provide strace: \"which strace\" failed." + exit 1 +fi + +HAVE_3=`/sbin/ldconfig -v 2>/dev/null | grep libgtk-3.so | wc -l` + + +if [ "${HAVE_3}" = "0" ] +then + + echo "No GTK 3 library found: we should bail out to 2" + strace -o strace.log -fe open ${TESTJAVA}/bin/java -cp ${TESTCLASSPATH} -Djdk.gtk.version=3 ProvokeGTK + EXECRES=$? + grep 'libgtk-x11.*=\ *[0-9]*$' strace.log > logg +else + echo "There is GTK 3 library: we should use it" + strace -o strace.log -fe open ${TESTJAVA}/bin/java -cp ${TESTCLASSPATH} -Djdk.gtk.version=3 ProvokeGTK + EXECRES=$? + grep 'libgtk-3.*=\ *[0-9]*$' strace.log > logg +fi + +if [ ${EXECRES} -ne 0 ] +then + echo "java execution failed for unknown reason, see logs" + exit 2 +fi + +cat logg +if [ -s logg ] +then + echo "Success." + exit 0 +else + echo "Failed. Examine logs." + exit 3 +fi --- /dev/null 2018-09-04 17:27:28.996000000 +0530 +++ new/test/javax/swing/LookAndFeel/8145547/ProvokeGTK.java 2018-09-05 12:09:54.114290000 +0530 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.JFrame; +import javax.swing.UIManager; +import javax.swing.SwingUtilities; + +public class ProvokeGTK { + + static JFrame frame; + public static void createAndShow() { + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); + } catch(Exception cnf) { + cnf.printStackTrace(); + } + frame = new JFrame("JFrame"); + frame.setSize(200, 200); + + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + } + + /** + * @param args the command line arguments + */ + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(ProvokeGTK::createAndShow); + Thread.sleep(1000); + SwingUtilities.invokeAndWait( () -> { + frame.setVisible(false); + frame.dispose(); + }); + + } +} --- old/src/solaris/classes/sun/misc/GThreadHelper.java 2018-09-05 12:09:55.246856000 +0530 +++ /dev/null 2018-09-04 17:27:28.996000000 +0530 @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.misc; - -import java.util.concurrent.locks.ReentrantLock; - -/** - * This class is used to prevent multiple calling of g_thread_init () - * and gdk_thread_init (). - * - * Since version 2.24 of GLib, calling g_thread_init () multiple times is - * allowed, but it will crash for older versions. There are two ways to - * find out if g_thread_init () has been called: - * g_thread_get_initialized (), but it was introduced in 2.20 - * g_thread_supported (), but it is a macro and cannot be loaded with dlsym. - * - * usage: - *
- * lock();
- * try {
- *    if (!getAndSetInitializationNeededFlag()) {
- *        //call to g_thread_init();
- *        //call to gdk_thread_init();
- *    }
- * } finally {
- *    unlock();
- * }
- * 
- */ -public final class GThreadHelper { - - private static final ReentrantLock LOCK = new ReentrantLock(); - private static boolean isGThreadInitialized = false; - - /** - * Acquires the lock. - */ - public static void lock() { - LOCK.lock(); - } - - /** - * Releases the lock. - */ - public static void unlock() { - LOCK.unlock(); - } - - /** - * Gets current value of initialization flag and sets it to {@code true}. - * MUST be called under the lock. - * - * A return value of {@code false} indicates that the calling code - * should call the g_thread_init() and gdk_thread_init() functions - * before releasing the lock. - * - * @return {@code true} if initialization has been completed. - */ - public static boolean getAndSetInitializationNeededFlag() { - boolean ret = isGThreadInitialized; - isGThreadInitialized = true; - return ret; - } -}