+2003-10-02 Thomas Fitzsimmons <fitzsim@redhat.com>
+
+ * gnu/java/awt/peer/gtk/GtkComponentPeer.java (insets): New
+ field.
+ (initializeInsets): New method.
+ (GtkComponentPeer): Call initializeInsets. Call setCursor and
+ setBounds unconditionally.
+ (setBounds): Convert coordinates if parent is a Window.
+ * gnu/java/awt/peer/gtk/GtkContainerPeer.java (insets): Move
+ field to GtkComponentPeer.
+ (GtkContainerPeer): Don't initialize insets.
+ * gnu/java/awt/peer/gtk/GtkDialogPeer.java (initializeInsets):
+ New method.
+ (create): Call new GtkWindowPeer create method.
+ * gnu/java/awt/peer/gtk/GtkFramePeer.java (initializeInsets):
+ New method.
+ (create): Call new GtkWindowPeer create method.
+ (setBounds): Remove method.
+ (postConfigureEvent): Likewise.
+ * gnu/java/awt/peer/gtk/GtkWindowPeer.java: Replace GTK window
+ type constants with GDK window type constants.
+ (create(int,boolean,int,int,GtkWindowPeer)): New method.
+ (create(int,boolean)): Likewise.
+ (create()): Call create(int,boolean).
+ (nativeSetBounds): New native method declaration.
+ (setBounds): Call native method declaration.
+ (setSize): New native method declaration.
+ (setBoundsCallback): Likewise.
+ (postConfigureEvent): Handle change in insets. Call setSize and
+ setBoundsCallback methods.
+ * java/awt/Window.java (Window): Set visible to false.
+ (setBoundsCallback): New method.
+ * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c
+ (gtkWidgetGetLocationOnScreen): If this component is not a
+ container, adjust the location returned based on the peer's
+ allocation.
+ (set(String,boolean)): Revert change from 2003-09-19.
+ * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c
+ (awt_event_handler): Fix inset calculation.
+ * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMainThread.c: Add JNI
+ glue for Window.setBoundsCallback.
+ * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c (create):
+ Set up stacking order, window decorations and window manager
+ hints.
+ (setBoundsCallback): New method.
+ (setSize): New method.
+ (nativeSetBounds): New method.
+ * jni/gtk-peer/gtkpeer.h: Declare setBoundsCallbackID.
+
2003-10-02 Tom Tromey <tromey@redhat.com>
* java/lang/VMClassLoader.java (loadClass): Now native.
{
Component awtComponent;
+ Insets insets;
+
/* this isEnabled differs from Component.isEnabled, in that it
knows if a parent is disabled. In that case Component.isEnabled
may return true, but our isEnabled will always return false */
throw new RuntimeException ();
}
+ void initializeInsets ()
+ {
+ insets = new Insets (0, 0, 0, 0);
+ }
+
native void connectHooks ();
protected GtkComponentPeer (Component awtComponent)
// c.setFont (cp.getFont ());
if (awtComponent.getFont() != null)
setFont(awtComponent.getFont());
-
- if (! (awtComponent instanceof Window))
- {
- setCursor (awtComponent.getCursor ());
- Rectangle bounds = awtComponent.getBounds ();
- setBounds (bounds.x, bounds.y, bounds.width, bounds.height);
- }
+
+ initializeInsets ();
+
+ setCursor (awtComponent.getCursor ());
+ Rectangle bounds = awtComponent.getBounds ();
+ setBounds (bounds.x, bounds.y, bounds.width, bounds.height);
+
} catch (RuntimeException ex) { ; }
}
{
Component parent = awtComponent.getParent ();
- if (parent instanceof Frame)
+ if (parent instanceof Window)
{
- Insets insets = ((Frame)parent).getInsets ();
- /* convert Java's coordinate space into GTK+'s coordinate space */
- setNativeBounds (x-insets.left, y-insets.top, width, height);
+ Insets insets = ((Window) parent).getInsets ();
+ // Convert from Java coordinates to GTK coordinates.
+ setNativeBounds (x - insets.left, y - insets.top, width, height);
}
else
setNativeBounds (x, y, width, height);
public class GtkContainerPeer extends GtkComponentPeer
implements ContainerPeer
{
- Insets insets;
Container c;
public GtkContainerPeer(Container c)
{
super (c);
this.c = c;
- insets = new Insets (0, 0, 0, 0);
}
public void beginValidate()
import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.Dialog;
+import java.awt.Insets;
import java.awt.peer.DialogPeer;
public class GtkDialogPeer extends GtkWindowPeer
super (dialog);
}
+ void initializeInsets ()
+ {
+ // Unfortunately, X does not provide a clean way to calculate the
+ // dimensions of a dialog's borders before it has been displayed.
+ // So we guess and then fix the dimensions upon receipt of the
+ // first configure event.
+ insets = new Insets (20, 6, 6, 6);
+ }
+
void create ()
{
- create (GTK_WINDOW_TOPLEVEL,
- awtComponent.getWidth(),
- awtComponent.getHeight());
+ // Create a decorated dialog window.
+ create (GDK_WINDOW_TYPE_HINT_DIALOG, true);
}
public void getArgs (Component component, GtkArgList args)
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
+import java.awt.Insets;
import java.awt.MenuBar;
import java.awt.Rectangle;
import java.awt.event.PaintEvent;
super (frame);
}
+ void initializeInsets ()
+ {
+ // Unfortunately, X does not provide a clean way to calculate the
+ // dimensions of a frame's borders before it has been displayed.
+ // So we guess and then fix the dimensions upon receipt of the
+ // first configure event.
+ insets = new Insets (20, 6, 6, 6);
+ }
+
void create ()
{
- create (GTK_WINDOW_TOPLEVEL);
+ // Create a normal decorated window.
+ create (GDK_WINDOW_TYPE_HINT_NORMAL, true);
}
public void getArgs (Component component, GtkArgList args)
return g;
}
- public void setBounds (int x, int y, int width, int height)
- {
- super.setBounds (0, 0, width - insets.left - insets.right,
- height - insets.top - insets.bottom + menuBarHeight);
- }
-
- protected void postConfigureEvent (int x, int y, int width, int height,
- int top, int left, int bottom, int right)
- {
- if (((Frame)awtComponent).getMenuBar () != null)
- {
- menuBarHeight = getMenuBarHeight ();
- top += menuBarHeight;
- }
-
- super.postConfigureEvent (0, 0,
- width + left + right,
- height + top + bottom - menuBarHeight,
- top, left, bottom, right);
- }
+ // FIXME: When MenuBars work, override postConfigureEvent and
+ // setBounds to account for MenuBar dimensions.
protected void postMouseEvent(int id, long when, int mods, int x, int y,
int clickCount, boolean popupTrigger)
protected void postExposeEvent (int x, int y, int width, int height)
{
-// System.out.println ("x + insets.left:" + (x + insets.left));
-// System.out.println ("y + insets.top :" + (y + insets.top));
q.postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT,
new Rectangle (x + insets.left,
y + insets.top,
import java.awt.Component;
import java.awt.Dimension;
+import java.awt.Insets;
import java.awt.Window;
import java.awt.peer.WindowPeer;
public class GtkWindowPeer extends GtkContainerPeer
implements WindowPeer
{
- static protected final int GTK_WINDOW_TOPLEVEL = 0;
- static protected final int GTK_WINDOW_POPUP = 1;
-
- native void create (int type, int width, int height);
-
- void create (int type)
+ static protected final int GDK_WINDOW_TYPE_HINT_NORMAL = 0;
+ static protected final int GDK_WINDOW_TYPE_HINT_DIALOG = 1;
+ static protected final int GDK_WINDOW_TYPE_HINT_MENU = 2;
+ static protected final int GDK_WINDOW_TYPE_HINT_TOOLBAR = 3;
+ static protected final int GDK_WINDOW_TYPE_HINT_SPLASHSCREEN = 4;
+ static protected final int GDK_WINDOW_TYPE_HINT_UTILITY = 5;
+ static protected final int GDK_WINDOW_TYPE_HINT_DOCK = 6;
+ static protected final int GDK_WINDOW_TYPE_HINT_DESKTOP = 7;
+
+ native void create (int type, boolean decorated,
+ int width, int height,
+ GtkWindowPeer parent);
+
+ void create (int type, boolean decorated)
{
- create (type,
+ GtkWindowPeer parent_peer = null;
+ Component parent = awtComponent.getParent();
+ if (parent != null)
+ parent_peer = (GtkWindowPeer) awtComponent.getParent().getPeer();
+
+ create (type, decorated,
awtComponent.getWidth(),
- awtComponent.getHeight());
+ awtComponent.getHeight(),
+ parent_peer);
}
void create ()
{
- create (GTK_WINDOW_POPUP,
- awtComponent.getWidth(),
- awtComponent.getHeight());
+ // Create a normal undecorated window.
+ create (GDK_WINDOW_TYPE_HINT_NORMAL, false);
}
native void connectHooks ();
native public void toBack ();
native public void toFront ();
- native public void setBounds (int x, int y, int width, int height);
+ native void nativeSetBounds (int x, int y, int width, int height);
+
+ public void setBounds (int x, int y, int width, int height)
+ {
+ nativeSetBounds (x, y,
+ width - insets.left - insets.right,
+ height - insets.top - insets.bottom);
+ }
public void setTitle (String title)
{
public void setResizable (boolean resizable)
{
+ // Call setSize; otherwise when resizable is changed from true to
+ // false the window will shrink to the dimensions it had before it
+ // was resizable.
+ setSize (awtComponent.getWidth() - insets.left - insets.right,
+ awtComponent.getHeight() - insets.top - insets.bottom);
set ("allow_shrink", resizable);
set ("allow_grow", resizable);
}
+ native void setSize (int width, int height);
+ native void setBoundsCallback (Window window,
+ int x, int y,
+ int width, int height);
+
protected void postConfigureEvent (int x, int y, int width, int height,
int top, int left, int bottom, int right)
{
- /*
- If our borders change (which often happens when we opaque resize),
- we need to make sure that a new layout will happen, since Sun
- forgets to handle this case.
- */
+ // Configure events tell us the location and dimensions of the
+ // window within the frame borders, and the dimensions of the
+ // frame borders (top, left, bottom, right).
+
+ // If our borders change we need to make sure that a new layout
+ // will happen, since Sun forgets to handle this case.
if (insets.top != top
|| insets.left != left
|| insets.bottom != bottom
|| insets.right != right)
{
- awtComponent.invalidate ();
+ // When our insets change, we receive a configure event with
+ // the new insets, the old window location and the old window
+ // dimensions. We update our Window object's location and
+ // size using our old inset values.
+ setBoundsCallback ((Window) awtComponent,
+ x - insets.left,
+ y - insets.top,
+ width + insets.left + insets.right,
+ height + insets.top + insets.bottom);
+
+ // The peer's dimensions do not get updated automatically when
+ // insets change so we need to do it manually.
+ setSize (width + (insets.left - left) + (insets.right - right),
+ height + (insets.top - top) + (insets.bottom - bottom));
+
+ insets.top = top;
+ insets.left = left;
+ insets.bottom = bottom;
+ insets.right = right;
+
+ awtComponent.validate();
+ }
+ else
+ {
+ int frame_x = x - insets.left;
+ int frame_y = y - insets.top;
+ int frame_width = width + insets.left + insets.right;
+ int frame_height = height + insets.top + insets.bottom;
+
+ if (frame_x != awtComponent.getX()
+ || frame_y != awtComponent.getY()
+ || frame_width != awtComponent.getWidth()
+ || frame_height != awtComponent.getHeight())
+ {
+ setBoundsCallback ((Window) awtComponent,
+ frame_x,
+ frame_y,
+ frame_width,
+ frame_height);
+
+ if (frame_width != awtComponent.getWidth()
+ || frame_height != awtComponent.getHeight())
+ setSize (width, height);
+
+ awtComponent.validate();
+ }
}
-
- insets.top = top;
- insets.left = left;
- insets.bottom = bottom;
- insets.right = right;
-
- awtComponent.setBounds (x, y, width, height);
- awtComponent.validate ();
}
-
+
native public void setVisible (boolean b);
}
*/
Window()
{
+ visible = false;
setLayout(new BorderLayout());
}
{
this.focusableWindowState = focusableWindowState;
}
+
+ // setBoundsCallback is needed so that when a user moves a window,
+ // the Window's location can be updated without calling the peer's
+ // setBounds method. When a user moves a window the peer window's
+ // location is updated automatically and the windowing system sends
+ // a message back to the application informing it of its updated
+ // dimensions. We must update the AWT Window class with these new
+ // dimensions. But we don't want to call the peer's setBounds
+ // method, because the peer's dimensions have already been updated.
+ // (Under X, having this method prevents Configure event loops when
+ // moving windows: Component.setBounds -> peer.setBounds ->
+ // postConfigureEvent -> Component.setBounds -> ... In some cases
+ // Configure event loops cause windows to jitter back and forth
+ // continuously).
+ void setBoundsCallback (int x, int y, int w, int h)
+ {
+ if (this.x == x && this.y == y && width == w && height == h)
+ return;
+ invalidate();
+ this.x = x;
+ this.y = y;
+ width = w;
+ height = h;
+ }
}
point = (*env)->GetIntArrayElements (env, jpoint, 0);
gdk_threads_enter ();
+
gdk_window_get_origin (GTK_WIDGET (ptr)->window, point, point+1);
+
+ if (!GTK_IS_CONTAINER (ptr))
+ {
+ *point += GTK_WIDGET(ptr)->allocation.x;
+ *(point+1) += GTK_WIDGET(ptr)->allocation.y;
+ }
+
gdk_threads_leave ();
(*env)->ReleaseIntArrayElements(env, jpoint, point, 0);
}
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_set__Ljava_lang_String_2Z
- (JNIEnv *env, jobject obj, jstring jname, jboolean jvalue)
+ (JNIEnv *env, jobject obj, jstring jname, jboolean value)
{
const char *name;
- gboolean value;
void *ptr;
ptr = NSA_GET_PTR (env, obj);
name = (*env)->GetStringUTFChars (env, jname, NULL);
- /* Apparently a jboolean can have a value greater than 1. gboolean
- variables may only contain the value TRUE or FALSE. */
- value = jvalue ? TRUE : FALSE;
gdk_threads_enter();
g_object_set(ptr, name, value, NULL);
if (widget && GTK_WIDGET_TOPLEVEL (widget))
{
gint top, left, right, bottom;
- gint x, y, w, h, wb, d;
+ gint x, y, w, h, d;
+ GdkRectangle r;
- /* calculate our insets */
- gdk_window_get_root_geometry (event->any.window,
- &x, &y, &w, &h, &wb, &d);
+ /* Configure events are not posted to the AWT event
+ queue, and as such, the gdk/gtk peer functions will
+ be called back before postConfigureEvent
+ returns. */
+ gdk_threads_leave ();
- /* We used to compute these based on the configure
- event's fields. However, that gives strange and
- apparently incorrect results. */
- top = left = bottom = right = 0;
+ /* Calculate our insets. */
- /* configure events are not posted to the AWT event queue,
- and as such, gdk/gtk will be called back before
- postConfigureEvent returns */
- gdk_threads_leave ();
- (*gdk_env)->CallVoidMethod (gdk_env, *obj_ptr,
+ /* When called from within the gdk_threads critical
+ section these functions seem to return strange
+ results, so we call them after
+ gdk_threads_leave. */
+ gdk_window_get_geometry (event->any.window,
+ &x, &y, &w, &h, &d);
+ gdk_window_get_frame_extents (event->any.window, &r);
+
+ top = y;
+ left = x;
+ bottom = r.height - h - y;
+ right = r.width - w - x;
+
+ (*gdk_env)->CallVoidMethod (gdk_env, *obj_ptr,
postConfigureEventID,
- (jint)event->configure.x,
- (jint)event->configure.y,
- (jint)event->configure.width,
- (jint)event->configure.height,
- (jint)top,
- (jint)left,
- (jint)bottom,
- (jint)right);
+ (jint) event->configure.x,
+ (jint) event->configure.y,
+ (jint) event->configure.width,
+ (jint) event->configure.height,
+ (jint) top,
+ (jint) left,
+ (jint) bottom,
+ (jint) right);
gdk_threads_enter ();
}
}
struct state_table *native_state_table;
#endif
+jmethodID setBoundsCallbackID;
+
jmethodID postActionEventID;
jmethodID postMenuActionEventID;
jmethodID postMouseEventID;
char *homedir, *rcpath = NULL;
/* jclass gtkgenericpeer; */
jclass gtkcomponentpeer, gtkwindowpeer, gtkscrollbarpeer, gtklistpeer,
- gtkmenuitempeer, gtktextcomponentpeer;
+ gtkmenuitempeer, gtktextcomponentpeer, window;
NSA_INIT (env, clazz);
/* setup cached IDs for posting GTK events to Java */
/* gtkgenericpeer = (*env)->FindClass (env, */
/* "gnu/java/awt/peer/gtk/GtkGenericPeer"); */
+
+ window = (*env)->FindClass (env, "java/awt/Window");
+
gtkcomponentpeer = (*env)->FindClass (env,
"gnu/java/awt/peer/gtk/GtkComponentPeer");
gtkwindowpeer = (*env)->FindClass (env,
/* "postActionEvent", */
/* "(Ljava/lang/String;I)V"); */
+ setBoundsCallbackID = (*env)->GetMethodID (env, window,
+ "setBoundsCallback",
+ "(IIII)V");
+
postMenuActionEventID = (*env)->GetMethodID (env, gtkmenuitempeer,
"postMenuActionEvent",
"()V");
#include <gdk/gdkx.h>
/*
- * Make a new window (any type)
+ * Make a new window.
*/
JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkWindowPeer_create
- (JNIEnv *env, jobject obj, jint type, jint width, jint height)
+ (JNIEnv *env, jobject obj, jint type, jboolean decorated,
+ jint width, jint height, jobject parent)
{
- GtkWidget *window;
+ GtkWidget *window_widget;
+ GtkWindow *window;
+ void *window_parent;
GtkWidget *vbox, *layout;
gdk_threads_enter ();
- window = gtk_window_new (type);
+ window_widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ window = GTK_WINDOW (window_widget);
- gtk_window_set_default_size (GTK_WINDOW(window), width, height);
+ gtk_window_set_default_size (window, width, height);
/* We must set this window's size requisition. Otherwise when a
resize is queued (when gtk_widget_queue_resize is called) the
when their resizable property changes. */
gtk_widget_set_size_request (window, width, height);
+ /* Keep this window in front of its parent, if it has one. */
+ if (parent)
+ {
+ window_parent = NSA_GET_PTR (env, parent);
+ gtk_window_set_transient_for (window, GTK_WINDOW(window_parent));
+ }
+
+ gtk_window_set_decorated (window, decorated);
+
+ gtk_window_set_type_hint (window, type);
+
vbox = gtk_vbox_new (0, 0);
layout = gtk_layout_new (NULL, NULL);
gtk_box_pack_end (GTK_BOX (vbox), layout, 1, 1, 0);
- gtk_container_add (GTK_CONTAINER (window), vbox);
+ gtk_container_add (GTK_CONTAINER (window_widget), vbox);
gtk_widget_show (layout);
gtk_widget_show (vbox);
gdk_threads_leave ();
- NSA_SET_PTR (env, obj, window);
+ NSA_SET_PTR (env, obj, window_widget);
}
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setVisible
gdk_threads_leave ();
}
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setBounds
- (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height)
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setBoundsCallback
+ (JNIEnv *env, jobject obj, jobject window,
+ jint x, jint y, jint width, jint height)
{
- void *ptr;
- GtkWidget *widget;
+ /* Circumvent package-private access to call Window's
+ setBoundsCallback method. */
+ (*gdk_env)->CallVoidMethod (gdk_env, window, setBoundsCallbackID,
+ x, y, width, height);
+}
- ptr = NSA_GET_PTR (env, obj);
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setSize
+ (JNIEnv *env, jobject obj, jint width, jint height)
+{
+ void *ptr = NSA_GET_PTR (env, obj);
gdk_threads_enter ();
+ gtk_widget_set_size_request (GTK_WIDGET(ptr), width, height);
+ gdk_threads_leave ();
+}
- widget = GTK_WIDGET (ptr);
- gtk_widget_set_size_request (widget, width, height);
- gtk_window_resize (GTK_WINDOW(widget), width, height);
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetBounds
+ (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height)
+{
+ void *ptr = NSA_GET_PTR (env, obj);
+ gdk_threads_enter ();
+ gtk_window_move (GTK_WINDOW(ptr), x, y);
+ /* Need to change the widget's request size. */
+ gtk_widget_set_size_request (GTK_WIDGET(ptr), width, height);
+ /* Also need to call gtk_window_resize. If the resize is requested
+ by the program and the window's "resizable" property is true then
+ the size request will not be honoured. */
+ gtk_window_resize (GTK_WINDOW (ptr), width, height);
gdk_threads_leave ();
}
#define AWT_FOCUS_LOST 1004
#define AWT_FOCUS_GAINED 1005
+extern jmethodID setBoundsCallbackID;
+
extern jmethodID postActionEventID;
extern jmethodID postMenuActionEventID;
extern jmethodID postMouseEventID;