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 */
30 #include "console-gtk.h"
32 #include "glyphs-gtk.h"
33 #include "objects-gtk.h"
34 #include "scrollbar-gtk.h"
36 #include "gtk-xemacs.h"
46 #include <libgnomeui/libgnomeui.h>
53 #define BORDER_WIDTH 0
54 #define INTERNAL_BORDER_WIDTH 0
56 #define TRANSIENT_DATA_IDENTIFIER "xemacs::transient_for"
57 #define FRAME_DATA_IDENTIFIER "xemacs::frame"
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 corresponding to an X window */
103 gtk_window_to_frame (struct device *d, GdkWindow *wdesc)
105 Lisp_Object tail, frame;
108 /* This function was previously written to accept only a window argument
109 (and to loop over all devices looking for a matching window), but
110 that is incorrect because window ID's are not unique across displays. */
112 for (tail = DEVICE_FRAME_LIST (d); CONSP (tail); tail = XCDR (tail))
118 if (FRAME_GTK_P (f) && GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f)) == wdesc)
124 /* Like gtk_window_to_frame but also compares the window with the widget's
127 gtk_any_window_to_frame (struct device *d, GdkWindow *w)
133 DEVICE_FRAME_LOOP (frmcons, d)
135 struct frame *fr = XFRAME (XCAR (frmcons));
136 if ((w == GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (fr))) ||
137 (w == GET_GTK_WIDGET_WINDOW (FRAME_GTK_CONTAINER_WIDGET (fr))) ||
139 (w == GET_GTK_WIDGET_WINDOW (FRAME_GTK_MENUBAR_WIDGET (fr))) ||
141 (w == GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (fr))))
146 w = gdk_window_get_parent (w);
153 gtk_any_widget_or_parent_to_frame (struct device *d, GtkWidget *widget)
155 return (gtk_any_window_to_frame (d, GET_GTK_WIDGET_WINDOW (widget)));
159 gtk_any_window_to_device (GdkWindow *w)
161 struct device *d = NULL;
162 Lisp_Object devcons, concons;
164 DEVICE_LOOP_NO_BREAK (devcons, concons)
166 d = XDEVICE (XCAR (devcons));
167 if (!DEVICE_GTK_P (d)) continue;
168 if (gtk_any_window_to_frame (d, w))
175 decode_gtk_frame (Lisp_Object frame)
178 XSETFRAME (frame, selected_frame ());
179 CHECK_LIVE_FRAME (frame);
180 /* this will also catch dead frames, but putting in the above check
181 results in a more useful error */
182 CHECK_GTK_FRAME (frame);
183 return XFRAME (frame);
187 /************************************************************************/
188 /* window-manager interactions */
189 /************************************************************************/
191 gtk_frame_iconified_p (struct frame *f)
193 return (f->iconified);
197 /************************************************************************/
198 /* frame properties */
199 /************************************************************************/
202 gtk_frame_property (struct frame *f, Lisp_Object property)
204 GtkWidget *shell = FRAME_GTK_SHELL_WIDGET (f);
206 if (EQ (Qleft, property) || EQ (Qtop, property))
209 if (!GET_GTK_WIDGET_WINDOW(shell))
211 gdk_window_get_deskrelative_origin (GET_GTK_WIDGET_WINDOW (shell), &x, &y);
212 if (EQ (Qleft, property)) return make_int (x);
213 if (EQ (Qtop, property)) return make_int (y);
215 if (EQ (Qshell_widget, property))
217 return (FRAME_GTK_LISP_WIDGETS (f)[0]);
219 if (EQ (Qcontainer_widget, property))
221 return (FRAME_GTK_LISP_WIDGETS (f)[1]);
223 if (EQ (Qtext_widget, property))
225 return (FRAME_GTK_LISP_WIDGETS (f)[2]);
227 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
228 if (EQ (Qwindow_id, property))
229 return Fgtk_window_id (make_frame (f));
236 gtk_internal_frame_property_p (struct frame *f, Lisp_Object property)
238 return EQ (property, Qleft)
239 || EQ (property, Qtop)
240 || EQ (Qshell_widget, property)
241 || EQ (Qcontainer_widget, property)
242 || EQ (Qtext_widget, property)
243 || EQ (property, Qwindow_id)
244 || STRINGP (property);
248 gtk_frame_properties (struct frame *f)
250 Lisp_Object props = Qnil;
251 GtkWidget *shell = FRAME_GTK_SHELL_WIDGET (f);
254 props = cons3 (Qshell_widget, FRAME_GTK_LISP_WIDGETS (f)[0], props);
255 props = cons3 (Qcontainer_widget, FRAME_GTK_LISP_WIDGETS (f)[1], props);
256 props = cons3 (Qtext_widget, FRAME_GTK_LISP_WIDGETS (f)[2], props);
258 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
259 props = cons3 (Qwindow_id, Fgtk_window_id (make_frame (f)), props);
262 if (!GET_GTK_WIDGET_WINDOW (shell))
265 gdk_window_get_deskrelative_origin (GET_GTK_WIDGET_WINDOW (shell), &x, &y);
267 props = cons3 (Qtop, make_int (y), props);
268 props = cons3 (Qleft, make_int (x), props);
274 /* Functions called only from `gtk_set_frame_properties' to set
275 individual properties. */
278 gtk_set_frame_text_value (struct frame *f, Bufbyte *value,
279 void (*func) (gpointer, gchar *),
282 gchar *the_text = (gchar *) value;
284 /* Programmer fuckup or window is not realized yet. */
285 if (!func || !arg) return;
291 /* Optimize for common ASCII case */
292 for (ptr = value; *ptr; ptr++)
293 if (!BYTE_ASCII_P (*ptr))
296 C_STRING_TO_EXTERNAL (value, tmp, Qctext);
303 (*func) (arg, (gchar *) the_text);
307 gtk_set_title_from_bufbyte (struct frame *f, Bufbyte *name)
309 if (GTK_IS_WINDOW (FRAME_GTK_SHELL_WIDGET (f)))
310 gtk_set_frame_text_value (f, name,
311 (void (*)(gpointer, gchar *))
312 gtk_window_set_title, FRAME_GTK_SHELL_WIDGET (f));
316 gtk_set_icon_name_from_bufbyte (struct frame *f, Bufbyte *name)
318 gtk_set_frame_text_value (f, name,
319 (void (*)(gpointer, gchar *))
320 gdk_window_set_icon_name, FRAME_GTK_SHELL_WIDGET (f)->window);
323 /* Set the initial frame size as specified. This function is used
324 when the frame's widgets have not yet been realized.
327 gtk_set_initial_frame_size (struct frame *f, int x, int y,
328 unsigned int w, unsigned int h)
330 GtkWidget *shell = FRAME_GTK_SHELL_WIDGET (f);
331 GdkGeometry geometry;
332 GdkWindowHints geometry_mask = 0x00;
334 if (GTK_IS_WINDOW (shell))
336 /* Deal with the cell size */
337 default_face_height_and_width (make_frame (f), &geometry.height_inc, &geometry.width_inc);
338 geometry_mask |= GDK_HINT_RESIZE_INC;
340 gtk_window_set_geometry_hints (GTK_WINDOW (shell),
341 FRAME_GTK_TEXT_WIDGET (f), &geometry, geometry_mask);
342 gdk_window_set_hints (GET_GTK_WIDGET_WINDOW (shell), x, y, 0, 0, 0, 0, GDK_HINT_POS);
343 gtk_window_set_policy (GTK_WINDOW (shell), TRUE, TRUE, FALSE);
346 FRAME_HEIGHT (f) = h;
349 change_frame_size (f, h, w, 0);
353 gtk_widget_size_request (FRAME_GTK_SHELL_WIDGET (f), &req);
354 gtk_widget_set_usize (FRAME_GTK_SHELL_WIDGET (f), req.width, req.height);
358 /* Report that a frame property of frame S is being set or changed.
359 If the property is not specially recognized, do nothing.
363 gtk_set_frame_properties (struct frame *f, Lisp_Object plist)
366 gint width = 0, height = 0;
367 gboolean width_specified_p = FALSE;
368 gboolean height_specified_p = FALSE;
369 gboolean x_position_specified_p = FALSE;
370 gboolean y_position_specified_p = FALSE;
373 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
375 Lisp_Object prop = Fcar (tail);
376 Lisp_Object val = Fcar (Fcdr (tail));
380 if (EQ (prop, Qfont))
382 /* If the value is not a string we silently ignore it. */
385 Lisp_Object frm, font_spec;
388 font_spec = Fget (Fget_face (Qdefault), Qfont, Qnil);
390 Fadd_spec_to_specifier (font_spec, val, frm, Qnil, Qnil);
391 update_frame_face_values (f);
395 else if (EQ (prop, Qwidth))
399 width_specified_p = TRUE;
402 else if (EQ (prop, Qheight))
406 height_specified_p = TRUE;
409 /* Further kludge the x/y. */
410 else if (EQ (prop, Qx))
413 x = (gint) XINT (val);
414 x_position_specified_p = TRUE;
417 else if (EQ (prop, Qy))
420 y = (gint) XINT (val);
421 y_position_specified_p = TRUE;
427 /* Kludge kludge kludge. We need to deal with the size and position
430 int size_specified_p = width_specified_p || height_specified_p;
431 int position_specified_p = x_position_specified_p || y_position_specified_p;
433 if (!width_specified_p)
435 if (!height_specified_p)
438 /* Kludge kludge kludge kludge. */
439 if (position_specified_p &&
440 (!x_position_specified_p || !y_position_specified_p))
443 GtkWidget *shell = FRAME_GTK_SHELL_WIDGET (f);
444 gdk_window_get_deskrelative_origin (GET_GTK_WIDGET_WINDOW (shell),
445 (x_position_specified_p ? &dummy : &x),
446 (y_position_specified_p ? &dummy : &y));
449 if (!f->init_finished)
451 if (size_specified_p || position_specified_p)
452 gtk_set_initial_frame_size (f, x, y, width, height);
456 if (size_specified_p)
459 XSETFRAME (frame, f);
460 Fset_frame_size (frame, make_int (width), make_int (height), Qnil);
462 if (position_specified_p)
465 XSETFRAME (frame, f);
466 Fset_frame_position (frame, make_int (x), make_int (y));
473 /************************************************************************/
474 /* widget creation */
475 /************************************************************************/
476 /* Figure out what size the shell widget should initially be,
477 and set it. Should be called after the default font has been
478 determined but before the widget has been realized. */
480 extern Lisp_Object Vgtk_initial_geometry;
484 get_number (const char **geometry)
489 if (**geometry == '-'){
493 while (**geometry && isdigit (**geometry)){
494 value = value * 10 + (**geometry - '0');
504 * gnome_parse_geometry
505 * @geometry: geometry string to be parsed
506 * @xpos: X position geometry component
507 * @ypos: Y position geometry component
508 * @width: pixel width geometry component
509 * @height: pixel height geometry component
512 * Parses the geometry string passed in @geometry, and fills
513 * @xpos, @ypos, @width, and @height with
514 * the corresponding values upon completion of the parse.
515 * If the parse fails, it should be assumed that @xpos, @ypos, @width,
516 * and @height contain undefined values.
519 * %TRUE if the geometry was successfully parsed, %FALSE otherwise.
523 gnome_parse_geometry (const gchar *geometry, gint *xpos,
524 gint *ypos, gint *width, gint *height)
528 g_return_val_if_fail (xpos != NULL, FALSE);
529 g_return_val_if_fail (ypos != NULL, FALSE);
530 g_return_val_if_fail (width != NULL, FALSE);
531 g_return_val_if_fail (height != NULL, FALSE);
533 *xpos = *ypos = *width = *height = -1;
538 if (*geometry == '=')
542 if (isdigit (*geometry))
543 *width = get_number (&geometry);
546 if (*geometry == 'x' || *geometry == 'X'){
548 *height = get_number (&geometry);
552 if (*geometry == '+'){
555 } else if (*geometry == '-'){
556 subtract = gdk_screen_width ();
560 *xpos = get_number (&geometry);
562 *xpos = subtract - *xpos;
565 if (*geometry == '+'){
568 } else if (*geometry == '-'){
569 subtract = gdk_screen_height ();
573 *ypos = get_number (&geometry);
575 *ypos = subtract - *ypos;
581 gtk_initialize_frame_size (struct frame *f)
583 gint x = 10, y = 10, w = 80, h = 30;
585 if (STRINGP (Vgtk_initial_geometry))
587 if (!gnome_parse_geometry (XSTRING_DATA (Vgtk_initial_geometry), &x,&y,&w,&h))
595 /* set the position of the frame's root window now. When the
596 frame was created, the position was initialized to (0,0). */
598 struct window *win = XWINDOW (f->root_window);
600 WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f);
601 WINDOW_TOP (win) = FRAME_TOP_BORDER_END (f);
603 if (!NILP (f->minibuffer_window))
605 win = XWINDOW (f->minibuffer_window);
606 WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f);
610 gtk_set_initial_frame_size (f, x, y, w, h);
614 resize_event_cb (GtkWidget *w, GtkAllocation *allocation, gpointer user_data)
616 struct frame *f = (struct frame *) user_data;
618 f->pixwidth = allocation->width;
619 f->pixheight = allocation->height;
621 if (FRAME_GTK_TEXT_WIDGET (f)->window)
624 XSETFRAME (frame, f);
625 Fredraw_frame (frame, Qt);
632 delete_event_cb (GtkWidget *w, GdkEvent *ev, gpointer user_data)
634 struct frame *f = (struct frame *) user_data;
637 XSETFRAME (frame, f);
638 enqueue_misc_user_event (frame, Qeval, list3 (Qdelete_frame, frame, Qt));
640 /* See if tickling the event queue helps us with our delays when
642 signal_fake_event ();
647 extern gboolean emacs_shell_event_handler (GtkWidget *wid, GdkEvent *event, gpointer closure);
648 extern Lisp_Object build_gtk_object (GtkObject *obj);
651 #define GNOME_IS_APP(x) 0
652 #define gnome_app_set_contents(x,y) 0
656 cleanup_deleted_frame (gpointer data)
658 struct frame *f = (struct frame *) data;
661 XSETFRAME (frame, f);
662 Fdelete_frame (frame, Qt);
665 #ifdef HAVE_DRAGNDROP
667 dragndrop_data_received (GtkWidget *widget,
668 GdkDragContext *context,
671 GtkSelectionData *data,
676 dragndrop_dropped (GtkWidget *widget,
677 GdkDragContext *drag_context,
683 Lisp_Object Vcurrent_drag_object;
685 #define DRAG_SELECTION_DATA_ERROR "Error converting drag data to external format"
687 dragndrop_get_drag (GtkWidget *widget,
688 GdkDragContext *drag_context,
689 GtkSelectionData *data,
694 gtk_selection_data_set (data, GDK_SELECTION_TYPE_STRING, 8,
695 DRAG_SELECTION_DATA_ERROR,
696 strlen (DRAG_SELECTION_DATA_ERROR));
700 case TARGET_TYPE_STRING:
702 Lisp_Object string = Vcurrent_drag_object;
704 if (!STRINGP (Vcurrent_drag_object))
706 string = Fprin1_to_string (string, Qnil);
707 /* Convert to a string */
710 gtk_selection_data_set (data, GDK_SELECTION_TYPE_STRING,
711 8, XSTRING_DATA (string), XSTRING_LENGTH (string));
714 case TARGET_TYPE_URI_LIST:
719 Vcurrent_drag_object = Qnil;
722 DEFUN ("gtk-start-drag-internal", Fgtk_start_drag_internal, 2, 3, 0, /*
723 Start a GTK drag from a buffer.
724 First arg is the event that started the drag,
725 second arg should be some string, and the third
726 is the type of the data (this should be a MIME type as a string (ie: text/plain)).
727 The type defaults to text/plain.
733 struct frame *f = decode_gtk_frame (Fselected_frame (Qnil));
734 GtkWidget *wid = FRAME_GTK_TEXT_WIDGET (f);
735 struct Lisp_Event *lisp_event = XEVENT(event);
737 GtkTargetList *tl = gtk_target_list_new (dnd_target_table, dnd_n_targets);
739 /* only drag if this is really a press */
740 if (EVENT_TYPE(lisp_event) != button_press_event)
743 /* get the desired type */
744 if (!NILP (dtyp) && STRINGP (dtyp))
745 dnd_typ = gdk_atom_intern (XSTRING_DATA (dtyp), FALSE);
747 gtk_drag_begin (wid, tl, GDK_ACTION_COPY, lisp_event->event.button.button, NULL);
749 Vcurrent_drag_object = data;
751 gtk_target_list_unref (tl);
757 /* Creates the widgets for a frame.
758 lisp_window_id is a Lisp description of an X window or Xt
761 This function does not map the windows. (That is
762 done by gtk_popup_frame().)
765 gtk_create_widgets (struct frame *f, Lisp_Object lisp_window_id, Lisp_Object parent)
768 GtkWidget *text, *container, *shell;
769 gboolean embedded_p = !NILP (lisp_window_id);
774 if (STRINGP (f->name))
775 TO_EXTERNAL_FORMAT (LISP_STRING, f->name, C_STRING_ALLOCA, name, Qctext);
779 FRAME_GTK_TOP_LEVEL_FRAME_P (f) = 1;
783 CHECK_GTK_OBJECT (lisp_window_id);
785 if (!GTK_IS_CONTAINER (XGTK_OBJECT (lisp_window_id)->object))
787 signal_simple_error ("Window ID must be a GtkContainer subclass", lisp_window_id);
790 shell = gtk_vbox_new (FALSE, 0);
792 gtk_object_weakref (GTK_OBJECT (shell), cleanup_deleted_frame, f);
793 gtk_container_add (GTK_CONTAINER (XGTK_OBJECT (lisp_window_id)->object), shell);
798 shell = GTK_WIDGET (gnome_app_new ("XEmacs", "XEmacs/GNOME"));
800 shell = GTK_WIDGET (gtk_window_new (GTK_WINDOW_TOPLEVEL));
806 /* If this is a transient window, keep the parent info around */
807 GtkWidget *parentwid = FRAME_GTK_SHELL_WIDGET (XFRAME (parent));
808 gtk_object_set_data (GTK_OBJECT (shell), TRANSIENT_DATA_IDENTIFIER, parentwid);
809 gtk_window_set_transient_for (GTK_WINDOW (shell), GTK_WINDOW (parentwid));
812 gtk_container_set_border_width (GTK_CONTAINER (shell), 0);
814 gtk_object_set_data (GTK_OBJECT (shell), FRAME_DATA_IDENTIFIER, f);
816 FRAME_GTK_SHELL_WIDGET (f) = shell;
818 text = GTK_WIDGET (gtk_xemacs_new (f));
820 if (!GNOME_IS_APP (shell))
821 container = GTK_WIDGET (gtk_vbox_new (FALSE, INTERNAL_BORDER_WIDTH));
825 FRAME_GTK_CONTAINER_WIDGET (f) = container;
826 FRAME_GTK_TEXT_WIDGET (f) = text;
828 #ifdef HAVE_DRAGNDROP
829 gtk_drag_dest_set (text, GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT,
830 dnd_target_table, dnd_n_targets,
831 GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_ASK);
832 gtk_signal_connect (GTK_OBJECT (text), "drag_drop",
833 GTK_SIGNAL_FUNC (dragndrop_dropped), text);
834 gtk_signal_connect (GTK_OBJECT (text), "drag_data_received",
835 GTK_SIGNAL_FUNC (dragndrop_data_received), text);
836 gtk_signal_connect (GTK_OBJECT (text), "drag_data_get",
837 GTK_SIGNAL_FUNC (dragndrop_get_drag), NULL);
841 /* Create the initial menubar widget. */
842 menubar_visible = gtk_initialize_frame_menubar (f);
846 gtk_widget_show_all (FRAME_GTK_MENUBAR_WIDGET (f));
848 #endif /* HAVE_MENUBARS */
851 if (GNOME_IS_APP (shell))
852 gnome_app_set_contents (GNOME_APP (shell), text);
855 /* Now comes the drawing area, which should fill the rest of the
858 gtk_box_pack_end (GTK_BOX (container), text, TRUE, TRUE, 0);
860 /* Connect main event handler */
861 gtk_signal_connect (GTK_OBJECT (shell), "delete-event", GTK_SIGNAL_FUNC (delete_event_cb), f);
864 static char *events_to_frob[] = { "focus-in-event",
866 "enter-notify-event",
867 "leave-notify-event",
870 "property-notify-event",
871 "selection-clear-event",
872 "selection-request-event",
873 "selection-notify-event",
875 /* "configure-event", */
876 "visibility-notify-event",
880 for (i = 0; events_to_frob[i]; i++)
882 gtk_signal_connect (GTK_OBJECT (shell), events_to_frob[i],
883 GTK_SIGNAL_FUNC (emacs_shell_event_handler), f);
887 gtk_signal_connect (GTK_OBJECT (shell), "size-allocate", GTK_SIGNAL_FUNC (resize_event_cb), f);
889 /* This might be safe to call now... */
890 /* gtk_signal_connect (GTK_OBJECT (shell), "event", GTK_SIGNAL_FUNC (emacs_shell_event_handler), f); */
892 /* Let's make sure we get all the events we can */
893 gtk_widget_set_events (text, GDK_ALL_EVENTS_MASK);
895 if (shell != container)
896 gtk_container_add (GTK_CONTAINER (shell), container);
898 gtk_widget_set_name (shell, "XEmacs::shell");
899 gtk_widget_set_name (container, "XEmacs::container");
900 gtk_widget_set_name (text, "XEmacs::text");
902 FRAME_GTK_LISP_WIDGETS(f)[0] = build_gtk_object (GTK_OBJECT (shell));
903 FRAME_GTK_LISP_WIDGETS(f)[1] = build_gtk_object (GTK_OBJECT (container));
904 FRAME_GTK_LISP_WIDGETS(f)[2] = build_gtk_object (GTK_OBJECT (text));
906 gtk_widget_realize (shell);
909 /* create the windows for the specified frame and display them.
910 Note that the widgets have already been created, and any
911 necessary geometry calculations have already been done. */
913 gtk_popup_frame (struct frame *f)
917 if (gtk_object_get_data (GTK_OBJECT (FRAME_GTK_SHELL_WIDGET (f)), UNMAPPED_DATA_IDENTIFIER))
919 FRAME_GTK_TOTALLY_VISIBLE_P (f) = 0;
921 gtk_widget_realize (FRAME_GTK_SHELL_WIDGET (f));
922 gtk_widget_realize (FRAME_GTK_TEXT_WIDGET (f));
923 gtk_widget_hide_all (FRAME_GTK_SHELL_WIDGET (f));
927 gtk_widget_show_all (FRAME_GTK_SHELL_WIDGET (f));
932 allocate_gtk_frame_struct (struct frame *f)
934 /* zero out all slots. */
935 f->frame_data = xnew_and_zero (struct gtk_frame);
937 /* yeah, except the lisp ones */
938 FRAME_GTK_ICON_PIXMAP (f) = Qnil;
939 FRAME_GTK_ICON_PIXMAP_MASK (f) = Qnil;
943 /************************************************************************/
945 /************************************************************************/
948 gtk_init_frame_1 (struct frame *f, Lisp_Object props)
950 /* This function can GC */
951 Lisp_Object initially_unmapped;
952 Lisp_Object device = FRAME_DEVICE (f);
953 Lisp_Object lisp_window_id = Fplist_get (props, Qwindow_id, Qnil);
954 Lisp_Object popup = Fplist_get (props, Qpopup, Qnil);
959 popup = Fselected_frame (device);
960 CHECK_LIVE_FRAME (popup);
961 if (!EQ (device, FRAME_DEVICE (XFRAME (popup))))
962 signal_simple_error_2 ("Parent must be on same device as frame",
966 initially_unmapped = Fplist_get (props, Qinitially_unmapped, Qnil);
969 * Previously we set this only if NILP (DEVICE_SELECTED_FRAME (d))
970 * to make sure that messages were displayed as soon as possible
971 * if we're creating the first frame on a device. But it is
972 * better to just set this all the time, so that when a new frame
973 * is created that covers the selected frame, echo area status
974 * messages can still be seen. f->visible is reset later if the
975 * initially-unmapped property is found to be non-nil in the
980 allocate_gtk_frame_struct (f);
981 gtk_create_widgets (f, lisp_window_id, popup);
983 if (!NILP (initially_unmapped))
985 gtk_object_set_data (GTK_OBJECT (FRAME_GTK_SHELL_WIDGET (f)),
986 UNMAPPED_DATA_IDENTIFIER, (gpointer) 1);
991 gtk_init_frame_2 (struct frame *f, Lisp_Object props)
993 /* Set up the values of the widget/frame. A case could be made for putting
994 this inside of the widget's initialize method. */
996 update_frame_face_values (f);
997 gtk_initialize_frame_size (f);
999 * update_frame_title() can't be done here, because some of the
1000 * modeline specs depend on the frame's device having a selected
1001 * frame, and that may not have been set up yet. The redisplay
1002 * will update the frame title anyway, so nothing is lost.
1004 * It turns out it gives problems with FVWMs name based mapping.
1005 * We'll just need to be carefull in the modeline specs.
1007 update_frame_title (f);
1011 gtk_init_frame_3 (struct frame *f)
1013 /* Pop up the frame. */
1014 gtk_popup_frame (f);
1018 gtk_mark_frame (struct frame *f)
1020 mark_object (FRAME_GTK_ICON_PIXMAP (f));
1021 mark_object (FRAME_GTK_ICON_PIXMAP_MASK (f));
1022 mark_object (FRAME_GTK_LISP_WIDGETS (f)[0]);
1023 mark_object (FRAME_GTK_LISP_WIDGETS (f)[1]);
1024 mark_object (FRAME_GTK_LISP_WIDGETS (f)[2]);
1028 gtk_set_frame_icon (struct frame *f)
1030 GdkPixmap *gtk_pixmap = NULL, *gtk_mask = NULL;
1032 if (IMAGE_INSTANCEP (f->icon)
1033 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (f->icon)))
1035 gtk_pixmap = XIMAGE_INSTANCE_GTK_PIXMAP (f->icon);
1036 gtk_mask = XIMAGE_INSTANCE_GTK_MASK (f->icon);
1044 gdk_window_set_icon (GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f)), NULL, gtk_pixmap, gtk_mask);
1048 gtk_set_frame_pointer (struct frame *f)
1050 GtkWidget *w = FRAME_GTK_TEXT_WIDGET (f);
1051 GdkCursor *c = XIMAGE_INSTANCE_GTK_CURSOR (f->pointer);
1053 if (POINTER_IMAGE_INSTANCEP (f->pointer))
1055 gdk_window_set_cursor (GET_GTK_WIDGET_WINDOW (w), c);
1061 stderr_out ("POINTER_IMAGE_INSTANCEP (f->pointer) failed!\n");
1066 gtk_get_frame_parent (struct frame *f)
1068 GtkWidget *parentwid = gtk_object_get_data (GTK_OBJECT (FRAME_GTK_SHELL_WIDGET (f)),
1069 TRANSIENT_DATA_IDENTIFIER);
1071 /* find the frame whose wid is parentwid */
1074 Lisp_Object frmcons;
1075 DEVICE_FRAME_LOOP (frmcons, XDEVICE (FRAME_DEVICE (f)))
1077 Lisp_Object frame = XCAR (frmcons);
1078 if (FRAME_GTK_SHELL_WIDGET (XFRAME (frame)) == parentwid)
1085 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
1086 DEFUN ("gtk-window-id", Fgtk_window_id, 0, 1, 0, /*
1087 Get the ID of the Gtk window.
1088 This gives us a chance to manipulate the Emacs window from within a
1089 different program. Since the ID is an unsigned long, we return it as
1095 struct frame *f = decode_gtk_frame (frame);
1097 /* Arrrrggghhh... this defeats the whole purpose of using Gdk... do we really need this? */
1098 sprintf (str, "%lu", GDK_WINDOW_XWINDOW( GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f))));
1099 return build_string (str);
1104 /************************************************************************/
1105 /* manipulating the X window */
1106 /************************************************************************/
1109 gtk_set_frame_position (struct frame *f, int xoff, int yoff)
1111 gtk_widget_set_uposition (FRAME_GTK_SHELL_WIDGET (f), xoff, yoff);
1114 /* Call this to change the size of frame S's x-window. */
1117 gtk_set_frame_size (struct frame *f, int cols, int rows)
1119 GtkWidget *shell = FRAME_GTK_SHELL_WIDGET (f);
1120 GdkGeometry geometry;
1121 GdkWindowHints geometry_mask = 0x00;
1123 if (GTK_IS_WINDOW (shell))
1125 /* Update the cell size */
1126 default_face_height_and_width (make_frame (f), &geometry.height_inc, &geometry.width_inc);
1127 geometry_mask |= GDK_HINT_RESIZE_INC;
1129 gtk_window_set_geometry_hints (GTK_WINDOW (shell),
1130 FRAME_GTK_TEXT_WIDGET (f), &geometry, geometry_mask);
1133 change_frame_size (f, rows, cols, 0);
1138 gtk_widget_size_request (FRAME_GTK_SHELL_WIDGET (f), &req);
1139 gtk_widget_set_usize (FRAME_GTK_SHELL_WIDGET (f), req.width, req.height);
1143 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
1144 /* There is NO equivalent to XWarpPointer under Gtk */
1146 gtk_set_mouse_position (struct window *w, int x, int y)
1148 struct frame *f = XFRAME (w->frame);
1149 Display *display = GDK_DISPLAY ();
1150 XWarpPointer (display, None,
1151 GDK_WINDOW_XWINDOW (GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f))),
1152 0, 0, 0, 0, w->pixel_left + x, w->pixel_top + y);
1154 #endif /* STUPID_X_SPECIFIC_GTK_STUFF */
1157 gtk_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y)
1159 /* Returns the pixel position within the editor text widget */
1161 GdkWindow *w = gdk_window_at_pointer (&win_x, &win_y);
1162 struct frame *f = NULL;
1166 /* At this point, w is the innermost GdkWindow containing the
1167 ** pointer and win_x and win_y are the coordinates of that window.
1169 f = gtk_any_window_to_frame (d, w);
1173 XSETFRAME (*frame, f);
1175 gdk_window_get_pointer (GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f)),
1176 &win_x, &win_y, NULL);
1185 gtk_cant_notify_wm_error (void)
1187 error ("Can't notify window manager of iconification.");
1190 /* Raise frame F. */
1192 gtk_raise_frame_1 (struct frame *f, int force)
1194 if (FRAME_VISIBLE_P (f) || force)
1196 GdkWindow *emacs_window = GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f));
1198 gdk_window_raise (emacs_window);
1203 gtk_raise_frame (struct frame *f)
1205 gtk_raise_frame_1 (f, 1);
1208 /* Lower frame F. */
1210 gtk_lower_frame (struct frame *f)
1212 if (FRAME_VISIBLE_P (f))
1214 gdk_window_lower (GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f)));
1218 /* Change from withdrawn state to mapped state. */
1220 gtk_make_frame_visible (struct frame *f)
1222 gtk_widget_show_all (FRAME_GTK_SHELL_WIDGET (f));
1223 gtk_raise_frame_1 (f, 0);
1226 /* Change from mapped state to withdrawn state. */
1228 gtk_make_frame_invisible (struct frame *f)
1230 gtk_widget_hide (FRAME_GTK_SHELL_WIDGET (f));
1234 gtk_frame_visible_p (struct frame *f)
1236 GtkWidget *w = FRAME_GTK_SHELL_WIDGET (f);
1238 f->visible = (GTK_OBJECT_FLAGS (w) & GTK_VISIBLE);
1244 gtk_frame_totally_visible_p (struct frame *f)
1246 return FRAME_GTK_TOTALLY_VISIBLE_P (f);
1249 /* Change window state from mapped to iconified. */
1251 gtk_iconify_frame (struct frame *f)
1253 GdkWindow *w = GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f));
1255 /* There is no equivalent to XIconifyWindow in Gtk/Gdk. */
1256 if (!XIconifyWindow (GDK_WINDOW_XDISPLAY (w),
1257 GDK_WINDOW_XWINDOW (w),
1258 DefaultScreen (GDK_WINDOW_XDISPLAY (w))))
1259 gtk_cant_notify_wm_error ();
1264 /* Sets the X focus to frame f. */
1266 gtk_focus_on_frame (struct frame *f)
1268 GtkWidget *shell_widget;
1270 assert (FRAME_GTK_P (f));
1272 shell_widget = FRAME_GTK_SHELL_WIDGET (f);
1273 if (!GET_GTK_WIDGET_WINDOW (shell_widget))
1276 gtk_widget_grab_focus (shell_widget);
1279 /* Destroy the window of frame S. */
1281 gtk_delete_frame (struct frame *f)
1283 GtkWidget *w = FRAME_GTK_SHELL_WIDGET (f);
1285 gtk_widget_destroy (w);
1287 if (FRAME_GTK_GEOM_FREE_ME_PLEASE (f))
1288 xfree (FRAME_GTK_GEOM_FREE_ME_PLEASE (f));
1289 xfree (f->frame_data);
1294 gtk_recompute_cell_sizes (struct frame *frm)
1296 if (GTK_IS_WINDOW (FRAME_GTK_SHELL_WIDGET (frm)))
1298 GtkWindow *w = GTK_WINDOW (FRAME_GTK_SHELL_WIDGET (frm));
1299 GdkGeometry geometry;
1300 GdkWindowHints geometry_mask;
1301 gint width_inc = 10;
1302 gint height_inc = 10;
1304 default_face_height_and_width (make_frame (frm), &height_inc, &width_inc);
1305 geometry_mask = GDK_HINT_RESIZE_INC;
1306 geometry.width_inc = width_inc;
1307 geometry.height_inc = height_inc;
1309 gtk_window_set_geometry_hints (w, FRAME_GTK_TEXT_WIDGET (frm), &geometry, geometry_mask);
1314 gtk_update_frame_external_traits (struct frame* frm, Lisp_Object name)
1316 Lisp_Object frame = Qnil;
1318 XSETFRAME(frame, frm);
1320 if (EQ (name, Qforeground))
1322 Lisp_Object color = FACE_FOREGROUND (Vdefault_face, frame);
1325 if (!EQ (color, Vthe_null_color_instance))
1327 fgc = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (color));
1328 /* #### BILL!!! The X code set the XtNforeground property of
1329 the text widget here. Why did they bother? All that type
1330 of thing is done down in the guts of the redisplay code,
1331 not in the Emacs* widgets. */
1334 else if (EQ (name, Qbackground))
1336 Lisp_Object color = FACE_BACKGROUND (Vdefault_face, frame);
1339 if (!EQ (color, Vthe_null_color_instance))
1341 bgc = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (color));
1342 if (FRAME_GTK_SHELL_WIDGET (frm)->window)
1344 gdk_window_set_background (FRAME_GTK_SHELL_WIDGET (frm)->window, bgc);
1346 if (FRAME_GTK_TEXT_WIDGET (frm)->window)
1348 gdk_window_set_background (FRAME_GTK_TEXT_WIDGET (frm)->window, bgc);
1352 /* Really crappy way to force the modeline shadows to be
1353 redrawn. But effective. */
1354 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (frm);
1355 MARK_FRAME_CHANGED (frm);
1357 else if (EQ (name, Qfont))
1359 Lisp_Object font = FACE_FONT (Vdefault_face, frame, Vcharset_ascii);
1361 if (!EQ (font, Vthe_null_font_instance))
1363 /* #### BILL!!! The X code set the XtNfont property of the
1364 text widget here. Why did they bother? All that type of
1365 thing is done down in the guts of the redisplay code, not
1366 in the Emacs* widgets. */
1372 #ifdef HAVE_TOOLBARS
1373 /* Setting the background clears the entire frame area
1374 including the toolbar so we force an immediate redraw of
1376 if (EQ (name, Qbackground))
1377 MAYBE_DEVMETH (XDEVICE (frm->device), redraw_frame_toolbars, (frm));
1378 #endif /* HAVE_TOOLBARS */
1380 /* Set window manager resize increment hints according to
1381 the new character size */
1382 if (EQ (name, Qfont) && FRAME_GTK_TOP_LEVEL_FRAME_P (frm))
1383 gtk_recompute_cell_sizes (frm);
1387 /************************************************************************/
1388 /* initialization */
1389 /************************************************************************/
1392 syms_of_frame_gtk (void)
1394 defsymbol (&Qwindow_id, "window-id");
1395 defsymbol (&Qtext_widget, "text-widget");
1396 defsymbol (&Qcontainer_widget, "container-widget");
1397 defsymbol (&Qshell_widget, "shell-widget");
1398 defsymbol (&Qdetachable_menubar, "detachable-menubar");
1400 #ifdef HAVE_DRAGNDROP
1401 staticpro (&Vcurrent_drag_object);
1402 Vcurrent_drag_object = Qnil;
1403 DEFSUBR (Fgtk_start_drag_internal);
1405 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
1406 DEFSUBR (Fgtk_window_id);
1411 console_type_create_frame_gtk (void)
1414 CONSOLE_HAS_METHOD (gtk, init_frame_1);
1415 CONSOLE_HAS_METHOD (gtk, init_frame_2);
1416 CONSOLE_HAS_METHOD (gtk, init_frame_3);
1417 CONSOLE_HAS_METHOD (gtk, mark_frame);
1418 CONSOLE_HAS_METHOD (gtk, focus_on_frame);
1419 CONSOLE_HAS_METHOD (gtk, delete_frame);
1420 CONSOLE_HAS_METHOD (gtk, get_mouse_position);
1421 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
1422 CONSOLE_HAS_METHOD (gtk, set_mouse_position);
1424 CONSOLE_HAS_METHOD (gtk, raise_frame);
1425 CONSOLE_HAS_METHOD (gtk, lower_frame);
1426 CONSOLE_HAS_METHOD (gtk, make_frame_visible);
1427 CONSOLE_HAS_METHOD (gtk, make_frame_invisible);
1428 CONSOLE_HAS_METHOD (gtk, iconify_frame);
1429 CONSOLE_HAS_METHOD (gtk, set_frame_size);
1430 CONSOLE_HAS_METHOD (gtk, set_frame_position);
1431 CONSOLE_HAS_METHOD (gtk, frame_property);
1432 CONSOLE_HAS_METHOD (gtk, internal_frame_property_p);
1433 CONSOLE_HAS_METHOD (gtk, frame_properties);
1434 CONSOLE_HAS_METHOD (gtk, set_frame_properties);
1435 CONSOLE_HAS_METHOD (gtk, set_title_from_bufbyte);
1436 CONSOLE_HAS_METHOD (gtk, set_icon_name_from_bufbyte);
1437 CONSOLE_HAS_METHOD (gtk, frame_visible_p);
1438 CONSOLE_HAS_METHOD (gtk, frame_totally_visible_p);
1439 CONSOLE_HAS_METHOD (gtk, frame_iconified_p);
1440 CONSOLE_HAS_METHOD (gtk, set_frame_pointer);
1441 CONSOLE_HAS_METHOD (gtk, set_frame_icon);
1442 CONSOLE_HAS_METHOD (gtk, get_frame_parent);
1443 CONSOLE_HAS_METHOD (gtk, update_frame_external_traits);
1447 vars_of_frame_gtk (void)
1449 DEFVAR_LISP ("default-gtk-frame-plist", &Vdefault_gtk_frame_plist /*
1450 Plist of default frame-creation properties for Gtk frames.
1451 These override what is specified in the resource database and in
1452 `default-frame-plist', but are overridden by the arguments to the
1453 particular call to `make-frame'.
1455 Note: In many cases, properties of a frame are available as specifiers
1456 instead of through the frame-properties mechanism.
1458 Here is a list of recognized frame properties, other than those
1459 documented in `set-frame-properties' (they can be queried and
1460 set at any time, except as otherwise noted):
1462 initially-unmapped If non-nil, the frame will not be visible
1463 when it is created. In this case, you
1464 need to call `make-frame-visible' to make
1466 popup If non-nil, it should be a frame, and this
1467 frame will be created as a "popup" frame
1468 whose parent is the given frame. This
1469 will make the window manager treat the
1470 frame as a dialog box, which may entail
1471 doing different things (e.g. not asking
1472 for positioning, and not iconifying
1473 separate from its parent).
1474 inter-line-space Not currently implemented.
1475 toolbar-shadow-thickness Thickness of toolbar shadows.
1476 background-toolbar-color Color of toolbar background.
1477 bottom-toolbar-shadow-color Color of bottom shadows on toolbars.
1478 (*Not* specific to the bottom-toolbar.)
1479 top-toolbar-shadow-color Color of top shadows on toolbars.
1480 (*Not* specific to the top-toolbar.)
1481 internal-border-width Width of internal border around text area.
1482 border-width Width of external border around text area.
1483 top Y position (in pixels) of the upper-left
1484 outermost corner of the frame (i.e. the
1485 upper-left of the window-manager
1487 left X position (in pixels) of the upper-left
1488 outermost corner of the frame (i.e. the
1489 upper-left of the window-manager
1491 border-color Color of external border around text area.
1492 cursor-color Color of text cursor.
1494 See also `default-frame-plist', which specifies properties which apply
1495 to all frames, not just Gtk frames.
1497 Vdefault_gtk_frame_plist = Qnil;
1499 gtk_console_methods->device_specific_frame_props = &Vdefault_gtk_frame_plist;