/* gtkwindowpeer.c -- Native implementation of GtkWindowPeer
- Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2002, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
#include "gtkpeer.h"
#include "gnu_java_awt_peer_gtk_GtkWindowPeer.h"
-#include "gnu_java_awt_peer_gtk_GtkFramePeer.h"
#include <gdk/gdkprivate.h>
#include <gdk/gdkx.h>
+#include <X11/Xatom.h>
+
+/* FIXME: we're currently seeing the double-activation that occurs
+ with metacity and GTK. See
+ http://bugzilla.gnome.org/show_bug.cgi?id=140977 for details. */
+
+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 void window_delete_cb (GtkWidget *widget, GdkEvent *event,
+ jobject peer);
+static void window_destroy_cb (GtkWidget *widget, GdkEvent *event,
+ jobject peer);
+static void window_show_cb (GtkWidget *widget, jobject peer);
+static void window_active_state_change_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ jobject peer);
+static void window_focus_state_change_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ jobject peer);
+static gboolean window_focus_in_cb (GtkWidget * widget,
+ GdkEventFocus *event,
+ jobject peer);
+static gboolean window_focus_out_cb (GtkWidget * widget,
+ GdkEventFocus *event,
+ jobject peer);
+static gboolean window_window_state_cb (GtkWidget *widget,
+ GdkEvent *event,
+ jobject peer);
+static jint window_get_new_state (GtkWidget *widget);
+static gboolean window_property_changed_cb (GtkWidget *widget,
+ GdkEventProperty *event,
+ jobject peer);
+static void realize_cb (GtkWidget *widget, jobject peer);
+
+/* Union used for type punning. */
+union extents_union
+{
+ guchar **gu_extents;
+ unsigned long **extents;
+};
-static void setBounds (GtkWidget *, jint, jint, jint, jint);
-
-/*
- * Make a new window (any type)
- */
+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)
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkWindowPeer_create
+ (JNIEnv *env, jobject obj, jint type, jboolean decorated, jobject parent)
{
- gpointer window;
- GtkWidget *vbox, *layout;
+ GtkWidget *window_widget;
+ GtkWindow *window;
+ void *window_parent;
+ GtkWidget *fixed;
+
+ NSA_SET_GLOBAL_REF (env, obj);
gdk_threads_enter ();
- window = gtk_window_new (type);
+
+ window_widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ window = GTK_WINDOW (window_widget);
+
+ /* 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_window_group_add_window (global_gtk_window_group, window);
- gtk_widget_show (layout);
- gtk_widget_show (vbox);
+ fixed = gtk_fixed_new ();
+ gtk_container_add (GTK_CONTAINER (window_widget), fixed);
+
+ gtk_widget_show (fixed);
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
- (JNIEnv *env, jobject obj, jboolean visible)
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetTitle
+ (JNIEnv *env, jobject obj, jstring title)
{
+ const char *c_title;
void *ptr;
ptr = NSA_GET_PTR (env, obj);
+ c_title = (*env)->GetStringUTFChars (env, title, NULL);
+
gdk_threads_enter ();
- if (visible)
- gtk_widget_show (GTK_WIDGET (ptr));
- else
- gtk_widget_hide (GTK_WIDGET (ptr));
+ gtk_window_set_title (GTK_WINDOW (ptr), c_title);
- XFlush (GDK_DISPLAY ());
gdk_threads_leave ();
+
+ (*env)->ReleaseStringUTFChars (env, title, c_title);
}
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_connectHooks
- (JNIEnv *env, jobject obj)
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetResizable
+ (JNIEnv *env, jobject obj, jboolean resizable)
{
void *ptr;
- GtkVBox* vbox;
- GtkWidget *layout;
- GList* children;
- char* name;
+
ptr = NSA_GET_PTR (env, obj);
gdk_threads_enter ();
- children = gtk_container_get_children(GTK_CONTAINER(ptr));
- vbox = children->data;
- name = GTK_OBJECT_TYPE_NAME(vbox);
- if(!GTK_IS_VBOX(vbox))
- {
- printf("*** this is not a vbox\n");
- }
- children = gtk_container_get_children(GTK_CONTAINER(vbox));
- layout = children->data;
- name = GTK_OBJECT_TYPE_NAME(layout);
- if(!GTK_IS_LAYOUT(layout))
- {
- printf("*** widget is not a layout ***");
- }
-
- gtk_widget_realize (layout);
-
- connect_awt_hook (env, obj, 1, GTK_LAYOUT (layout)->bin_window);
-
- gtk_widget_realize (ptr);
+ gtk_window_set_policy (GTK_WINDOW (ptr), resizable, resizable, FALSE);
- connect_awt_hook (env, obj, 1, GTK_WIDGET (ptr)->window);
-
gdk_threads_leave ();
}
-void
-setup_window (JNIEnv *env, jobject obj, GtkWidget *window, jint width,
- jint height, jboolean visible)
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetModal
+ (JNIEnv *env, jobject obj, jboolean modal)
{
- GtkWidget *layout, *vbox;
-
- gdk_threads_enter();
- gtk_window_set_policy (GTK_WINDOW (window), 1, 1, 0);
- gtk_widget_set_usize (window, width, height);
-
- 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_widget_realize (layout);
- connect_awt_hook (env, obj, 1, GTK_LAYOUT(layout)->bin_window);
- gtk_widget_show (layout);
- gtk_widget_show (vbox);
-
- gtk_widget_realize (window);
-/* setBounds (window, x, y, width, height); */
-
- connect_awt_hook (env, obj, 1, window->window);
- set_visible (window, visible);
+ void *ptr;
+
+ ptr = NSA_GET_PTR (env, obj);
+
+ gdk_threads_enter ();
+
+ gtk_window_set_modal (GTK_WINDOW (ptr), modal);
+
gdk_threads_leave ();
}
-/*
- * Set a frame's title
- */
-
-JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setTitle
- (JNIEnv *env, jobject obj, jstring title)
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetVisible
+ (JNIEnv *env, jobject obj, jboolean visible)
{
void *ptr;
- const char *str;
ptr = NSA_GET_PTR (env, obj);
-
- str = (*env)->GetStringUTFChars (env, title, NULL);
-
+
gdk_threads_enter ();
- gtk_window_set_title (GTK_WINDOW (ptr), str);
+
+ if (visible)
+ gtk_widget_show (GTK_WIDGET (ptr));
+ else
+ gtk_widget_hide (GTK_WIDGET (ptr));
+
+ XFlush (GDK_DISPLAY ());
+
gdk_threads_leave ();
-
- (*env)->ReleaseStringUTFChars (env, title, str);
}
-/*
- * Set a window's resizing policy
- */
-
JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setResizable
- (JNIEnv *env, jobject obj, jboolean resize)
+Java_gnu_java_awt_peer_gtk_GtkWindowPeer_connectSignals
+ (JNIEnv *env, jobject obj)
{
void *ptr;
-
+ jobject *gref;
+
ptr = NSA_GET_PTR (env, obj);
-
+ gref = NSA_GET_GLOBAL_REF (env, obj);
+
gdk_threads_enter ();
- gtk_window_set_policy (GTK_WINDOW (ptr), resize, resize, 0);
- gdk_threads_leave ();
-}
+ g_signal_connect (G_OBJECT (ptr), "event",
+ G_CALLBACK (pre_event_handler), *gref);
+
+ g_signal_connect (G_OBJECT (ptr), "delete-event",
+ G_CALLBACK (window_delete_cb), *gref);
+
+ g_signal_connect (G_OBJECT (ptr), "destroy-event",
+ G_CALLBACK (window_destroy_cb), *gref);
+
+ g_signal_connect (G_OBJECT (ptr), "show",
+ G_CALLBACK (window_show_cb), *gref);
+
+ g_signal_connect (G_OBJECT (ptr), "notify::is-active",
+ G_CALLBACK (window_active_state_change_cb), *gref);
+
+ g_signal_connect (G_OBJECT (ptr), "notify::has-toplevel-focus",
+ G_CALLBACK (window_focus_state_change_cb), *gref);
+
+ g_signal_connect (G_OBJECT (ptr), "focus-in-event",
+ G_CALLBACK (window_focus_in_cb), *gref);
+
+ g_signal_connect (G_OBJECT (ptr), "focus-out-event",
+ G_CALLBACK (window_focus_out_cb), *gref);
-/*
- * Lower the z-level of a window.
- */
+ g_signal_connect (G_OBJECT (ptr), "window-state-event",
+ G_CALLBACK (window_window_state_cb), *gref);
+
+ g_signal_connect (G_OBJECT (ptr), "property-notify-event",
+ G_CALLBACK (window_property_changed_cb), *gref);
+
+ g_signal_connect_after (G_OBJECT (ptr), "realize",
+ G_CALLBACK (realize_cb), *gref);
+
+ g_signal_connect_after (G_OBJECT (ptr), "realize",
+ G_CALLBACK (connect_awt_hook_cb), *gref);
+
+
+ /* Realize the window here so that its frame extents are known now.
+ That way Window.pack can operate with the accurate insets
+ returned by the window manager rather than the default
+ estimates. */
+ gtk_widget_realize (GTK_WIDGET (ptr));
+
+ gdk_threads_leave ();
+}
JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toBack (JNIEnv *env,
ptr = NSA_GET_PTR (env, obj);
gdk_threads_enter ();
+
gdk_window_lower (GTK_WIDGET (ptr)->window);
+ gdk_flush ();
- XFlush (GDK_DISPLAY ());
gdk_threads_leave ();
}
-/*
- * Raise the z-level of a window.
- */
-
JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toFront (JNIEnv *env,
jobject obj)
ptr = NSA_GET_PTR (env, obj);
gdk_threads_enter ();
+
gdk_window_raise (GTK_WIDGET (ptr)->window);
+ gdk_flush ();
- XFlush (GDK_DISPLAY ());
gdk_threads_leave ();
}
-static void
-setBounds (GtkWidget *widget, jint x, jint y, jint width, jint height)
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setBoundsCallback
+ (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
+ jobject window, jint x, jint y, jint width, jint height)
{
-/* gdk_window_get_root_origin (widget->window, ¤t_x, ¤t_y); */
+ /* Circumvent package-private access to call Window's
+ setBoundsCallback method. */
+ (*gdk_env())->CallVoidMethod (gdk_env(), window, setBoundsCallbackID,
+ x, y, width, height);
+}
+
+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);
+
+ /* Avoid GTK runtime assertion failures. */
+ width = (width < 1) ? 1 : width;
+ height = (height < 1) ? 1 : height;
+
+ gdk_threads_enter ();
-/* if (current_x != x || current_y != y) */
-/* { */
-/* gdk_window_set_hints (widget->window, x, y, 0, 0, 0, 0, GDK_HINT_POS); */
-/* gdk_window_move (widget->window, x, y); */
-/* } */
+ gtk_widget_set_size_request (GTK_WIDGET(ptr), width, height);
- gtk_widget_set_usize (widget, width, height);
+ gdk_threads_leave ();
}
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setBounds
+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;
- GtkWidget *widget;
+ void *ptr = NSA_GET_PTR (env, obj);
- ptr = NSA_GET_PTR (env, obj);
+ /* Avoid GTK runtime assertion failures. */
+ width = (width < 1) ? 1 : width;
+ height = (height < 1) ? 1 : height;
gdk_threads_enter ();
- widget = GTK_WIDGET (ptr);
- setBounds (widget, x, y, width, height);
-
+ gtk_window_move (GTK_WINDOW(ptr), x, y);
+ /* The call to gdk_window_move is needed in addition to the call to
+ gtk_window_move. If gdk_window_move isn't called, then the
+ following set of operations doesn't give the expected results:
+
+ 1. show a window
+ 2. manually move it to another position on the screen
+ 3. hide the window
+ 4. reposition the window with Component.setLocation
+ 5. show the window
+
+ Instead of being at the position set by setLocation, the window
+ is reshown at the position to which it was moved manually. */
+ if (GTK_WIDGET (ptr)->window != NULL)
+ gdk_window_move (GTK_WIDGET (ptr)->window, 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 ();
}
-JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GtkFramePeer_setMenuBarPeer
- (JNIEnv *env, jobject obj, jobject menubar)
+static void
+window_get_frame_extents (GtkWidget *window,
+ int *top, int *left, int *bottom, int *right)
{
- void *wptr, *mptr;
- GtkBox *box;
+ unsigned long *extents = NULL;
+ union extents_union gu_ex;
+
+ /* Guess frame extents in case _NET_FRAME_EXTENTS is not
+ supported. */
+ *top = 23;
+ *left = 6;
+ *bottom = 6;
+ *right = 6;
+
+ /* 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];
+ }
+}
- if (!menubar) return;
+static Atom extents_atom = 0;
- wptr = NSA_GET_PTR (env, obj);
- mptr = NSA_GET_PTR (env, menubar);
+/* 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);
- if (!mptr) return; /* this case should remove a menu */
+ /* 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 void
+window_delete_cb (GtkWidget *widget __attribute__((unused)),
+ GdkEvent *event __attribute__((unused)),
+ jobject peer)
+{
+ gdk_threads_leave ();
+ (*gdk_env())->CallVoidMethod (gdk_env(), peer,
+ postWindowEventID,
+ (jint) AWT_WINDOW_CLOSING,
+ (jobject) NULL, (jint) 0);
gdk_threads_enter ();
- box = GTK_BOX (GTK_BIN (wptr)->child);
- gtk_box_pack_start (box, GTK_WIDGET (mptr), 0, 0, 0);
+}
+
+static void
+window_destroy_cb (GtkWidget *widget __attribute__((unused)),
+ GdkEvent *event __attribute__((unused)),
+ jobject peer)
+{
gdk_threads_leave ();
+ (*gdk_env())->CallVoidMethod (gdk_env(), peer,
+ postWindowEventID,
+ (jint) AWT_WINDOW_CLOSED,
+ (jobject) NULL, (jint) 0);
+ gdk_threads_enter ();
}
-JNIEXPORT jint JNICALL
-Java_gnu_java_awt_peer_gtk_GtkFramePeer_getMenuBarHeight
- (JNIEnv *env, jobject obj)
+static void
+window_show_cb (GtkWidget *widget __attribute__((unused)),
+ jobject peer)
{
- void *ptr;
- GList *children;
- jint height = 0;
+ gdk_threads_leave ();
+ (*gdk_env())->CallVoidMethod (gdk_env(), peer,
+ postWindowEventID,
+ (jint) AWT_WINDOW_OPENED,
+ (jobject) NULL, (jint) 0);
+ gdk_threads_enter ();
+}
- ptr = NSA_GET_PTR (env, obj);
+static void
+window_active_state_change_cb (GtkWidget *widget __attribute__((unused)),
+ GParamSpec *pspec __attribute__((unused)),
+ jobject peer __attribute__((unused)))
+{
+ /* FIXME: not sure if this is needed or not. */
+ /* Remove the unused attributes if you fix the below. */
+#if 0
+ gdk_threads_leave ();
+ if (GTK_WINDOW (widget)->is_active)
+ (*gdk_env())->CallVoidMethod (gdk_env(), peer,
+ postWindowEventID,
+ (jint) AWT_WINDOW_GAINED_FOCUS,
+ (jobject) NULL, (jint) 0);
+ else
+ (*gdk_env())->CallVoidMethod (gdk_env(), peer,
+ postWindowEventID,
+ (jint) AWT_WINDOW_DEACTIVATED,
+ (jobject) NULL, (jint) 0);
+ gdk_threads_enter ();
+#endif
+}
+
+static void
+window_focus_state_change_cb (GtkWidget *widget,
+ GParamSpec *pspec __attribute__((unused)),
+ jobject peer)
+{
+ gdk_threads_leave ();
+ if (GTK_WINDOW (widget)->has_toplevel_focus)
+ (*gdk_env())->CallVoidMethod (gdk_env(), peer,
+ postWindowEventID,
+ (jint) AWT_WINDOW_ACTIVATED,
+ (jobject) NULL, (jint) 0);
+ else
+ (*gdk_env())->CallVoidMethod (gdk_env(), peer,
+ postWindowEventID,
+ (jint) AWT_WINDOW_DEACTIVATED,
+ (jobject) NULL, (jint) 0);
+ gdk_threads_enter ();
+}
+static gboolean
+window_focus_in_cb (GtkWidget * widget __attribute__((unused)),
+ GdkEventFocus *event __attribute__((unused)),
+ jobject peer)
+{
+ gdk_threads_leave ();
+ (*gdk_env())->CallVoidMethod (gdk_env(), peer,
+ postWindowEventID,
+ (jint) AWT_WINDOW_GAINED_FOCUS,
+ (jobject) NULL, (jint) 0);
+ /* FIXME: somewhere after this is handled, the child window is
+ getting an expose event. */
gdk_threads_enter ();
- children = gtk_container_children (GTK_CONTAINER (GTK_BIN (ptr)->child));
- if (g_list_length (children) == 2)
- {
- GtkWidget *menubar = GTK_WIDGET (children->data);
- height = menubar->allocation.height;
+ return FALSE;
+}
- }
+static gboolean
+window_focus_out_cb (GtkWidget * widget __attribute__((unused)),
+ GdkEventFocus *event __attribute__((unused)),
+ jobject peer)
+{
gdk_threads_leave ();
+ (*gdk_env())->CallVoidMethod (gdk_env(), peer,
+ postWindowEventID,
+ (jint) AWT_WINDOW_LOST_FOCUS,
+ (jobject) NULL, (jint) 0);
+ /* FIXME: somewhere after this is handled, the child window is
+ getting an expose event. */
+ gdk_threads_enter ();
+ return FALSE;
+}
- return height;
+static gboolean
+window_window_state_cb (GtkWidget *widget,
+ GdkEvent *event,
+ jobject peer)
+{
+ jint new_state;
+
+ /* Handle WINDOW_ICONIFIED and WINDOW_DEICONIFIED events. */
+ if (event->window_state.changed_mask & GDK_WINDOW_STATE_ICONIFIED)
+ {
+ /* We've either been iconified or deiconified. */
+ if (event->window_state.new_window_state & GDK_WINDOW_STATE_ICONIFIED)
+ {
+ /* We've been iconified. */
+ gdk_threads_leave ();
+ (*gdk_env())->CallVoidMethod (gdk_env(), peer,
+ postWindowEventID,
+ (jint) AWT_WINDOW_ICONIFIED,
+ (jobject) NULL, (jint) 0);
+ gdk_threads_enter ();
+ }
+ else
+ {
+ /* We've been deiconified. */
+ gdk_threads_leave ();
+ (*gdk_env())->CallVoidMethod (gdk_env(), peer,
+ postWindowEventID,
+ (jint) AWT_WINDOW_DEICONIFIED,
+ (jobject) NULL, (jint) 0);
+ gdk_threads_enter ();
+ }
+ }
+
+ /* Post a WINDOW_STATE_CHANGED event, passing the new frame state to
+ GtkWindowPeer. */
+ new_state = AWT_FRAME_STATE_NORMAL;
+
+ if (event->window_state.new_window_state & GDK_WINDOW_STATE_ICONIFIED)
+ new_state |= AWT_FRAME_STATE_ICONIFIED;
+
+ new_state |= window_get_new_state (widget);
+
+ gdk_threads_leave ();
+ (*gdk_env())->CallVoidMethod (gdk_env(), peer,
+ postWindowEventID,
+ (jint) AWT_WINDOW_STATE_CHANGED,
+ (jobject) NULL, new_state);
+ gdk_threads_enter ();
+ return TRUE;
}
+static jint
+window_get_new_state (GtkWidget *widget)
+{
+ GdkDisplay *display = gtk_widget_get_display(widget);
+ jint new_state = AWT_FRAME_STATE_NORMAL;
+ Atom type;
+ gint format;
+ gulong atom_count;
+ gulong bytes_after;
+ Atom *atom_list = NULL;
+ union atom_list_union alu;
+ gulong i;
+
+ alu.atom_list = &atom_list;
+ XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
+ GDK_WINDOW_XID (widget->window),
+ gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
+ 0, G_MAXLONG, False, XA_ATOM, &type, &format, &atom_count,
+ &bytes_after, alu.gu_extents);
+
+ if (type != None)
+ {
+ Atom maxvert = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_VERT");
+ Atom maxhorz = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_HORZ");
+
+ i = 0;
+ while (i < atom_count)
+ {
+ if (atom_list[i] == maxhorz)
+ new_state |= AWT_FRAME_STATE_MAXIMIZED_HORIZ;
+ else if (atom_list[i] == maxvert)
+ new_state |= AWT_FRAME_STATE_MAXIMIZED_VERT;
+
+ ++i;
+ }
+
+ XFree (atom_list);
+ }
+ return new_state;
+}
-void
-gdk_window_get_root_geometry (GdkWindow *window,
- gint *x,
- gint *y,
- gint *width,
- gint *height,
- gint *border,
- gint *depth)
+static gboolean
+window_property_changed_cb (GtkWidget *widget __attribute__((unused)),
+ GdkEventProperty *event,
+ jobject peer)
{
- GdkWindow *private;
- unsigned int nchildren;
-
- g_return_if_fail (window != NULL);
-
- private = (GdkWindow*) window;
- if (x)
- *x = 0;
- if (y)
- *y = 0;
- if (width)
- *width = 0;
- if (height)
- *height = 0;
- if (border)
- *border = 0;
- if (depth)
- *depth = 0;
-
- if (GDK_WINDOW_DESTROYED (private))
- return;
-
- private = gdk_window_get_toplevel (private);
- if (GDK_WINDOW_DESTROYED(private))
- return;
+ unsigned long *extents;
+ union extents_union gu_ex;
+
+ gu_ex.extents = &extents;
+ if (gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE) == event->atom
+ && gdk_property_get (event->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))
+ {
+ gdk_threads_leave ();
+ (*gdk_env())->CallVoidMethod (gdk_env(), peer,
+ postInsetsChangedEventID,
+ (jint) extents[2], /* top */
+ (jint) extents[0], /* left */
+ (jint) extents[3], /* bottom */
+ (jint) extents[1]); /* right */
+ gdk_threads_enter ();
+ }
- gdk_window_get_geometry (private, x, y, width, height, depth);
-
+
+ return FALSE;
}
+static void
+realize_cb (GtkWidget *widget, jobject peer)
+{
+ jint top = 0;
+ jint left = 0;
+ jint bottom = 0;
+ jint right = 0;
+ jint width = 0;
+ jint height = 0;
+
+ width = (*gdk_env())->CallIntMethod (gdk_env(), peer, windowGetWidthID);
+ height = (*gdk_env())->CallIntMethod (gdk_env(), peer, windowGetHeightID);
+
+ window_get_frame_extents (widget, &top, &left, &bottom, &right);
+
+ (*gdk_env())->CallVoidMethod (gdk_env(), peer,
+ postInsetsChangedEventID,
+ top, left, bottom, right);
+
+ gtk_window_set_default_size (GTK_WINDOW (widget),
+ MAX (1, width - left - right),
+ MAX (1, height - top - bottom));
+
+ /* set the size like we do in nativeSetBounds */
+ gtk_widget_set_size_request (widget,
+ MAX (1, width - left - right),
+ MAX (1, height - top - bottom));
+
+ gtk_window_resize (GTK_WINDOW (widget),
+ MAX (1, width - left - right),
+ MAX (1, height - top - bottom));
+}