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)
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
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
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. */
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>
45 #include <X11/Xatom.h>
47 static void window_delete_cb (GtkWidget
*widget
, GdkEvent
*event
,
49 static void window_destroy_cb (GtkWidget
*widget
, GdkEvent
*event
,
51 static void window_show_cb (GtkWidget
*widget
, jobject peer
);
52 static gboolean
window_focus_in_cb (GtkWidget
* widget
,
55 static gboolean
window_focus_out_cb (GtkWidget
* widget
,
58 static gboolean
window_window_state_cb (GtkWidget
*widget
,
61 static jint
window_get_new_state (GtkWidget
*widget
);
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
;
75 GtkWidget
*vbox
, *layout
;
77 /* Create global reference and save it for future use */
78 NSA_SET_GLOBAL_REF (env
, obj
);
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. */
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
)
130 ptr
= NSA_GET_PTR (env
, obj
);
132 gdk_threads_enter ();
135 gtk_widget_show (GTK_WIDGET (ptr
));
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
)
149 GtkWidget
* vbox
, *layout
;
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
);
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
)
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
,
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
,
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
)
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
)
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 ();
368 window_delete_cb (GtkWidget
*widget
__attribute__((unused
)),
369 GdkEvent
*event
__attribute__((unused
)),
372 (*gdk_env
)->CallVoidMethod (gdk_env
, peer
,
374 (jint
) AWT_WINDOW_CLOSING
,
375 (jobject
) NULL
, (jint
) 0);
379 window_destroy_cb (GtkWidget
*widget
__attribute__((unused
)),
380 GdkEvent
*event
__attribute__((unused
)),
383 (*gdk_env
)->CallVoidMethod (gdk_env
, peer
,
385 (jint
) AWT_WINDOW_CLOSED
,
386 (jobject
) NULL
, (jint
) 0);
390 window_show_cb (GtkWidget
*widget
__attribute__((unused
)),
393 (*gdk_env
)->CallVoidMethod (gdk_env
, peer
,
395 (jint
) AWT_WINDOW_OPENED
,
396 (jobject
) NULL
, (jint
) 0);
400 window_focus_in_cb (GtkWidget
* widget
__attribute__((unused
)),
401 GdkEventFocus
*event
__attribute__((unused
)),
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
,
408 (jint
) AWT_WINDOW_ACTIVATED
,
409 (jobject
) NULL
, (jint
) 0);
411 (*gdk_env
)->CallVoidMethod (gdk_env
, peer
,
413 (jint
) AWT_WINDOW_GAINED_FOCUS
,
414 (jobject
) NULL
, (jint
) 0);
419 window_focus_out_cb (GtkWidget
* widget
__attribute__((unused
)),
420 GdkEventFocus
*event
__attribute__((unused
)),
423 (*gdk_env
)->CallVoidMethod (gdk_env
, peer
,
425 (jint
) AWT_WINDOW_LOST_FOCUS
,
426 (jobject
) NULL
, (jint
) 0);
428 (*gdk_env
)->CallVoidMethod (gdk_env
, peer
,
430 (jint
) AWT_WINDOW_DEACTIVATED
,
431 (jobject
) NULL
, (jint
) 0);
436 window_window_state_cb (GtkWidget
*widget
,
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
,
451 (jint
) AWT_WINDOW_ICONIFIED
,
452 (jobject
) NULL
, (jint
) 0);
456 /* We've been deiconified. */
457 (*gdk_env
)->CallVoidMethod (gdk_env
, peer
,
459 (jint
) AWT_WINDOW_DEICONIFIED
,
460 (jobject
) NULL
, (jint
) 0);
464 /* Post a WINDOW_STATE_CHANGED event, passing the new frame state to
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
,
475 (jint
) AWT_WINDOW_STATE_CHANGED
,
476 (jobject
) NULL
, new_state
);
481 window_get_new_state (GtkWidget
*widget
)
483 GdkDisplay
*display
= gtk_widget_get_display(widget
);
484 jint new_state
= AWT_FRAME_STATE_NORMAL
;
489 Atom
*atom_list
= NULL
;
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
);
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");
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
;