1 /* Functions for the X window system.
2 Copyright (C) 1989, 1992-5, 1997 Free Software Foundation, Inc.
3 Copyright (C) 1995, 1996 Ben Wing.
5 This file is part of XEmacs.
7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* Synched up with: Not synched with FSF. */
24 /* Substantially rewritten for XEmacs. */
25 /* Revamped to use Gdk/Gtk by William Perry */
31 #include "console-gtk.h"
33 #include "glyphs-gtk.h"
34 #include "objects-gtk.h"
35 #include "scrollbar-gtk.h"
37 #include "gtk-xemacs.h"
47 #include <libgnomeui/libgnomeui.h>
54 #define BORDER_WIDTH 0
55 #define INTERNAL_BORDER_WIDTH 0
57 #define TRANSIENT_DATA_IDENTIFIER "xemacs::transient_for"
58 #define UNMAPPED_DATA_IDENTIFIER "xemacs::initially_unmapped"
60 #define STUPID_X_SPECIFIC_GTK_STUFF
62 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
66 /* Default properties to use when creating frames. */
67 Lisp_Object Vdefault_gtk_frame_plist;
69 Lisp_Object Qwindow_id;
70 Lisp_Object Qdetachable_menubar;
71 Lisp_Object Qtext_widget;
72 Lisp_Object Qcontainer_widget;
73 Lisp_Object Qshell_widget;
75 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
76 EXFUN (Fgtk_window_id, 1);
85 static GtkTargetEntry dnd_target_table[] = {
86 { "STRING", 0, TARGET_TYPE_STRING },
87 { "text/plain", 0, TARGET_TYPE_STRING },
88 { "text/uri-list", 0, TARGET_TYPE_URI_LIST },
89 { "_NETSCAPE_URL", 0, TARGET_TYPE_STRING }
92 static guint dnd_n_targets = sizeof(dnd_target_table) / sizeof(dnd_target_table[0]);
97 /************************************************************************/
98 /* helper functions */
99 /************************************************************************/
101 /* Return the Emacs frame-object which contains the given widget. */
103 gtk_widget_to_frame (GtkWidget *w)
105 struct frame *f = NULL;
107 for (; w; w = w->parent)
109 if ((f = (struct frame *) gtk_object_get_data (GTK_OBJECT (w),
110 GTK_DATA_FRAME_IDENTIFIER)))
114 return (selected_frame());
118 /* Return the Emacs frame-object corresponding to an X window */
120 gtk_window_to_frame (struct device *d, GdkWindow *wdesc)
122 Lisp_Object tail, frame;
125 /* This function was previously written to accept only a window argument
126 (and to loop over all devices looking for a matching window), but
127 that is incorrect because window ID's are not unique across displays. */
129 for (tail = DEVICE_FRAME_LIST (d); CONSP (tail); tail = XCDR (tail))
135 if (FRAME_GTK_P (f) && GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f)) == wdesc)
141 /* Like gtk_window_to_frame but also compares the window with the widget's
144 gtk_any_window_to_frame (struct device *d, GdkWindow *w)
150 DEVICE_FRAME_LOOP (frmcons, d)
152 struct frame *fr = XFRAME (XCAR (frmcons));
153 if ((w == GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (fr))) ||
154 (w == GET_GTK_WIDGET_WINDOW (FRAME_GTK_CONTAINER_WIDGET (fr))) ||
156 (w == GET_GTK_WIDGET_WINDOW (FRAME_GTK_MENUBAR_WIDGET (fr))) ||
158 (w == GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (fr))))
163 w = gdk_window_get_parent (w);
170 gtk_any_widget_or_parent_to_frame (struct device *d, GtkWidget *widget)
172 return (gtk_any_window_to_frame (d, GET_GTK_WIDGET_WINDOW (widget)));
176 gtk_any_window_to_device (GdkWindow *w)
178 struct device *d = NULL;
179 Lisp_Object devcons, concons;
181 DEVICE_LOOP_NO_BREAK (devcons, concons)
183 d = XDEVICE (XCAR (devcons));
184 if (!DEVICE_GTK_P (d)) continue;
185 if (gtk_any_window_to_frame (d, w))
192 decode_gtk_frame (Lisp_Object frame)
195 XSETFRAME (frame, selected_frame ());
196 CHECK_LIVE_FRAME (frame);
197 /* this will also catch dead frames, but putting in the above check
198 results in a more useful error */
199 CHECK_GTK_FRAME (frame);
200 return XFRAME (frame);
204 /************************************************************************/
205 /* window-manager interactions */
206 /************************************************************************/
208 gtk_frame_iconified_p (struct frame *f)
210 return (f->iconified);
214 /************************************************************************/
215 /* frame properties */
216 /************************************************************************/
219 gtk_frame_property (struct frame *f, Lisp_Object property)
221 GtkWidget *shell = FRAME_GTK_SHELL_WIDGET (f);
223 if (EQ (Qleft, property) || EQ (Qtop, property))
226 if (!GET_GTK_WIDGET_WINDOW(shell))
228 gdk_window_get_deskrelative_origin (GET_GTK_WIDGET_WINDOW (shell), &x, &y);
229 if (EQ (Qleft, property)) return make_int (x);
230 if (EQ (Qtop, property)) return make_int (y);
232 if (EQ (Qshell_widget, property))
234 return (FRAME_GTK_LISP_WIDGETS (f)[0]);
236 if (EQ (Qcontainer_widget, property))
238 return (FRAME_GTK_LISP_WIDGETS (f)[1]);
240 if (EQ (Qtext_widget, property))
242 return (FRAME_GTK_LISP_WIDGETS (f)[2]);
244 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
245 if (EQ (Qwindow_id, property))
246 return Fgtk_window_id (make_frame (f));
253 gtk_internal_frame_property_p (struct frame *f, Lisp_Object property)
255 return EQ (property, Qleft)
256 || EQ (property, Qtop)
257 || EQ (Qshell_widget, property)
258 || EQ (Qcontainer_widget, property)
259 || EQ (Qtext_widget, property)
260 || EQ (property, Qwindow_id)
261 || STRINGP (property);
265 gtk_frame_properties (struct frame *f)
267 Lisp_Object props = Qnil;
268 GtkWidget *shell = FRAME_GTK_SHELL_WIDGET (f);
271 props = cons3 (Qshell_widget, FRAME_GTK_LISP_WIDGETS (f)[0], props);
272 props = cons3 (Qcontainer_widget, FRAME_GTK_LISP_WIDGETS (f)[1], props);
273 props = cons3 (Qtext_widget, FRAME_GTK_LISP_WIDGETS (f)[2], props);
275 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
276 props = cons3 (Qwindow_id, Fgtk_window_id (make_frame (f)), props);
279 if (!GET_GTK_WIDGET_WINDOW (shell))
282 gdk_window_get_deskrelative_origin (GET_GTK_WIDGET_WINDOW (shell), &x, &y);
284 props = cons3 (Qtop, make_int (y), props);
285 props = cons3 (Qleft, make_int (x), props);
291 /* Functions called only from `gtk_set_frame_properties' to set
292 individual properties. */
295 gtk_set_frame_text_value (struct frame *f, Bufbyte *value,
296 void (*func) (gpointer, gchar *),
299 gchar *the_text = (gchar *) value;
301 /* Programmer fuckup or window is not realized yet. */
302 if (!func || !arg) return;
308 /* Optimize for common ASCII case */
309 for (ptr = value; *ptr; ptr++)
310 if (!BYTE_ASCII_P (*ptr))
313 C_STRING_TO_EXTERNAL (value, tmp, Qctext);
320 (*func) (arg, (gchar *) the_text);
324 gtk_set_title_from_bufbyte (struct frame *f, Bufbyte *name)
326 if (GTK_IS_WINDOW (FRAME_GTK_SHELL_WIDGET (f)))
327 gtk_set_frame_text_value (f, name,
328 (void (*)(gpointer, gchar *))
329 gtk_window_set_title, FRAME_GTK_SHELL_WIDGET (f));
333 gtk_set_icon_name_from_bufbyte (struct frame *f, Bufbyte *name)
335 gtk_set_frame_text_value (f, name,
336 (void (*)(gpointer, gchar *))
337 gdk_window_set_icon_name, FRAME_GTK_SHELL_WIDGET (f)->window);
340 /* Set the initial frame size as specified. This function is used
341 when the frame's widgets have not yet been realized.
344 gtk_set_initial_frame_size (struct frame *f, int x, int y,
345 unsigned int w, unsigned int h)
347 GtkWidget *shell = FRAME_GTK_SHELL_WIDGET (f);
348 GdkGeometry geometry;
349 GdkWindowHints geometry_mask = 0x00;
351 if (GTK_IS_WINDOW (shell))
353 /* Deal with the cell size */
354 default_face_height_and_width (make_frame (f), &geometry.height_inc, &geometry.width_inc);
355 geometry_mask |= GDK_HINT_RESIZE_INC;
357 gtk_window_set_geometry_hints (GTK_WINDOW (shell),
358 FRAME_GTK_TEXT_WIDGET (f), &geometry, geometry_mask);
359 gdk_window_set_hints (GET_GTK_WIDGET_WINDOW (shell), x, y, 0, 0, 0, 0, GDK_HINT_POS);
360 gtk_window_set_policy (GTK_WINDOW (shell), TRUE, TRUE, FALSE);
363 FRAME_HEIGHT (f) = h;
366 change_frame_size (f, h, w, 0);
370 gtk_widget_size_request (FRAME_GTK_SHELL_WIDGET (f), &req);
371 gtk_widget_set_usize (FRAME_GTK_SHELL_WIDGET (f), req.width, req.height);
375 /* Report that a frame property of frame S is being set or changed.
376 If the property is not specially recognized, do nothing.
380 gtk_set_frame_properties (struct frame *f, Lisp_Object plist)
383 gint width = 0, height = 0;
384 gboolean width_specified_p = FALSE;
385 gboolean height_specified_p = FALSE;
386 gboolean x_position_specified_p = FALSE;
387 gboolean y_position_specified_p = FALSE;
390 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
392 Lisp_Object prop = Fcar (tail);
393 Lisp_Object val = Fcar (Fcdr (tail));
397 if (EQ (prop, Qfont))
399 /* If the value is not a string we silently ignore it. */
402 Lisp_Object frm, font_spec;
405 font_spec = Fget (Fget_face (Qdefault), Qfont, Qnil);
407 Fadd_spec_to_specifier (font_spec, val, frm, Qnil, Qnil);
408 update_frame_face_values (f);
412 else if (EQ (prop, Qwidth))
416 width_specified_p = TRUE;
419 else if (EQ (prop, Qheight))
423 height_specified_p = TRUE;
426 /* Further kludge the x/y. */
427 else if (EQ (prop, Qx))
430 x = (gint) XINT (val);
431 x_position_specified_p = TRUE;
434 else if (EQ (prop, Qy))
437 y = (gint) XINT (val);
438 y_position_specified_p = TRUE;
444 /* Kludge kludge kludge. We need to deal with the size and position
447 int size_specified_p = width_specified_p || height_specified_p;
448 int position_specified_p = x_position_specified_p || y_position_specified_p;
450 if (!width_specified_p)
452 if (!height_specified_p)
455 /* Kludge kludge kludge kludge. */
456 if (position_specified_p &&
457 (!x_position_specified_p || !y_position_specified_p))
460 GtkWidget *shell = FRAME_GTK_SHELL_WIDGET (f);
461 gdk_window_get_deskrelative_origin (GET_GTK_WIDGET_WINDOW (shell),
462 (x_position_specified_p ? &dummy : &x),
463 (y_position_specified_p ? &dummy : &y));
466 if (!f->init_finished)
468 if (size_specified_p || position_specified_p)
469 gtk_set_initial_frame_size (f, x, y, width, height);
473 if (size_specified_p)
476 XSETFRAME (frame, f);
477 Fset_frame_size (frame, make_int (width), make_int (height), Qnil);
479 if (position_specified_p)
482 XSETFRAME (frame, f);
483 Fset_frame_position (frame, make_int (x), make_int (y));
490 /************************************************************************/
491 /* widget creation */
492 /************************************************************************/
493 /* Figure out what size the shell widget should initially be,
494 and set it. Should be called after the default font has been
495 determined but before the widget has been realized. */
497 extern Lisp_Object Vgtk_initial_geometry;
501 get_number (const char **geometry)
506 if (**geometry == '-'){
510 while (**geometry && isdigit (**geometry)){
511 value = value * 10 + (**geometry - '0');
521 * gnome_parse_geometry
522 * @geometry: geometry string to be parsed
523 * @xpos: X position geometry component
524 * @ypos: Y position geometry component
525 * @width: pixel width geometry component
526 * @height: pixel height geometry component
529 * Parses the geometry string passed in @geometry, and fills
530 * @xpos, @ypos, @width, and @height with
531 * the corresponding values upon completion of the parse.
532 * If the parse fails, it should be assumed that @xpos, @ypos, @width,
533 * and @height contain undefined values.
536 * %TRUE if the geometry was successfully parsed, %FALSE otherwise.
540 gnome_parse_geometry (const gchar *geometry, gint *xpos,
541 gint *ypos, gint *width, gint *height)
545 g_return_val_if_fail (xpos != NULL, FALSE);
546 g_return_val_if_fail (ypos != NULL, FALSE);
547 g_return_val_if_fail (width != NULL, FALSE);
548 g_return_val_if_fail (height != NULL, FALSE);
550 *xpos = *ypos = *width = *height = -1;
555 if (*geometry == '=')
559 if (isdigit (*geometry))
560 *width = get_number (&geometry);
563 if (*geometry == 'x' || *geometry == 'X'){
565 *height = get_number (&geometry);
569 if (*geometry == '+'){
572 } else if (*geometry == '-'){
573 subtract = gdk_screen_width ();
577 *xpos = get_number (&geometry);
579 *xpos = subtract - *xpos;
582 if (*geometry == '+'){
585 } else if (*geometry == '-'){
586 subtract = gdk_screen_height ();
590 *ypos = get_number (&geometry);
592 *ypos = subtract - *ypos;
598 gtk_initialize_frame_size (struct frame *f)
600 gint x = 10, y = 10, w = 80, h = 30;
602 if (STRINGP (Vgtk_initial_geometry))
604 if (!gnome_parse_geometry (XSTRING_DATA (Vgtk_initial_geometry), &x,&y,&w,&h))
612 /* set the position of the frame's root window now. When the
613 frame was created, the position was initialized to (0,0). */
615 struct window *win = XWINDOW (f->root_window);
617 WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f);
618 WINDOW_TOP (win) = FRAME_TOP_BORDER_END (f);
620 if (!NILP (f->minibuffer_window))
622 win = XWINDOW (f->minibuffer_window);
623 WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f);
627 gtk_set_initial_frame_size (f, x, y, w, h);
631 resize_event_cb (GtkWidget *w, GtkAllocation *allocation, gpointer user_data)
633 struct frame *f = (struct frame *) user_data;
635 f->pixwidth = allocation->width;
636 f->pixheight = allocation->height;
638 if (FRAME_GTK_TEXT_WIDGET (f)->window)
641 XSETFRAME (frame, f);
642 Fredraw_frame (frame, Qt);
649 delete_event_cb (GtkWidget *w, GdkEvent *ev, gpointer user_data)
651 struct frame *f = (struct frame *) user_data;
654 XSETFRAME (frame, f);
655 enqueue_misc_user_event (frame, Qeval, list3 (Qdelete_frame, frame, Qt));
657 /* See if tickling the event queue helps us with our delays when
659 signal_fake_event ();
664 extern gboolean emacs_shell_event_handler (GtkWidget *wid, GdkEvent *event, gpointer closure);
665 extern Lisp_Object build_gtk_object (GtkObject *obj);
668 #define GNOME_IS_APP(x) 0
669 #define gnome_app_set_contents(x,y) 0
673 cleanup_deleted_frame (gpointer data)
675 struct frame *f = (struct frame *) data;
678 XSETFRAME (frame, f);
679 Fdelete_frame (frame, Qt);
682 #ifdef HAVE_DRAGNDROP
684 dragndrop_data_received (GtkWidget *widget,
685 GdkDragContext *context,
688 GtkSelectionData *data,
693 dragndrop_dropped (GtkWidget *widget,
694 GdkDragContext *drag_context,
700 Lisp_Object Vcurrent_drag_object;
702 #define DRAG_SELECTION_DATA_ERROR "Error converting drag data to external format"
704 dragndrop_get_drag (GtkWidget *widget,
705 GdkDragContext *drag_context,
706 GtkSelectionData *data,
711 gtk_selection_data_set (data, GDK_SELECTION_TYPE_STRING, 8,
712 DRAG_SELECTION_DATA_ERROR,
713 strlen (DRAG_SELECTION_DATA_ERROR));
717 case TARGET_TYPE_STRING:
719 Lisp_Object string = Vcurrent_drag_object;
721 if (!STRINGP (Vcurrent_drag_object))
723 string = Fprin1_to_string (string, Qnil);
724 /* Convert to a string */
727 gtk_selection_data_set (data, GDK_SELECTION_TYPE_STRING,
728 8, XSTRING_DATA (string), XSTRING_LENGTH (string));
731 case TARGET_TYPE_URI_LIST:
736 Vcurrent_drag_object = Qnil;
739 DEFUN ("gtk-start-drag-internal", Fgtk_start_drag_internal, 2, 3, 0, /*
740 Start a GTK drag from a buffer.
741 First arg is the event that started the drag,
742 second arg should be some string, and the third
743 is the type of the data (this should be a MIME type as a string (ie: text/plain)).
744 The type defaults to text/plain.
750 struct frame *f = decode_gtk_frame (Fselected_frame (Qnil));
751 GtkWidget *wid = FRAME_GTK_TEXT_WIDGET (f);
752 struct Lisp_Event *lisp_event = XEVENT(event);
754 GtkTargetList *tl = gtk_target_list_new (dnd_target_table, dnd_n_targets);
756 /* only drag if this is really a press */
757 if (EVENT_TYPE(lisp_event) != button_press_event)
760 /* get the desired type */
761 if (!NILP (dtyp) && STRINGP (dtyp))
762 dnd_typ = gdk_atom_intern (XSTRING_DATA (dtyp), FALSE);
764 gtk_drag_begin (wid, tl, GDK_ACTION_COPY, lisp_event->event.button.button, NULL);
766 Vcurrent_drag_object = data;
768 gtk_target_list_unref (tl);
774 /* Creates the widgets for a frame.
775 lisp_window_id is a Lisp description of an X window or Xt
778 This function does not map the windows. (That is
779 done by gtk_popup_frame().)
782 gtk_create_widgets (struct frame *f, Lisp_Object lisp_window_id, Lisp_Object parent)
785 GtkWidget *text, *container, *shell;
786 gboolean embedded_p = !NILP (lisp_window_id);
791 if (STRINGP (f->name))
792 TO_EXTERNAL_FORMAT (LISP_STRING, f->name, C_STRING_ALLOCA, name, Qctext);
796 FRAME_GTK_TOP_LEVEL_FRAME_P (f) = 1;
800 CHECK_GTK_OBJECT (lisp_window_id);
802 if (!GTK_IS_CONTAINER (XGTK_OBJECT (lisp_window_id)->object))
804 signal_simple_error ("Window ID must be a GtkContainer subclass", lisp_window_id);
807 shell = gtk_vbox_new (FALSE, 0);
809 gtk_object_weakref (GTK_OBJECT (shell), cleanup_deleted_frame, f);
810 gtk_container_add (GTK_CONTAINER (XGTK_OBJECT (lisp_window_id)->object), shell);
815 shell = GTK_WIDGET (gnome_app_new ("XEmacs", "XEmacs/GNOME"));
817 shell = GTK_WIDGET (gtk_window_new (GTK_WINDOW_TOPLEVEL));
823 /* If this is a transient window, keep the parent info around */
824 GtkWidget *parentwid = FRAME_GTK_SHELL_WIDGET (XFRAME (parent));
825 gtk_object_set_data (GTK_OBJECT (shell), TRANSIENT_DATA_IDENTIFIER, parentwid);
826 gtk_window_set_transient_for (GTK_WINDOW (shell), GTK_WINDOW (parentwid));
829 gtk_container_set_border_width (GTK_CONTAINER (shell), 0);
831 gtk_object_set_data (GTK_OBJECT (shell), GTK_DATA_FRAME_IDENTIFIER, f);
833 FRAME_GTK_SHELL_WIDGET (f) = shell;
835 text = GTK_WIDGET (gtk_xemacs_new (f));
837 if (!GNOME_IS_APP (shell))
838 container = GTK_WIDGET (gtk_vbox_new (FALSE, INTERNAL_BORDER_WIDTH));
842 FRAME_GTK_CONTAINER_WIDGET (f) = container;
843 FRAME_GTK_TEXT_WIDGET (f) = text;
845 #ifdef HAVE_DRAGNDROP
846 gtk_drag_dest_set (text, GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT,
847 dnd_target_table, dnd_n_targets,
848 GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_ASK);
849 gtk_signal_connect (GTK_OBJECT (text), "drag_drop",
850 GTK_SIGNAL_FUNC (dragndrop_dropped), text);
851 gtk_signal_connect (GTK_OBJECT (text), "drag_data_received",
852 GTK_SIGNAL_FUNC (dragndrop_data_received), text);
853 gtk_signal_connect (GTK_OBJECT (text), "drag_data_get",
854 GTK_SIGNAL_FUNC (dragndrop_get_drag), NULL);
858 /* Create the initial menubar widget. */
859 menubar_visible = gtk_initialize_frame_menubar (f);
863 gtk_widget_show_all (FRAME_GTK_MENUBAR_WIDGET (f));
865 #endif /* HAVE_MENUBARS */
868 if (GNOME_IS_APP (shell))
869 gnome_app_set_contents (GNOME_APP (shell), text);
872 /* Now comes the drawing area, which should fill the rest of the
875 gtk_box_pack_end (GTK_BOX (container), text, TRUE, TRUE, 0);
877 /* Connect main event handler */
878 gtk_signal_connect (GTK_OBJECT (shell), "delete-event", GTK_SIGNAL_FUNC (delete_event_cb), f);
881 static char *events_to_frob[] = { "focus-in-event",
883 "enter-notify-event",
884 "leave-notify-event",
887 "property-notify-event",
888 "selection-clear-event",
889 "selection-request-event",
890 "selection-notify-event",
892 /* "configure-event", */
893 "visibility-notify-event",
897 for (i = 0; events_to_frob[i]; i++)
899 gtk_signal_connect (GTK_OBJECT (shell), events_to_frob[i],
900 GTK_SIGNAL_FUNC (emacs_shell_event_handler), f);
904 gtk_signal_connect (GTK_OBJECT (shell), "size-allocate", GTK_SIGNAL_FUNC (resize_event_cb), f);
906 /* This might be safe to call now... */
907 /* gtk_signal_connect (GTK_OBJECT (shell), "event", GTK_SIGNAL_FUNC (emacs_shell_event_handler), f); */
909 /* Let's make sure we get all the events we can */
910 gtk_widget_set_events (text, GDK_ALL_EVENTS_MASK);
912 if (shell != container)
913 gtk_container_add (GTK_CONTAINER (shell), container);
915 gtk_widget_set_name (shell, "XEmacs::shell");
916 gtk_widget_set_name (container, "XEmacs::container");
917 gtk_widget_set_name (text, "XEmacs::text");
919 FRAME_GTK_LISP_WIDGETS(f)[0] = build_gtk_object (GTK_OBJECT (shell));
920 FRAME_GTK_LISP_WIDGETS(f)[1] = build_gtk_object (GTK_OBJECT (container));
921 FRAME_GTK_LISP_WIDGETS(f)[2] = build_gtk_object (GTK_OBJECT (text));
923 gtk_widget_realize (shell);
926 /* create the windows for the specified frame and display them.
927 Note that the widgets have already been created, and any
928 necessary geometry calculations have already been done. */
930 gtk_popup_frame (struct frame *f)
934 if (gtk_object_get_data (GTK_OBJECT (FRAME_GTK_SHELL_WIDGET (f)), UNMAPPED_DATA_IDENTIFIER))
936 FRAME_GTK_TOTALLY_VISIBLE_P (f) = 0;
938 gtk_widget_realize (FRAME_GTK_SHELL_WIDGET (f));
939 gtk_widget_realize (FRAME_GTK_TEXT_WIDGET (f));
940 gtk_widget_hide_all (FRAME_GTK_SHELL_WIDGET (f));
944 gtk_widget_show_all (FRAME_GTK_SHELL_WIDGET (f));
949 allocate_gtk_frame_struct (struct frame *f)
951 /* zero out all slots. */
952 f->frame_data = xnew_and_zero (struct gtk_frame);
954 /* yeah, except the lisp ones */
955 FRAME_GTK_ICON_PIXMAP (f) = Qnil;
956 FRAME_GTK_ICON_PIXMAP_MASK (f) = Qnil;
959 Hashtables of callback data for glyphs on the frame. Make them EQ because
960 we only use ints as keys. Otherwise we run into stickiness in redisplay
961 because internal_equal() can QUIT. See enter_redisplay_critical_section().
963 FRAME_GTK_WIDGET_INSTANCE_HASH_TABLE (f) =
964 make_lisp_hash_table (50, HASH_TABLE_VALUE_WEAK, HASH_TABLE_EQ);
965 FRAME_GTK_WIDGET_CALLBACK_HASH_TABLE (f) =
966 make_lisp_hash_table (50, HASH_TABLE_VALUE_WEAK, HASH_TABLE_EQ);
967 FRAME_GTK_WIDGET_CALLBACK_EX_HASH_TABLE (f) =
968 make_lisp_hash_table (50, HASH_TABLE_VALUE_WEAK, HASH_TABLE_EQ);
972 /************************************************************************/
974 /************************************************************************/
977 gtk_init_frame_1 (struct frame *f, Lisp_Object props)
979 /* This function can GC */
980 Lisp_Object initially_unmapped;
981 Lisp_Object device = FRAME_DEVICE (f);
982 Lisp_Object lisp_window_id = Fplist_get (props, Qwindow_id, Qnil);
983 Lisp_Object popup = Fplist_get (props, Qpopup, Qnil);
988 popup = Fselected_frame (device);
989 CHECK_LIVE_FRAME (popup);
990 if (!EQ (device, FRAME_DEVICE (XFRAME (popup))))
991 signal_simple_error_2 ("Parent must be on same device as frame",
995 initially_unmapped = Fplist_get (props, Qinitially_unmapped, Qnil);
998 * Previously we set this only if NILP (DEVICE_SELECTED_FRAME (d))
999 * to make sure that messages were displayed as soon as possible
1000 * if we're creating the first frame on a device. But it is
1001 * better to just set this all the time, so that when a new frame
1002 * is created that covers the selected frame, echo area status
1003 * messages can still be seen. f->visible is reset later if the
1004 * initially-unmapped property is found to be non-nil in the
1009 allocate_gtk_frame_struct (f);
1010 gtk_create_widgets (f, lisp_window_id, popup);
1012 if (!NILP (initially_unmapped))
1014 gtk_object_set_data (GTK_OBJECT (FRAME_GTK_SHELL_WIDGET (f)),
1015 UNMAPPED_DATA_IDENTIFIER, (gpointer) 1);
1020 gtk_init_frame_2 (struct frame *f, Lisp_Object props)
1022 /* Set up the values of the widget/frame. A case could be made for putting
1023 this inside of the widget's initialize method. */
1025 update_frame_face_values (f);
1026 gtk_initialize_frame_size (f);
1028 * update_frame_title() can't be done here, because some of the
1029 * modeline specs depend on the frame's device having a selected
1030 * frame, and that may not have been set up yet. The redisplay
1031 * will update the frame title anyway, so nothing is lost.
1033 * It turns out it gives problems with FVWMs name based mapping.
1034 * We'll just need to be carefull in the modeline specs.
1036 update_frame_title (f);
1040 gtk_init_frame_3 (struct frame *f)
1042 /* Pop up the frame. */
1043 gtk_popup_frame (f);
1047 gtk_mark_frame (struct frame *f)
1049 mark_object (FRAME_GTK_ICON_PIXMAP (f));
1050 mark_object (FRAME_GTK_ICON_PIXMAP_MASK (f));
1051 mark_object (FRAME_GTK_LISP_WIDGETS (f)[0]);
1052 mark_object (FRAME_GTK_LISP_WIDGETS (f)[1]);
1053 mark_object (FRAME_GTK_LISP_WIDGETS (f)[2]);
1054 mark_object (FRAME_GTK_WIDGET_INSTANCE_HASH_TABLE (f));
1055 mark_object (FRAME_GTK_WIDGET_CALLBACK_HASH_TABLE (f));
1056 mark_object (FRAME_GTK_WIDGET_CALLBACK_EX_HASH_TABLE (f));
1060 gtk_set_frame_icon (struct frame *f)
1062 GdkPixmap *gtk_pixmap = NULL, *gtk_mask = NULL;
1064 if (IMAGE_INSTANCEP (f->icon)
1065 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (f->icon)))
1067 gtk_pixmap = XIMAGE_INSTANCE_GTK_PIXMAP (f->icon);
1068 gtk_mask = XIMAGE_INSTANCE_GTK_MASK (f->icon);
1076 gdk_window_set_icon (GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f)), NULL, gtk_pixmap, gtk_mask);
1080 gtk_set_frame_pointer (struct frame *f)
1082 GtkWidget *w = FRAME_GTK_TEXT_WIDGET (f);
1083 GdkCursor *c = XIMAGE_INSTANCE_GTK_CURSOR (f->pointer);
1085 if (POINTER_IMAGE_INSTANCEP (f->pointer))
1087 gdk_window_set_cursor (GET_GTK_WIDGET_WINDOW (w), c);
1093 stderr_out ("POINTER_IMAGE_INSTANCEP (f->pointer) failed!\n");
1098 gtk_get_frame_parent (struct frame *f)
1100 GtkWidget *parentwid = gtk_object_get_data (GTK_OBJECT (FRAME_GTK_SHELL_WIDGET (f)),
1101 TRANSIENT_DATA_IDENTIFIER);
1103 /* find the frame whose wid is parentwid */
1106 Lisp_Object frmcons;
1107 DEVICE_FRAME_LOOP (frmcons, XDEVICE (FRAME_DEVICE (f)))
1109 Lisp_Object frame = XCAR (frmcons);
1110 if (FRAME_GTK_SHELL_WIDGET (XFRAME (frame)) == parentwid)
1117 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
1118 DEFUN ("gtk-window-id", Fgtk_window_id, 0, 1, 0, /*
1119 Get the ID of the Gtk window.
1120 This gives us a chance to manipulate the Emacs window from within a
1121 different program. Since the ID is an unsigned long, we return it as
1127 struct frame *f = decode_gtk_frame (frame);
1129 /* Arrrrggghhh... this defeats the whole purpose of using Gdk... do we really need this? */
1130 sprintf (str, "%lu", GDK_WINDOW_XWINDOW( GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f))));
1131 return build_string (str);
1136 /************************************************************************/
1137 /* manipulating the X window */
1138 /************************************************************************/
1141 gtk_set_frame_position (struct frame *f, int xoff, int yoff)
1143 gtk_widget_set_uposition (FRAME_GTK_SHELL_WIDGET (f), xoff, yoff);
1146 /* Call this to change the size of frame S's x-window. */
1149 gtk_set_frame_size (struct frame *f, int cols, int rows)
1151 GtkWidget *shell = FRAME_GTK_SHELL_WIDGET (f);
1152 GdkGeometry geometry;
1153 GdkWindowHints geometry_mask = 0x00;
1155 if (GTK_IS_WINDOW (shell))
1157 /* Update the cell size */
1158 default_face_height_and_width (make_frame (f), &geometry.height_inc, &geometry.width_inc);
1159 geometry_mask |= GDK_HINT_RESIZE_INC;
1161 gtk_window_set_geometry_hints (GTK_WINDOW (shell),
1162 FRAME_GTK_TEXT_WIDGET (f), &geometry, geometry_mask);
1165 change_frame_size (f, rows, cols, 0);
1170 gtk_widget_size_request (FRAME_GTK_SHELL_WIDGET (f), &req);
1171 gtk_widget_set_usize (FRAME_GTK_SHELL_WIDGET (f), req.width, req.height);
1175 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
1176 /* There is NO equivalent to XWarpPointer under Gtk */
1178 gtk_set_mouse_position (struct window *w, int x, int y)
1180 struct frame *f = XFRAME (w->frame);
1181 Display *display = GDK_DISPLAY ();
1182 XWarpPointer (display, None,
1183 GDK_WINDOW_XWINDOW (GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f))),
1184 0, 0, 0, 0, w->pixel_left + x, w->pixel_top + y);
1186 #endif /* STUPID_X_SPECIFIC_GTK_STUFF */
1189 gtk_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y)
1191 /* Returns the pixel position within the editor text widget */
1193 GdkWindow *w = gdk_window_at_pointer (&win_x, &win_y);
1194 struct frame *f = NULL;
1198 /* At this point, w is the innermost GdkWindow containing the
1199 ** pointer and win_x and win_y are the coordinates of that window.
1201 f = gtk_any_window_to_frame (d, w);
1205 XSETFRAME (*frame, f);
1207 gdk_window_get_pointer (GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f)),
1208 &win_x, &win_y, NULL);
1217 gtk_cant_notify_wm_error (void)
1219 error ("Can't notify window manager of iconification.");
1222 /* Raise frame F. */
1224 gtk_raise_frame_1 (struct frame *f, int force)
1226 if (FRAME_VISIBLE_P (f) || force)
1228 GdkWindow *emacs_window = GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f));
1230 gdk_window_raise (emacs_window);
1235 gtk_raise_frame (struct frame *f)
1237 gtk_raise_frame_1 (f, 1);
1240 /* Lower frame F. */
1242 gtk_lower_frame (struct frame *f)
1244 if (FRAME_VISIBLE_P (f))
1246 gdk_window_lower (GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f)));
1250 /* Change from withdrawn state to mapped state. */
1252 gtk_make_frame_visible (struct frame *f)
1254 gtk_widget_map (FRAME_GTK_SHELL_WIDGET (f));
1255 gtk_raise_frame_1 (f, 0);
1258 /* Change from mapped state to withdrawn state. */
1260 gtk_make_frame_invisible (struct frame *f)
1262 gtk_widget_unmap(FRAME_GTK_SHELL_WIDGET (f));
1266 gtk_frame_visible_p (struct frame *f)
1268 GtkWidget *w = FRAME_GTK_SHELL_WIDGET (f);
1270 f->visible = (GTK_OBJECT_FLAGS (w) & GTK_VISIBLE);
1276 gtk_frame_totally_visible_p (struct frame *f)
1278 return FRAME_GTK_TOTALLY_VISIBLE_P (f);
1281 /* Change window state from mapped to iconified. */
1283 gtk_iconify_frame (struct frame *f)
1285 GdkWindow *w = GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f));
1287 /* There is no equivalent to XIconifyWindow in Gtk/Gdk. */
1288 if (!XIconifyWindow (GDK_WINDOW_XDISPLAY (w),
1289 GDK_WINDOW_XWINDOW (w),
1290 DefaultScreen (GDK_WINDOW_XDISPLAY (w))))
1291 gtk_cant_notify_wm_error ();
1296 /* Sets the X focus to frame f. */
1298 gtk_focus_on_frame (struct frame *f)
1300 GtkWidget *shell_widget;
1302 assert (FRAME_GTK_P (f));
1304 shell_widget = FRAME_GTK_SHELL_WIDGET (f);
1305 if (!GET_GTK_WIDGET_WINDOW (shell_widget))
1308 gtk_widget_grab_focus (shell_widget);
1311 /* Destroy the window of frame S. */
1313 gtk_delete_frame (struct frame *f)
1315 GtkWidget *w = FRAME_GTK_SHELL_WIDGET (f);
1317 gtk_widget_destroy (w);
1319 if (FRAME_GTK_GEOM_FREE_ME_PLEASE (f))
1320 xfree (FRAME_GTK_GEOM_FREE_ME_PLEASE (f));
1321 xfree (f->frame_data);
1326 gtk_recompute_cell_sizes (struct frame *frm)
1328 if (GTK_IS_WINDOW (FRAME_GTK_SHELL_WIDGET (frm)))
1330 GtkWindow *w = GTK_WINDOW (FRAME_GTK_SHELL_WIDGET (frm));
1331 GdkGeometry geometry;
1332 GdkWindowHints geometry_mask;
1333 gint width_inc = 10;
1334 gint height_inc = 10;
1336 default_face_height_and_width (make_frame (frm), &height_inc, &width_inc);
1337 geometry_mask = GDK_HINT_RESIZE_INC;
1338 geometry.width_inc = width_inc;
1339 geometry.height_inc = height_inc;
1341 gtk_window_set_geometry_hints (w, FRAME_GTK_TEXT_WIDGET (frm), &geometry, geometry_mask);
1346 gtk_update_frame_external_traits (struct frame* frm, Lisp_Object name)
1348 Lisp_Object frame = Qnil;
1350 XSETFRAME(frame, frm);
1352 if (EQ (name, Qforeground))
1354 Lisp_Object color = FACE_FOREGROUND (Vdefault_face, frame);
1357 if (!EQ (color, Vthe_null_color_instance))
1359 fgc = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (color));
1360 /* #### BILL!!! The X code set the XtNforeground property of
1361 the text widget here. Why did they bother? All that type
1362 of thing is done down in the guts of the redisplay code,
1363 not in the Emacs* widgets. */
1366 else if (EQ (name, Qbackground))
1368 Lisp_Object color = FACE_BACKGROUND (Vdefault_face, frame);
1371 if (!EQ (color, Vthe_null_color_instance))
1373 bgc = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (color));
1374 if (FRAME_GTK_SHELL_WIDGET (frm)->window)
1376 gdk_window_set_background (FRAME_GTK_SHELL_WIDGET (frm)->window, bgc);
1378 if (FRAME_GTK_TEXT_WIDGET (frm)->window)
1380 gdk_window_set_background (FRAME_GTK_TEXT_WIDGET (frm)->window, bgc);
1384 /* Really crappy way to force the modeline shadows to be
1385 redrawn. But effective. */
1386 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (frm);
1387 MARK_FRAME_CHANGED (frm);
1389 else if (EQ (name, Qfont))
1391 Lisp_Object font = FACE_FONT (Vdefault_face, frame, Vcharset_ascii);
1393 if (!EQ (font, Vthe_null_font_instance))
1395 /* #### BILL!!! The X code set the XtNfont property of the
1396 text widget here. Why did they bother? All that type of
1397 thing is done down in the guts of the redisplay code, not
1398 in the Emacs* widgets. */
1404 #ifdef HAVE_TOOLBARS
1405 /* Setting the background clears the entire frame area
1406 including the toolbar so we force an immediate redraw of
1408 if (EQ (name, Qbackground))
1409 MAYBE_DEVMETH (XDEVICE (frm->device), redraw_frame_toolbars, (frm));
1410 #endif /* HAVE_TOOLBARS */
1412 /* Set window manager resize increment hints according to
1413 the new character size */
1414 if (EQ (name, Qfont) && FRAME_GTK_TOP_LEVEL_FRAME_P (frm))
1415 gtk_recompute_cell_sizes (frm);
1419 /************************************************************************/
1420 /* initialization */
1421 /************************************************************************/
1424 syms_of_frame_gtk (void)
1426 defsymbol (&Qwindow_id, "window-id");
1427 defsymbol (&Qtext_widget, "text-widget");
1428 defsymbol (&Qcontainer_widget, "container-widget");
1429 defsymbol (&Qshell_widget, "shell-widget");
1430 defsymbol (&Qdetachable_menubar, "detachable-menubar");
1432 #ifdef HAVE_DRAGNDROP
1433 staticpro (&Vcurrent_drag_object);
1434 Vcurrent_drag_object = Qnil;
1435 DEFSUBR (Fgtk_start_drag_internal);
1437 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
1438 DEFSUBR (Fgtk_window_id);
1443 console_type_create_frame_gtk (void)
1446 CONSOLE_HAS_METHOD (gtk, init_frame_1);
1447 CONSOLE_HAS_METHOD (gtk, init_frame_2);
1448 CONSOLE_HAS_METHOD (gtk, init_frame_3);
1449 CONSOLE_HAS_METHOD (gtk, mark_frame);
1450 CONSOLE_HAS_METHOD (gtk, focus_on_frame);
1451 CONSOLE_HAS_METHOD (gtk, delete_frame);
1452 CONSOLE_HAS_METHOD (gtk, get_mouse_position);
1453 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
1454 CONSOLE_HAS_METHOD (gtk, set_mouse_position);
1456 CONSOLE_HAS_METHOD (gtk, raise_frame);
1457 CONSOLE_HAS_METHOD (gtk, lower_frame);
1458 CONSOLE_HAS_METHOD (gtk, make_frame_visible);
1459 CONSOLE_HAS_METHOD (gtk, make_frame_invisible);
1460 CONSOLE_HAS_METHOD (gtk, iconify_frame);
1461 CONSOLE_HAS_METHOD (gtk, set_frame_size);
1462 CONSOLE_HAS_METHOD (gtk, set_frame_position);
1463 CONSOLE_HAS_METHOD (gtk, frame_property);
1464 CONSOLE_HAS_METHOD (gtk, internal_frame_property_p);
1465 CONSOLE_HAS_METHOD (gtk, frame_properties);
1466 CONSOLE_HAS_METHOD (gtk, set_frame_properties);
1467 CONSOLE_HAS_METHOD (gtk, set_title_from_bufbyte);
1468 CONSOLE_HAS_METHOD (gtk, set_icon_name_from_bufbyte);
1469 CONSOLE_HAS_METHOD (gtk, frame_visible_p);
1470 CONSOLE_HAS_METHOD (gtk, frame_totally_visible_p);
1471 CONSOLE_HAS_METHOD (gtk, frame_iconified_p);
1472 CONSOLE_HAS_METHOD (gtk, set_frame_pointer);
1473 CONSOLE_HAS_METHOD (gtk, set_frame_icon);
1474 CONSOLE_HAS_METHOD (gtk, get_frame_parent);
1475 CONSOLE_HAS_METHOD (gtk, update_frame_external_traits);
1479 vars_of_frame_gtk (void)
1481 DEFVAR_LISP ("default-gtk-frame-plist", &Vdefault_gtk_frame_plist /*
1482 Plist of default frame-creation properties for Gtk frames.
1483 These override what is specified in the resource database and in
1484 `default-frame-plist', but are overridden by the arguments to the
1485 particular call to `make-frame'.
1487 Note: In many cases, properties of a frame are available as specifiers
1488 instead of through the frame-properties mechanism.
1490 Here is a list of recognized frame properties, other than those
1491 documented in `set-frame-properties' (they can be queried and
1492 set at any time, except as otherwise noted):
1494 initially-unmapped If non-nil, the frame will not be visible
1495 when it is created. In this case, you
1496 need to call `make-frame-visible' to make
1498 popup If non-nil, it should be a frame, and this
1499 frame will be created as a "popup" frame
1500 whose parent is the given frame. This
1501 will make the window manager treat the
1502 frame as a dialog box, which may entail
1503 doing different things (e.g. not asking
1504 for positioning, and not iconifying
1505 separate from its parent).
1506 inter-line-space Not currently implemented.
1507 toolbar-shadow-thickness Thickness of toolbar shadows.
1508 background-toolbar-color Color of toolbar background.
1509 bottom-toolbar-shadow-color Color of bottom shadows on toolbars.
1510 (*Not* specific to the bottom-toolbar.)
1511 top-toolbar-shadow-color Color of top shadows on toolbars.
1512 (*Not* specific to the top-toolbar.)
1513 internal-border-width Width of internal border around text area.
1514 border-width Width of external border around text area.
1515 top Y position (in pixels) of the upper-left
1516 outermost corner of the frame (i.e. the
1517 upper-left of the window-manager
1519 left X position (in pixels) of the upper-left
1520 outermost corner of the frame (i.e. the
1521 upper-left of the window-manager
1523 border-color Color of external border around text area.
1524 cursor-color Color of text cursor.
1526 See also `default-frame-plist', which specifies properties which apply
1527 to all frames, not just Gtk frames.
1529 Vdefault_gtk_frame_plist = Qnil;
1531 gtk_console_methods->device_specific_frame_props = &Vdefault_gtk_frame_plist;