--- old/./build.gradle 2018-10-10 16:43:24.106662979 +0530 +++ new/./build.gradle 2018-10-10 16:43:23.870662979 +0530 @@ -340,11 +340,11 @@ // Define the SWT.jar that we are going to have to download during the build process based // on what platform we are compiling from (not based on our target). -ext.SWT_FILE_NAME = IS_MAC ? "org.eclipse.swt.cocoa.macosx.x86_64_3.7.2.v3740f" : - IS_WINDOWS && IS_64 ? "org.eclipse.swt.win32.win32.x86_64_3.7.2.v3740f" : - IS_WINDOWS && !IS_64 ? "org.eclipse.swt.win32.win32.x86_3.7.2.v3740f" : - IS_LINUX && IS_64 ? "org.eclipse.swt.gtk.linux.x86_64_3.7.2.v3740f" : - IS_LINUX && !IS_64 ? "org.eclipse.swt.gtk.linux.x86_3.7.2.v3740f" : "" +ext.SWT_FILE_NAME = IS_MAC ? "org.eclipse.swt.cocoa.macosx.x86_64_3.105.3.v20170228-0512" : + IS_WINDOWS && IS_64 ? "org.eclipse.swt.win32.win32.x86_64_3.105.3.v20170228-0512" : + IS_WINDOWS && !IS_64 ? "org.eclipse.swt.win32.win32.x86_3.105.3.v20170228-0512" : + IS_LINUX && IS_64 ? "org.eclipse.swt.gtk.linux.x86_64_3.105.3.v20170228-0512" : + IS_LINUX && !IS_64 ? "org.eclipse.swt.gtk.linux.x86_3.105.3.v20170228-0512" : "" // Build javadocs only if BUILD_JAVADOC=true defineProperty("BUILD_JAVADOC", "false") @@ -1139,7 +1139,7 @@ repositories { mavenCentral() ivy { - url "http://download.eclipse.org/eclipse/updates/3.7/R-3.7.2-201202080800/plugins/" + url "http://download.eclipse.org/eclipse/updates/4.6/R-4.6.3-201703010400/plugins/" layout "pattern", { artifact "[artifact].[ext]" } --- old/buildSrc/linux.gradle 2018-10-10 16:43:24.746662979 +0530 +++ new/buildSrc/linux.gradle 2018-10-10 16:43:24.502662979 +0530 @@ -54,31 +54,70 @@ commonFlags, "-I$JDK_HOME/include", "-I$JDK_HOME/include/linux", "-c", "-ffunction-sections", "-fdata-sections", IS_DEBUG_NATIVE ? ["-ggdb", "-DVERBOSE"] : ["-O2", "-DNDEBUG"]].flatten() +def ccFlagsGTK3 = ccFlags //ccFlags.addAll(["-Wnon-virtual-dtor", "-Woverloaded-virtual", "-std=c++0x"]) def linkFlags = ["-static-libgcc", "-static-libstdc++", "-shared", commonFlags, "-Wl,--gc-sections"].flatten() def defaultLinkFlags = linkFlags.flatten() +def gtk2CCFlags = [ ]; +def gtk3CCFlags = [ "-Wno-deprecated-declarations" ]; +def gtk2LinkFlags = [ ]; +def gtk3LinkFlags = [ ]; +LINUX.buildGTK3 = true + // Create $buildDir/linux_tools.properties file and load props from it -setupTools("linux_tools", +setupTools("linux_gtk2", { propFile -> - ByteArrayOutputStream results = new ByteArrayOutputStream(); + ByteArrayOutputStream results1 = new ByteArrayOutputStream(); exec { - commandLine("pkg-config", "--cflags", "gtk+-2.0", "gthread-2.0", "xtst"); - setStandardOutput(results); + commandLine("pkg-config", "--cflags", "gtk+-2.0", "gthread-2.0", "xtst") + setStandardOutput(results1); } - propFile << "cflags=" << results.toString().trim() << "\n"; + propFile << "cflagsGTK2=" << results1.toString().trim() << "\n"; - results = new ByteArrayOutputStream(); + ByteArrayOutputStream results3 = new ByteArrayOutputStream(); exec { - commandLine "pkg-config", "--libs", "gtk+-2.0", "gthread-2.0", "xtst" - standardOutput = results + commandLine("pkg-config", "--libs", "gtk+-2.0", "gthread-2.0", "xtst") + setStandardOutput(results3); } - propFile << "libs=" << results.toString().trim(); + propFile << "libsGTK2=" << results3.toString().trim() << "\n"; + }, + { properties -> + gtk2CCFlags.addAll(properties.getProperty("cflagsGTK2").split(" ")) + gtk2LinkFlags.addAll(properties.getProperty("libsGTK2").split(" ")) + } +) + +setupTools("linux_gtk3", + { propFile -> + ByteArrayOutputStream results2 = new ByteArrayOutputStream(); + exec { + commandLine("pkg-config", "--cflags", "gtk+-3.0", "gthread-2.0", "xtst") + setStandardOutput(results2); + ignoreExitValue(true) + } + propFile << "cflagsGTK3=" << results2.toString().trim() << "\n"; + + ByteArrayOutputStream results4 = new ByteArrayOutputStream(); + exec { + commandLine("pkg-config", "--libs", "gtk+-3.0", "gthread-2.0", "xtst") + setStandardOutput(results4); + ignoreExitValue(true) + } + propFile << "libsGTK3=" << results4.toString().trim() << "\n"; + }, { properties -> - ccFlags.addAll(properties.getProperty("cflags").split(" ")) - linkFlags.addAll(properties.getProperty("libs").split(" ")) + String ccflags = properties.getProperty("cflagsGTK3") + String ldflags = properties.getProperty("libsGTK3") + if (ccflags != null && ! ccflags.equals("")) { + gtk3CCFlags.addAll(properties.getProperty("cflagsGTK3").split(" ")) + gtk3LinkFlags.addAll(properties.getProperty("libsGTK3").split(" ")) + } else { + logger.info("Warning: GTK3 development packages not found, not building GTK3 support"); + LINUX.buildGTK3 = false + } } ) @@ -135,16 +174,49 @@ def linker = IS_COMPILE_PARFAIT ? "parfait-g++" : "g++"; LINUX.glass = [:] +LINUX.glass.variants = ["glass", "glassgtk2"] +if (LINUX.buildGTK3) { + logger.info("Building libglassgtk3") + LINUX.glass.variants += "glassgtk3" +} else { + logger.warn("NOT Building libglassgtk3") +} + +FileTree ft_gtk_launcher = fileTree("${project(":graphics").projectDir}/src/main/native-glass/gtk/") { + include("**/launcher.c") +} + +FileTree ft_gtk = fileTree("${project(":graphics").projectDir}/src/main/native-glass/gtk/") { + exclude("**/launcher.c") +} + +LINUX.glass.glass = [:] LINUX.glass.javahInclude = [ "com/sun/glass/events/**", "com/sun/glass/ui/*", "com/sun/glass/ui/gtk/*"] -LINUX.glass.nativeSource = file("modules/graphics/src/main/native-glass/gtk") -LINUX.glass.compiler = compiler -LINUX.glass.ccFlags = [ccFlags, "-Werror"].flatten() -LINUX.glass.linker = linker -LINUX.glass.linkFlags = [linkFlags].flatten() -LINUX.glass.lib = "glass" +LINUX.glass.glass.nativeSource = ft_gtk_launcher.getFiles() +LINUX.glass.glass.compiler = compiler +LINUX.glass.glass.ccFlags = [ccFlags, gtk2CCFlags, "-Werror"].flatten() +LINUX.glass.glass.linker = linker +LINUX.glass.glass.linkFlags = [linkFlags, "-lX11", "-ldl" ].flatten() +LINUX.glass.glass.lib = "glass" + +LINUX.glass.glassgtk2 = [:] +LINUX.glass.glassgtk2.nativeSource = ft_gtk.getFiles() +LINUX.glass.glassgtk2.compiler = compiler +LINUX.glass.glassgtk2.ccFlags = [ccFlags, gtk2CCFlags, "-Werror"].flatten() +LINUX.glass.glassgtk2.linker = linker +LINUX.glass.glassgtk2.linkFlags = [linkFlags, gtk2LinkFlags ].flatten() +LINUX.glass.glassgtk2.lib = "glassgtk2" + +LINUX.glass.glassgtk3 = [:] +LINUX.glass.glassgtk3.nativeSource = ft_gtk.getFiles() +LINUX.glass.glassgtk3.compiler = compiler +LINUX.glass.glassgtk3.ccFlags = [ccFlags, gtk3CCFlags, "-Werror"].flatten() +LINUX.glass.glassgtk3.linker = linker +LINUX.glass.glassgtk3.linkFlags = [linkFlags, gtk3LinkFlags ].flatten() +LINUX.glass.glassgtk3.lib = "glassgtk3" LINUX.decora = [:] LINUX.decora.compiler = compiler --- old/buildSrc/src/main/groovy/com/sun/javafx/gradle/NativeCompileTask.groovy 2018-10-10 16:43:25.390662979 +0530 +++ new/buildSrc/src/main/groovy/com/sun/javafx/gradle/NativeCompileTask.groovy 2018-10-10 16:43:25.134662979 +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 @@ -82,7 +82,7 @@ // Get the existing native-dependencies file from build/dependency-cache and load its contents into // memory. If the file doesn't exist, then we will just have an empty dependency map. final Map dependencies = new ConcurrentHashMap<>(); - final File nativeDependenciesFile = project.file("$project.buildDir/dependency-cache/native-dependencies"); + final File nativeDependenciesFile = project.file("$project.buildDir/dependency-cache/native-dependencies-${output.getName()}"); if (nativeDependenciesFile.exists()) { nativeDependenciesFile.splitEachLine("\t", { strings -> try { --- old/modules/graphics/src/main/java/com/sun/glass/ui/Window.java 2018-10-10 16:43:26.006662979 +0530 +++ new/modules/graphics/src/main/java/com/sun/glass/ui/Window.java 2018-10-10 16:43:25.774662979 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2017, 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 @@ -295,6 +295,9 @@ if (this.ptr == 0L) { throw new RuntimeException("could not create platform window"); } + if (screen == null) { + screen = Screen.getMainScreen(); // start with a default + } } public boolean isClosed() { --- old/modules/graphics/src/main/java/com/sun/glass/ui/gtk/GtkApplication.java 2018-10-10 16:43:26.690662979 +0530 +++ new/modules/graphics/src/main/java/com/sun/glass/ui/gtk/GtkApplication.java 2018-10-10 16:43:26.426662979 +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 @@ -36,18 +36,73 @@ import com.sun.glass.ui.Timer; import com.sun.glass.ui.View; import com.sun.glass.ui.Window; +import com.sun.javafx.util.Logging; +import com.sun.glass.utils.NativeLibLoader; +import sun.util.logging.PlatformLogger; import java.io.File; +import java.lang.reflect.Method; import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Map; import java.util.concurrent.CountDownLatch; +import java.lang.annotation.Native; -final class GtkApplication extends Application implements InvokeLaterDispatcher.InvokeLaterSubmitter { +final class GtkApplication extends Application implements + InvokeLaterDispatcher.InvokeLaterSubmitter { + private static final String SWT_INTERNAL_CLASS = + "org.eclipse.swt.internal.gtk.OS"; + private static final int forcedGtkVersion; + + static { + //check for SWT-GTK lib presence + Class OS = AccessController. + doPrivileged((PrivilegedAction>) () -> { + try { + return Class.forName(SWT_INTERNAL_CLASS, true, + ClassLoader.getSystemClassLoader()); + } catch (Exception e) {} + try { + return Class.forName(SWT_INTERNAL_CLASS, true, + Thread.currentThread().getContextClassLoader()); + } catch (Exception e) {} + return null; + }); + if (OS != null) { + PlatformLogger logger = Logging.getJavaFXLogger(); + logger.fine("SWT-GTK library found. Try to obtain GTK version."); + Method method = AccessController. + doPrivileged((PrivilegedAction) () -> { + try { + return OS.getMethod("gtk_major_version"); + } catch (Exception e) { + return null; + } + }); + int ver = 0; + if (method != null) { + try { + ver = ((Number)method.invoke(OS)).intValue(); + } catch (Exception e) { + logger.warning("Method gtk_major_version() of " + + "the org.eclipse.swt.internal.gtk.OS class " + + "returns error. SWT GTK version cannot be detected. " + + "GTK3 will be used as default."); + ver = 3; + } + } + if (ver < 2 || ver > 3) { + logger.warning("SWT-GTK uses unsupported major GTK version " + + ver + ". GTK3 will be used as default."); + ver = 3; + } + forcedGtkVersion = ver; + } else { + forcedGtkVersion = 0; + } - static { AccessController.doPrivileged((PrivilegedAction) () -> { Application.loadNativeLibrary(); return null; @@ -61,11 +116,53 @@ private final InvokeLaterDispatcher invokeLaterDispatcher; GtkApplication() { - // Check whether the Display is valid and throw an exception if not. - // We use UnsupportedOperationException rather than HeadlessException - // so as not to introduce a dependency on AWT. - if (!isDisplayValid()) { - throw new UnsupportedOperationException("Unable to open DISPLAY"); + + final int gtkVersion = forcedGtkVersion == 0 ? + AccessController.doPrivileged((PrivilegedAction) () -> { + String v = System.getProperty("jdk.gtk.version","2"); + int ret = 0; + if ("3".equals(v) || v.startsWith("3.")) { + ret = 3; + } else if ("2".equals(v) || v.startsWith("2.")) { + ret = 2; + } + return ret; + }) : forcedGtkVersion; + + boolean gtkVersionVerbose = + AccessController.doPrivileged((PrivilegedAction) () -> { + return Boolean.getBoolean("jdk.gtk.verbose"); + + }); + + int libraryToLoad = _queryLibrary(gtkVersion, gtkVersionVerbose); + + AccessController.doPrivileged((PrivilegedAction) () -> { + if (libraryToLoad == QUERY_NO_DISPLAY) { + throw new UnsupportedOperationException("Unable to open DISPLAY"); + } else if (libraryToLoad == QUERY_USE_CURRENT) { + if (gtkVersionVerbose) { + System.out.println("Glass GTK library to load is already loaded"); + } + } else if (libraryToLoad == QUERY_LOAD_GTK2) { + if (gtkVersionVerbose) { + System.out.println("Glass GTK library to load is glassgtk2"); + } + NativeLibLoader.loadLibrary("glassgtk2"); + } else if (libraryToLoad == QUERY_LOAD_GTK3) { + if (gtkVersionVerbose) { + System.out.println("Glass GTK library to load is glassgtk3"); + } + NativeLibLoader.loadLibrary("glassgtk3"); + } else { + throw new UnsupportedOperationException("Internal Error"); + } + return null; + }); + + int version = _initGTK(gtkVersion, gtkVersionVerbose); + if (version == -1) { + throw new RuntimeException("Error loading GTK libraries"); } // Embedded in SWT, with shared event thread @@ -79,9 +176,18 @@ } } - private static boolean isDisplayValid() { - return _isDisplayValid(); - } + @Native private static final int QUERY_ERROR = -2; + @Native private static final int QUERY_NO_DISPLAY = -1; + @Native private static final int QUERY_USE_CURRENT = 1; + @Native private static final int QUERY_LOAD_GTK2 = 2; + @Native private static final int QUERY_LOAD_GTK3 = 3; + /* + * check the system and return an indication of which library to load + * return values are the QUERY_ constants + */ + private static native int _queryLibrary(int version, boolean verbose); + + private static native int _initGTK(int version, boolean verbose); private void initDisplay() { Map ds = getDeviceDetails(); @@ -156,8 +262,6 @@ return true; } - private static native boolean _isDisplayValid(); - private native void _terminateLoop(); private native void _init(long eventProc, boolean disableGrab); --- old/modules/graphics/src/main/native-glass/gtk/GlassApplication.cpp 2018-10-10 16:43:27.322662979 +0530 +++ new/modules/graphics/src/main/native-glass/gtk/GlassApplication.cpp 2018-10-10 16:43:27.074662979 +0530 @@ -64,18 +64,74 @@ extern "C" { + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +static void init_threads() { + gboolean is_g_thread_get_initialized = FALSE; + if (glib_check_version(2, 32, 0)) { // < 2.32 + if (!glib_check_version(2, 20, 0)) { + is_g_thread_get_initialized = g_thread_get_initialized(); + } + if (!is_g_thread_get_initialized) { + g_thread_init(NULL); + } + } + gdk_threads_init(); +} +#pragma GCC diagnostic pop + +jboolean gtk_verbose = JNI_FALSE; + +/* + * Class: com_sun_glass_ui_gtk_GtkApplication + * Method: _initGTK + * Signature: (IZ)I + */ +JNIEXPORT jint JNICALL Java_com_sun_glass_ui_gtk_GtkApplication__1initGTK + (JNIEnv *env, jclass clazz, jint version, jboolean verbose) +{ + (void) clazz; + (void) version; + + gtk_verbose = verbose; + + env->ExceptionClear(); + init_threads(); + + gdk_threads_enter(); + gtk_init(NULL, NULL); + + return JNI_TRUE; +} + /* * Class: com_sun_glass_ui_gtk_GtkApplication - * Method: _isDisplayValid - * Signature: ()Z + * Method: _queryLibrary + * Signature: Signature: (IZ)I */ -JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_gtk_GtkApplication__1isDisplayValid - (JNIEnv * env, jclass clazz) +JNIEXPORT jint JNICALL Java_com_sun_glass_ui_gtk_GtkApplication__1queryLibrary + (JNIEnv *env, jclass clazz, jint suggestedVersion, jboolean verbose) { + // If we are being called, then the launcher is + // not in use, and we are in the proper glass library already. + // This can be done by renaming the gtk versioned native + // libraries to be libglass.so + // Note: we will make no effort to complain if the suggestedVersion + // is out of phase. + (void)env; (void)clazz; + (void)suggestedVersion; + (void)verbose; + + Display *display = XOpenDisplay(NULL); + if (display == NULL) { + return com_sun_glass_ui_gtk_GtkApplication_QUERY_NO_DISPLAY; + } + XCloseDisplay(display); - return is_display_valid(); + return com_sun_glass_ui_gtk_GtkApplication_QUERY_USE_CURRENT; } /* @@ -92,6 +148,7 @@ process_events_prev = (GdkEventFunc) handler; disableGrab = (gboolean) _disableGrab; + glass_gdk_x11_display_set_window_scale(gdk_display_get_default(), 1); gdk_event_handler_set(process_events, NULL, NULL); GdkScreen *default_gdk_screen = gdk_screen_get_default(); --- old/modules/graphics/src/main/native-glass/gtk/GlassRobot.cpp 2018-10-10 16:43:27.962662979 +0530 +++ new/modules/graphics/src/main/native-glass/gtk/GlassRobot.cpp 2018-10-10 16:43:27.722662979 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, 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 @@ -33,7 +33,6 @@ #include #include #include "glass_general.h" -#include "glass_gtkcompat.h" #include "glass_key.h" @@ -247,8 +246,7 @@ GdkPixbuf *screenshot, *tmp; GdkWindow *root_window = gdk_get_default_root_window(); - tmp = gdk_pixbuf_get_from_drawable (NULL, root_window, NULL, - x, y, 0, 0, width, height); + tmp = glass_pixbuf_from_window(root_window, x, y, width, height); screenshot = gdk_pixbuf_add_alpha(tmp, FALSE, 0, 0, 0); g_object_unref(tmp); --- old/modules/graphics/src/main/native-glass/gtk/GlassSystemClipboard.cpp 2018-10-10 16:43:28.626662979 +0530 +++ new/modules/graphics/src/main/native-glass/gtk/GlassSystemClipboard.cpp 2018-10-10 16:43:28.382662979 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, 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 @@ -23,7 +23,6 @@ * questions. */ #include "com_sun_glass_ui_gtk_GtkSystemClipboard.h" -#include "glass_gtkcompat.h" #include "glass_general.h" #include --- old/modules/graphics/src/main/native-glass/gtk/GlassView.cpp 2018-10-10 16:43:29.250662979 +0530 +++ new/modules/graphics/src/main/native-glass/gtk/GlassView.cpp 2018-10-10 16:43:29.006662979 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, 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 @@ -32,7 +32,6 @@ #include "glass_general.h" #include "glass_view.h" #include "glass_window.h" -#include "glass_gtkcompat.h" #define JLONG_TO_GLASSVIEW(value) ((GlassView *) JLONG_TO_PTR(value)) --- old/modules/graphics/src/main/native-glass/gtk/GlassWindow.cpp 2018-10-10 16:43:29.878662979 +0530 +++ new/modules/graphics/src/main/native-glass/gtk/GlassWindow.cpp 2018-10-10 16:43:29.630662979 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, 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 @@ -28,7 +28,6 @@ #include #include -#include "glass_gtkcompat.h" #include "glass_general.h" #include "glass_evloop.h" #include "glass_window.h" @@ -83,8 +82,9 @@ { (void)env; + WindowContext* parent = JLONG_TO_WINDOW_CTX(owner); WindowContext* ctx = new WindowContextTop(obj, - (WindowContext*)JLONG_TO_PTR(owner), + parent, screen, glass_mask_to_window_frame_type(mask), glass_mask_to_window_type(mask), @@ -109,9 +109,9 @@ WindowContextPlug *parent_ctx = NULL; WindowContext *ctx = NULL; - parent_window = GLASS_GDK_WINDOW_LOOKUP_FOR_DISPLAY( + parent_window = gdk_x11_window_lookup_for_display( gdk_display_get_default(), - (GdkNativeWindow)PTR_TO_JLONG(owner)); + (Window)PTR_TO_JLONG(owner)); if (parent_window != NULL) { parent_ctx = (WindowContextPlug *)g_object_get_data(G_OBJECT(parent_window), GDK_WINDOW_DATA_CONTEXT); --- old/modules/graphics/src/main/native-glass/gtk/glass_dnd.cpp 2018-10-10 16:43:30.478662979 +0530 +++ new/modules/graphics/src/main/native-glass/gtk/glass_dnd.cpp 2018-10-10 16:43:30.242662979 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, 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 @@ -23,7 +23,6 @@ * questions. */ #include "glass_dnd.h" -#include "glass_gtkcompat.h" #include "glass_general.h" #include "glass_evloop.h" @@ -35,6 +34,7 @@ #include #include +#include /************************* COMMON *********************************************/ static jint translate_gdk_action_to_glass(GdkDragAction action) @@ -165,7 +165,7 @@ return; // Do not process motion events if no enter event was received } jmethodID method = enter_ctx.just_entered ? jViewNotifyDragEnter : jViewNotifyDragOver; - GdkDragAction suggested = GLASS_GDK_DRAG_CONTEXT_GET_SUGGESTED_ACTION(event->context); + GdkDragAction suggested = gdk_drag_context_get_suggested_action(event->context); GdkDragAction result = translate_glass_action_to_gdk(mainEnv->CallIntMethod(ctx->get_jview(), method, (jint)event->x_root - enter_ctx.dx, (jint)event->y_root - enter_ctx.dy, (jint)event->x_root, (jint)event->y_root, @@ -193,7 +193,7 @@ gdk_drop_reply(event->context, FALSE, GDK_CURRENT_TIME); return; // Do not process drop events if no enter event and subsequent motion event were received } - GdkDragAction selected = GLASS_GDK_DRAG_CONTEXT_GET_SELECTED_ACTION(event->context); + GdkDragAction selected = gdk_drag_context_get_selected_action(event->context); mainEnv->CallIntMethod(ctx->get_jview(), jViewNotifyDragDrop, (jint)event->x_root - enter_ctx.dx, (jint)event->y_root - enter_ctx.dy, @@ -245,7 +245,7 @@ return NULL; } if (!enter_ctx.mimes) { - GList* targets = GLASS_GDK_DRAG_CONTEXT_LIST_TARGETS(enter_ctx.ctx); + GList* targets = gdk_drag_context_list_targets(enter_ctx.ctx); jobject set = env->NewObject(jHashSetCls, jHashSetInit, NULL); EXCEPTION_OCCURED(env); @@ -312,13 +312,13 @@ if (check_state_in_drag(env)) { return 0; } - return translate_gdk_action_to_glass(GLASS_GDK_DRAG_CONTEXT_GET_ACTIONS(enter_ctx.ctx)); + return translate_gdk_action_to_glass(gdk_drag_context_get_actions(enter_ctx.ctx)); } static void wait_for_selection_data_hook(GdkEvent * event, void * data) { selection_data_ctx *ctx = (selection_data_ctx*)data; - GdkWindow *dest = GLASS_GDK_DRAG_CONTEXT_GET_DEST_WINDOW(enter_ctx.ctx); + GdkWindow *dest = glass_gdk_drag_context_get_dest_window(enter_ctx.ctx); if (event->type == GDK_SELECTION_NOTIFY && event->selection.window == dest) { if (event->selection.property) { // if 0, that we received negative response @@ -334,7 +334,7 @@ memset(selection_ctx, 0, sizeof(selection_data_ctx)); - gdk_selection_convert(GLASS_GDK_DRAG_CONTEXT_GET_DEST_WINDOW(enter_ctx.ctx), gdk_drag_get_selection(enter_ctx.ctx), target, + gdk_selection_convert(glass_gdk_drag_context_get_dest_window(enter_ctx.ctx), gdk_drag_get_selection(enter_ctx.ctx), target, GDK_CURRENT_TIME); hookReg = @@ -560,7 +560,7 @@ if (dnd_window) { dnd_set_performed_action( translate_gdk_action_to_glass( - GLASS_GDK_DRAG_CONTEXT_GET_SELECTED_ACTION( + gdk_drag_context_get_selected_action( get_drag_context()))); gdk_window_destroy(dnd_window); @@ -785,7 +785,12 @@ { (void)window; - GdkWindow *requestor = GLASS_GDK_SELECTION_EVENT_GET_REQUESTOR(event); +#ifdef GLASS_GTK3 + GdkWindow *requestor = (event->requestor); +#else + GdkWindow *requestor = + gdk_x11_window_foreign_new_for_display(gdk_display_get_default(), event->requestor); +#endif gboolean is_data_set = FALSE; if (event->target == TARGET_UTF8_STRING_ATOM @@ -812,7 +817,7 @@ glass_gdk_master_pointer_ungrab(); - if (GLASS_GDK_DRAG_CONTEXT_GET_SELECTED_ACTION(get_drag_context())) { + if (gdk_drag_context_get_selected_action(get_drag_context())) { gdk_drag_drop(get_drag_context(), GDK_CURRENT_TIME); } else { gdk_drag_abort(get_drag_context(), GDK_CURRENT_TIME); @@ -881,7 +886,7 @@ { (void)window; - GdkDragAction selected = GLASS_GDK_DRAG_CONTEXT_GET_SELECTED_ACTION(event->context); + GdkDragAction selected = gdk_drag_context_get_selected_action(event->context); GdkCursor* cursor; if (selected & GDK_ACTION_COPY) { @@ -1212,10 +1217,6 @@ gtk_widget_realize(widget); - GdkRegion* region = gdk_region_new(); - gdk_window_input_shape_combine_region(gtk_widget_get_window(widget), region, 0,0); - gdk_region_destroy(region); - gtk_widget_set_app_paintable(widget, TRUE); g_signal_connect(G_OBJECT(widget), "expose-event", G_CALLBACK(on_expose), this); @@ -1231,23 +1232,18 @@ void DragView::View::screen_changed() { GdkScreen *screen = gtk_widget_get_screen(widget); - GdkColormap *colormap = gdk_screen_get_rgba_colormap(screen); + glass_configure_window_transparency(widget, true); - if (!colormap || !gdk_screen_is_composited(screen)) { + if (!gdk_screen_is_composited(screen)) { if (!is_offset_set) { offset_x = 1; offset_y = 1; } } - - if (!colormap) { - colormap = gdk_screen_get_rgb_colormap(screen); - } - gtk_widget_set_colormap(widget, colormap); } void DragView::View::expose() { - cairo_t *context = gdk_cairo_create(widget->window); + cairo_t *context = gdk_cairo_create(gtk_widget_get_window(widget)); cairo_surface_t* cairo_surface; --- old/modules/graphics/src/main/native-glass/gtk/glass_general.cpp 2018-10-10 16:43:31.090662979 +0530 +++ new/modules/graphics/src/main/native-glass/gtk/glass_general.cpp 2018-10-10 16:43:30.866662979 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, 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 @@ -111,26 +111,6 @@ jmethodID jApplicationGetApplication; jmethodID jApplicationGetName; -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -void init_threads() { - gboolean is_g_thread_get_initialized = FALSE; - if (glib_check_version(2, 32, 0)) { // < 2.32 - if (!glib_check_version(2, 20, 0)) { - is_g_thread_get_initialized = g_thread_get_initialized(); - } - if (!is_g_thread_get_initialized) { - // 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. - // g_thread_init is no longer necessary for GLib >=2.32 - g_thread_init(NULL); - } - } - gdk_threads_init(); -} -#pragma GCC diagnostic pop - static jboolean displayValid = JNI_FALSE; jboolean @@ -338,41 +318,6 @@ jApplicationGetName = env->GetMethodID(jApplicationCls, "getName", "()Ljava/lang/String;"); if (env->ExceptionCheck()) return JNI_ERR; - // Before doing anything with GTK we validate that the DISPLAY can be opened - display = XOpenDisplay(NULL); - if (display != NULL) { - XCloseDisplay(display); - displayValid = JNI_TRUE; - } else { - // Invalid DISPLAY, skip initialization - return JNI_VERSION_1_6; - } - - clazz = env->FindClass("sun/misc/GThreadHelper"); - if (env->ExceptionCheck()) return JNI_ERR; - if (clazz) { - jmethodID mid_getAndSetInitializationNeededFlag = env->GetStaticMethodID(clazz, "getAndSetInitializationNeededFlag", "()Z"); - if (env->ExceptionCheck()) return JNI_ERR; - jmethodID mid_lock = env->GetStaticMethodID(clazz, "lock", "()V"); - if (env->ExceptionCheck()) return JNI_ERR; - jmethodID mid_unlock = env->GetStaticMethodID(clazz, "unlock", "()V"); - if (env->ExceptionCheck()) return JNI_ERR; - - env->CallStaticVoidMethod(clazz, mid_lock); - - if (!env->CallStaticBooleanMethod(clazz, mid_getAndSetInitializationNeededFlag)) { - init_threads(); - } - - env->CallStaticVoidMethod(clazz, mid_unlock); - } else { - env->ExceptionClear(); - init_threads(); - } - - gdk_threads_enter(); - gtk_init(NULL, NULL); - return JNI_VERSION_1_6; } @@ -541,3 +486,441 @@ g_strfreev(uris); return result; } + +//*************************************************************************** + +typedef struct _DeviceGrabContext { + GdkWindow * window; + gboolean grabbed; +} DeviceGrabContext; + +gboolean disableGrab = FALSE; +static gboolean configure_transparent_window(GtkWidget *window); +static void configure_opaque_window(GtkWidget *window); + +static void grab_mouse_device(GdkDevice *device, DeviceGrabContext *context); +static void ungrab_mouse_device(GdkDevice *device); + +gint glass_gdk_visual_get_depth (GdkVisual * visual) +{ + // gdk_visual_get_depth is GTK 2.2 + + return gdk_visual_get_depth(visual); +} + +GdkScreen * glass_gdk_window_get_screen(GdkWindow * gdkWindow) +{ +#ifdef GLASS_GTK3 + GdkVisual * gdkVisual = gdk_window_get_visual(gdkWindow); + return gdk_visual_get_screen(gdkVisual); +#else + return gdk_window_get_screen(gdkWindow); +#endif +} + +gboolean +glass_gdk_mouse_devices_grab(GdkWindow *gdkWindow) { +#ifdef GLASS_GTK3_DISABLED +//this GTK 3 approach has synchronization issues covered in JDK-8176844 +// As the approach is also deprecated in GTK 3.20+, revert back to using GTK 2 mechanism + + if (disableGrab) { + return TRUE; + } + DeviceGrabContext context; + GList *devices = gdk_device_manager_list_devices ( + gdk_display_get_device_manager( + gdk_display_get_default()), + GDK_DEVICE_TYPE_MASTER); + + context.window = gdkWindow; + context.grabbed = FALSE; + g_list_foreach(devices, (GFunc) grab_mouse_device, &context); + g_list_free(devices); + + return context.grabbed; +#else + return glass_gdk_mouse_devices_grab_with_cursor(gdkWindow, NULL, TRUE); +#endif +} + +gboolean +glass_gdk_mouse_devices_grab_with_cursor(GdkWindow *gdkWindow, GdkCursor *cursor, gboolean owner_events) { + if (disableGrab) { + return TRUE; + } + GdkGrabStatus status = gdk_pointer_grab(gdkWindow, owner_events, (GdkEventMask) + (GDK_POINTER_MOTION_MASK + | GDK_POINTER_MOTION_HINT_MASK + | GDK_BUTTON_MOTION_MASK + | GDK_BUTTON1_MOTION_MASK + | GDK_BUTTON2_MOTION_MASK + | GDK_BUTTON3_MOTION_MASK + | GDK_BUTTON_PRESS_MASK + | GDK_BUTTON_RELEASE_MASK), + NULL, cursor, GDK_CURRENT_TIME); + + return (status == GDK_GRAB_SUCCESS) ? TRUE : FALSE; +} + +void +glass_gdk_mouse_devices_ungrab() { +#ifdef GLASS_GTK3_DISABLED +//this GTK 3 approach has synchronization issues covered in JDK-8176844 +// As the approach is also deprecated in GTK 3.20+, revert back to using GTK 2 mechanism + GList *devices = gdk_device_manager_list_devices( + gdk_display_get_device_manager( + gdk_display_get_default()), + GDK_DEVICE_TYPE_MASTER); + g_list_foreach(devices, (GFunc) ungrab_mouse_device, NULL); + g_list_free(devices); +#else + gdk_pointer_ungrab(GDK_CURRENT_TIME); +#endif +} + +void +glass_gdk_master_pointer_grab(GdkWindow *window, GdkCursor *cursor) { + if (disableGrab) { + gdk_window_set_cursor(window, cursor); + return; + } +#ifdef GLASS_GTK3 + gdk_device_grab(gdk_device_manager_get_client_pointer( + gdk_display_get_device_manager( + gdk_display_get_default())), + window, GDK_OWNERSHIP_NONE, FALSE, GDK_ALL_EVENTS_MASK, + cursor, GDK_CURRENT_TIME); +#else + gdk_pointer_grab(window, FALSE, (GdkEventMask) + (GDK_POINTER_MOTION_MASK + | GDK_BUTTON_MOTION_MASK + | GDK_BUTTON1_MOTION_MASK + | GDK_BUTTON2_MOTION_MASK + | GDK_BUTTON3_MOTION_MASK + | GDK_BUTTON_RELEASE_MASK), + NULL, cursor, GDK_CURRENT_TIME); +#endif +} + +void +glass_gdk_master_pointer_ungrab() { +#ifdef GLASS_GTK3 + gdk_device_ungrab(gdk_device_manager_get_client_pointer( + gdk_display_get_device_manager( + gdk_display_get_default())), + GDK_CURRENT_TIME); +#else + gdk_pointer_ungrab(GDK_CURRENT_TIME); +#endif +} + +void +glass_gdk_master_pointer_get_position(gint *x, gint *y) { +#ifdef GLASS_GTK3 + gdk_device_get_position(gdk_device_manager_get_client_pointer( + gdk_display_get_device_manager( + gdk_display_get_default())), + NULL, x, y); +#else + gdk_display_get_pointer(gdk_display_get_default(), NULL, x, y, NULL); +#endif +} + +gboolean +glass_gdk_device_is_grabbed(GdkDevice *device) { +#ifdef GLASS_GTK3 + return gdk_display_device_is_grabbed(gdk_display_get_default(), device); +#else + (void) device; + return gdk_display_pointer_is_grabbed(gdk_display_get_default()); +#endif +} + +void +glass_gdk_device_ungrab(GdkDevice *device) { +#ifdef GLASS_GTK3 + gdk_device_ungrab(device, GDK_CURRENT_TIME); +#else + (void) device; + gdk_pointer_ungrab(GDK_CURRENT_TIME); +#endif +} + +GdkWindow * +glass_gdk_device_get_window_at_position(GdkDevice *device, gint *x, gint *y) { +#ifdef GLASS_GTK3 + return gdk_device_get_window_at_position(device, x, y); +#else + (void) device; + return gdk_display_get_window_at_pointer(gdk_display_get_default(), x, y); +#endif +} + +void +glass_gtk_configure_transparency_and_realize(GtkWidget *window, + gboolean transparent) { + gboolean isTransparent = glass_configure_window_transparency(window, transparent); + gtk_widget_realize(window); +} + +void +glass_gtk_window_configure_from_visual(GtkWidget *widget, GdkVisual *visual) { + glass_widget_set_visual(widget, visual); +} + +static gboolean +configure_transparent_window(GtkWidget *window) { + GdkScreen *default_screen = gdk_screen_get_default(); + GdkDisplay *default_display = gdk_display_get_default(); + +#ifdef GLASS_GTK3 + GdkVisual *visual = gdk_screen_get_rgba_visual(default_screen); + if (visual + && gdk_display_supports_composite(default_display) + && gdk_screen_is_composited(default_screen)) { + glass_widget_set_visual(window, visual); + return TRUE; + } +#else + GdkColormap *colormap = gdk_screen_get_rgba_colormap(default_screen); + if (colormap + && gdk_display_supports_composite(default_display) + && gdk_screen_is_composited(default_screen)) { + gtk_widget_set_colormap(window, colormap); + return TRUE; + } +#endif + + return FALSE; +} + +void +glass_gdk_window_get_size(GdkWindow *window, gint *w, gint *h) { + *w = gdk_window_get_width(window); + *h = gdk_window_get_height(window); +} + +void +glass_gdk_display_get_pointer(GdkDisplay* display, gint* x, gint *y) { +#ifdef GLASS_GTK3 + gdk_device_get_position( + gdk_device_manager_get_client_pointer( + gdk_display_get_device_manager(display)), NULL , x, y); +#else + gdk_display_get_pointer(display, NULL, x, y, NULL); +#endif +} + + +const guchar* +glass_gtk_selection_data_get_data_with_length( + GtkSelectionData * selectionData, + gint * length) { + if (selectionData == NULL) { + return NULL; + } + + *length = gtk_selection_data_get_length(selectionData); + return gtk_selection_data_get_data(selectionData); +} + +static void +configure_opaque_window(GtkWidget *window) { + (void) window; +/* We need to pick a visual that really is glx compatible + * instead of using the default visual + */ + /* see: JDK-8087516 for why this is commented out + glass_widget_set_visual(window, + gdk_screen_get_system_visual( + gdk_screen_get_default())); + */ +} + +gboolean +glass_configure_window_transparency(GtkWidget *window, gboolean transparent) { + if (transparent) { + if (configure_transparent_window(window)) { + return TRUE; + } + + fprintf(stderr,"Can't create transparent stage, because your screen doesn't" + " support alpha channel." + " You need to enable XComposite extension.\n"); + fflush(stderr); + } + + configure_opaque_window(window); + return FALSE; +} + +static void +grab_mouse_device(GdkDevice *device, DeviceGrabContext *context) { + GdkInputSource source = gdk_device_get_source(device); + if (source == GDK_SOURCE_MOUSE) { +#ifdef GLASS_GTK3 + GdkGrabStatus status = gdk_device_grab(device, + context->window, + GDK_OWNERSHIP_NONE, + TRUE, + GDK_ALL_EVENTS_MASK, + NULL, + GDK_CURRENT_TIME); +#else + GdkGrabStatus status = GDK_GRAB_SUCCESS; +/* FIXME reachable by 2? + GdkGrabStatus status = gdk_device_grab(device, + context->window, + GDK_OWNERSHIP_NONE, + TRUE, + GDK_ALL_EVENTS_MASK, + NULL, + GDK_CURRENT_TIME); + */ +#endif + if (status == GDK_GRAB_SUCCESS) { + context->grabbed = TRUE; + } + } +} + +static void +ungrab_mouse_device(GdkDevice *device) { +#ifdef GLASS_GTK3 + GdkInputSource source = gdk_device_get_source(device); + if (source == GDK_SOURCE_MOUSE) { + gdk_device_ungrab(device, GDK_CURRENT_TIME); + } +#else + (void) device; + // not used on the GTK2 path +#endif +} + +GdkPixbuf * +glass_pixbuf_from_window(GdkWindow *window, + gint srcx, gint srcy, + gint width, gint height) +{ + GdkPixbuf * ret = NULL; + +#ifdef GLASS_GTK3 + ret = gdk_pixbuf_get_from_window (window, srcx, srcy, width, height); +#else + ret = gdk_pixbuf_get_from_drawable (NULL, + window, + NULL, + srcx, srcy, + 0, 0, + width, height); +#endif + return ret; +} + +void +glass_window_apply_shape_mask(GdkWindow *window, + void* data, uint width, uint height) +{ +#ifdef GLASS_GTK3 + (void) window; + (void) data; + (void) width; + (void) height; +#else + GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data((guchar *) data, + GDK_COLORSPACE_RGB, TRUE, 8, width, height, width * 4, NULL, NULL); + + if (GDK_IS_PIXBUF(pixbuf)) { + GdkBitmap* mask = NULL; + gdk_pixbuf_render_pixmap_and_mask(pixbuf, NULL, &mask, 128); + + gdk_window_input_shape_combine_mask(window, mask, 0, 0); + + g_object_unref(pixbuf); + if (mask) { + g_object_unref(mask); + } + } +#endif +} + +void +glass_window_reset_input_shape_mask(GdkWindow *window) +{ +#ifdef GLASS_GTK3 + gdk_window_input_shape_combine_region(window, NULL, 0, 0); +#else + gdk_window_input_shape_combine_mask(window, NULL, 0, 0); +#endif +} + +GdkWindow * +glass_gdk_drag_context_get_dest_window (GdkDragContext * context) +{ + return ((context != NULL) ? gdk_drag_context_get_dest_window(context) : NULL); +} + + +void glass_gdk_x11_display_set_window_scale (GdkDisplay *display, + gint scale) +{ +#ifdef GLASS_GTK3 + // Optional call, if it does not exist then GTK3 is not yet + // doing automatic scaling of coordinates so we do not need + // to override it. + wrapped_gdk_x11_display_set_window_scale(display, scale); +#else + (void) display; + (void) scale; +#endif +} + +//-------- Glass utility ---------------------------------------- + +void +glass_widget_set_visual(GtkWidget *widget, GdkVisual *visual) +{ +#ifdef GLASS_GTK3 + gtk_widget_set_visual (widget, visual); +#else + GdkColormap *colormap = gdk_colormap_new(visual, TRUE); + gtk_widget_set_colormap (widget, colormap); +#endif +} + +guint glass_settings_get_guint_opt (const gchar *schema_name, + const gchar *key_name, + int defval) +{ + GSettingsSchemaSource *default_schema_source = + wrapped_g_settings_schema_source_get_default(); + if (default_schema_source == NULL) { + if (gtk_verbose) { + fprintf(stderr, "No schema source dir found!\n"); + } + return defval; + } + GSettingsSchema *the_schema = + wrapped_g_settings_schema_source_lookup(default_schema_source, schema_name, TRUE); + if (the_schema == NULL) { + if (gtk_verbose) { + fprintf(stderr, "schema '%s' not found!\n", schema_name); + } + return defval; + } + if (!wrapped_g_settings_schema_has_key(the_schema, key_name)) { + if (gtk_verbose) { + fprintf(stderr, "key '%s' not found in schema '%s'!\n", key_name, schema_name); + } + return defval; + } + if (gtk_verbose) { + fprintf(stderr, "found schema '%s' and key '%s'\n", schema_name, key_name); + } + + GSettings *gset = g_settings_new(schema_name); + + wrapped_g_settings_schema_unref(the_schema); + + return g_settings_get_uint(gset, key_name); +} --- old/modules/graphics/src/main/native-glass/gtk/glass_general.h 2018-10-10 16:43:31.718662979 +0530 +++ new/modules/graphics/src/main/native-glass/gtk/glass_general.h 2018-10-10 16:43:31.474662979 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, 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 @@ -27,12 +27,21 @@ #include - #include #include #include +#include #include +#include "wrapped.h" + +#if GTK_CHECK_VERSION(3, 0, 0) +#if ! GTK_CHECK_VERSION(3, 8, 0) +#error GTK development version is not the minimum 3.8 +#endif +#define GLASS_GTK3 +#endif + #define JLONG_TO_PTR(value) ((void*)(intptr_t)(value)) #define PTR_TO_JLONG(value) ((jlong)(intptr_t)(value)) @@ -42,6 +51,8 @@ extern JNIEnv* mainEnv; // Use only with main loop thread!!! +#define GLASS_GDK_KEY_CONSTANT(key) (GDK_KEY_ ## key) + #include struct jni_exception: public std::exception { @@ -247,5 +258,96 @@ jobject uris_to_java(JNIEnv *env, gchar **uris, gboolean files); +#ifdef __cplusplus +extern "C" { +#endif + +extern jboolean gtk_verbose; + +void +glass_widget_set_visual (GtkWidget *widget, GdkVisual *visual); + +gint +glass_gdk_visual_get_depth (GdkVisual * visual); + +GdkScreen * +glass_gdk_window_get_screen(GdkWindow * gdkWindow); + +gboolean +glass_gdk_mouse_devices_grab(GdkWindow * gdkWindow); + +gboolean +glass_gdk_mouse_devices_grab_with_cursor(GdkWindow * gdkWindow, GdkCursor *cursor, gboolean owner_events); + +void +glass_gdk_mouse_devices_ungrab(); + +void +glass_gdk_master_pointer_grab(GdkWindow *window, GdkCursor *cursor); + +void +glass_gdk_master_pointer_ungrab(); + +void +glass_gdk_master_pointer_get_position(gint *x, gint *y); + +gboolean +glass_gdk_device_is_grabbed(GdkDevice *device); + +void +glass_gdk_device_ungrab(GdkDevice *device); + +GdkWindow * +glass_gdk_device_get_window_at_position( + GdkDevice *device, gint *x, gint *y); + +void +glass_gtk_configure_transparency_and_realize(GtkWidget *window, + gboolean transparent); + +const guchar * +glass_gtk_selection_data_get_data_with_length( + GtkSelectionData * selectionData, + gint * length); + +void +glass_gtk_window_configure_from_visual(GtkWidget *widget, GdkVisual *visual); + +void +glass_gdk_window_get_size(GdkWindow *window, gint *w, gint *h); + +void +glass_gdk_display_get_pointer(GdkDisplay* display, gint* x, gint *y); + +void +glass_gdk_x11_display_set_window_scale(GdkDisplay *display, gint scale); + +gboolean +glass_configure_window_transparency(GtkWidget *window, gboolean transparent); + +GdkPixbuf * +glass_pixbuf_from_window(GdkWindow *window, + gint srcx, gint srcy, + gint width, gint height); + +void +glass_window_apply_shape_mask(GdkWindow *window, + void* data, uint width, uint height); + +void +glass_window_reset_input_shape_mask(GdkWindow *window); + +GdkWindow * +glass_gdk_drag_context_get_dest_window (GdkDragContext * context); + +guint +glass_settings_get_guint_opt (const gchar *schema_name, + const gchar *key_name, + int defval); + +#ifdef __cplusplus +} +#endif + #endif /* GLASS_GENERAL_H */ --- old/modules/graphics/src/main/native-glass/gtk/glass_key.cpp 2018-10-10 16:43:32.422662979 +0530 +++ new/modules/graphics/src/main/native-glass/gtk/glass_key.cpp 2018-10-10 16:43:32.138662979 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, 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 @@ -23,13 +23,12 @@ * questions. */ #include "glass_key.h" -#include "glass_gtkcompat.h" #include #include #include -#include -#include +#include "glass_general.h" +#include static gboolean key_initialized = FALSE; static GHashTable *keymap; --- old/modules/graphics/src/main/native-glass/gtk/glass_screen.cpp 2018-10-10 16:43:33.262662979 +0530 +++ new/modules/graphics/src/main/native-glass/gtk/glass_screen.cpp 2018-10-10 16:43:32.954662979 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, 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 @@ -119,7 +119,7 @@ jobject jScreen = env->NewObject(jScreenCls, jScreenInit, (jlong)monitor_idx, - visual ? visual->depth : 0, + (visual ? glass_gdk_visual_get_depth(visual) : 0), monitor_geometry.x, monitor_geometry.y, --- old/modules/graphics/src/main/native-glass/gtk/glass_window.cpp 2018-10-10 16:43:34.086662979 +0530 +++ new/modules/graphics/src/main/native-glass/gtk/glass_window.cpp 2018-10-10 16:43:33.786662979 +0530 @@ -24,7 +24,6 @@ */ #include "glass_window.h" #include "glass_general.h" -#include "glass_gtkcompat.h" #include "glass_key.h" #include "glass_screen.h" #include "glass_dnd.h" @@ -42,6 +41,10 @@ #include #include +#ifdef GLASS_GTK3 +#include +#endif + #include #include @@ -49,8 +52,6 @@ WindowContext * WindowContextBase::sm_grab_window = NULL; WindowContext * WindowContextBase::sm_mouse_drag_window = NULL; -GdkAtom atom_net_wm_state = gdk_atom_intern_static_string("_NET_WM_STATE"); - GdkWindow* WindowContextBase::get_gdk_window(){ return gdk_window; } @@ -353,6 +354,11 @@ // converting direction to change in pixels switch (event->direction) { +#if GTK_CHECK_VERSION(3, 4, 0) + case GDK_SCROLL_SMOOTH: + //FIXME 3.4 ??? + break; +#endif case GDK_SCROLL_UP: dy = 1; break; @@ -418,7 +424,21 @@ if (key >= 'a' && key <= 'z' && (event->state & GDK_CONTROL_MASK)) { key = key - 'a' + 1; // map 'a' to ctrl-a, and so on. } else { - key = glass_gtk_fixup_typed_key(key, event->keyval); +#ifdef GLASS_GTK2 + if (key == 0) { + // Work around "bug" fixed in gtk-3.0: + // http://mail.gnome.org/archives/commits-list/2011-March/msg06832.html + switch (event->keyval) { + case 0xFF08 /* Backspace */: key = '\b'; + case 0xFF09 /* Tab */: key = '\t'; + case 0xFF0A /* Linefeed */: key = '\n'; + case 0xFF0B /* Vert. Tab */: key = '\v'; + case 0xFF0D /* Return */: key = '\r'; + case 0xFF1B /* Escape */: key = '\033'; + case 0xFFFF /* Delete */: key = '\177'; + } + } +#endif } if (key > 0) { @@ -464,8 +484,13 @@ return; } +#ifdef GLASS_GTK3 + cairo_region_t *region = gdk_window_get_clip_region(gdk_window); + gdk_window_begin_paint_region(gdk_window, region); +#endif + cairo_t* context; - context = gdk_cairo_create(GDK_DRAWABLE(gdk_window)); + context = gdk_cairo_create(gdk_window); cairo_surface_t* cairo_surface; cairo_surface = cairo_image_surface_create_for_data( @@ -476,8 +501,13 @@ applyShapeMask(data, width, height); cairo_set_source_surface(context, cairo_surface, 0, 0); + cairo_set_operator (context, CAIRO_OPERATOR_SOURCE); cairo_paint(context); +#ifdef GLASS_GTK3 + gdk_window_end_paint(gdk_window); + cairo_region_destroy(region); +#endif cairo_destroy(context); cairo_surface_destroy(cairo_surface); @@ -496,7 +526,7 @@ void WindowContextBase::show_or_hide_children(bool show) { std::set::iterator it; for (it = children.begin(); it != children.end(); ++it) { - (*it)->set_visible(show); + (*it)->set_minimized(!show); (*it)->show_or_hide_children(show); } } @@ -599,18 +629,26 @@ WindowContextBase::sm_mouse_drag_window->get_gdk_window(), cursor, FALSE); } else if (WindowContextBase::sm_grab_window) { glass_gdk_mouse_devices_grab_with_cursor( - WindowContextBase::sm_grab_window->get_gdk_window(), cursor); + WindowContextBase::sm_grab_window->get_gdk_window(), cursor, TRUE); } } gdk_window_set_cursor(gdk_window, cursor); } void WindowContextBase::set_background(float r, float g, float b) { +#ifdef GLASS_GTK3 + GdkRGBA rgba = {0, 0, 0, 1.}; + rgba.red = r; + rgba.green = g; + rgba.blue = b; + gdk_window_set_background_rgba(gdk_window, &rgba); +#else GdkColor color; color.red = (guint16) (r * 65535); color.green = (guint16) (g * 65535); color.blue = (guint16) (b * 65535); gtk_widget_modify_bg(gtk_widget, GTK_STATE_NORMAL, &color); +#endif } WindowContextBase::~WindowContextBase() { @@ -636,7 +674,6 @@ frame_type(_frame_type), owner(_owner), geometry(), - stale_config_notifications(), resizable(), frame_extents_initialized(), map_received(false), @@ -719,7 +756,7 @@ void WindowContextTop::request_frame_extents() { - Display *display = GDK_WINDOW_XDISPLAY(gdk_window); + Display *display = GDK_DISPLAY_XDISPLAY(gdk_window_get_display(gdk_window)); Atom rfeAtom = XInternAtom(display, "_NET_REQUEST_FRAME_EXTENTS", True); if (rfeAtom != None) { XClientMessageEvent clientMessage; @@ -738,7 +775,7 @@ } void WindowContextTop::activate_window() { - Display *display = GDK_WINDOW_XDISPLAY(gdk_window); + Display *display = GDK_DISPLAY_XDISPLAY (gdk_window_get_display (gdk_window)); Atom navAtom = XInternAtom(display, "_NET_ACTIVE_WINDOW", True); if (navAtom != None) { XClientMessageEvent clientMessage; @@ -797,7 +834,6 @@ return false; } - static int geometry_get_window_width(const WindowGeometry *windowGeometry) { return (windowGeometry->final_width.type != BOUNDSTYPE_WINDOW) ? windowGeometry->final_width.value @@ -869,6 +905,7 @@ // Workaround for https://bugs.launchpad.net/unity/+bug/998073 static GdkAtom atom_atom = gdk_atom_intern_static_string("ATOM"); + static GdkAtom atom_net_wm_state = gdk_atom_intern_static_string("_NET_WM_STATE"); static GdkAtom atom_net_wm_state_hidden = gdk_atom_intern_static_string("_NET_WM_STATE_HIDDEN"); static GdkAtom atom_net_wm_state_above = gdk_atom_intern_static_string("_NET_WM_STATE_ABOVE"); @@ -904,102 +941,77 @@ } void WindowContextTop::process_property_notify(GdkEventProperty* event) { + static GdkAtom atom_net_wm_state = gdk_atom_intern_static_string("_NET_WM_STATE"); + if (event->atom == atom_net_wm_state && event->window == gdk_window) { process_net_wm_property(); - } else if (event->atom == get_net_frame_extents_atom() && - event->window == gdk_window) { - int top, left, bottom, right; - if (get_frame_extents_property(&top, &left, &bottom, &right)) { - int oldX = geometry_get_window_x(&geometry); - int oldY = geometry_get_window_y(&geometry); - int oldWidth = geometry_get_content_width(&geometry); - int oldHeight = geometry_get_content_height(&geometry); - - bool updateWindowConstraints = geometry.extents.top != top - || geometry.extents.left != left - || geometry.extents.bottom != bottom - || geometry.extents.right != right; + } +} +void WindowContextTop::process_configure(GdkEventConfigure* event) { + gint x, y, w, h; + bool updateWindowConstraints = false; + if (gtk_window_get_decorated(GTK_WINDOW(gtk_widget))) { + GdkRectangle frame; + gint top, left, bottom, right; + + gdk_window_get_frame_extents(gdk_window, &frame); + gint contentX, contentY; + gdk_window_get_origin(gdk_window, &contentX, &contentY); +#ifdef GLASS_GTK3 + gdk_window_get_geometry(gdk_window, NULL, NULL, &w, &h); +#else + gdk_window_get_geometry(gdk_window, NULL, NULL, &w, &h, NULL); +#endif + x = frame.x; + y = frame.y; + geometry.current_width = frame.width; + geometry.current_height = frame.height; + + top = contentY - frame.y; + left = contentX - frame.x; + bottom = frame.y + frame.height - (contentY + h); + right = frame.x + frame.width - (contentX + w); + if (geometry.extents.top != top + || geometry.extents.left != left + || geometry.extents.bottom != bottom + || geometry.extents.right != right) { + updateWindowConstraints = true; geometry.extents.top = top; geometry.extents.left = left; geometry.extents.bottom = bottom; geometry.extents.right = right; - - if (updateWindowConstraints) { - update_window_constraints(); - } - - XWindowChanges windowChanges; - unsigned int windowChangesMask = 0; - - int newX = geometry_get_window_x(&geometry); - int newY = geometry_get_window_y(&geometry); - int newWidth = geometry_get_content_width(&geometry); - int newHeight = geometry_get_content_height(&geometry); - - if (oldX != newX) { - windowChanges.x = newX; - windowChangesMask |= CWX; - } - - if (oldY != newY) { - windowChanges.y = newY; - windowChangesMask |= CWY; - } - - if (oldWidth != newWidth) { - windowChanges.width = newWidth; - windowChangesMask |= CWWidth; - } - - if (oldHeight != newHeight) { - windowChanges.height = newHeight; - windowChangesMask |= CWHeight; - } - - window_configure(&windowChanges, windowChangesMask); - - if (jview) { - mainEnv->CallVoidMethod(jview, jViewNotifyView, com_sun_glass_events_ViewEvent_MOVE); - CHECK_JNI_EXCEPTION(mainEnv) - } } - } -} - -void WindowContextTop::process_configure(GdkEventConfigure* event) { - - geometry.current_width = event->width + geometry.extents.left - + geometry.extents.right; - geometry.current_height = event->height + geometry.extents.top - + geometry.extents.bottom; - gint x, y; - if (gtk_window_get_decorated(GTK_WINDOW(gtk_widget))) { - gtk_window_get_position(GTK_WINDOW(gtk_widget), &x, &y); } else { x = event->x; y = event->y; + w = event->width; + h = event->height; } - if (stale_config_notifications == 0) { - if ((geometry_get_content_width(&geometry) != event->width) - || (geometry_get_content_height(&geometry) != event->height)) { - geometry.final_width.value = event->width; - geometry.final_width.type = BOUNDSTYPE_CONTENT; - geometry.final_height.value = event->height; - geometry.final_height.type = BOUNDSTYPE_CONTENT; - } - geometry_set_window_x(&geometry, x); - geometry_set_window_y(&geometry, y); - } else { - --stale_config_notifications; + if (size_assigned && w <= 1 && h <= 1 && (geometry.final_width.value > 1 || + geometry.final_height.value > 1)) { + // skip artifact + return; } + + geometry.final_width.value = w; + geometry.final_width.type = BOUNDSTYPE_CONTENT; + geometry.final_height.value = h; + geometry.final_height.type = BOUNDSTYPE_CONTENT; + geometry_set_window_x(&geometry, x); + geometry_set_window_y(&geometry, y); + if (jview) { mainEnv->CallVoidMethod(jview, jViewNotifyResize, event->width, event->height); CHECK_JNI_EXCEPTION(mainEnv) + mainEnv->CallVoidMethod(jview, jViewNotifyView, + com_sun_glass_events_ViewEvent_MOVE); + CHECK_JNI_EXCEPTION(mainEnv) } + if (jwindow) { mainEnv->CallVoidMethod(jwindow, jWindowNotifyResize, (is_maximized) @@ -1027,8 +1039,12 @@ } if (resizable.request != REQUEST_NONE) { - set_window_resizable(resizable.request == REQUEST_RESIZABLE, true); + set_window_resizable(resizable.request == REQUEST_RESIZABLE); resizable.request = REQUEST_NONE; + } else if (!resizable.value) { + set_window_resizable(false); + } else if (updateWindowConstraints) { + update_window_constraints(); } } @@ -1050,7 +1066,7 @@ } } -void WindowContextTop::set_window_resizable(bool res, bool grip) { +void WindowContextTop::set_window_resizable(bool res) { if(!res) { int w = geometry_get_content_width(&geometry); int h = geometry_get_content_height(&geometry); @@ -1060,24 +1076,19 @@ GdkGeometry geom = {w, h, w, h, 0, 0, 0, 0, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST}; gtk_window_set_geometry_hints(GTK_WINDOW(gtk_widget), NULL, &geom, static_cast(GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE)); - GLASS_GTK_WINDOW_SET_HAS_RESIZE_GRIP(gdk_window, FALSE); - resizable.prev = resizable.value; resizable.value = false; } else { - resizable.prev = resizable.value; resizable.value = true; update_window_constraints(); - if (grip) { - GLASS_GTK_WINDOW_SET_HAS_RESIZE_GRIP(gdk_window, TRUE); - } } } void WindowContextTop::set_resizable(bool res) { + resizable.prev = false; gint w, h; gtk_window_get_size(GTK_WINDOW(gtk_widget), &w, &h); if (map_received || w > 1 || h > 1) { - set_window_resizable(res, true); + set_window_resizable(res); } else { //Since window is not ready yet set only request for change of resizable. resizable.request = res ? REQUEST_RESIZABLE : REQUEST_NOT_RESIZABLE; @@ -1170,84 +1181,37 @@ return; } - if (!gtk_widget_get_visible(gtk_widget)) { - // not visible yet, synchronize with gtk only - if (windowChangesMask & (CWX | CWY)) { - gint newX, newY; - gtk_window_get_position(GTK_WINDOW(gtk_widget), &newX, &newY); - - if (windowChangesMask & CWX) { - newX = windowChanges->x; - } - if (windowChangesMask & CWY) { - newY = windowChanges->y; - } - - gtk_window_move(GTK_WINDOW(gtk_widget), newX, newY); + if (windowChangesMask & (CWX | CWY)) { + gint newX, newY; + gtk_window_get_position(GTK_WINDOW(gtk_widget), &newX, &newY); + if (windowChangesMask & CWX) { + newX = windowChanges->x; } - - if (windowChangesMask & (CWWidth | CWHeight)) { - gint newWidth, newHeight; - gtk_window_get_size(GTK_WINDOW(gtk_widget), - &newWidth, &newHeight); - - if (windowChangesMask & CWWidth) { - newWidth = windowChanges->width; - } - if (windowChangesMask & CWHeight) { - newHeight = windowChanges->height; - } - - gtk_window_resize(GTK_WINDOW(gtk_widget), newWidth, newHeight); + if (windowChangesMask & CWY) { + newY = windowChanges->y; } - stale_config_notifications = 1; - return; + gtk_window_move(GTK_WINDOW(gtk_widget), newX, newY); } - ++stale_config_notifications; - - if (!resizable.value && (windowChangesMask & (CWWidth | CWHeight))) { - XSizeHints *sizeHints = XAllocSizeHints(); - if (sizeHints != NULL) { - int fixedWidth = (windowChangesMask & CWWidth) - ? windowChanges->width - : geometry_get_content_width(&geometry); - int fixedHeight = (windowChangesMask & CWHeight) - ? windowChanges->height - : geometry_get_content_height(&geometry); - - sizeHints->flags = PMinSize | PMaxSize; - - sizeHints->min_width = 1; - sizeHints->min_height = 1; - sizeHints->max_width = INT_MAX; - sizeHints->max_height = INT_MAX; - XSetWMNormalHints(GDK_WINDOW_XDISPLAY(gdk_window), - GDK_WINDOW_XID(gdk_window), - sizeHints); - - XConfigureWindow(GDK_WINDOW_XDISPLAY(gdk_window), - GDK_WINDOW_XID(gdk_window), - windowChangesMask, - windowChanges); - - sizeHints->min_width = fixedWidth; - sizeHints->min_height = fixedHeight; - sizeHints->max_width = fixedWidth; - sizeHints->max_height = fixedHeight; - XSetWMNormalHints(GDK_WINDOW_XDISPLAY(gdk_window), - GDK_WINDOW_XID(gdk_window), - sizeHints); + if (windowChangesMask & (CWWidth | CWHeight)) { + gint newWidth, newHeight; + gtk_window_get_size(GTK_WINDOW(gtk_widget), &newWidth, &newHeight); - XFree(sizeHints); - return; + if (windowChangesMask & CWWidth) { + newWidth = windowChanges->width; + } + if (windowChangesMask & CWHeight) { + newHeight = windowChanges->height; } + if (!resizable.value) { + GdkGeometry geom; + GdkWindowHints hints = (GdkWindowHints)(GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE); + geom.min_width = geom.max_width = newWidth; + geom.min_height = geom.max_height = newHeight; + gtk_window_set_geometry_hints(GTK_WINDOW(gtk_widget), NULL, &geom, hints); + } + gtk_window_resize(GTK_WINDOW(gtk_widget), newWidth, newHeight); } - - XConfigureWindow(GDK_WINDOW_XDISPLAY(gdk_window), - GDK_WINDOW_XID(gdk_window), - windowChangesMask, - windowChanges); } void WindowContextTop::applyShapeMask(void* data, uint width, uint height) @@ -1256,19 +1220,21 @@ return; } - GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data((guchar *) data, - GDK_COLORSPACE_RGB, TRUE, 8, width, height, width * 4, NULL, NULL); + glass_window_apply_shape_mask(gtk_widget_get_window(gtk_widget), data, width, height); +} - if (GDK_IS_PIXBUF(pixbuf)) { - GdkBitmap* mask = NULL; - gdk_pixbuf_render_pixmap_and_mask(pixbuf, NULL, &mask, 128); - - gdk_window_input_shape_combine_mask(gdk_window, mask, 0, 0); - - g_object_unref(pixbuf); - if (mask) { - g_object_unref(mask); - } +void WindowContextTop::ensure_window_size() { + gint w, h; +#ifdef GLASS_GTK3 + gdk_window_get_geometry(gdk_window, NULL, NULL, &w, &h); +#else + gdk_window_get_geometry(gdk_window, NULL, NULL, &w, &h, NULL); +#endif + if (size_assigned && (geometry.final_width.value != w + || geometry.final_height.value != h)) { + + gdk_window_resize(gdk_window, geometry.final_width.value, + geometry.final_height.value); } } @@ -1277,7 +1243,7 @@ if (minimize) { if (frame_type == TRANSPARENT) { // https://bugs.launchpad.net/ubuntu/+source/unity/+bug/1245571 - gdk_window_input_shape_combine_mask(gdk_window, NULL, 0, 0); + glass_window_reset_input_shape_mask(gtk_widget_get_window(gtk_widget)); } if ((gdk_windowManagerFunctions & GDK_FUNC_MINIMIZE) == 0) { @@ -1295,6 +1261,7 @@ void WindowContextTop::set_maximized(bool maximize) { is_maximized = maximize; if (maximize) { + ensure_window_size(); gtk_window_maximize(GTK_WINDOW(gtk_widget)); } else { gtk_window_unmaximize(GTK_WINDOW(gtk_widget)); @@ -1302,6 +1269,7 @@ } void WindowContextTop::enter_fullscreen() { + ensure_window_size(); gtk_window_fullscreen(GTK_WINDOW(gtk_widget)); } @@ -1327,11 +1295,17 @@ void WindowContextTop::set_enabled(bool enabled) { if (enabled) { - //set back proper resizable value. - set_window_resizable(resizable.prev, true); + if (resizable.prev) { + set_window_resizable(true); + } } else { - //disabled window can't be resizable. - set_window_resizable(false, false); + if (resizable.value) { + set_window_resizable(false); + resizable.prev = true; + } else if (resizable.request == REQUEST_RESIZABLE) { + resizable.request = REQUEST_NOT_RESIZABLE; + resizable.prev = true; + } } } @@ -1470,8 +1444,7 @@ parent() { jwindow = mainEnv->NewGlobalRef(_jwindow); - - gtk_widget = gtk_plug_new((GdkNativeWindow)PTR_TO_JLONG(_owner)); + gtk_widget = gtk_plug_new((Window)PTR_TO_JLONG(_owner)); g_signal_connect(G_OBJECT(gtk_widget), "configure-event", G_CALLBACK(plug_configure), this); @@ -1704,8 +1677,10 @@ if (view) { gint width, height; jview = mainEnv->NewGlobalRef(view); - width = gtk_widget->allocation.width; - height = gtk_widget->allocation.height; + GtkAllocation ws; + gtk_widget_get_allocation(gtk_widget, &ws); + width = ws.width; + height = ws.height; mainEnv->CallVoidMethod(view, jViewNotifyResize, width, height); CHECK_JNI_EXCEPTION_RET(mainEnv, FALSE) } else { @@ -1734,8 +1709,10 @@ if (w > 0 || h > 0) { gint newWidth, newHeight; - newWidth = gtk_widget->allocation.width; - newHeight = gtk_widget->allocation.height; + GtkAllocation ws; + gtk_widget_get_allocation(gtk_widget, &ws); + newWidth = ws.width; + newHeight = ws.height; if (w > 0) { newWidth = w; @@ -1793,7 +1770,11 @@ NORMAL, (GdkWMFunction) 0); int x, y, w, h; gdk_window_get_origin(gdk_window, &x, &y); +#ifdef GLASS_GTK3 + gdk_window_get_geometry(gdk_window, NULL, NULL, &w, &h); +#else gdk_window_get_geometry(gdk_window, NULL, NULL, &w, &h, NULL); +#endif full_screen_window->set_bounds(x, y, true, true, w, h, -1, -1); if (WindowContextBase::sm_grab_window == this) { --- old/modules/graphics/src/main/native-glass/gtk/glass_window.h 2018-10-10 16:43:34.830662979 +0530 +++ new/modules/graphics/src/main/native-glass/gtk/glass_window.h 2018-10-10 16:43:34.554662979 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, 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 @@ -367,7 +367,6 @@ WindowFrameType frame_type; struct WindowContext *owner; WindowGeometry geometry; - int stale_config_notifications; struct _Resizable{// we can't use set/get gtk_window_resizable function _Resizable(): request(REQUEST_NONE), value(true), prev(false), minw(-1), minh(-1), maxw(-1), maxh(-1){} @@ -427,10 +426,11 @@ void initialize_frame_extents(); void window_configure(XWindowChanges *, unsigned int); void update_window_constraints(); - void set_window_resizable(bool, bool); + void set_window_resizable(bool); void update_ontop_tree(bool); bool on_top_inherited(); bool effective_on_top(); + void ensure_window_size(); WindowContextTop(WindowContextTop&); WindowContextTop& operator= (const WindowContextTop&); }; --- old/modules/graphics/src/main/native-glass/gtk/glass_window_ime.cpp 2018-10-10 16:43:35.478662979 +0530 +++ new/modules/graphics/src/main/native-glass/gtk/glass_window_ime.cpp 2018-10-10 16:43:35.194662979 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, 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 @@ -26,7 +26,6 @@ #include "com_sun_glass_ui_View.h" #include "glass_window.h" #include "glass_general.h" -#include "glass_gtkcompat.h" #include #include @@ -41,7 +40,7 @@ result.type = (event->type == GDK_KEY_PRESS) ? KeyPress : KeyRelease; result.send_event = event->send_event; - result.display = gdk_x11_display_get_xdisplay(glass_gdk_window_get_display(event->window)); + result.display = gdk_x11_display_get_xdisplay(gdk_window_get_display(event->window)); result.window = result.subwindow = GDK_WINDOW_XID(event->window); result.root = GDK_WINDOW_XID(gdk_screen_get_root_window(glass_gdk_window_get_screen(event->window))); result.time = event->time; @@ -222,7 +221,7 @@ } void WindowContextBase::enableOrResetIME() { - Display *display = gdk_x11_display_get_xdisplay(glass_gdk_window_get_display(gdk_window)); + Display *display = gdk_x11_display_get_xdisplay(gdk_window_get_display(gdk_window)); if (xim.im == NULL || xim.ic == NULL) { xim.im = XOpenIM(display, NULL, NULL, NULL); if (xim.im == NULL) { --- /dev/null 2018-10-10 12:18:08.824000000 +0530 +++ new/modules/graphics/src/main/native-glass/gtk/launcher.c 2018-10-10 16:43:35.878662979 +0530 @@ -0,0 +1,213 @@ +/* + * 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. 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 +#ifndef __USE_GNU // required for dladdr() & Dl_info +#define __USE_GNU +#endif +#include +#include + +#include +#include +#include + +#include + +#include + +#include + +#include + +static jboolean gtk_versionDebug = JNI_FALSE; + +static const char * gtk2_chain[] = { + "libglassgtk2.so", "libglassgtk3.so", 0 +}; + +static const char * gtk3_chain[] = { + "libglassgtk3.so", "libglassgtk2.so", 0 +}; + +static JavaVM* javaVM; + +JNIEXPORT jint JNICALL +JNI_OnLoad(JavaVM *jvm, void *reserved) +{ + (void) reserved; + + javaVM = jvm; + + return JNI_VERSION_1_6; +} + +// our library combinations defined +// "version" "libgtk", "libdgdk", "libpixbuf" +// note that currently only the first char of the version is used +static char * gtk2_versioned[] = { + "2", "libgtk-x11-2.0.so.0" +}; + +static char * gtk2_not_versioned[] = { + "2", "libgtk-x11-2.0.so" +}; + +static char * gtk3_versioned[] = { + "3", "libgtk-3.so.0" +}; + +static char * gtk3_not_versioned[] = { + "3", "libgtk-3.so" +}; + +// our library set orders defined, null terminated +static char ** two_to_three[] = { + gtk2_versioned, gtk2_not_versioned, + gtk3_versioned, gtk3_not_versioned, + 0 +}; + +static char ** three_to_two[] = { + gtk3_versioned, gtk3_not_versioned, + gtk2_versioned, gtk2_not_versioned, + 0 +}; + +static int try_opening_libraries(char *names[3]) +{ + void * gtk; + + gtk = dlopen (names[1], RTLD_LAZY | RTLD_LOCAL); + if (!gtk) { + return 0; + } + + return 1; +} + +static int try_libraries_noload(char *names[3]) +{ +#ifdef RTLD_NOLOAD + void *gtk; + gtk = dlopen(names[1], RTLD_LAZY | RTLD_NOLOAD); + return gtk ? 1 : 0; +#else + return 0; +#endif +} + +static int sniffLibs(int wantVersion) { + + if (gtk_versionDebug) { + printf("checking GTK version %d\n",wantVersion); + } + + int success = 1; + char *** use_chain = two_to_three; + int i, found = 0; + + //at first try to detect already loaded GTK version + for (i = 0; use_chain[i] && !found; i++) { + found = try_libraries_noload(use_chain[i]); + if (found && gtk_versionDebug) { + printf("found already loaded GTK library %s\n", use_chain[i][1]); + } + } + + if (!found) { + if (wantVersion == 0 || wantVersion == 2) { + use_chain = two_to_three; + } else if (wantVersion == 3) { + use_chain = three_to_two; + } else { + // Note, this should never happen, java should be protecting us + if (gtk_versionDebug) { + printf("bad GTK version specified, assuming 2\n"); + } + wantVersion = 2; + use_chain = two_to_three; + } + + for (i = 0; use_chain[i] && !found; i++) { + if (gtk_versionDebug) { + printf("trying GTK library %s\n", use_chain[i][1]); + } + found = try_opening_libraries(use_chain[i]); + } + } + + if (found) { + if (gtk_versionDebug) { + i--; + printf("using GTK library version %s set %s\n", + use_chain[i][0], + use_chain[i][1]); + fflush(stdout); + } + return use_chain[i][0][0]; + } + if (gtk_versionDebug) { + fflush(stdout); + } + return -1; +} + +/* + * Class: com_sun_glass_ui_gtk_GtkApplication + * Method: _queryLibrary + * Signature: Signature: (IZ)I + */ +JNIEXPORT jint JNICALL Java_com_sun_glass_ui_gtk_GtkApplication__1queryLibrary + (JNIEnv *env, jclass clazz, jint suggestedVersion, jboolean verbose) +{ + (void) env; + (void) clazz; + + gtk_versionDebug = verbose; + + // Before doing anything with GTK we validate that the DISPLAY can be opened + Display *display = XOpenDisplay(NULL); + if (display == NULL) { + return com_sun_glass_ui_gtk_GtkApplication_QUERY_NO_DISPLAY; + } + XCloseDisplay(display); + + // now check the the presence of the libraries + + char version = sniffLibs(suggestedVersion); + + if (version == '2') { + return com_sun_glass_ui_gtk_GtkApplication_QUERY_LOAD_GTK2; + } else if (version == '3') { + return com_sun_glass_ui_gtk_GtkApplication_QUERY_LOAD_GTK3; + } + + return com_sun_glass_ui_gtk_GtkApplication_QUERY_ERROR; +} + --- /dev/null 2018-10-10 12:18:08.824000000 +0530 +++ new/modules/graphics/src/main/native-glass/gtk/wrapped.c 2018-10-10 16:43:36.490662979 +0530 @@ -0,0 +1,150 @@ +/* + * 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. 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 +#ifndef __USE_GNU // required for dladdr() & Dl_info +#define __USE_GNU +#endif +#include +#include + +#include +#include +#include + +#include "wrapped.h" + +extern jboolean gtk_verbose; + +/* + * cpp and dlsym don't play nicely together. Do all dynamic loading in C + */ + +// Note added in Glib 2.36 which is >= our OEL 7.0 version of 2.36 +// but does not seem to be in the headers properly +static GSettingsSchemaSource * (*_g_settings_schema_source_get_default) (void); + +GSettingsSchemaSource * wrapped_g_settings_schema_source_get_default (void) +{ + if(_g_settings_schema_source_get_default == NULL) { + _g_settings_schema_source_get_default = dlsym(RTLD_DEFAULT, "g_settings_schema_source_get_default"); + if (gtk_verbose && _g_settings_schema_source_get_default) { + fprintf(stderr, "loaded g_settings_schema_source_get_default\n"); fflush(stderr); + } + } + + if(_g_settings_schema_source_get_default != NULL) { + return (*_g_settings_schema_source_get_default)(); + } + + return NULL; +} + + +// Note added in Glib 2.36 which is >= our OEL 7.0 version of 2.36 +// but does not seem to be in the headers properly +static GSettingsSchema * + (*_g_settings_schema_source_lookup) (GSettingsSchemaSource *source, + const gchar *schema_id, + gboolean recursive); + +GSettingsSchema * +wrapped_g_settings_schema_source_lookup (GSettingsSchemaSource *source, + const gchar *schema_id, + gboolean recursive) +{ + if(_g_settings_schema_source_lookup == NULL) { + _g_settings_schema_source_lookup = dlsym(RTLD_DEFAULT, "g_settings_schema_source_lookup"); + if (gtk_verbose && _g_settings_schema_source_lookup) { + fprintf(stderr, "loaded g_settings_schema_source_lookup\n"); fflush(stderr); + } + } + + if(_g_settings_schema_source_lookup != NULL) { + return (*_g_settings_schema_source_lookup)(source, schema_id, recursive); + } + + return NULL; +} + +// Note added in Glib 2.40 which is > our OEL 7.0 version of 2.36 +static gboolean (*_g_settings_schema_has_key) (GSettingsSchema *schema, const gchar *name); + +gboolean wrapped_g_settings_schema_has_key (GSettingsSchema *schema, + const gchar *name) +{ + if(_g_settings_schema_has_key == NULL) { + _g_settings_schema_has_key = dlsym(RTLD_DEFAULT, "g_settings_schema_has_key"); + if (gtk_verbose && _g_settings_schema_has_key) { + fprintf(stderr, "loaded g_settings_schema_has_key\n"); fflush(stderr); + } + } + + if(_g_settings_schema_has_key != NULL) { + return (*_g_settings_schema_has_key)(schema, name); + } + + return 0; +} + +static void (*_g_settings_schema_unref) (GSettingsSchema *schema); + +void wrapped_g_settings_schema_unref (GSettingsSchema *schema) +{ + if(_g_settings_schema_unref == NULL) { + _g_settings_schema_unref = dlsym(RTLD_DEFAULT, "g_settings_schema_unref"); + if (gtk_verbose && _g_settings_schema_unref) { + fprintf(stderr, "loaded g_settings_schema_unref\n"); fflush(stderr); + } + } + + if(_g_settings_schema_unref != NULL) { + (*_g_settings_schema_unref)(schema); + } + +} + +static void (*_gdk_x11_display_set_window_scale) (GdkDisplay *display, gint scale); + +// Note added in libgdk 3.10 which is > our OEL 7.0 version of 3.8 +void wrapped_gdk_x11_display_set_window_scale (GdkDisplay *display, + gint scale) +{ +#if GTK_CHECK_VERSION(3, 0, 0) + if(_gdk_x11_display_set_window_scale == NULL) { + _gdk_x11_display_set_window_scale = dlsym(RTLD_DEFAULT, "gdk_x11_display_set_window_scale"); + if (gtk_verbose && _gdk_x11_display_set_window_scale) { + fprintf(stderr, "loaded gdk_x11_display_set_window_scale\n"); fflush(stderr); + } + } +#endif + + if(_gdk_x11_display_set_window_scale != NULL) { + (*_gdk_x11_display_set_window_scale)(display, scale); + } +} + --- /dev/null 2018-10-10 12:18:08.824000000 +0530 +++ new/modules/graphics/src/main/native-glass/gtk/wrapped.h 2018-10-10 16:43:37.054662979 +0530 @@ -0,0 +1,51 @@ +/* + * 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. 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 WRAPPED_H +#define WRAPPED_H + +#ifdef __cplusplus +extern "C" { +#endif + +GSettingsSchemaSource * wrapped_g_settings_schema_source_get_default (void); + +GSettingsSchema * +wrapped_g_settings_schema_source_lookup (GSettingsSchemaSource *source, + const gchar *schema_id, + gboolean recursive); + +gboolean wrapped_g_settings_schema_has_key (GSettingsSchema *schema, const gchar *name); + +void wrapped_g_settings_schema_unref (GSettingsSchema *schema); + +void wrapped_gdk_x11_display_set_window_scale (GdkDisplay *display, gint scale); + +#ifdef __cplusplus +} +#endif + +#endif /* WRAPPED_H */ + --- /dev/null 2018-10-10 12:18:08.824000000 +0530 +++ new/tests/system/src/test/java/javafx/scene/NewSceneSizeTest.java 2018-10-10 16:43:37.654662979 +0530 @@ -0,0 +1,143 @@ +/* + * 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. 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 test.javafx.scene; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javafx.application.Application; +import javafx.application.Platform; +import javafx.beans.value.ChangeListener; +import javafx.scene.Scene; +import javafx.scene.layout.VBox; +import javafx.stage.Stage; +import javafx.stage.WindowEvent; +import junit.framework.Assert; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.fail; + +public class NewSceneSizeTest { + static CountDownLatch startupLatch; + static volatile Stage stage; + + public static void main(String[] args) throws Exception { + initFX(); + try { + NewSceneSizeTest test = new NewSceneSizeTest(); + test.testNewSceneSize(); + } catch (Throwable e) { + e.printStackTrace(); + } finally { + teardown(); + } + } + + public static class TestApp extends Application { + + @Override + public void start(Stage primaryStage) throws Exception { + primaryStage.setScene(new Scene(new VBox())); + stage = primaryStage; + stage.addEventHandler(WindowEvent.WINDOW_SHOWN, e -> + Platform.runLater(startupLatch::countDown)); + stage.show(); + } + } + + @BeforeClass + public static void initFX() { + startupLatch = new CountDownLatch(1); + new Thread(() -> Application.launch(TestApp.class, (String[])null)).start(); + try { + if (!startupLatch.await(15, TimeUnit.SECONDS)) { + fail("Timeout waiting for FX runtime to start"); + } + } catch (InterruptedException ex) { + fail("Unexpected exception: " + ex); + } + } + + @Test + public void testNewSceneSize() throws Exception { + Thread.sleep(200); + final int nTries = 100; + Stage childStage[] = new Stage[nTries]; + double w[] = new double[nTries]; + double h[] = new double[nTries]; + CountDownLatch latch = new CountDownLatch(2 * nTries); + for (int i = 0; i < nTries; i++) { + int fI = i; + Platform.runLater(new Runnable() { + ChangeListener listenerW; + ChangeListener listenerH; + + @Override + public void run() { + Stage stage = new Stage(); + childStage[fI] = stage; + stage.setResizable(fI % 2 == 0); + Scene scene = new Scene(new VBox(), 300 - fI, 200 - fI); + stage.setScene(scene); + w[fI] = stage.getScene().getWidth(); + h[fI] = stage.getScene().getHeight(); + Assert.assertTrue(w[fI] > 1); + Assert.assertTrue(h[fI] > 1); + stage.widthProperty().addListener(listenerW = (v, o, n) -> { + if (Math.abs((Double) n - w[fI]) < 0.1) { + stage.widthProperty().removeListener(listenerW); + Platform.runLater(latch::countDown); + } + }); + stage.heightProperty().addListener(listenerH = (v, o, n) -> { + if (Math.abs((Double) n - h[fI]) < 0.1) { + stage.heightProperty().removeListener(listenerH); + Platform.runLater(latch::countDown); + } + }); + stage.show(); + } + }); + } + latch.await(5, TimeUnit.SECONDS); + Thread.sleep(200); + for (int i = 0; i < nTries; i++) { + Assert.assertEquals("Wrong scene " + i + " width", w[i], + childStage[i].getScene().getWidth()); + Assert.assertEquals("Wrong scene " + i + " height", h[i], + childStage[i].getScene().getHeight()); + } + } + + @AfterClass + public static void teardown() { + Platform.runLater(stage::hide); + Platform.exit(); + } +} + --- /dev/null 2018-10-10 12:18:08.824000000 +0530 +++ new/tests/system/src/test/java/javafx/stage/ChildStageLocationTest.java 2018-10-10 16:43:38.322662979 +0530 @@ -0,0 +1,139 @@ +/* + * 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. 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 test.javafx.stage; + +import java.util.TimerTask; +import java.util.Timer; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javafx.application.Application; +import javafx.application.Platform; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.geometry.Rectangle2D; +import javafx.scene.Scene; +import javafx.scene.control.Label; +import javafx.stage.Screen; +import javafx.stage.Stage; + +import javafx.stage.Window; +import org.junit.BeforeClass; +import org.junit.Test; + +import static junit.framework.Assert.assertTrue; +import static org.junit.Assert.fail; + +public class ChildStageLocationTest { + static CountDownLatch startupLatch; + static Timer timer; + static Runnable runNext; + static volatile Stage stage; + static volatile Stage childStage; + static double x, y; + + public static void main(String[] args) { + initFX(); + new ChildStageLocationTest().testLocation(); + } + + @BeforeClass + public static void initFX() { + startupLatch = new CountDownLatch(1); + new Thread(() -> Application.launch(TestApp.class, (String[])null)).start(); + try { + if (!startupLatch.await(15, TimeUnit.SECONDS)) { + fail("Timeout waiting for FX runtime to start"); + } + } catch (InterruptedException ex) { + fail("Unexpected exception: " + ex); + } + } + + @Test + public void testLocation() { + Rectangle2D bounds = Screen.getPrimary().getVisualBounds(); + Window window = stage.getScene().getWindow(); + double minX = bounds.getMinX() + (bounds.getWidth() - window.getWidth())/2 - 50; + double minY = bounds.getMinY() + (bounds.getHeight() - window.getHeight())/3 - 100; + System.out.println("Primary stage location: " + stage.getX() + " " + stage.getY()); + assertTrue("Primary stage X location should be >" + minX, stage.getX() > minX); + assertTrue("Primary stage Y location should be >" + minY, stage.getY() > minY); + + window = childStage.getScene().getWindow(); + minX = bounds.getMinX() + (bounds.getWidth() - window.getWidth())/2 - 50; + minY = bounds.getMinY() + (bounds.getHeight() - window.getHeight())/3 - 100; + System.out.println("Child stage location: " + childStage.getX() + " " + childStage.getY()); + assertTrue("Child stage X location should be >" + minX, childStage.getX() > minX); + assertTrue("Child stage Y location should be >" + minY, childStage.getY() > minY); + } + + public static class TestApp extends Application implements ChangeListener { + + @Override + public void start(Stage stage) throws Exception { + stage.setScene(new Scene(new Label("Label"))); + stage.xProperty().addListener(this); + stage.yProperty().addListener(this); + stage.widthProperty().addListener(this); + stage.heightProperty().addListener(this); + ChildStageLocationTest.stage = stage; + runNext = () -> { + runNext = () -> {}; + Platform.runLater(this::createChildStage); + }; + stage.show(); + } + + @Override + public void changed(ObservableValue observable, Object oldValue, Object newValue) { + if (timer != null) { + timer.cancel(); + } + timer = new Timer(); + timer.schedule(new TimerTask() { + @Override + public void run() { + runNext.run(); + } + }, 1500); + } + + void createChildStage() { + childStage = new Stage(); + childStage.setScene(new Scene(new Label("Label"))); + childStage.sizeToScene(); + childStage.xProperty().addListener(this); + childStage.yProperty().addListener(this); + childStage.widthProperty().addListener(this); + childStage.heightProperty().addListener(this); + runNext = startupLatch::countDown; + childStage.showAndWait(); + } + } + +} + --- /dev/null 2018-10-10 12:18:08.824000000 +0530 +++ new/tests/system/src/test/java/javafx/stage/MakeResizableAndResizeTest.java 2018-10-10 16:43:38.934662979 +0530 @@ -0,0 +1,155 @@ +/* + * 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. 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 test.javafx.stage; + +import java.io.FileNotFoundException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.TimerTask; +import java.util.Timer; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javafx.application.Application; +import javafx.application.Platform; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.scene.control.Alert; +import javafx.scene.control.Label; +import javafx.scene.control.TextArea; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.Priority; +import javafx.stage.Stage; + +import org.junit.BeforeClass; +import org.junit.Test; + +import static junit.framework.Assert.assertTrue; +import static org.junit.Assert.fail; + +public class MakeResizableAndResizeTest { + static CountDownLatch startupLatch; + static Timer timer; + static Runnable runNext; + static volatile Alert alert; + + public static void main(String[] args) { + initFX(); + new MakeResizableAndResizeTest().testSize(); + } + + @BeforeClass + public static void initFX() { + startupLatch = new CountDownLatch(1); + new Thread(() -> Application.launch(TestApp.class, (String[])null)).start(); + try { + if (!startupLatch.await(15, TimeUnit.SECONDS)) { + fail("Timeout waiting for FX runtime to start"); + } + } catch (InterruptedException ex) { + fail("Unexpected exception: " + ex); + } + } + + @Test + public void testSize() { + assertTrue("Wrong window width", alert.getWidth() >= alert.getDialogPane().getWidth()); + assertTrue("Wrong window height", alert.getHeight() >= alert.getDialogPane().getHeight()); + } + + public static class TestApp extends Application implements ChangeListener { + + + @Override + public void start(Stage stage) throws Exception { + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle("Exception Dialog"); + alert.setHeaderText("ERROR"); + alert.setContentText("Exception: ..."); + + Exception ex = new FileNotFoundException("Could not find file ..."); + + // Create expandable Exception. + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + ex.printStackTrace(pw); + String exceptionText = sw.toString(); + + Label label = new Label("The exception stacktrace was:"); + + TextArea textArea = new TextArea(exceptionText); + textArea.setEditable(false); + textArea.setWrapText(true); + + textArea.setMaxWidth(Double.MAX_VALUE); + textArea.setMaxHeight(Double.MAX_VALUE); + GridPane.setVgrow(textArea, Priority.ALWAYS); + GridPane.setHgrow(textArea, Priority.ALWAYS); + + GridPane expContent = new GridPane(); + expContent.setMaxWidth(Double.MAX_VALUE); + expContent.add(label, 0, 0); + expContent.add(textArea, 0, 1); + + // Set expandable Exception into the dialog pane. + alert.getDialogPane().setExpandableContent(expContent); + alert.xProperty().addListener(this); + alert.yProperty().addListener(this); + alert.widthProperty().addListener(this); + alert.heightProperty().addListener(this); + + MakeResizableAndResizeTest.alert = alert; + runNext = () -> { + System.out.println("Alert window created."); + runNext = () -> {}; + Platform.runLater(this::resize); + }; + alert.showAndWait(); + } + + @Override + public void changed(ObservableValue observable, Object oldValue, Object newValue) { + if (timer != null) { + timer.cancel(); + } + timer = new Timer(); + timer.schedule(new TimerTask() { + @Override + public void run() { + runNext.run(); + } + }, 1500); + } + + void resize() { + alert.getDialogPane().setExpanded(true); + System.out.println("Details expanded."); + runNext = startupLatch::countDown; + } + } + +} + --- /dev/null 2018-10-10 12:18:08.824000000 +0530 +++ new/tests/system/src/test/java/javafx/stage/RestoreStagePositionTest.java 2018-10-10 16:43:39.518662979 +0530 @@ -0,0 +1,165 @@ +/* + * 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. 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 test.javafx.stage; + +import javafx.application.Application; +import javafx.application.Platform; +import javafx.beans.value.ChangeListener; +import javafx.scene.Scene; +import javafx.scene.layout.VBox; +import javafx.stage.Stage; +import javafx.stage.WindowEvent; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.fail; + +public class RestoreStagePositionTest { + static CountDownLatch startupLatch; + static Stage stage; + + public static void main(String[] args) throws Exception { + initFX(); + try { + RestoreStagePositionTest test = new RestoreStagePositionTest(); + test.testUfullscreenPosition(); + test.testDemaximizedPosition(); + } catch (Throwable e) { + e.printStackTrace(); + } finally { + teardown(); + } + } + + public static class TestApp extends Application { + + @Override + public void start(Stage primaryStage) throws Exception { + primaryStage.setScene(new Scene(new VBox())); + stage = primaryStage; + stage.setX(300); + stage.setY(400); + stage.addEventHandler(WindowEvent.WINDOW_SHOWN, e -> + Platform.runLater(startupLatch::countDown)); + stage.show(); + } + } + + @BeforeClass + public static void initFX() { + startupLatch = new CountDownLatch(1); + new Thread(() -> Application.launch(TestApp.class, (String[])null)).start(); + try { + if (!startupLatch.await(15, TimeUnit.SECONDS)) { + fail("Timeout waiting for FX runtime to start"); + } + } catch (InterruptedException ex) { + fail("Unexpected exception: " + ex); + } + } + + + @Test + public void testUfullscreenPosition() throws Exception { + Thread.sleep(200); + Assert.assertTrue(stage.isShowing()); + Assert.assertFalse(stage.isFullScreen()); + + double x = stage.getX(); + double y = stage.getY(); + + Platform.runLater(() -> stage.setFullScreen(true)); + Thread.sleep(400); + Assert.assertTrue(stage.isFullScreen()); + CountDownLatch latch = new CountDownLatch(2); + + ChangeListener listenerX = (observable, oldValue, newValue) -> { + if (Math.abs((Double) newValue - x) < 0.1) { + latch.countDown(); + }; + }; + ChangeListener listenerY = (observable, oldValue, newValue) -> { + if (Math.abs((Double) newValue - y) < 0.1) { + latch.countDown(); + }; + }; + stage.xProperty().addListener(listenerX); + stage.yProperty().addListener(listenerY); + Platform.runLater(() -> stage.setFullScreen(false)); + latch.await(5, TimeUnit.SECONDS); + stage.xProperty().removeListener(listenerX); + stage.xProperty().removeListener(listenerY); + + Assert.assertEquals("Window was moved", x, stage.getX(), 0.1); + Assert.assertEquals("Window was moved", y, stage.getY(), 0.1); + } + + @Test + public void testDemaximizedPosition() throws Exception { + Thread.sleep(200); + Assert.assertTrue(stage.isShowing()); + Assert.assertFalse(stage.isMaximized()); + + double x = stage.getX(); + double y = stage.getY(); + + Platform.runLater(() -> stage.setMaximized(true)); + Thread.sleep(200); + Assert.assertTrue(stage.isMaximized()); + CountDownLatch latch = new CountDownLatch(2); + + ChangeListener listenerX = (observable, oldValue, newValue) -> { + if (Math.abs((Double) newValue - x) < 0.1) { + latch.countDown(); + }; + }; + ChangeListener listenerY = (observable, oldValue, newValue) -> { + if (Math.abs((Double) newValue - y) < 0.1) { + latch.countDown(); + }; + }; + stage.xProperty().addListener(listenerX); + stage.yProperty().addListener(listenerY); + Platform.runLater(() -> stage.setMaximized(false)); + latch.await(5, TimeUnit.SECONDS); + stage.xProperty().removeListener(listenerX); + stage.xProperty().removeListener(listenerY); + + Assert.assertEquals("Window was moved", x, stage.getX(), 0.1); + Assert.assertEquals("Window was moved", y, stage.getY(), 0.1); + } + + @AfterClass + public static void teardown() { + Platform.runLater(stage::hide); + Platform.exit(); + } +} + --- /dev/null 2018-10-10 12:18:08.824000000 +0530 +++ new/tests/system/src/test/java/test/javafx/scene/RestoreSceneSizeTest.java 2018-10-10 16:43:40.134662979 +0530 @@ -0,0 +1,126 @@ +/* + * 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. 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 test.javafx.scene; + +import javafx.application.Application; +import javafx.application.Platform; +import javafx.beans.value.ChangeListener; +import javafx.scene.Scene; +import javafx.scene.layout.VBox; +import javafx.stage.Stage; +import javafx.stage.WindowEvent; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.fail; + +public class RestoreSceneSizeTest { + static CountDownLatch startupLatch; + static Stage stage; + static double w; + static double h; + + public static void main(String[] args) throws Exception { + initFX(); + try { + RestoreSceneSizeTest test = new RestoreSceneSizeTest(); + test.testUnfullscreenSize(); + } catch (Throwable e) { + e.printStackTrace(); + } finally { + teardown(); + } + } + + public static class TestApp extends Application { + + @Override + public void start(Stage primaryStage) throws Exception { + primaryStage.setScene(new Scene(new VBox(), 234, 255)); + stage = primaryStage; + w = stage.getScene().getWidth(); + h = stage.getScene().getHeight(); + stage.setFullScreen(true); + stage.addEventHandler(WindowEvent.WINDOW_SHOWN, e -> + Platform.runLater(startupLatch::countDown)); + stage.show(); + } + } + + @BeforeClass + public static void initFX() { + startupLatch = new CountDownLatch(1); + new Thread(() -> Application.launch(TestApp.class, (String[])null)).start(); + try { + if (!startupLatch.await(15, TimeUnit.SECONDS)) { + fail("Timeout waiting for FX runtime to start"); + } + } catch (InterruptedException ex) { + fail("Unexpected exception: " + ex); + } + } + + @Test + public void testUnfullscreenSize() throws Exception { + Thread.sleep(200); + Assert.assertTrue(stage.isShowing()); + Assert.assertTrue(stage.isFullScreen()); + + CountDownLatch latch = new CountDownLatch(2); + ChangeListener listenerW = (observable, oldValue, newValue) -> { + if (Math.abs((Double) newValue - w) < 0.1) { + latch.countDown(); + }; + }; + ChangeListener listenerH = (observable, oldValue, newValue) -> { + if (Math.abs((Double) newValue - h) < 0.1) { + latch.countDown(); + }; + }; + stage.getScene().widthProperty().addListener(listenerW); + stage.getScene().heightProperty().addListener(listenerH); + Platform.runLater(() -> stage.setFullScreen(false)); + latch.await(5, TimeUnit.SECONDS); + Thread.sleep(200); + Assert.assertFalse(stage.isFullScreen()); + stage.getScene().widthProperty().removeListener(listenerW); + stage.getScene().heightProperty().removeListener(listenerH); + + Assert.assertEquals("Scene got wrong width", w, stage.getScene().getWidth(), 0.1); + Assert.assertEquals("Scene got wrong height", h, stage.getScene().getHeight(), 0.1); + } + + @AfterClass + public static void teardown() { + Platform.runLater(stage::hide); + Platform.exit(); + } +} + --- /dev/null 2018-10-10 12:18:08.824000000 +0530 +++ new/tests/system/src/test/java/test/javafx/stage/DeiconifiedWithChildTest.java 2018-10-10 16:43:40.778662979 +0530 @@ -0,0 +1,112 @@ +/* + * 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. 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 test.javafx.stage; + +import javafx.application.Application; +import javafx.application.Platform; +import javafx.scene.Scene; +import javafx.scene.layout.VBox; +import javafx.stage.Stage; +import javafx.stage.WindowEvent; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.fail; + +public class DeiconifiedWithChildTest { + static CountDownLatch startupLatch; + static Stage stage; + static Stage childStage; + + public static void main(String[] args) throws Exception { + initFX(); + try { + new DeiconifiedWithChildTest().testDeiconifiedPosition(); + } finally { + teardown(); + } + } + + public static class TestApp extends Application { + + @Override + public void start(Stage primaryStage) throws Exception { + primaryStage.setScene(new Scene(new VBox(), 200, 200)); + stage = primaryStage; + stage.show(); + + childStage = new Stage(); + childStage.initOwner(stage); + childStage.setScene(new Scene(new VBox(), 100, 100)); + childStage.addEventHandler(WindowEvent.WINDOW_SHOWN, e -> + Platform.runLater(startupLatch::countDown)); + childStage.show(); + } + } + + @BeforeClass + public static void initFX() { + startupLatch = new CountDownLatch(1); + new Thread(() -> Application.launch(TestApp.class, (String[])null)).start(); + try { + if (!startupLatch.await(15, TimeUnit.SECONDS)) { + fail("Timeout waiting for FX runtime to start"); + } + } catch (InterruptedException ex) { + fail("Unexpected exception: " + ex); + } + } + + @Test + public void testDeiconifiedPosition() throws Exception { + Thread.sleep(200); + Assert.assertTrue(stage.isShowing()); + Assert.assertTrue(childStage.isShowing()); + Assert.assertFalse(stage.isIconified()); + + double x = childStage.getX(); + double y = childStage.getY(); + + Platform.runLater(() -> stage.setIconified(true)); + Thread.sleep(200); + Platform.runLater(() -> stage.setIconified(false)); + Thread.sleep(200); + Assert.assertEquals("Child window was moved", x, childStage.getX(), 0.1); + Assert.assertEquals("Child window was moved", y, childStage.getY(), 0.1); + } + + @AfterClass + public static void teardown() { + Platform.runLater(childStage::hide); + Platform.runLater(stage::hide); + Platform.exit(); + } +} + --- /dev/null 2018-10-10 12:18:08.824000000 +0530 +++ new/tests/system/src/test/java/test/robot/javafx/scene/AfterModalClosedTest.java 2018-10-10 16:43:41.362662979 +0530 @@ -0,0 +1,130 @@ +/* + * 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. 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 test.robot.javafx.scene; + +import com.sun.glass.ui.Robot; +import com.sun.javafx.PlatformUtil; +import javafx.application.Application; +import javafx.application.Platform; +import javafx.scene.Scene; +import javafx.scene.layout.VBox; +import javafx.stage.Modality; +import javafx.stage.Stage; +import javafx.stage.WindowEvent; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.fail; + +public class AfterModalClosedTest { + static CountDownLatch startupLatch; + static volatile Stage stage; + private Robot robot; + private int x, y; + private boolean w, h; + + public static void main(String[] args) throws Exception { + initFX(); + new AfterModalClosedTest().testResizability(); + teardown(); + } + + public static class TestApp extends Application { + @Override + public void start(Stage primaryStage) throws Exception { + primaryStage.setScene(new Scene(new VBox())); + primaryStage.setResizable(true); + primaryStage.show(); + stage = primaryStage; + + Stage modalStage = new Stage(); + modalStage.setScene(new Scene(new VBox())); + modalStage.initModality(Modality.APPLICATION_MODAL); + modalStage.addEventHandler(WindowEvent.WINDOW_SHOWN, e -> + Platform.runLater(modalStage::hide)); + modalStage.addEventHandler(WindowEvent.WINDOW_HIDDEN, e -> + Platform.runLater(startupLatch::countDown)); + modalStage.show(); + } + } + + @BeforeClass + public static void initFX() { + startupLatch = new CountDownLatch(1); + new Thread(() -> Application.launch(TestApp.class, (String[])null)).start(); + try { + if (!startupLatch.await(15, TimeUnit.SECONDS)) { + fail("Timeout waiting for FX runtime to start"); + } + } catch (InterruptedException ex) { + fail("Unexpected exception: " + ex); + } + } + + @Test + public void testResizability() throws Exception { + Assert.assertTrue(stage.isResizable()); + CountDownLatch resizeLatch = new CountDownLatch(2); + Platform.runLater(() -> { + stage.widthProperty().addListener((ov, o, n) -> { + if (!w && o != n) { + w = true; + resizeLatch.countDown(); + } + }); + stage.heightProperty().addListener((ov, o, n) -> { + if (!h && o != n) { + h = true; + resizeLatch.countDown(); + } + }); + robot = com.sun.glass.ui.Application.GetApplication().createRobot(); + x = (int) (stage.getX() + stage.getWidth()); + y = (int) (stage.getY() + stage.getHeight()); + int d = PlatformUtil.isLinux() ? -1 : 2; + robot.mouseMove(x - d, y - d); + robot.mousePress(Robot.MOUSE_LEFT_BTN); + }); + Thread.sleep(100); + Platform.runLater(() -> { + robot.mouseMove(x + 20, y + 20); + robot.mouseRelease(Robot.MOUSE_LEFT_BTN); + }); + resizeLatch.await(5, TimeUnit.SECONDS); + Assert.assertTrue("Window is not resized", w && h); + } + + @AfterClass + public static void teardown() { + Platform.runLater(stage::hide); + Platform.exit(); + } +} + --- old/modules/graphics/src/main/native-glass/gtk/glass_gtkcompat.cpp 2018-10-10 16:43:42.234662979 +0530 +++ /dev/null 2018-10-10 12:18:08.824000000 +0530 @@ -1,379 +0,0 @@ -/* - * Copyright (c) 2011, 2014, 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 "glass_gtkcompat.h" -#include "glass_general.h" -#include -#include - -gboolean disableGrab = FALSE; - -static gboolean configure_transparent_window(GtkWidget *window); -static void configure_opaque_window(GtkWidget *window); -static gboolean configure_window_transparency(GtkWidget *window, - gboolean transparent); - -#if GTK_CHECK_VERSION(3, 0, 0) -typedef struct _DeviceGrabContext { - GdkWindow * window; - gboolean grabbed; -} DeviceGrabContext; - -static void grab_mouse_device(GdkDevice *device, DeviceGrabContext *context); -static void ungrab_mouse_device(GdkDevice *device); - -GdkScreen * -glass_gdk_window_get_screen(GdkWindow * gdkWindow) { - GdkVisual * gdkVisual = gdk_window_get_visual(gdkWindow); - return gdk_visual_get_screen(gdkVisual); -} - -GdkDisplay * glass_gdk_window_get_display(GdkWindow * gdkWindow) { - return gdk_window_get_display(gdkWindow); -} - - -gboolean -glass_gdk_mouse_devices_grab(GdkWindow *gdkWindow) { - if (disableGrab) { - return TRUE; - } - - DeviceGrabContext context; - GList *devices = gdk_device_manager_list_devices( - gdk_display_get_device_manager( - gdk_display_get_default()), - GDK_DEVICE_TYPE_MASTER); - - context.window = gdkWindow; - context.grabbed = FALSE; - g_list_foreach(devices, (GFunc) grab_mouse_device, &context); - - return context.grabbed; -} - -void -glass_gdk_mouse_devices_ungrab() { - GList *devices = gdk_device_manager_list_devices( - gdk_display_get_device_manager( - gdk_display_get_default()), - GDK_DEVICE_TYPE_MASTER); - g_list_foreach(devices, (GFunc) ungrab_mouse_device, NULL); -} - -void -glass_gdk_master_pointer_grab(GdkWindow *window, GdkCursor *cursor) { - if (disableGrab) { - gdk_window_set_cursor(window, cursor); - return; - } - gdk_device_grab(gdk_device_manager_get_client_pointer( - gdk_display_get_device_manager( - gdk_display_get_default())), - window, GDK_OWNERSHIP_NONE, FALSE, GDK_ALL_EVENTS_MASK, - cursor, GDK_CURRENT_TIME); -} - -void -glass_gdk_master_pointer_ungrab() { - gdk_device_ungrab(gdk_device_manager_get_client_pointer( - gdk_display_get_device_manager( - gdk_display_get_default())), - GDK_CURRENT_TIME); -} - -void -glass_gdk_master_pointer_get_position(gint *x, gint *y) { - gdk_device_get_position(gdk_device_manager_get_client_pointer( - gdk_display_get_device_manager( - gdk_display_get_default())), - NULL, x, y); -} - -gboolean -glass_gdk_device_is_grabbed(GdkDevice *device) { - return gdk_display_device_is_grabbed(gdk_display_get_default(), device); -} - -void -glass_gdk_device_ungrab(GdkDevice *device) { - gdk_device_ungrab(device, GDK_CURRENT_TIME); -} - -GdkWindow * -glass_gdk_device_get_window_at_position(GdkDevice *device, gint *x, gint *y) { - return gdk_device_get_window_at_position(device, x, y); -} - -void -glass_gtk_configure_transparency_and_realize(GtkWidget *window, - gboolean transparent) { - gboolean isTransparent = configure_window_transparency(window, transparent); - gtk_widget_realize(window); - if (isTransparent) { - GdkRGBA rgba = { 1.0, 1.0, 1.0, 0.0 }; - gdk_window_set_background_rgba(gtk_widget_get_window(window), &rgba); - } -} - -void -glass_gtk_window_configure_from_visual(GtkWidget *widget, GdkVisual *visual) { - gtk_widget_set_visual(widget, visual); -} - -static gboolean -configure_transparent_window(GtkWidget *window) { - GdkScreen *default_screen = gdk_screen_get_default(); - GdkDisplay *default_display = gdk_display_get_default(); - GdkVisual *visual = gdk_screen_get_rgba_visual(default_screen); - if (visual - && gdk_display_supports_composite(default_display) - && gdk_screen_is_composited(default_screen)) { - gtk_widget_set_visual(window, visual); - return TRUE; - } - - return FALSE; -} - -static void -grab_mouse_device(GdkDevice *device, DeviceGrabContext *context) { - GdkInputSource source = gdk_device_get_source(device); - if (source == GDK_SOURCE_MOUSE) { - GdkGrabStatus status = gdk_device_grab(device, - context->window, - GDK_OWNERSHIP_NONE, - TRUE, - GDK_ALL_EVENTS_MASK, - NULL, - GDK_CURRENT_TIME); - if (status == GDK_GRAB_SUCCESS) { - context->grabbed = TRUE; - } - } -} - -static void -ungrab_mouse_device(GdkDevice *device) { - GdkInputSource source = gdk_device_get_source(device); - if (source == GDK_SOURCE_MOUSE) { - gdk_device_ungrab(device, GDK_CURRENT_TIME); - } -} - -int glass_gtk_fixup_typed_key(int key, int keyval) { - return key; -} - -void glass_gdk_window_get_size(GdkWindow *window, gint *w, gint *h) { - *w = gdk_window_get_width(window); - *h = gdk_window_get_height(window); -} - -void glass_gdk_display_get_pointer(GdkDisplay* display, gint* x, gint *y) { - gdk_device_get_position(gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(display)), - NULL , x, y); -} - -#else /* GTK_CHECK_VERSION(3, 0, 0) */ - -GdkScreen * -glass_gdk_window_get_screen(GdkWindow * gdkWindow) { - return gdk_drawable_get_screen(GDK_DRAWABLE(gdkWindow)); -} - -GdkDisplay * glass_gdk_window_get_display(GdkWindow * gdkWindow) { - return gdk_drawable_get_display(GDK_DRAWABLE(gdkWindow)); -} - -gboolean -glass_gdk_mouse_devices_grab(GdkWindow *gdkWindow) { - return glass_gdk_mouse_devices_grab_with_cursor(gdkWindow, NULL, TRUE); -} - -gboolean -glass_gdk_mouse_devices_grab_with_cursor(GdkWindow *gdkWindow, GdkCursor *cursor) { - return glass_gdk_mouse_devices_grab_with_cursor(gdkWindow, cursor, TRUE); -} - -gboolean -glass_gdk_mouse_devices_grab_with_cursor(GdkWindow *gdkWindow, GdkCursor *cursor, gboolean owner_events) { - if (disableGrab) { - return TRUE; - } - GdkGrabStatus status = gdk_pointer_grab(gdkWindow, owner_events, (GdkEventMask) - (GDK_POINTER_MOTION_MASK - | GDK_POINTER_MOTION_HINT_MASK - | GDK_BUTTON_MOTION_MASK - | GDK_BUTTON1_MOTION_MASK - | GDK_BUTTON2_MOTION_MASK - | GDK_BUTTON3_MOTION_MASK - | GDK_BUTTON_PRESS_MASK - | GDK_BUTTON_RELEASE_MASK), - NULL, cursor, GDK_CURRENT_TIME); - - return (status == GDK_GRAB_SUCCESS) ? TRUE : FALSE; -} - -void -glass_gdk_mouse_devices_ungrab() { - gdk_pointer_ungrab(GDK_CURRENT_TIME); -} - -void -glass_gdk_master_pointer_grab(GdkWindow *window, GdkCursor *cursor) { - if (disableGrab) { - gdk_window_set_cursor(window, cursor); - return; - } - gdk_pointer_grab(window, FALSE, (GdkEventMask) - (GDK_POINTER_MOTION_MASK - | GDK_BUTTON_MOTION_MASK - | GDK_BUTTON1_MOTION_MASK - | GDK_BUTTON2_MOTION_MASK - | GDK_BUTTON3_MOTION_MASK - | GDK_BUTTON_RELEASE_MASK), - NULL, cursor, GDK_CURRENT_TIME); -} - -void -glass_gdk_master_pointer_ungrab() { - gdk_pointer_ungrab(GDK_CURRENT_TIME); -} - -void -glass_gdk_master_pointer_get_position(gint *x, gint *y) { - gdk_display_get_pointer(gdk_display_get_default(), NULL, x, y, NULL); -} - -gboolean -glass_gdk_device_is_grabbed(GdkDevice *device) { - (void) device; - return gdk_display_pointer_is_grabbed(gdk_display_get_default()); -} - -void -glass_gdk_device_ungrab(GdkDevice *device) { - (void) device; - gdk_pointer_ungrab(GDK_CURRENT_TIME); -} - -GdkWindow * -glass_gdk_device_get_window_at_position(GdkDevice *device, gint *x, gint *y) { - (void) device; - return gdk_display_get_window_at_pointer(gdk_display_get_default(), x, y); -} - -void -glass_gtk_configure_transparency_and_realize(GtkWidget *window, - gboolean transparent) { - configure_window_transparency(window, transparent); - gtk_widget_realize(window); -} - -void -glass_gtk_window_configure_from_visual(GtkWidget *widget, GdkVisual *visual) { - GdkColormap *colormap = gdk_colormap_new(visual, TRUE); - gtk_widget_set_colormap(widget, colormap); -} - -static gboolean -configure_transparent_window(GtkWidget *window) { - GdkScreen *default_screen = gdk_screen_get_default(); - GdkDisplay *default_display = gdk_display_get_default(); - GdkColormap *colormap = gdk_screen_get_rgba_colormap(default_screen); - if (colormap - && gdk_display_supports_composite(default_display) - && gdk_screen_is_composited(default_screen)) { - gtk_widget_set_colormap(window, colormap); - return TRUE; - } - - return FALSE; -} - -int glass_gtk_fixup_typed_key(int key, int keyval) { - if (key == 0) { - // Work around "bug" fixed in gtk-3.0: - // http://mail.gnome.org/archives/commits-list/2011-March/msg06832.html - switch (keyval) { - case 0xFF08 /* Backspace */: return '\b'; - case 0xFF09 /* Tab */: return '\t'; - case 0xFF0A /* Linefeed */: return '\n'; - case 0xFF0B /* Vert. Tab */: return '\v'; - case 0xFF0D /* Return */: return '\r'; - case 0xFF1B /* Escape */: return '\033'; - case 0xFFFF /* Delete */: return '\177'; - } - } - return key; -} - -void glass_gdk_window_get_size(GdkWindow *window, gint *w, gint *h) { - gdk_drawable_get_size(GDK_DRAWABLE(window), w, h); -} - -void glass_gdk_display_get_pointer(GdkDisplay* display, gint* x, gint *y) { - gdk_display_get_pointer(display, NULL, x, y, NULL); -} - -#endif /* GTK_CHECK_VERSION(3, 0, 0) */ - -const guchar* -glass_gtk_selection_data_get_data_with_length( - GtkSelectionData * selectionData, - gint * length) { - if (selectionData == NULL) { - return NULL; - } - - *length = gtk_selection_data_get_length(selectionData); - return gtk_selection_data_get_data(selectionData); -} - -static void -configure_opaque_window(GtkWidget *window) { - (void)window; - - gtk_widget_set_visual(window, - gdk_screen_get_system_visual( - gdk_screen_get_default())); -} - -static gboolean -configure_window_transparency(GtkWidget *window, gboolean transparent) { - if (transparent) { - if (configure_transparent_window(window)) { - return TRUE; - } - - ERROR0("Can't create transparent stage, because your screen doesn't" - " support alpha channel." - " You need to enable XComposite extension.\n"); - } - - configure_opaque_window(window); - return FALSE; -} - --- old/modules/graphics/src/main/native-glass/gtk/glass_gtkcompat.h 2018-10-10 16:43:42.674662979 +0530 +++ /dev/null 2018-10-10 12:18:08.824000000 +0530 @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ -#ifndef GLASS_GTKCOMPAT_H -#define GLASS_GTKCOMPAT_H - -#include -#include -#include - -#if GTK_CHECK_VERSION(2, 22, 0) - -#define GLASS_GDK_DRAG_CONTEXT_GET_SELECTED_ACTION(context) \ - gdk_drag_context_get_selected_action(context) - -#define GLASS_GDK_DRAG_CONTEXT_GET_ACTIONS(context) \ - gdk_drag_context_get_actions(context) - -#define GLASS_GDK_DRAG_CONTEXT_LIST_TARGETS(context) \ - gdk_drag_context_list_targets(context) - -#define GLASS_GDK_DRAG_CONTEXT_GET_SUGGESTED_ACTION(context) \ - gdk_drag_context_get_suggested_action(context) - -#else /* GTK_CHECK_VERSION(2, 22, 0) */ - -#define GLASS_GDK_DRAG_CONTEXT_GET_SELECTED_ACTION(context) \ - (context->action) - -#define GLASS_GDK_DRAG_CONTEXT_GET_ACTIONS(context) \ - (context->actions) - -#define GLASS_GDK_DRAG_CONTEXT_LIST_TARGETS(context) \ - (context->targets) - -#define GLASS_GDK_DRAG_CONTEXT_GET_SUGGESTED_ACTION(context) \ - (context->suggested_action) - -#endif /* GTK_CHECK_VERSION(2, 22, 0) */ - -#if GTK_CHECK_VERSION(2, 24, 0) - -#define GLASS_GDK_KEY_CONSTANT(key) (GDK_KEY_ ## key) - -#define GLASS_GDK_WINDOW_FOREIGN_NEW_FOR_DISPLAY(display, anid) \ - gdk_x11_window_foreign_new_for_display(display, anid) - -#define GLASS_GDK_WINDOW_LOOKUP_FOR_DISPLAY(display, anid) \ - gdk_x11_window_lookup_for_display(display, anid) - -#else /* GTK_CHECK_VERSION(2, 24, 0) */ - -#define GLASS_GDK_KEY_CONSTANT(key) (GDK_ ## key) - -#define GLASS_GDK_WINDOW_FOREIGN_NEW_FOR_DISPLAY(display, anid) \ - gdk_window_foreign_new_for_display(display, anid) - -#define GLASS_GDK_WINDOW_LOOKUP_FOR_DISPLAY(display, anid) \ - gdk_window_lookup_for_display(display, anid) - -#endif /* GTK_CHECK_VERSION(2, 24, 0) */ - -#if GTK_CHECK_VERSION(3, 0, 0) - -#define GLASS_GTK_WINDOW_SET_HAS_RESIZE_GRIP(window, value) \ - gtk_window_set_has_resize_grip(window, TRUE) - -#define GLASS_GDK_SELECTION_EVENT_GET_REQUESTOR(event) \ - (event->requestor) - -#define GLASS_GDK_DRAG_CONTEXT_GET_DEST_WINDOW(context) \ - gdk_drag_context_get_dest_window(context) - -#else /* GTK_CHECK_VERSION(3, 0, 0) */ - -#define GLASS_GTK_WINDOW_SET_HAS_RESIZE_GRIP(window, value) \ - (void) window; \ - (void) value; - -#define GLASS_GDK_SELECTION_EVENT_GET_REQUESTOR(event) \ - GLASS_GDK_WINDOW_FOREIGN_NEW_FOR_DISPLAY( \ - gdk_display_get_default(), event->requestor) - -#define GLASS_GDK_DRAG_CONTEXT_GET_DEST_WINDOW(context) \ - ((context != NULL) ? context->dest_window : NULL) - -#endif /* GTK_CHECK_VERSION(3, 0, 0) */ - -GdkScreen * glass_gdk_window_get_screen(GdkWindow * gdkWindow); -GdkDisplay * glass_gdk_window_get_display(GdkWindow * gdkWindow); - -gboolean glass_gdk_mouse_devices_grab(GdkWindow * gdkWindow); -gboolean glass_gdk_mouse_devices_grab_with_cursor(GdkWindow * gdkWindow, GdkCursor *cursor); -gboolean glass_gdk_mouse_devices_grab_with_cursor(GdkWindow * gdkWindow, GdkCursor *cursor, gboolean owner_events); -void glass_gdk_mouse_devices_ungrab(); - -void glass_gdk_master_pointer_grab(GdkWindow *window, GdkCursor *cursor); -void glass_gdk_master_pointer_ungrab(); -void glass_gdk_master_pointer_get_position(gint *x, gint *y); - -gboolean glass_gdk_device_is_grabbed(GdkDevice *device); -void glass_gdk_device_ungrab(GdkDevice *device); -GdkWindow *glass_gdk_device_get_window_at_position( - GdkDevice *device, gint *x, gint *y); - -void glass_gtk_configure_transparency_and_realize(GtkWidget *window, - gboolean transparent); - -const guchar * glass_gtk_selection_data_get_data_with_length( - GtkSelectionData * selectionData, - gint * length); - -void glass_gtk_window_configure_from_visual(GtkWidget *widget, GdkVisual *visual); - -int glass_gtk_fixup_typed_key(int key, int keyval); - -void glass_gdk_window_get_size(GdkWindow *window, gint *w, gint *h); - -void glass_gdk_display_get_pointer(GdkDisplay* display, gint* x, gint *y); - - -#endif /* GLASS_GTKCOMPAT_H */ -