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 */
850 if (GNOME_IS_APP (shell))
851 gnome_app_set_contents (GNOME_APP (shell), text);
853 /* Now comes the drawing area, which should fill the rest of the
856 gtk_box_pack_end (GTK_BOX (container), text, TRUE, TRUE, 0);
858 /* Connect main event handler */
859 gtk_signal_connect (GTK_OBJECT (shell), "delete-event", GTK_SIGNAL_FUNC (delete_event_cb), f);
862 static char *events_to_frob[] = { "focus-in-event",
864 "enter-notify-event",
865 "leave-notify-event",
868 "property-notify-event",
869 "selection-clear-event",
870 "selection-request-event",
871 "selection-notify-event",
873 /* "configure-event", */
874 "visibility-notify-event",
878 for (i = 0; events_to_frob[i]; i++)
880 gtk_signal_connect (GTK_OBJECT (shell), events_to_frob[i],
881 GTK_SIGNAL_FUNC (emacs_shell_event_handler), f);
885 gtk_signal_connect (GTK_OBJECT (shell), "size-allocate", GTK_SIGNAL_FUNC (resize_event_cb), f);
887 /* This might be safe to call now... */
888 /* gtk_signal_connect (GTK_OBJECT (shell), "event", GTK_SIGNAL_FUNC (emacs_shell_event_handler), f); */
890 /* Let's make sure we get all the events we can */
891 gtk_widget_set_events (text, GDK_ALL_EVENTS_MASK);
893 if (shell != container)
894 gtk_container_add (GTK_CONTAINER (shell), container);
896 gtk_widget_set_name (shell, "XEmacs::shell");
897 gtk_widget_set_name (container, "XEmacs::container");
898 gtk_widget_set_name (text, "XEmacs::text");
900 FRAME_GTK_LISP_WIDGETS(f)[0] = build_gtk_object (GTK_OBJECT (shell));
901 FRAME_GTK_LISP_WIDGETS(f)[1] = build_gtk_object (GTK_OBJECT (container));
902 FRAME_GTK_LISP_WIDGETS(f)[2] = build_gtk_object (GTK_OBJECT (text));
904 gtk_widget_realize (shell);
907 /* create the windows for the specified frame and display them.
908 Note that the widgets have already been created, and any
909 necessary geometry calculations have already been done. */
911 gtk_popup_frame (struct frame *f)
915 if (gtk_object_get_data (GTK_OBJECT (FRAME_GTK_SHELL_WIDGET (f)), UNMAPPED_DATA_IDENTIFIER))
917 FRAME_GTK_TOTALLY_VISIBLE_P (f) = 0;
919 gtk_widget_realize (FRAME_GTK_SHELL_WIDGET (f));
920 gtk_widget_realize (FRAME_GTK_TEXT_WIDGET (f));
921 gtk_widget_hide_all (FRAME_GTK_SHELL_WIDGET (f));
925 gtk_widget_show_all (FRAME_GTK_SHELL_WIDGET (f));
930 allocate_gtk_frame_struct (struct frame *f)
932 /* zero out all slots. */
933 f->frame_data = xnew_and_zero (struct gtk_frame);
935 /* yeah, except the lisp ones */
936 FRAME_GTK_ICON_PIXMAP (f) = Qnil;
937 FRAME_GTK_ICON_PIXMAP_MASK (f) = Qnil;
941 /************************************************************************/
943 /************************************************************************/
946 gtk_init_frame_1 (struct frame *f, Lisp_Object props)
948 /* This function can GC */
949 Lisp_Object initially_unmapped;
950 Lisp_Object device = FRAME_DEVICE (f);
951 Lisp_Object lisp_window_id = Fplist_get (props, Qwindow_id, Qnil);
952 Lisp_Object popup = Fplist_get (props, Qpopup, Qnil);
957 popup = Fselected_frame (device);
958 CHECK_LIVE_FRAME (popup);
959 if (!EQ (device, FRAME_DEVICE (XFRAME (popup))))
960 signal_simple_error_2 ("Parent must be on same device as frame",
964 initially_unmapped = Fplist_get (props, Qinitially_unmapped, Qnil);
967 * Previously we set this only if NILP (DEVICE_SELECTED_FRAME (d))
968 * to make sure that messages were displayed as soon as possible
969 * if we're creating the first frame on a device. But it is
970 * better to just set this all the time, so that when a new frame
971 * is created that covers the selected frame, echo area status
972 * messages can still be seen. f->visible is reset later if the
973 * initially-unmapped property is found to be non-nil in the
978 allocate_gtk_frame_struct (f);
979 gtk_create_widgets (f, lisp_window_id, popup);
981 if (!NILP (initially_unmapped))
983 gtk_object_set_data (GTK_OBJECT (FRAME_GTK_SHELL_WIDGET (f)),
984 UNMAPPED_DATA_IDENTIFIER, (gpointer) 1);
989 gtk_init_frame_2 (struct frame *f, Lisp_Object props)
991 /* Set up the values of the widget/frame. A case could be made for putting
992 this inside of the widget's initialize method. */
994 update_frame_face_values (f);
995 gtk_initialize_frame_size (f);
997 * update_frame_title() can't be done here, because some of the
998 * modeline specs depend on the frame's device having a selected
999 * frame, and that may not have been set up yet. The redisplay
1000 * will update the frame title anyway, so nothing is lost.
1002 * It turns out it gives problems with FVWMs name based mapping.
1003 * We'll just need to be carefull in the modeline specs.
1005 update_frame_title (f);
1009 gtk_init_frame_3 (struct frame *f)
1011 /* Pop up the frame. */
1012 gtk_popup_frame (f);
1016 gtk_mark_frame (struct frame *f)
1018 mark_object (FRAME_GTK_ICON_PIXMAP (f));
1019 mark_object (FRAME_GTK_ICON_PIXMAP_MASK (f));
1020 mark_object (FRAME_GTK_LISP_WIDGETS (f)[0]);
1021 mark_object (FRAME_GTK_LISP_WIDGETS (f)[1]);
1022 mark_object (FRAME_GTK_LISP_WIDGETS (f)[2]);
1026 gtk_set_frame_icon (struct frame *f)
1028 GdkPixmap *gtk_pixmap = NULL, *gtk_mask = NULL;
1030 if (IMAGE_INSTANCEP (f->icon)
1031 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (f->icon)))
1033 gtk_pixmap = XIMAGE_INSTANCE_GTK_PIXMAP (f->icon);
1034 gtk_mask = XIMAGE_INSTANCE_GTK_MASK (f->icon);
1042 gdk_window_set_icon (GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f)), NULL, gtk_pixmap, gtk_mask);
1046 gtk_set_frame_pointer (struct frame *f)
1048 GtkWidget *w = FRAME_GTK_TEXT_WIDGET (f);
1049 GdkCursor *c = XIMAGE_INSTANCE_GTK_CURSOR (f->pointer);
1051 if (POINTER_IMAGE_INSTANCEP (f->pointer))
1053 gdk_window_set_cursor (GET_GTK_WIDGET_WINDOW (w), c);
1059 stderr_out ("POINTER_IMAGE_INSTANCEP (f->pointer) failed!\n");
1064 gtk_get_frame_parent (struct frame *f)
1066 GtkWidget *parentwid = gtk_object_get_data (GTK_OBJECT (FRAME_GTK_SHELL_WIDGET (f)),
1067 TRANSIENT_DATA_IDENTIFIER);
1069 /* find the frame whose wid is parentwid */
1072 Lisp_Object frmcons;
1073 DEVICE_FRAME_LOOP (frmcons, XDEVICE (FRAME_DEVICE (f)))
1075 Lisp_Object frame = XCAR (frmcons);
1076 if (FRAME_GTK_SHELL_WIDGET (XFRAME (frame)) == parentwid)
1083 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
1084 DEFUN ("gtk-window-id", Fgtk_window_id, 0, 1, 0, /*
1085 Get the ID of the Gtk window.
1086 This gives us a chance to manipulate the Emacs window from within a
1087 different program. Since the ID is an unsigned long, we return it as
1093 struct frame *f = decode_gtk_frame (frame);
1095 /* Arrrrggghhh... this defeats the whole purpose of using Gdk... do we really need this? */
1096 sprintf (str, "%lu", GDK_WINDOW_XWINDOW( GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f))));
1097 return build_string (str);
1102 /************************************************************************/
1103 /* manipulating the X window */
1104 /************************************************************************/
1107 gtk_set_frame_position (struct frame *f, int xoff, int yoff)
1109 gtk_widget_set_uposition (FRAME_GTK_SHELL_WIDGET (f), xoff, yoff);
1112 /* Call this to change the size of frame S's x-window. */
1115 gtk_set_frame_size (struct frame *f, int cols, int rows)
1117 GtkWidget *shell = FRAME_GTK_SHELL_WIDGET (f);
1118 GdkGeometry geometry;
1119 GdkWindowHints geometry_mask = 0x00;
1121 if (GTK_IS_WINDOW (shell))
1123 /* Update the cell size */
1124 default_face_height_and_width (make_frame (f), &geometry.height_inc, &geometry.width_inc);
1125 geometry_mask |= GDK_HINT_RESIZE_INC;
1127 gtk_window_set_geometry_hints (GTK_WINDOW (shell),
1128 FRAME_GTK_TEXT_WIDGET (f), &geometry, geometry_mask);
1131 change_frame_size (f, rows, cols, 0);
1136 gtk_widget_size_request (FRAME_GTK_SHELL_WIDGET (f), &req);
1137 gtk_widget_set_usize (FRAME_GTK_SHELL_WIDGET (f), req.width, req.height);
1141 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
1142 /* There is NO equivalent to XWarpPointer under Gtk */
1144 gtk_set_mouse_position (struct window *w, int x, int y)
1146 struct frame *f = XFRAME (w->frame);
1147 Display *display = GDK_DISPLAY ();
1148 XWarpPointer (display, None,
1149 GDK_WINDOW_XWINDOW (GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f))),
1150 0, 0, 0, 0, w->pixel_left + x, w->pixel_top + y);
1152 #endif /* STUPID_X_SPECIFIC_GTK_STUFF */
1155 gtk_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y)
1157 /* Returns the pixel position within the editor text widget */
1159 GdkWindow *w = gdk_window_at_pointer (&win_x, &win_y);
1160 struct frame *f = NULL;
1164 /* At this point, w is the innermost GdkWindow containing the
1165 ** pointer and win_x and win_y are the coordinates of that window.
1167 f = gtk_any_window_to_frame (d, w);
1171 XSETFRAME (*frame, f);
1173 gdk_window_get_pointer (GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f)),
1174 &win_x, &win_y, NULL);
1183 gtk_cant_notify_wm_error (void)
1185 error ("Can't notify window manager of iconification.");
1188 /* Raise frame F. */
1190 gtk_raise_frame_1 (struct frame *f, int force)
1192 if (FRAME_VISIBLE_P (f) || force)
1194 GdkWindow *emacs_window = GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f));
1196 gdk_window_raise (emacs_window);
1201 gtk_raise_frame (struct frame *f)
1203 gtk_raise_frame_1 (f, 1);
1206 /* Lower frame F. */
1208 gtk_lower_frame (struct frame *f)
1210 if (FRAME_VISIBLE_P (f))
1212 gdk_window_lower (GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f)));
1216 /* Change from withdrawn state to mapped state. */
1218 gtk_make_frame_visible (struct frame *f)
1220 gtk_widget_show_all (FRAME_GTK_SHELL_WIDGET (f));
1221 gtk_raise_frame_1 (f, 0);
1224 /* Change from mapped state to withdrawn state. */
1226 gtk_make_frame_invisible (struct frame *f)
1228 gtk_widget_hide (FRAME_GTK_SHELL_WIDGET (f));
1232 gtk_frame_visible_p (struct frame *f)
1234 GtkWidget *w = FRAME_GTK_SHELL_WIDGET (f);
1236 f->visible = (GTK_OBJECT_FLAGS (w) & GTK_VISIBLE);
1242 gtk_frame_totally_visible_p (struct frame *f)
1244 return FRAME_GTK_TOTALLY_VISIBLE_P (f);
1247 /* Change window state from mapped to iconified. */
1249 gtk_iconify_frame (struct frame *f)
1251 GdkWindow *w = GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f));
1253 /* There is no equivalent to XIconifyWindow in Gtk/Gdk. */
1254 if (!XIconifyWindow (GDK_WINDOW_XDISPLAY (w),
1255 GDK_WINDOW_XWINDOW (w),
1256 DefaultScreen (GDK_WINDOW_XDISPLAY (w))))
1257 gtk_cant_notify_wm_error ();
1262 /* Sets the X focus to frame f. */
1264 gtk_focus_on_frame (struct frame *f)
1266 GtkWidget *shell_widget;
1268 assert (FRAME_GTK_P (f));
1270 shell_widget = FRAME_GTK_SHELL_WIDGET (f);
1271 if (!GET_GTK_WIDGET_WINDOW (shell_widget))
1274 gtk_widget_grab_focus (shell_widget);
1277 /* Destroy the window of frame S. */
1279 gtk_delete_frame (struct frame *f)
1281 GtkWidget *w = FRAME_GTK_SHELL_WIDGET (f);
1283 gtk_widget_destroy (w);
1285 if (FRAME_GTK_GEOM_FREE_ME_PLEASE (f))
1286 xfree (FRAME_GTK_GEOM_FREE_ME_PLEASE (f));
1287 xfree (f->frame_data);
1292 gtk_recompute_cell_sizes (struct frame *frm)
1294 if (GTK_IS_WINDOW (FRAME_GTK_SHELL_WIDGET (frm)))
1296 GtkWindow *w = GTK_WINDOW (FRAME_GTK_SHELL_WIDGET (frm));
1297 GdkGeometry geometry;
1298 GdkWindowHints geometry_mask;
1299 gint width_inc = 10;
1300 gint height_inc = 10;
1302 default_face_height_and_width (make_frame (frm), &height_inc, &width_inc);
1303 geometry_mask = GDK_HINT_RESIZE_INC;
1304 geometry.width_inc = width_inc;
1305 geometry.height_inc = height_inc;
1307 gtk_window_set_geometry_hints (w, FRAME_GTK_TEXT_WIDGET (frm), &geometry, geometry_mask);
1312 gtk_update_frame_external_traits (struct frame* frm, Lisp_Object name)
1314 Lisp_Object frame = Qnil;
1316 XSETFRAME(frame, frm);
1318 if (EQ (name, Qforeground))
1320 Lisp_Object color = FACE_FOREGROUND (Vdefault_face, frame);
1323 if (!EQ (color, Vthe_null_color_instance))
1325 fgc = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (color));
1326 /* #### BILL!!! The X code set the XtNforeground property of
1327 the text widget here. Why did they bother? All that type
1328 of thing is done down in the guts of the redisplay code,
1329 not in the Emacs* widgets. */
1332 else if (EQ (name, Qbackground))
1334 Lisp_Object color = FACE_BACKGROUND (Vdefault_face, frame);
1337 if (!EQ (color, Vthe_null_color_instance))
1339 bgc = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (color));
1340 if (FRAME_GTK_SHELL_WIDGET (frm)->window)
1342 gdk_window_set_background (FRAME_GTK_SHELL_WIDGET (frm)->window, bgc);
1344 if (FRAME_GTK_TEXT_WIDGET (frm)->window)
1346 gdk_window_set_background (FRAME_GTK_TEXT_WIDGET (frm)->window, bgc);
1350 /* Really crappy way to force the modeline shadows to be
1351 redrawn. But effective. */
1352 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (frm);
1353 MARK_FRAME_CHANGED (frm);
1355 else if (EQ (name, Qfont))
1357 Lisp_Object font = FACE_FONT (Vdefault_face, frame, Vcharset_ascii);
1359 if (!EQ (font, Vthe_null_font_instance))
1361 /* #### BILL!!! The X code set the XtNfont property of the
1362 text widget here. Why did they bother? All that type of
1363 thing is done down in the guts of the redisplay code, not
1364 in the Emacs* widgets. */
1370 #ifdef HAVE_TOOLBARS
1371 /* Setting the background clears the entire frame area
1372 including the toolbar so we force an immediate redraw of
1374 if (EQ (name, Qbackground))
1375 MAYBE_DEVMETH (XDEVICE (frm->device), redraw_frame_toolbars, (frm));
1376 #endif /* HAVE_TOOLBARS */
1378 /* Set window manager resize increment hints according to
1379 the new character size */
1380 if (EQ (name, Qfont) && FRAME_GTK_TOP_LEVEL_FRAME_P (frm))
1381 gtk_recompute_cell_sizes (frm);
1385 /************************************************************************/
1386 /* initialization */
1387 /************************************************************************/
1390 syms_of_frame_gtk (void)
1392 defsymbol (&Qwindow_id, "window-id");
1393 defsymbol (&Qtext_widget, "text-widget");
1394 defsymbol (&Qcontainer_widget, "container-widget");
1395 defsymbol (&Qshell_widget, "shell-widget");
1396 defsymbol (&Qdetachable_menubar, "detachable-menubar");
1398 #ifdef HAVE_DRAGNDROP
1399 staticpro (&Vcurrent_drag_object);
1400 Vcurrent_drag_object = Qnil;
1401 DEFSUBR (Fgtk_start_drag_internal);
1403 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
1404 DEFSUBR (Fgtk_window_id);
1409 console_type_create_frame_gtk (void)
1412 CONSOLE_HAS_METHOD (gtk, init_frame_1);
1413 CONSOLE_HAS_METHOD (gtk, init_frame_2);
1414 CONSOLE_HAS_METHOD (gtk, init_frame_3);
1415 CONSOLE_HAS_METHOD (gtk, mark_frame);
1416 CONSOLE_HAS_METHOD (gtk, focus_on_frame);
1417 CONSOLE_HAS_METHOD (gtk, delete_frame);
1418 CONSOLE_HAS_METHOD (gtk, get_mouse_position);
1419 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
1420 CONSOLE_HAS_METHOD (gtk, set_mouse_position);
1422 CONSOLE_HAS_METHOD (gtk, raise_frame);
1423 CONSOLE_HAS_METHOD (gtk, lower_frame);
1424 CONSOLE_HAS_METHOD (gtk, make_frame_visible);
1425 CONSOLE_HAS_METHOD (gtk, make_frame_invisible);
1426 CONSOLE_HAS_METHOD (gtk, iconify_frame);
1427 CONSOLE_HAS_METHOD (gtk, set_frame_size);
1428 CONSOLE_HAS_METHOD (gtk, set_frame_position);
1429 CONSOLE_HAS_METHOD (gtk, frame_property);
1430 CONSOLE_HAS_METHOD (gtk, internal_frame_property_p);
1431 CONSOLE_HAS_METHOD (gtk, frame_properties);
1432 CONSOLE_HAS_METHOD (gtk, set_frame_properties);
1433 CONSOLE_HAS_METHOD (gtk, set_title_from_bufbyte);
1434 CONSOLE_HAS_METHOD (gtk, set_icon_name_from_bufbyte);
1435 CONSOLE_HAS_METHOD (gtk, frame_visible_p);
1436 CONSOLE_HAS_METHOD (gtk, frame_totally_visible_p);
1437 CONSOLE_HAS_METHOD (gtk, frame_iconified_p);
1438 CONSOLE_HAS_METHOD (gtk, set_frame_pointer);
1439 CONSOLE_HAS_METHOD (gtk, set_frame_icon);
1440 CONSOLE_HAS_METHOD (gtk, get_frame_parent);
1441 CONSOLE_HAS_METHOD (gtk, update_frame_external_traits);
1445 vars_of_frame_gtk (void)
1447 DEFVAR_LISP ("default-gtk-frame-plist", &Vdefault_gtk_frame_plist /*
1448 Plist of default frame-creation properties for Gtk frames.
1449 These override what is specified in the resource database and in
1450 `default-frame-plist', but are overridden by the arguments to the
1451 particular call to `make-frame'.
1453 Note: In many cases, properties of a frame are available as specifiers
1454 instead of through the frame-properties mechanism.
1456 Here is a list of recognized frame properties, other than those
1457 documented in `set-frame-properties' (they can be queried and
1458 set at any time, except as otherwise noted):
1460 initially-unmapped If non-nil, the frame will not be visible
1461 when it is created. In this case, you
1462 need to call `make-frame-visible' to make
1464 popup If non-nil, it should be a frame, and this
1465 frame will be created as a "popup" frame
1466 whose parent is the given frame. This
1467 will make the window manager treat the
1468 frame as a dialog box, which may entail
1469 doing different things (e.g. not asking
1470 for positioning, and not iconifying
1471 separate from its parent).
1472 inter-line-space Not currently implemented.
1473 toolbar-shadow-thickness Thickness of toolbar shadows.
1474 background-toolbar-color Color of toolbar background.
1475 bottom-toolbar-shadow-color Color of bottom shadows on toolbars.
1476 (*Not* specific to the bottom-toolbar.)
1477 top-toolbar-shadow-color Color of top shadows on toolbars.
1478 (*Not* specific to the top-toolbar.)
1479 internal-border-width Width of internal border around text area.
1480 border-width Width of external border around text area.
1481 top Y position (in pixels) of the upper-left
1482 outermost corner of the frame (i.e. the
1483 upper-left of the window-manager
1485 left X position (in pixels) of the upper-left
1486 outermost corner of the frame (i.e. the
1487 upper-left of the window-manager
1489 border-color Color of external border around text area.
1490 cursor-color Color of text cursor.
1492 See also `default-frame-plist', which specifies properties which apply
1493 to all frames, not just Gtk frames.
1495 Vdefault_gtk_frame_plist = Qnil;
1497 gtk_console_methods->device_specific_frame_props = &Vdefault_gtk_frame_plist;