Merge r21-4-11-chise-0_20-=ucs.
[chise/xemacs-chise.git.1] / src / frame-gtk.c
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.
4
5 This file is part of XEmacs.
6
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
10 later version.
11
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
15 for more details.
16
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.  */
21
22 /* Synched up with: Not synched with FSF. */
23
24 /* Substantially rewritten for XEmacs.  */
25 /* Revamped to use Gdk/Gtk by William Perry */
26
27 #include <config.h>
28 #include "lisp.h"
29
30 #include "console-gtk.h"
31 #include "ui-gtk.h"
32 #include "glyphs-gtk.h"
33 #include "objects-gtk.h"
34 #include "scrollbar-gtk.h"
35
36 #include "gtk-xemacs.h"
37
38 #include "buffer.h"
39 #include "events.h"
40 #include "extents.h"
41 #include "faces.h"
42 #include "frame.h"
43 #include "window.h"
44
45 #ifdef HAVE_GNOME
46 #include <libgnomeui/libgnomeui.h>
47 #endif
48
49 #ifdef HAVE_DRAGNDROP
50 #include "dragdrop.h"
51 #endif
52
53 #define BORDER_WIDTH 0
54 #define INTERNAL_BORDER_WIDTH 0
55
56 #define TRANSIENT_DATA_IDENTIFIER "xemacs::transient_for"
57 #define FRAME_DATA_IDENTIFIER "xemacs::frame"
58 #define UNMAPPED_DATA_IDENTIFIER "xemacs::initially_unmapped"
59
60 #define STUPID_X_SPECIFIC_GTK_STUFF
61
62 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
63 #include <gdk/gdkx.h>
64 #endif
65
66 /* Default properties to use when creating frames.  */
67 Lisp_Object Vdefault_gtk_frame_plist;
68
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;
74
75 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
76 EXFUN (Fgtk_window_id, 1);
77 #endif
78
79 #ifdef HAVE_DRAGNDROP
80 enum {
81   TARGET_TYPE_STRING,
82   TARGET_TYPE_URI_LIST,
83 };
84
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 }
90 };
91
92 static guint dnd_n_targets = sizeof(dnd_target_table) / sizeof(dnd_target_table[0]);
93
94 #endif
95
96 \f
97 /************************************************************************/
98 /*                          helper functions                            */
99 /************************************************************************/
100
101 /* Return the Emacs frame-object corresponding to an X window */
102 struct frame *
103 gtk_window_to_frame (struct device *d, GdkWindow *wdesc)
104 {
105   Lisp_Object tail, frame;
106   struct frame *f;
107
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. */
111
112   for (tail = DEVICE_FRAME_LIST (d); CONSP (tail); tail = XCDR (tail))
113     {
114       frame = XCAR (tail);
115       if (!FRAMEP (frame))
116         continue;
117       f = XFRAME (frame);
118       if (FRAME_GTK_P (f) && GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f)) == wdesc)
119         return f;
120     }
121   return 0;
122 }
123
124 /* Like gtk_window_to_frame but also compares the window with the widget's
125    windows */
126 struct frame *
127 gtk_any_window_to_frame (struct device *d, GdkWindow *w)
128 {
129     do
130     {
131         Lisp_Object frmcons;
132
133         DEVICE_FRAME_LOOP (frmcons, d)
134             {
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))) ||
138 #ifdef HAVE_MENUBARS
139                     (w == GET_GTK_WIDGET_WINDOW (FRAME_GTK_MENUBAR_WIDGET (fr))) ||
140 #endif
141                     (w == GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (fr))))
142                 {
143                     return (fr);
144                 }
145             }
146         w = gdk_window_get_parent (w);
147     } while (w);
148
149     return (0);
150 }
151
152 struct frame *
153 gtk_any_widget_or_parent_to_frame (struct device *d, GtkWidget *widget)
154 {
155     return (gtk_any_window_to_frame (d, GET_GTK_WIDGET_WINDOW (widget)));
156 }
157
158 struct device *
159 gtk_any_window_to_device (GdkWindow *w)
160 {
161         struct device *d = NULL;
162         Lisp_Object devcons, concons;
163
164         DEVICE_LOOP_NO_BREAK (devcons, concons)
165                 {
166                         d = XDEVICE (XCAR (devcons));
167                         if (!DEVICE_GTK_P (d)) continue;
168                         if (gtk_any_window_to_frame (d, w))
169                                 return (d);
170                 }
171         return (NULL);
172 }
173
174 struct frame *
175 decode_gtk_frame (Lisp_Object frame)
176 {
177   if (NILP (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);
184 }
185
186 \f
187 /************************************************************************/
188 /*                      window-manager interactions                     */
189 /************************************************************************/
190 static int
191 gtk_frame_iconified_p (struct frame *f)
192 {
193     return (f->iconified);
194 }
195
196 \f
197 /************************************************************************/
198 /*                          frame properties                            */
199 /************************************************************************/
200
201 static Lisp_Object
202 gtk_frame_property (struct frame *f, Lisp_Object property)
203 {
204   GtkWidget *shell = FRAME_GTK_SHELL_WIDGET (f);
205
206   if (EQ (Qleft, property) || EQ (Qtop, property))
207     {
208       gint x, y;
209       if (!GET_GTK_WIDGET_WINDOW(shell))
210         return Qzero;
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);
214     }
215   if (EQ (Qshell_widget, property))
216     {
217       return (FRAME_GTK_LISP_WIDGETS (f)[0]);
218     }
219   if (EQ (Qcontainer_widget, property))
220     {
221       return (FRAME_GTK_LISP_WIDGETS (f)[1]);
222     }
223   if (EQ (Qtext_widget, property))
224     {
225       return (FRAME_GTK_LISP_WIDGETS (f)[2]);
226     }
227 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
228   if (EQ (Qwindow_id, property))
229     return Fgtk_window_id (make_frame (f));
230 #endif
231
232   return Qunbound;
233 }
234
235 static int
236 gtk_internal_frame_property_p (struct frame *f, Lisp_Object property)
237 {
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);
245 }
246
247 static Lisp_Object
248 gtk_frame_properties (struct frame *f)
249 {
250   Lisp_Object props = Qnil;
251   GtkWidget *shell = FRAME_GTK_SHELL_WIDGET (f);
252   gint x, y;
253
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);
257
258 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
259   props = cons3 (Qwindow_id, Fgtk_window_id (make_frame (f)), props);
260 #endif
261
262   if (!GET_GTK_WIDGET_WINDOW (shell))
263     x = y = 0;
264   else
265     gdk_window_get_deskrelative_origin (GET_GTK_WIDGET_WINDOW (shell), &x, &y);
266
267   props = cons3 (Qtop,  make_int (y), props);
268   props = cons3 (Qleft, make_int (x), props);
269
270   return props;
271 }
272
273 \f
274 /* Functions called only from `gtk_set_frame_properties' to set
275    individual properties. */
276
277 static void
278 gtk_set_frame_text_value (struct frame *f, Bufbyte *value,
279                           void (*func) (gpointer, gchar *),
280                           gpointer arg)
281 {
282   gchar *the_text = (gchar *) value;
283
284   /* Programmer fuckup or window is not realized yet. */
285   if (!func || !arg) return;
286
287 #ifdef MULE
288   {
289     Bufbyte *ptr;
290     
291     /* Optimize for common ASCII case */
292     for (ptr = value; *ptr; ptr++)
293       if (!BYTE_ASCII_P (*ptr))
294         {
295           char *tmp;
296           C_STRING_TO_EXTERNAL (value, tmp, Qctext);
297           the_text = tmp;
298           break;
299         }
300   }
301 #endif /* MULE */
302
303   (*func) (arg, (gchar *) the_text);
304 }
305
306 static void
307 gtk_set_title_from_bufbyte (struct frame *f, Bufbyte *name)
308 {
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));
313 }
314
315 static void
316 gtk_set_icon_name_from_bufbyte (struct frame *f, Bufbyte *name)
317 {
318   gtk_set_frame_text_value (f, name,
319                             (void (*)(gpointer, gchar *))
320                             gdk_window_set_icon_name, FRAME_GTK_SHELL_WIDGET (f)->window);
321 }
322
323 /* Set the initial frame size as specified.  This function is used
324    when the frame's widgets have not yet been realized.
325 */
326 static void
327 gtk_set_initial_frame_size (struct frame *f, int x, int y,
328                             unsigned int w, unsigned int h)
329 {
330   GtkWidget *shell = FRAME_GTK_SHELL_WIDGET (f);
331   GdkGeometry geometry;
332   GdkWindowHints geometry_mask = 0x00;
333
334   if (GTK_IS_WINDOW (shell))
335     {
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;
339
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);
344     }
345
346   FRAME_HEIGHT (f) = h;
347   FRAME_WIDTH (f) = w;
348
349   change_frame_size (f, h, w, 0);
350   {
351     GtkRequisition req;
352  
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);
355   }
356 }
357
358 /* Report that a frame property of frame S is being set or changed.
359    If the property is not specially recognized, do nothing.
360  */
361
362 static void
363 gtk_set_frame_properties (struct frame *f, Lisp_Object plist)
364 {
365   gint x, y;
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;
371   Lisp_Object tail;
372
373   for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
374     {
375       Lisp_Object prop = Fcar (tail);
376       Lisp_Object val = Fcar (Fcdr (tail));
377
378       if (SYMBOLP (prop))
379         {
380           if (EQ (prop, Qfont))
381           {
382               /* If the value is not a string we silently ignore it. */
383               if (STRINGP (val))
384               {
385                   Lisp_Object frm, font_spec;
386
387                   XSETFRAME (frm, f);
388                   font_spec = Fget (Fget_face (Qdefault), Qfont, Qnil);
389
390                   Fadd_spec_to_specifier (font_spec, val, frm, Qnil, Qnil);
391                   update_frame_face_values (f);
392               }
393               continue;
394           }
395           else if (EQ (prop, Qwidth))
396           {
397               CHECK_INT (val);
398               width = XINT (val);
399               width_specified_p = TRUE;
400               continue;
401           }
402           else if (EQ (prop, Qheight))
403           {
404               CHECK_INT (val);
405               height = XINT (val);
406               height_specified_p = TRUE;
407               continue;
408           }
409           /* Further kludge the x/y. */
410           else if (EQ (prop, Qx))
411           {
412               CHECK_INT (val);
413               x = (gint) XINT (val);
414               x_position_specified_p = TRUE;
415               continue;
416           }
417           else if (EQ (prop, Qy))
418           {
419               CHECK_INT (val);
420               y = (gint) XINT (val);
421               y_position_specified_p = TRUE;
422               continue;
423           }
424         }
425     }
426
427   /* Kludge kludge kludge.   We need to deal with the size and position
428    specially. */
429   {
430     int size_specified_p = width_specified_p || height_specified_p;
431     int position_specified_p = x_position_specified_p || y_position_specified_p;
432
433     if (!width_specified_p)
434       width = 80;
435     if (!height_specified_p)
436       height = 30;
437
438     /* Kludge kludge kludge kludge. */
439     if (position_specified_p &&
440         (!x_position_specified_p || !y_position_specified_p))
441       {
442         gint dummy;
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));
447       }
448
449     if (!f->init_finished)
450       {
451         if (size_specified_p || position_specified_p)
452           gtk_set_initial_frame_size (f, x, y, width, height);
453       }
454     else
455       {
456         if (size_specified_p)
457           {
458             Lisp_Object frame;
459             XSETFRAME (frame, f);
460             Fset_frame_size (frame, make_int (width), make_int (height), Qnil);
461           }
462         if (position_specified_p)
463           {
464             Lisp_Object frame;
465             XSETFRAME (frame, f);
466             Fset_frame_position (frame, make_int (x), make_int (y));
467           }
468       }
469   }
470 }
471
472 \f
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. */
479
480 extern Lisp_Object Vgtk_initial_geometry;
481
482 #ifndef HAVE_GNOME
483 static int
484 get_number (const char **geometry)
485 {
486   int value = 0;
487   int mult  = 1;
488         
489   if (**geometry == '-'){
490     mult = -1;
491     (*geometry)++;
492   }
493   while (**geometry && isdigit (**geometry)){
494     value = value * 10 + (**geometry - '0');
495     (*geometry)++;
496   }
497   return value * mult;
498 }
499
500 /*
501  */
502
503 /**
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
510  *
511  * Description:
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.
517  *
518  * Returns:
519  * %TRUE if the geometry was successfully parsed, %FALSE otherwise.
520  **/
521
522 static gboolean
523 gnome_parse_geometry (const gchar *geometry, gint *xpos, 
524                       gint *ypos, gint *width, gint *height)
525 {
526   int subtract;
527
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);
532         
533   *xpos = *ypos = *width = *height = -1;
534
535   if (!geometry)
536     return FALSE;
537
538   if (*geometry == '=')
539     geometry++;
540   if (!*geometry)
541     return FALSE;
542   if (isdigit (*geometry))
543     *width = get_number (&geometry);
544   if (!*geometry)
545     return TRUE;
546   if (*geometry == 'x' || *geometry == 'X'){
547     geometry++;
548     *height = get_number (&geometry);
549   }
550   if (!*geometry)
551     return 1;
552   if (*geometry == '+'){
553     subtract = 0;
554     geometry++;
555   } else if (*geometry == '-'){
556     subtract = gdk_screen_width ();
557     geometry++;
558   } else
559     return FALSE;
560   *xpos = get_number (&geometry);
561   if (subtract)
562     *xpos = subtract - *xpos;
563   if (!*geometry)
564     return TRUE;
565   if (*geometry == '+'){
566     subtract = 0;
567     geometry++;
568   } else if (*geometry == '-'){
569     subtract = gdk_screen_height ();
570     geometry++;
571   } else
572     return FALSE;
573   *ypos = get_number (&geometry);
574   if (subtract)
575     *ypos = subtract - *ypos;
576   return TRUE;
577 }
578 #endif
579
580 static void
581 gtk_initialize_frame_size (struct frame *f)
582 {
583   gint x = 10, y = 10, w = 80, h = 30;
584
585   if (STRINGP (Vgtk_initial_geometry))
586     {
587       if (!gnome_parse_geometry (XSTRING_DATA (Vgtk_initial_geometry), &x,&y,&w,&h))
588         {
589           x = y = 10;
590           w = 80;
591           h = 30;
592         }
593     }
594
595   /* set the position of the frame's root window now.  When the
596      frame was created, the position was initialized to (0,0). */
597   {
598     struct window *win = XWINDOW (f->root_window);
599
600     WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f);
601     WINDOW_TOP (win) = FRAME_TOP_BORDER_END (f);
602
603     if (!NILP (f->minibuffer_window))
604       {
605         win = XWINDOW (f->minibuffer_window);
606         WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f);
607       }
608   }
609
610   gtk_set_initial_frame_size (f, x, y, w, h);
611 }
612
613 static gboolean
614 resize_event_cb (GtkWidget *w, GtkAllocation *allocation, gpointer user_data)
615 {
616   struct frame *f = (struct frame *) user_data;
617
618   f->pixwidth = allocation->width;
619   f->pixheight = allocation->height;
620
621   if (FRAME_GTK_TEXT_WIDGET (f)->window)
622     {
623       Lisp_Object frame;
624       XSETFRAME (frame, f);
625       Fredraw_frame (frame, Qt);
626     }
627
628   return (FALSE);
629 }
630
631 static gboolean
632 delete_event_cb (GtkWidget *w, GdkEvent *ev, gpointer user_data)
633 {
634     struct frame *f = (struct frame *) user_data;
635     Lisp_Object frame;
636
637     XSETFRAME (frame, f);
638     enqueue_misc_user_event (frame, Qeval, list3 (Qdelete_frame, frame, Qt));
639
640     /* See if tickling the event queue helps us with our delays when
641        clicking 'close' */
642     signal_fake_event ();
643
644     return (TRUE);
645 }
646
647 extern gboolean emacs_shell_event_handler (GtkWidget *wid, GdkEvent *event, gpointer closure);
648 extern Lisp_Object build_gtk_object (GtkObject *obj);
649
650 #ifndef GNOME_IS_APP
651 #define GNOME_IS_APP(x) 0
652 #define gnome_app_set_contents(x,y) 0
653 #endif
654
655 static void
656 cleanup_deleted_frame (gpointer data)
657 {
658   struct frame *f = (struct frame *) data;
659   Lisp_Object frame;
660
661   XSETFRAME (frame, f);
662   Fdelete_frame (frame, Qt);
663 }
664
665 #ifdef HAVE_DRAGNDROP
666 extern void
667 dragndrop_data_received (GtkWidget          *widget,
668                          GdkDragContext     *context,
669                          gint                x,
670                          gint                y,
671                          GtkSelectionData   *data,
672                          guint               info,
673                          guint               time);
674
675 extern gboolean
676 dragndrop_dropped (GtkWidget *widget,
677                    GdkDragContext *drag_context,
678                    gint x,
679                    gint y,
680                    guint time,
681                    gpointer user_data);
682
683 Lisp_Object Vcurrent_drag_object;
684
685 #define DRAG_SELECTION_DATA_ERROR "Error converting drag data to external format"
686 static void
687 dragndrop_get_drag (GtkWidget *widget,
688                     GdkDragContext *drag_context,
689                     GtkSelectionData *data,
690                     guint info,
691                     guint time,
692                     gpointer user_data)
693 {
694   gtk_selection_data_set (data, GDK_SELECTION_TYPE_STRING, 8,
695                           DRAG_SELECTION_DATA_ERROR,
696                           strlen (DRAG_SELECTION_DATA_ERROR));
697
698   switch (info)
699     {
700     case TARGET_TYPE_STRING:
701       {
702         Lisp_Object string = Vcurrent_drag_object;
703         
704         if (!STRINGP (Vcurrent_drag_object))
705           {
706             string = Fprin1_to_string (string, Qnil);
707             /* Convert to a string */
708           }
709         
710         gtk_selection_data_set (data, GDK_SELECTION_TYPE_STRING,
711                                 8, XSTRING_DATA (string), XSTRING_LENGTH (string));
712       }
713       break;
714     case TARGET_TYPE_URI_LIST:
715       break;
716     default:
717       break;
718     }
719   Vcurrent_drag_object = Qnil;
720 }
721
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.
728 */
729        (event, data, dtyp))
730 {
731   if (EVENTP(event))
732     {
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);
736       GdkAtom dnd_typ;
737       GtkTargetList *tl = gtk_target_list_new (dnd_target_table, dnd_n_targets);
738
739       /* only drag if this is really a press */
740       if (EVENT_TYPE(lisp_event) != button_press_event)
741         return Qnil;
742
743       /* get the desired type */
744       if (!NILP (dtyp) && STRINGP (dtyp))
745         dnd_typ = gdk_atom_intern (XSTRING_DATA (dtyp), FALSE);
746
747       gtk_drag_begin (wid, tl, GDK_ACTION_COPY, lisp_event->event.button.button, NULL);
748
749       Vcurrent_drag_object = data;
750
751       gtk_target_list_unref (tl);
752     }
753   return Qnil;
754 }
755 #endif
756
757 /* Creates the widgets for a frame.
758    lisp_window_id is a Lisp description of an X window or Xt
759    widget to parse.
760
761    This function does not map the windows.  (That is
762    done by gtk_popup_frame().)
763 */
764 static void
765 gtk_create_widgets (struct frame *f, Lisp_Object lisp_window_id, Lisp_Object parent)
766 {
767   const char *name;
768   GtkWidget *text, *container, *shell;
769   gboolean embedded_p = !NILP (lisp_window_id);
770 #ifdef HAVE_MENUBARS
771   int menubar_visible;
772 #endif
773
774   if (STRINGP (f->name))
775     TO_EXTERNAL_FORMAT (LISP_STRING, f->name, C_STRING_ALLOCA, name, Qctext);
776   else
777     name = "emacs";
778
779   FRAME_GTK_TOP_LEVEL_FRAME_P (f) = 1;
780
781   if (embedded_p)
782     {
783       CHECK_GTK_OBJECT (lisp_window_id);
784
785       if (!GTK_IS_CONTAINER (XGTK_OBJECT (lisp_window_id)->object))
786         {
787           signal_simple_error ("Window ID must be a GtkContainer subclass", lisp_window_id);
788         }
789
790       shell = gtk_vbox_new (FALSE, 0);
791
792       gtk_object_weakref (GTK_OBJECT (shell), cleanup_deleted_frame, f);
793       gtk_container_add (GTK_CONTAINER (XGTK_OBJECT (lisp_window_id)->object), shell);
794     }
795   else
796     {
797 #ifdef HAVE_GNOME
798       shell = GTK_WIDGET (gnome_app_new ("XEmacs", "XEmacs/GNOME"));
799 #else
800       shell = GTK_WIDGET (gtk_window_new (GTK_WINDOW_TOPLEVEL));
801 #endif
802     }
803
804   if (!NILP (parent))
805   {
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));
810   }
811
812   gtk_container_set_border_width (GTK_CONTAINER (shell), 0);
813
814   gtk_object_set_data (GTK_OBJECT (shell), FRAME_DATA_IDENTIFIER, f);
815
816   FRAME_GTK_SHELL_WIDGET (f) = shell;
817
818   text = GTK_WIDGET (gtk_xemacs_new (f));
819
820   if (!GNOME_IS_APP (shell))
821     container = GTK_WIDGET (gtk_vbox_new (FALSE, INTERNAL_BORDER_WIDTH));
822   else
823     container = shell;
824
825   FRAME_GTK_CONTAINER_WIDGET (f) = container;
826   FRAME_GTK_TEXT_WIDGET (f) = text;
827
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);
838 #endif
839
840 #ifdef HAVE_MENUBARS
841   /* Create the initial menubar widget. */
842   menubar_visible = gtk_initialize_frame_menubar (f);
843
844   if (menubar_visible)
845     {
846       gtk_widget_show_all (FRAME_GTK_MENUBAR_WIDGET (f));
847     }
848 #endif /* HAVE_MENUBARS */
849
850 #ifdef HAVE_GNOME
851   if (GNOME_IS_APP (shell))
852     gnome_app_set_contents (GNOME_APP (shell), text);
853   else
854 #endif
855     /* Now comes the drawing area, which should fill the rest of the
856     ** frame completely.
857     */
858     gtk_box_pack_end (GTK_BOX (container), text, TRUE, TRUE, 0);
859
860   /* Connect main event handler */
861   gtk_signal_connect (GTK_OBJECT (shell), "delete-event", GTK_SIGNAL_FUNC (delete_event_cb), f);
862
863   {
864     static char *events_to_frob[] = { "focus-in-event",
865                                       "focus-out-event",
866                                       "enter-notify-event",
867                                       "leave-notify-event",
868                                       "map-event",
869                                       "unmap-event",
870                                       "property-notify-event",
871                                       "selection-clear-event",
872                                       "selection-request-event",
873                                       "selection-notify-event",
874                                       "client-event",
875                                       /* "configure-event", */
876                                       "visibility-notify-event",
877                                       NULL };
878     int i;
879
880     for (i = 0; events_to_frob[i]; i++)
881       {
882         gtk_signal_connect (GTK_OBJECT (shell), events_to_frob[i],
883                             GTK_SIGNAL_FUNC (emacs_shell_event_handler), f);
884       }
885   }
886
887   gtk_signal_connect (GTK_OBJECT (shell), "size-allocate", GTK_SIGNAL_FUNC (resize_event_cb), f);
888
889   /* This might be safe to call now... */
890   /* gtk_signal_connect (GTK_OBJECT (shell), "event", GTK_SIGNAL_FUNC (emacs_shell_event_handler), f); */
891
892   /* Let's make sure we get all the events we can */
893   gtk_widget_set_events (text, GDK_ALL_EVENTS_MASK);
894
895   if (shell != container)
896     gtk_container_add (GTK_CONTAINER (shell), container);
897
898   gtk_widget_set_name (shell, "XEmacs::shell");
899   gtk_widget_set_name (container, "XEmacs::container");
900   gtk_widget_set_name (text, "XEmacs::text");
901
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));
905
906   gtk_widget_realize (shell);
907 }
908
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. */
912 static void
913 gtk_popup_frame (struct frame *f)
914 {
915   /* */
916
917   if (gtk_object_get_data (GTK_OBJECT (FRAME_GTK_SHELL_WIDGET (f)), UNMAPPED_DATA_IDENTIFIER))
918     {
919       FRAME_GTK_TOTALLY_VISIBLE_P (f) = 0;
920       f->visible = 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));
924     }
925   else
926     {
927       gtk_widget_show_all (FRAME_GTK_SHELL_WIDGET (f));
928     }
929 }
930
931 static void
932 allocate_gtk_frame_struct (struct frame *f)
933 {
934   /* zero out all slots. */
935   f->frame_data = xnew_and_zero (struct gtk_frame);
936
937   /* yeah, except the lisp ones */
938   FRAME_GTK_ICON_PIXMAP (f) = Qnil;
939   FRAME_GTK_ICON_PIXMAP_MASK (f) = Qnil;
940 }
941
942 \f
943 /************************************************************************/
944 /*                              Lisp functions                          */
945 /************************************************************************/
946
947 static void
948 gtk_init_frame_1 (struct frame *f, Lisp_Object props)
949 {
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);
955
956   if (!NILP (popup))
957     {
958       if (EQ (popup, Qt))
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",
963                                device, popup);
964     }
965
966   initially_unmapped = Fplist_get (props, Qinitially_unmapped, Qnil);
967
968   /*
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
976    * frame properties.
977    */
978   f->visible = 1;
979
980   allocate_gtk_frame_struct (f);
981   gtk_create_widgets (f, lisp_window_id, popup);
982
983   if (!NILP (initially_unmapped))
984     {
985       gtk_object_set_data (GTK_OBJECT (FRAME_GTK_SHELL_WIDGET (f)),
986                            UNMAPPED_DATA_IDENTIFIER, (gpointer) 1);
987     }
988 }
989
990 static void
991 gtk_init_frame_2 (struct frame *f, Lisp_Object props)
992 {
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. */
995
996   update_frame_face_values (f);
997   gtk_initialize_frame_size (f);
998   /* Kyle:
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.
1003    * JV:
1004    *   It turns out it gives problems with FVWMs name based mapping.
1005    *   We'll just  need to be carefull in the modeline specs.
1006    */
1007   update_frame_title (f); 
1008 }
1009
1010 static void
1011 gtk_init_frame_3 (struct frame *f)
1012 {
1013   /* Pop up the frame. */
1014   gtk_popup_frame (f);
1015 }
1016
1017 static void
1018 gtk_mark_frame (struct frame *f)
1019 {
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]);
1025 }
1026
1027 static void
1028 gtk_set_frame_icon (struct frame *f)
1029 {
1030   GdkPixmap *gtk_pixmap = NULL, *gtk_mask = NULL;
1031
1032   if (IMAGE_INSTANCEP (f->icon)
1033       && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (f->icon)))
1034     {
1035       gtk_pixmap = XIMAGE_INSTANCE_GTK_PIXMAP (f->icon);
1036       gtk_mask = XIMAGE_INSTANCE_GTK_MASK (f->icon);
1037     }
1038   else
1039     {
1040       gtk_pixmap = 0;
1041       gtk_mask = 0;
1042     }
1043
1044   gdk_window_set_icon (GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f)), NULL, gtk_pixmap, gtk_mask);
1045 }
1046
1047 static void
1048 gtk_set_frame_pointer (struct frame *f)
1049 {
1050   GtkWidget *w = FRAME_GTK_TEXT_WIDGET (f);
1051   GdkCursor *c = XIMAGE_INSTANCE_GTK_CURSOR (f->pointer);
1052
1053   if (POINTER_IMAGE_INSTANCEP (f->pointer))
1054     {
1055       gdk_window_set_cursor (GET_GTK_WIDGET_WINDOW (w), c);
1056       gdk_flush ();
1057     }
1058   else
1059     {
1060       /* abort()? */
1061       stderr_out ("POINTER_IMAGE_INSTANCEP (f->pointer) failed!\n");
1062     }
1063 }
1064
1065 static Lisp_Object
1066 gtk_get_frame_parent (struct frame *f)
1067 {
1068     GtkWidget *parentwid = gtk_object_get_data (GTK_OBJECT (FRAME_GTK_SHELL_WIDGET (f)),
1069                                                 TRANSIENT_DATA_IDENTIFIER);
1070
1071     /* find the frame whose wid is parentwid */
1072     if (parentwid)
1073     {
1074         Lisp_Object frmcons;
1075         DEVICE_FRAME_LOOP (frmcons, XDEVICE (FRAME_DEVICE (f)))
1076             {
1077                 Lisp_Object frame = XCAR (frmcons);
1078                 if (FRAME_GTK_SHELL_WIDGET (XFRAME (frame)) == parentwid)
1079                     return frame;
1080             }
1081     }
1082     return Qnil;
1083 }
1084
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
1090 a string.
1091 */
1092        (frame))
1093 {
1094   char str[255];
1095   struct frame *f = decode_gtk_frame (frame);
1096
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);
1100 }
1101 #endif
1102
1103 \f
1104 /************************************************************************/
1105 /*                      manipulating the X window                       */
1106 /************************************************************************/
1107
1108 static void
1109 gtk_set_frame_position (struct frame *f, int xoff, int yoff)
1110 {
1111     gtk_widget_set_uposition (FRAME_GTK_SHELL_WIDGET (f), xoff, yoff);
1112 }
1113
1114 /* Call this to change the size of frame S's x-window. */
1115
1116 static void
1117 gtk_set_frame_size (struct frame *f, int cols, int rows)
1118 {
1119   GtkWidget *shell = FRAME_GTK_SHELL_WIDGET (f);
1120   GdkGeometry geometry;
1121   GdkWindowHints geometry_mask = 0x00;
1122
1123   if (GTK_IS_WINDOW (shell))
1124     {
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;
1128
1129       gtk_window_set_geometry_hints (GTK_WINDOW (shell),
1130                                      FRAME_GTK_TEXT_WIDGET (f), &geometry, geometry_mask);
1131     }
1132
1133   change_frame_size (f, rows, cols, 0);
1134
1135   {
1136     GtkRequisition req;
1137
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);
1140   }
1141 }
1142
1143 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
1144 /* There is NO equivalent to XWarpPointer under Gtk */
1145 static void
1146 gtk_set_mouse_position (struct window *w, int x, int y)
1147 {
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);
1153 }
1154 #endif /* STUPID_X_SPECIFIC_GTK_STUFF */
1155
1156 static int
1157 gtk_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y)
1158 {
1159     /* Returns the pixel position within the editor text widget */
1160     gint win_x, win_y;
1161     GdkWindow *w = gdk_window_at_pointer (&win_x, &win_y);
1162     struct frame *f = NULL;
1163
1164     if (!w) return (0);
1165
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.
1168     */
1169     f = gtk_any_window_to_frame (d, w);
1170
1171     if (!f) return (0);
1172
1173     XSETFRAME (*frame, f);
1174
1175     gdk_window_get_pointer (GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f)),
1176                             &win_x, &win_y, NULL);
1177
1178     *x = win_x;
1179     *y = win_y;
1180
1181     return (1);
1182 }
1183
1184 static void
1185 gtk_cant_notify_wm_error (void)
1186 {
1187   error ("Can't notify window manager of iconification.");
1188 }
1189
1190 /* Raise frame F.  */
1191 static void
1192 gtk_raise_frame_1 (struct frame *f, int force)
1193 {
1194   if (FRAME_VISIBLE_P (f) || force)
1195     {
1196       GdkWindow *emacs_window = GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f));
1197
1198       gdk_window_raise (emacs_window);
1199     }
1200 }
1201
1202 static void
1203 gtk_raise_frame (struct frame *f)
1204 {
1205   gtk_raise_frame_1 (f, 1);
1206 }
1207
1208 /* Lower frame F.  */
1209 static void
1210 gtk_lower_frame (struct frame *f)
1211 {
1212   if (FRAME_VISIBLE_P (f))
1213     {
1214         gdk_window_lower (GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f)));
1215     }
1216 }
1217
1218 /* Change from withdrawn state to mapped state. */
1219 static void
1220 gtk_make_frame_visible (struct frame *f)
1221 {
1222     gtk_widget_show_all (FRAME_GTK_SHELL_WIDGET (f));
1223     gtk_raise_frame_1 (f, 0);
1224 }
1225
1226 /* Change from mapped state to withdrawn state. */
1227 static void
1228 gtk_make_frame_invisible (struct frame *f)
1229 {
1230     gtk_widget_hide (FRAME_GTK_SHELL_WIDGET (f));
1231 }
1232
1233 static int
1234 gtk_frame_visible_p (struct frame *f)
1235 {
1236     GtkWidget *w = FRAME_GTK_SHELL_WIDGET (f);
1237
1238     f->visible = (GTK_OBJECT_FLAGS (w) & GTK_VISIBLE);
1239
1240     return f->visible;
1241 }
1242
1243 static int
1244 gtk_frame_totally_visible_p (struct frame *f)
1245 {
1246   return FRAME_GTK_TOTALLY_VISIBLE_P (f);
1247 }
1248
1249 /* Change window state from mapped to iconified. */
1250 static void
1251 gtk_iconify_frame (struct frame *f)
1252 {
1253   GdkWindow *w = GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f));
1254
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 ();
1260
1261   f->iconified = 1;
1262 }
1263
1264 /* Sets the X focus to frame f. */
1265 static void
1266 gtk_focus_on_frame (struct frame *f)
1267 {
1268   GtkWidget *shell_widget;
1269
1270   assert (FRAME_GTK_P (f));
1271
1272   shell_widget = FRAME_GTK_SHELL_WIDGET (f);
1273   if (!GET_GTK_WIDGET_WINDOW (shell_widget))
1274     return;
1275
1276   gtk_widget_grab_focus (shell_widget);
1277 }
1278
1279 /* Destroy the window of frame S.  */
1280 static void
1281 gtk_delete_frame (struct frame *f)
1282 {
1283     GtkWidget *w = FRAME_GTK_SHELL_WIDGET (f);
1284
1285     gtk_widget_destroy (w);
1286
1287     if (FRAME_GTK_GEOM_FREE_ME_PLEASE (f))
1288         xfree (FRAME_GTK_GEOM_FREE_ME_PLEASE (f));
1289     xfree (f->frame_data);
1290     f->frame_data = 0;
1291 }
1292
1293 static void
1294 gtk_recompute_cell_sizes (struct frame *frm)
1295 {
1296   if (GTK_IS_WINDOW (FRAME_GTK_SHELL_WIDGET (frm)))
1297     {
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;
1303
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;
1308
1309       gtk_window_set_geometry_hints (w, FRAME_GTK_TEXT_WIDGET (frm), &geometry, geometry_mask);
1310     }
1311 }
1312
1313 static void
1314 gtk_update_frame_external_traits (struct frame* frm, Lisp_Object name)
1315 {
1316   Lisp_Object frame = Qnil;
1317
1318   XSETFRAME(frame, frm);
1319
1320   if (EQ (name, Qforeground))
1321    {
1322      Lisp_Object color = FACE_FOREGROUND (Vdefault_face, frame);
1323      GdkColor *fgc;
1324
1325      if (!EQ (color, Vthe_null_color_instance))
1326        {
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. */
1332        }
1333    }
1334   else if (EQ (name, Qbackground))
1335    {
1336      Lisp_Object color = FACE_BACKGROUND (Vdefault_face, frame);
1337      GdkColor *bgc;
1338
1339      if (!EQ (color, Vthe_null_color_instance))
1340        {
1341          bgc = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (color));
1342          if (FRAME_GTK_SHELL_WIDGET (frm)->window)
1343            {
1344              gdk_window_set_background (FRAME_GTK_SHELL_WIDGET (frm)->window, bgc);
1345            }
1346          if (FRAME_GTK_TEXT_WIDGET (frm)->window)
1347            {
1348              gdk_window_set_background (FRAME_GTK_TEXT_WIDGET (frm)->window, bgc);
1349            }
1350        }
1351
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);
1356    }
1357   else if (EQ (name, Qfont))
1358    {
1359      Lisp_Object font = FACE_FONT (Vdefault_face, frame, Vcharset_ascii);
1360
1361      if (!EQ (font, Vthe_null_font_instance))
1362      {
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. */
1367      }
1368    }
1369   else
1370    abort ();
1371
1372 #ifdef HAVE_TOOLBARS
1373   /* Setting the background clears the entire frame area
1374     including the toolbar so we force an immediate redraw of
1375     it. */
1376   if (EQ (name, Qbackground))
1377     MAYBE_DEVMETH (XDEVICE (frm->device), redraw_frame_toolbars, (frm));
1378 #endif /* HAVE_TOOLBARS */
1379
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);
1384 }
1385
1386 \f
1387 /************************************************************************/
1388 /*                            initialization                            */
1389 /************************************************************************/
1390
1391 void
1392 syms_of_frame_gtk (void)
1393 {
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");
1399
1400 #ifdef HAVE_DRAGNDROP
1401   staticpro (&Vcurrent_drag_object);
1402   Vcurrent_drag_object = Qnil;
1403   DEFSUBR (Fgtk_start_drag_internal);
1404 #endif
1405 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
1406   DEFSUBR (Fgtk_window_id);
1407 #endif
1408 }
1409
1410 void
1411 console_type_create_frame_gtk (void)
1412 {
1413   /* frame methods */
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);
1423 #endif
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);
1444 }
1445
1446 void
1447 vars_of_frame_gtk (void)
1448 {
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'.
1454
1455 Note: In many cases, properties of a frame are available as specifiers
1456 instead of through the frame-properties mechanism.
1457
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):
1461
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
1465                                 the frame appear.
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
1486                                 decorations).
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
1490                                 decorations).
1491   border-color                  Color of external border around text area.
1492   cursor-color                  Color of text cursor.
1493
1494 See also `default-frame-plist', which specifies properties which apply
1495 to all frames, not just Gtk frames.
1496 */ );
1497   Vdefault_gtk_frame_plist = Qnil;
1498
1499   gtk_console_methods->device_specific_frame_props = &Vdefault_gtk_frame_plist;
1500 }