diff options
-rw-r--r-- | ChangeLog | 21 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java | 1 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/GtkComponentPeer.java | 16 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java | 14 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/GtkWindowPeer.java | 11 | ||||
-rw-r--r-- | include/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.h | 5 | ||||
-rw-r--r-- | java/awt/Component.java | 56 | ||||
-rw-r--r-- | java/awt/Container.java | 27 | ||||
-rw-r--r-- | native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c | 34 | ||||
-rw-r--r-- | native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c | 132 |
10 files changed, 279 insertions, 38 deletions
@@ -1,3 +1,24 @@ +2007-11-27 Thomas Fitzsimmons <fitzsim@redhat.com> + + * gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java, + native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c + (isWindowUnderMouse): New method. + * include/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.h: + Regenerate. + * gnu/java/awt/peer/gtk/GtkComponentPeer.java + (getLocationOnScreen): Move WindowPeer section to... + * gnu/java/awt/peer/gtk/GtkWindowPeer.java (getLocationOnScreen): + New method. + * gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java + (isWindowUnderMouse): Implement. + * java/awt/Component.java (getMousePosition): New method. + (getMousePositionHelper): Likewise. + (mouseOverComponent): Likewise. + * java/awt/Container.java (getMousePosition): New method. + (mouseOverComponent): Likewise. + * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c: + Revert 2007-09-11 changes. + 2007-11-27 Andrew John Hughes <gnu_andrew@member.fsf.org> * javax/management/package.html: Added. diff --git a/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java b/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java index 67040b82a..d06af8443 100644 --- a/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java +++ b/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java @@ -155,6 +155,7 @@ public class GdkGraphicsEnvironment extends ClasspathGraphicsEnvironment * Used by GtkMouseInfoPeer. */ native int[] getMouseCoordinates(); + native boolean isWindowUnderMouse(GtkWindowPeer windowPeer); public WritableRaster createRaster(ColorModel cm, SampleModel sm) { diff --git a/gnu/java/awt/peer/gtk/GtkComponentPeer.java b/gnu/java/awt/peer/gtk/GtkComponentPeer.java index 6d9ba8857..76fefaaa5 100644 --- a/gnu/java/awt/peer/gtk/GtkComponentPeer.java +++ b/gnu/java/awt/peer/gtk/GtkComponentPeer.java @@ -253,20 +253,10 @@ public class GtkComponentPeer extends GtkGenericPeer public Point getLocationOnScreen () { int point[] = new int[2]; - if( this instanceof WindowPeer ) - { - if (Thread.currentThread() == GtkMainThread.mainThread) - gtkWindowGetLocationOnScreenUnlocked (point); - else - gtkWindowGetLocationOnScreen (point); - } + if (Thread.currentThread() == GtkMainThread.mainThread) + gtkWidgetGetLocationOnScreenUnlocked (point); else - { - if (Thread.currentThread() == GtkMainThread.mainThread) - gtkWidgetGetLocationOnScreenUnlocked (point); - else - gtkWidgetGetLocationOnScreen (point); - } + gtkWidgetGetLocationOnScreen (point); return new Point (point[0], point[1]); } diff --git a/gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java b/gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java index 7aea50991..7407744af 100644 --- a/gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java +++ b/gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java @@ -60,17 +60,7 @@ public class GtkMouseInfoPeer implements MouseInfoPeer public boolean isWindowUnderMouse(Window w) { - int[] coords = gde.getMouseCoordinates(); - GraphicsDevice[] gds = gde.getScreenDevices(); - - // Check if the screen of the Window and the cursor match - if( gds[ coords[0] ] != w.getGraphicsConfiguration().getDevice() ) - return false; - - // Return the bounds-check. - Point p = w.getLocationOnScreen(); - return (coords[1] >= p.x && coords[1] < p.x + w.getWidth() && - coords[2] >= p.y && coords[2] < p.y + w.getHeight() ); - } + return gde.isWindowUnderMouse((GtkWindowPeer) w.getPeer()); + } } diff --git a/gnu/java/awt/peer/gtk/GtkWindowPeer.java b/gnu/java/awt/peer/gtk/GtkWindowPeer.java index d8054150d..9744c3a53 100644 --- a/gnu/java/awt/peer/gtk/GtkWindowPeer.java +++ b/gnu/java/awt/peer/gtk/GtkWindowPeer.java @@ -45,6 +45,7 @@ import java.awt.Font; import java.awt.Frame; import java.awt.Graphics; import java.awt.KeyboardFocusManager; +import java.awt.Point; import java.awt.Rectangle; import java.awt.Window; import java.awt.event.ComponentEvent; @@ -392,6 +393,16 @@ public class GtkWindowPeer extends GtkContainerPeer clickCount, popupTrigger); } + public Point getLocationOnScreen() + { + int point[] = new int[2]; + if (Thread.currentThread() == GtkMainThread.mainThread) + gtkWindowGetLocationOnScreenUnlocked(point); + else + gtkWindowGetLocationOnScreen(point); + return new Point(point[0], point[1]); + } + // We override this to keep it in sync with our internal // representation. public Rectangle getBounds() diff --git a/include/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.h b/include/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.h index aa0bd0156..de83f57a5 100644 --- a/include/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.h +++ b/include/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.h @@ -1,10 +1,10 @@ /* DO NOT EDIT THIS FILE - it is machine generated */ +#include <jni.h> + #ifndef __gnu_java_awt_peer_gtk_GdkGraphicsEnvironment__ #define __gnu_java_awt_peer_gtk_GdkGraphicsEnvironment__ -#include <jni.h> - #ifdef __cplusplus extern "C" { @@ -17,6 +17,7 @@ JNIEXPORT jobject JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphicsEnvironment_nati JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphicsEnvironment_nativeGetNumFontFamilies (JNIEnv *env, jobject); JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphicsEnvironment_nativeGetFontFamilies (JNIEnv *env, jobject, jobjectArray); JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphicsEnvironment_getMouseCoordinates (JNIEnv *env, jobject); +JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphicsEnvironment_isWindowUnderMouse (JNIEnv *env, jobject, jobject); #ifdef __cplusplus } diff --git a/java/awt/Component.java b/java/awt/Component.java index f8bed1761..fe4fb9b8b 100644 --- a/java/awt/Component.java +++ b/java/awt/Component.java @@ -5834,6 +5834,62 @@ p * <li>the set of backward traversal keys } /** + * Returns the mouse pointer position relative to this Component's + * top-left corner. + * + * @return relative mouse pointer position + * + * @throws HeadlessException if in a headless environment + */ + public Point getMousePosition() throws HeadlessException + { + return getMousePositionHelper(true); + } + + Point getMousePositionHelper(boolean allowChildren) throws HeadlessException + { + if (GraphicsEnvironment.isHeadless()) + throw new HeadlessException("can't get mouse position" + + " in headless environment"); + if (!isShowing()) + return null; + + Component parent = this; + int windowRelativeXOffset = 0; + int windowRelativeYOffset = 0; + while (parent != null && !(parent instanceof Window)) + { + windowRelativeXOffset += parent.getX(); + windowRelativeYOffset += parent.getY(); + parent = parent.getParent(); + } + if (parent == null) + return null; + + Window window = (Window) parent; + if (!Toolkit.getDefaultToolkit() + .getMouseInfoPeer().isWindowUnderMouse(window)) + return null; + + PointerInfo info = MouseInfo.getPointerInfo(); + Point mouseLocation = info.getLocation(); + Point windowLocation = window.getLocationOnScreen(); + + int x = mouseLocation.x - windowLocation.x; + int y = mouseLocation.y - windowLocation.y; + + if (!mouseOverComponent(window.getComponentAt(x, y), allowChildren)) + return null; + + return new Point(x - windowRelativeXOffset, y - windowRelativeYOffset); + } + + boolean mouseOverComponent(Component component, boolean allowChildren) + { + return component == this; + } + + /** * This method is used to implement transferFocus(). CHILD is the child * making the request. This is overridden by Container; when called for an * ordinary component there is no child and so we always return null. diff --git a/java/awt/Container.java b/java/awt/Container.java index 83d9f7b78..e7622f2e8 100644 --- a/java/awt/Container.java +++ b/java/awt/Container.java @@ -1098,6 +1098,33 @@ public class Container extends Component } /** + * Returns the mouse pointer position relative to this Container's + * top-left corner. If allowChildren is false, the mouse pointer + * must be directly over this container. If allowChildren is true, + * the mouse pointer may be over this container or any of its + * descendents. + * + * @param allowChildren true to allow descendents, false if pointer + * must be directly over Container. + * + * @return relative mouse pointer position + * + * @throws HeadlessException if in a headless environment + */ + public Point getMousePosition(boolean allowChildren) throws HeadlessException + { + return super.getMousePositionHelper(allowChildren); + } + + boolean mouseOverComponent(Component component, boolean allowChildren) + { + if (allowChildren) + return isAncestorOf(component); + else + return component == this; + } + + /** * Returns the component located at the specified point. This is done * by checking whether or not a child component claims to contain this * point. The first child component that does is returned. If no diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c index 1c88d1b51..6066a6bb2 100644 --- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c @@ -263,3 +263,37 @@ Java_gnu_java_awt_peer_gtk_GdkGraphicsEnvironment_getMouseCoordinates return retArray; } + +JNIEXPORT jboolean JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphicsEnvironment_isWindowUnderMouse +(JNIEnv *env, jobject obj, jobject windowPeer) +{ + GdkDisplay *display = NULL; + gint x = 0; + gint y = 0; + GtkWidget *windowToTest = NULL; + GdkWindow *windowAtPointer = NULL; + jboolean retVal = JNI_FALSE; + + display = (GdkDisplay *) gtkpeer_get_display (env, obj); + g_assert (display != NULL); + + windowToTest = (GtkWidget *) gtkpeer_get_widget (env, windowPeer); + + gdk_threads_enter (); + + windowAtPointer = gdk_display_get_window_at_pointer (display, &x, &y); + + while (windowAtPointer + && windowAtPointer != windowToTest->window) + windowAtPointer = gdk_window_get_parent (windowAtPointer); + + gdk_threads_leave (); + + if (windowAtPointer) + retVal = JNI_TRUE; + else + retVal = JNI_FALSE; + + return retVal; +} diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c index 4ea753a8e..6ba8d4767 100644 --- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c @@ -40,6 +40,8 @@ exception statement from your version. */ #include "gtkpeer.h" #include "gnu_java_awt_peer_gtk_GtkWindowPeer.h" #include <gdk/gdkprivate.h> +#include <gdk/gdkx.h> +#include <X11/Xatom.h> #include <gdk/gdkkeysyms.h> #define AWT_WINDOW_CLOSING 201 @@ -1037,6 +1039,12 @@ static void window_get_frame_extents (GtkWidget *window, int *top, int *left, int *bottom, int *right); +static void request_frame_extents (GtkWidget *window); + +static Bool property_notify_predicate (Display *display, + XEvent *xevent, + XPointer arg); + static gboolean window_delete_cb (GtkWidget *widget, GdkEvent *event, jobject peer); static void window_destroy_cb (GtkWidget *widget, GdkEvent *event, @@ -1142,6 +1150,12 @@ union extents_union unsigned long **extents; }; +union atom_list_union +{ + guchar **gu_extents; + Atom **atom_list; +}; + JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_create (JNIEnv *env, jobject obj, jint type, jboolean decorated, jobject parent) @@ -1503,22 +1517,118 @@ static void window_get_frame_extents (GtkWidget *window, int *top, int *left, int *bottom, int *right) { - GdkRectangle extents; - GdkWindow* gdkWindow; + unsigned long *extents = NULL; + union extents_union gu_ex; - gint x, y, w, h; + /* Guess frame extents in case _NET_FRAME_EXTENTS is not + supported. */ + if (!gtk_window_get_decorated (GTK_WINDOW (window))) + { + *top = 0; + *left = 0; + *bottom = 0; + *right = 0; - gdkWindow = window->window; + return; + } - gdk_window_get_frame_extents(gdkWindow, &extents); - gdk_drawable_get_size(gdkWindow, &w, &h); - gdk_window_get_origin(gdkWindow, &x, &y); + *top = 23; + *left = 6; + *bottom = 6; + *right = 6; - *left = extents.x - x; - *top = extents.y - y; - *right = extents.width - w - *left; - *bottom = extents.height - h - *top; + /* Request that the window manager set window's + _NET_FRAME_EXTENTS property. */ + request_frame_extents (window); + /* Attempt to retrieve window's frame extents. */ + gu_ex.extents = &extents; + if (gdk_property_get (window->window, + gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE), + gdk_atom_intern ("CARDINAL", FALSE), + 0, + sizeof (unsigned long) * 4, + FALSE, + NULL, + NULL, + NULL, + gu_ex.gu_extents)) + { + *left = extents [0]; + *right = extents [1]; + *top = extents [2]; + *bottom = extents [3]; + } +} + +static Atom extents_atom = 0; + +/* Requests that the window manager set window's + _NET_FRAME_EXTENTS property. */ +static void +request_frame_extents (GtkWidget *window) +{ + const char *request_str = "_NET_REQUEST_FRAME_EXTENTS"; + GdkAtom request_extents = gdk_atom_intern (request_str, FALSE); + + /* Check if the current window manager supports + _NET_REQUEST_FRAME_EXTENTS. */ + if (gdk_net_wm_supports (request_extents)) + { + GdkDisplay *display = gtk_widget_get_display (window); + Display *xdisplay = GDK_DISPLAY_XDISPLAY (display); + + GdkWindow *root_window = gdk_get_default_root_window (); + Window xroot_window = GDK_WINDOW_XID (root_window); + + Atom extents_request_atom = + gdk_x11_get_xatom_by_name_for_display (display, request_str); + + XEvent xevent; + XEvent notify_xevent; + + unsigned long window_id = GDK_WINDOW_XID (GDK_DRAWABLE(window->window)); + + if (!extents_atom) + { + const char *extents_str = "_NET_FRAME_EXTENTS"; + extents_atom = + gdk_x11_get_xatom_by_name_for_display (display, extents_str); + } + + xevent.xclient.type = ClientMessage; + xevent.xclient.message_type = extents_request_atom; + xevent.xclient.display = xdisplay; + xevent.xclient.window = window_id; + xevent.xclient.format = 32; + xevent.xclient.data.l[0] = 0; + xevent.xclient.data.l[1] = 0; + xevent.xclient.data.l[2] = 0; + xevent.xclient.data.l[3] = 0; + xevent.xclient.data.l[4] = 0; + + XSendEvent (xdisplay, xroot_window, False, + (SubstructureRedirectMask | SubstructureNotifyMask), + &xevent); + + XIfEvent(xdisplay, ¬ify_xevent, + property_notify_predicate, (XPointer) &window_id); + } +} + +static Bool +property_notify_predicate (Display *xdisplay __attribute__((unused)), + XEvent *event, + XPointer window_id) +{ + unsigned long *window = (unsigned long *) window_id; + + if (event->xany.type == PropertyNotify + && event->xany.window == *window + && event->xproperty.atom == extents_atom) + return True; + else + return False; } static gboolean |