2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / libjava / jni / gtk-peer / gnu_java_awt_peer_gtk_GtkWindowPeer.c
blob022677b06a9d50e3ef0f87bddeaa67a4837ca1c4
1 /* gtkwindowpeer.c -- Native implementation of GtkWindowPeer
2 Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 #include "gtkpeer.h"
40 #include "gnu_java_awt_peer_gtk_GtkComponentPeer.h"
41 #include "gnu_java_awt_peer_gtk_GtkWindowPeer.h"
42 #include "gnu_java_awt_peer_gtk_GtkFramePeer.h"
43 #include <gdk/gdkprivate.h>
44 #include <gdk/gdkx.h>
45 #include <X11/Xatom.h>
47 static void window_delete_cb (GtkWidget *widget, GdkEvent *event,
48 jobject peer);
49 static void window_destroy_cb (GtkWidget *widget, GdkEvent *event,
50 jobject peer);
51 static void window_show_cb (GtkWidget *widget, jobject peer);
52 static gboolean window_focus_in_cb (GtkWidget * widget,
53 GdkEventFocus *event,
54 jobject peer);
55 static gboolean window_focus_out_cb (GtkWidget * widget,
56 GdkEventFocus *event,
57 jobject peer);
58 static gboolean window_window_state_cb (GtkWidget *widget,
59 GdkEvent *event,
60 jobject peer);
61 static jint window_get_new_state (GtkWidget *widget);
64 * Make a new window.
67 JNIEXPORT void JNICALL
68 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_create
69 (JNIEnv *env, jobject obj, jint type, jboolean decorated,
70 jint width, jint height, jobject parent)
72 GtkWidget *window_widget;
73 GtkWindow *window;
74 void *window_parent;
75 GtkWidget *vbox, *layout;
77 /* Create global reference and save it for future use */
78 NSA_SET_GLOBAL_REF (env, obj);
80 gdk_threads_enter ();
82 window_widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
83 window = GTK_WINDOW (window_widget);
85 // Avoid GTK runtime assertion failures.
86 width = (width < 1) ? 1 : width;
87 height = (height < 1) ? 1 : height;
89 gtk_window_set_default_size (window, width, height);
91 /* We must set this window's size requisition. Otherwise when a
92 resize is queued (when gtk_widget_queue_resize is called) the
93 window will snap to its default requisition of 0x0. If we omit
94 this call, Frames and Dialogs shrink to degenerate 1x1 windows
95 when their resizable property changes. */
96 gtk_widget_set_size_request (window_widget, width, height);
98 /* Keep this window in front of its parent, if it has one. */
99 if (parent)
101 window_parent = NSA_GET_PTR (env, parent);
102 gtk_window_set_transient_for (window, GTK_WINDOW(window_parent));
105 gtk_window_set_decorated (window, decorated);
107 gtk_window_set_type_hint (window, type);
109 gtk_window_group_add_window (global_gtk_window_group, window);
111 vbox = gtk_vbox_new (0, 0);
112 layout = gtk_layout_new (NULL, NULL);
113 gtk_box_pack_end (GTK_BOX (vbox), layout, 1, 1, 0);
114 gtk_container_add (GTK_CONTAINER (window_widget), vbox);
116 gtk_widget_show (layout);
117 gtk_widget_show (vbox);
119 gdk_threads_leave ();
121 NSA_SET_PTR (env, obj, window_widget);
124 JNIEXPORT void JNICALL
125 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetVisible
126 (JNIEnv *env, jobject obj, jboolean visible)
128 void *ptr;
130 ptr = NSA_GET_PTR (env, obj);
132 gdk_threads_enter ();
134 if (visible)
135 gtk_widget_show (GTK_WIDGET (ptr));
136 else
137 gtk_widget_hide (GTK_WIDGET (ptr));
139 XFlush (GDK_DISPLAY ());
141 gdk_threads_leave ();
144 JNIEXPORT void JNICALL
145 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_connectJObject
146 (JNIEnv *env, jobject obj)
148 void *ptr;
149 GtkWidget* vbox, *layout;
150 GList* children;
152 ptr = NSA_GET_PTR (env, obj);
154 gdk_threads_enter ();
156 children = gtk_container_get_children(GTK_CONTAINER(ptr));
157 vbox = children->data;
159 if(!GTK_IS_VBOX(vbox))
161 printf("*** this is not a vbox\n");
163 children = gtk_container_get_children(GTK_CONTAINER(vbox));
164 layout = children->data;
166 if(!GTK_IS_LAYOUT(layout))
168 printf("*** widget is not a layout ***");
171 gtk_widget_realize (layout);
173 connect_awt_hook (env, obj, 1, GTK_LAYOUT (layout)->bin_window);
175 gtk_widget_realize (ptr);
177 connect_awt_hook (env, obj, 1, GTK_WIDGET (ptr)->window);
179 gdk_threads_leave ();
182 JNIEXPORT void JNICALL
183 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_connectSignals
184 (JNIEnv *env, jobject obj)
186 void *ptr = NSA_GET_PTR (env, obj);
187 jobject *gref = NSA_GET_GLOBAL_REF (env, obj);
188 g_assert (gref);
190 gdk_threads_enter ();
192 gtk_widget_realize (ptr);
194 /* Connect signals for window event support. */
195 g_signal_connect (G_OBJECT (ptr), "delete-event",
196 G_CALLBACK (window_delete_cb), *gref);
198 g_signal_connect (G_OBJECT (ptr), "destroy-event",
199 G_CALLBACK (window_destroy_cb), *gref);
201 g_signal_connect (G_OBJECT (ptr), "show",
202 G_CALLBACK (window_show_cb), *gref);
204 g_signal_connect (G_OBJECT (ptr), "focus-in-event",
205 G_CALLBACK (window_focus_in_cb), *gref);
207 g_signal_connect (G_OBJECT (ptr), "focus-out-event",
208 G_CALLBACK (window_focus_out_cb), *gref);
210 g_signal_connect (G_OBJECT (ptr), "window-state-event",
211 G_CALLBACK (window_window_state_cb), *gref);
213 gdk_threads_leave ();
215 /* Connect the superclass signals. */
216 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_connectSignals (env, obj);
220 * Set a frame's title
223 JNIEXPORT void JNICALL
224 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setTitle
225 (JNIEnv *env, jobject obj, jstring title)
227 void *ptr;
228 const char *str;
230 ptr = NSA_GET_PTR (env, obj);
232 str = (*env)->GetStringUTFChars (env, title, NULL);
234 gdk_threads_enter ();
235 gtk_window_set_title (GTK_WINDOW (ptr), str);
236 gdk_threads_leave ();
238 (*env)->ReleaseStringUTFChars (env, title, str);
242 * Lower the z-level of a window.
245 JNIEXPORT void JNICALL
246 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toBack (JNIEnv *env,
247 jobject obj)
249 void *ptr;
250 ptr = NSA_GET_PTR (env, obj);
252 gdk_threads_enter ();
253 gdk_window_lower (GTK_WIDGET (ptr)->window);
255 XFlush (GDK_DISPLAY ());
256 gdk_threads_leave ();
260 * Raise the z-level of a window.
263 JNIEXPORT void JNICALL
264 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toFront (JNIEnv *env,
265 jobject obj)
267 void *ptr;
268 ptr = NSA_GET_PTR (env, obj);
270 gdk_threads_enter ();
271 gdk_window_raise (GTK_WIDGET (ptr)->window);
273 XFlush (GDK_DISPLAY ());
274 gdk_threads_leave ();
277 JNIEXPORT void JNICALL
278 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setBoundsCallback
279 (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
280 jobject window, jint x, jint y, jint width, jint height)
282 /* Circumvent package-private access to call Window's
283 setBoundsCallback method. */
284 (*gdk_env)->CallVoidMethod (gdk_env, window, setBoundsCallbackID,
285 x, y, width, height);
288 JNIEXPORT void JNICALL
289 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setSize
290 (JNIEnv *env, jobject obj, jint width, jint height)
292 void *ptr = NSA_GET_PTR (env, obj);
294 // Avoid GTK runtime assertion failures.
295 width = (width < 1) ? 1 : width;
296 height = (height < 1) ? 1 : height;
298 gdk_threads_enter ();
299 gtk_widget_set_size_request (GTK_WIDGET(ptr), width, height);
300 gdk_threads_leave ();
303 JNIEXPORT void JNICALL
304 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetBounds
305 (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height)
307 void *ptr = NSA_GET_PTR (env, obj);
309 // Avoid GTK runtime assertion failures.
310 width = (width < 1) ? 1 : width;
311 height = (height < 1) ? 1 : height;
313 gdk_threads_enter ();
314 gtk_window_move (GTK_WINDOW(ptr), x, y);
315 /* Need to change the widget's request size. */
316 gtk_widget_set_size_request (GTK_WIDGET(ptr), width, height);
317 /* Also need to call gtk_window_resize. If the resize is requested
318 by the program and the window's "resizable" property is true then
319 the size request will not be honoured. */
320 gtk_window_resize (GTK_WINDOW (ptr), width, height);
321 gdk_threads_leave ();
324 JNIEXPORT void JNICALL
325 Java_gnu_java_awt_peer_gtk_GtkFramePeer_setMenuBarPeer
326 (JNIEnv *env, jobject obj, jobject menubar)
328 void *wptr, *mptr;
329 GtkBox *box;
331 if (!menubar) return;
333 wptr = NSA_GET_PTR (env, obj);
334 mptr = NSA_GET_PTR (env, menubar);
336 if (!mptr) return; /* this case should remove a menu */
338 gdk_threads_enter ();
339 box = GTK_BOX (GTK_BIN (wptr)->child);
340 gtk_box_pack_start (box, GTK_WIDGET (mptr), 0, 0, 0);
341 gdk_threads_leave ();
344 JNIEXPORT jint JNICALL
345 Java_gnu_java_awt_peer_gtk_GtkFramePeer_getMenuBarHeight
346 (JNIEnv *env, jobject obj)
348 void *ptr;
349 GList *children;
350 jint height = 0;
352 ptr = NSA_GET_PTR (env, obj);
354 gdk_threads_enter ();
355 children = gtk_container_children (GTK_CONTAINER (GTK_BIN (ptr)->child));
356 if (g_list_length (children) == 2)
358 GtkWidget *menubar = GTK_WIDGET (children->data);
359 height = menubar->allocation.height;
362 gdk_threads_leave ();
364 return height;
367 static void
368 window_delete_cb (GtkWidget *widget __attribute__((unused)),
369 GdkEvent *event __attribute__((unused)),
370 jobject peer)
372 (*gdk_env)->CallVoidMethod (gdk_env, peer,
373 postWindowEventID,
374 (jint) AWT_WINDOW_CLOSING,
375 (jobject) NULL, (jint) 0);
378 static void
379 window_destroy_cb (GtkWidget *widget __attribute__((unused)),
380 GdkEvent *event __attribute__((unused)),
381 jobject peer)
383 (*gdk_env)->CallVoidMethod (gdk_env, peer,
384 postWindowEventID,
385 (jint) AWT_WINDOW_CLOSED,
386 (jobject) NULL, (jint) 0);
389 static void
390 window_show_cb (GtkWidget *widget __attribute__((unused)),
391 jobject peer)
393 (*gdk_env)->CallVoidMethod (gdk_env, peer,
394 postWindowEventID,
395 (jint) AWT_WINDOW_OPENED,
396 (jobject) NULL, (jint) 0);
399 static gboolean
400 window_focus_in_cb (GtkWidget * widget __attribute__((unused)),
401 GdkEventFocus *event __attribute__((unused)),
402 jobject peer)
404 /* FIXME: when hiding then showing, we get two sets of
405 (LOST_FOCUS/DEACTIVATED, ACTIVATED/GAINED_FOCUS) events. */
406 (*gdk_env)->CallVoidMethod (gdk_env, peer,
407 postWindowEventID,
408 (jint) AWT_WINDOW_ACTIVATED,
409 (jobject) NULL, (jint) 0);
411 (*gdk_env)->CallVoidMethod (gdk_env, peer,
412 postWindowEventID,
413 (jint) AWT_WINDOW_GAINED_FOCUS,
414 (jobject) NULL, (jint) 0);
415 return TRUE;
418 static gboolean
419 window_focus_out_cb (GtkWidget * widget __attribute__((unused)),
420 GdkEventFocus *event __attribute__((unused)),
421 jobject peer)
423 (*gdk_env)->CallVoidMethod (gdk_env, peer,
424 postWindowEventID,
425 (jint) AWT_WINDOW_LOST_FOCUS,
426 (jobject) NULL, (jint) 0);
428 (*gdk_env)->CallVoidMethod (gdk_env, peer,
429 postWindowEventID,
430 (jint) AWT_WINDOW_DEACTIVATED,
431 (jobject) NULL, (jint) 0);
432 return TRUE;
435 static gboolean
436 window_window_state_cb (GtkWidget *widget,
437 GdkEvent *event,
438 jobject peer)
440 jint new_state;
442 /* Handle WINDOW_ICONIFIED and WINDOW_DEICONIFIED events. */
443 if (event->window_state.changed_mask & GDK_WINDOW_STATE_ICONIFIED)
445 /* We've either been iconified or deiconified. */
446 if (event->window_state.new_window_state & GDK_WINDOW_STATE_ICONIFIED)
448 /* We've been iconified. */
449 (*gdk_env)->CallVoidMethod (gdk_env, peer,
450 postWindowEventID,
451 (jint) AWT_WINDOW_ICONIFIED,
452 (jobject) NULL, (jint) 0);
454 else
456 /* We've been deiconified. */
457 (*gdk_env)->CallVoidMethod (gdk_env, peer,
458 postWindowEventID,
459 (jint) AWT_WINDOW_DEICONIFIED,
460 (jobject) NULL, (jint) 0);
464 /* Post a WINDOW_STATE_CHANGED event, passing the new frame state to
465 GtkWindowPeer. */
466 new_state = AWT_FRAME_STATE_NORMAL;
468 if (event->window_state.new_window_state & GDK_WINDOW_STATE_ICONIFIED)
469 new_state |= AWT_FRAME_STATE_ICONIFIED;
471 new_state |= window_get_new_state (widget);
473 (*gdk_env)->CallVoidMethod (gdk_env, peer,
474 postWindowEventID,
475 (jint) AWT_WINDOW_STATE_CHANGED,
476 (jobject) NULL, new_state);
477 return TRUE;
480 static jint
481 window_get_new_state (GtkWidget *widget)
483 GdkDisplay *display = gtk_widget_get_display(widget);
484 jint new_state = AWT_FRAME_STATE_NORMAL;
485 Atom type;
486 gint format;
487 gulong atom_count;
488 gulong bytes_after;
489 Atom *atom_list = NULL;
490 gulong i;
492 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (widget->window),
493 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
494 0, G_MAXLONG, False, XA_ATOM, &type, &format, &atom_count,
495 &bytes_after, (guchar **)&atom_list);
497 if (type != None)
499 Atom maxvert = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_VERT");
500 Atom maxhorz = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_HORZ");
502 i = 0;
503 while (i < atom_count)
505 if (atom_list[i] == maxhorz)
506 new_state |= AWT_FRAME_STATE_MAXIMIZED_HORIZ;
507 else if (atom_list[i] == maxvert)
508 new_state |= AWT_FRAME_STATE_MAXIMIZED_VERT;
510 ++i;
513 XFree (atom_list);
515 return new_state;