This commit was generated by cvs2svn to compensate for changes in r5670,
[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   if (GNOME_IS_APP (shell))
851     gnome_app_set_contents (GNOME_APP (shell), text);
852   else
853     /* Now comes the drawing area, which should fill the rest of the
854     ** frame completely.
855     */
856     gtk_box_pack_end (GTK_BOX (container), text, TRUE, TRUE, 0);
857
858   /* Connect main event handler */
859   gtk_signal_connect (GTK_OBJECT (shell), "delete-event", GTK_SIGNAL_FUNC (delete_event_cb), f);
860
861   {
862     static char *events_to_frob[] = { "focus-in-event",
863                                       "focus-out-event",
864                                       "enter-notify-event",
865                                       "leave-notify-event",
866                                       "map-event",
867                                       "unmap-event",
868                                       "property-notify-event",
869                                       "selection-clear-event",
870                                       "selection-request-event",
871                                       "selection-notify-event",
872                                       "client-event",
873                                       /* "configure-event", */
874                                       "visibility-notify-event",
875                                       NULL };
876     int i;
877
878     for (i = 0; events_to_frob[i]; i++)
879       {
880         gtk_signal_connect (GTK_OBJECT (shell), events_to_frob[i],
881                             GTK_SIGNAL_FUNC (emacs_shell_event_handler), f);
882       }
883   }
884
885   gtk_signal_connect (GTK_OBJECT (shell), "size-allocate", GTK_SIGNAL_FUNC (resize_event_cb), f);
886
887   /* This might be safe to call now... */
888   /* gtk_signal_connect (GTK_OBJECT (shell), "event", GTK_SIGNAL_FUNC (emacs_shell_event_handler), f); */
889
890   /* Let's make sure we get all the events we can */
891   gtk_widget_set_events (text, GDK_ALL_EVENTS_MASK);
892
893   if (shell != container)
894     gtk_container_add (GTK_CONTAINER (shell), container);
895
896   gtk_widget_set_name (shell, "XEmacs::shell");
897   gtk_widget_set_name (container, "XEmacs::container");
898   gtk_widget_set_name (text, "XEmacs::text");
899
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));
903
904   gtk_widget_realize (shell);
905 }
906
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. */
910 static void
911 gtk_popup_frame (struct frame *f)
912 {
913   /* */
914
915   if (gtk_object_get_data (GTK_OBJECT (FRAME_GTK_SHELL_WIDGET (f)), UNMAPPED_DATA_IDENTIFIER))
916     {
917       FRAME_GTK_TOTALLY_VISIBLE_P (f) = 0;
918       f->visible = 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));
922     }
923   else
924     {
925       gtk_widget_show_all (FRAME_GTK_SHELL_WIDGET (f));
926     }
927 }
928
929 static void
930 allocate_gtk_frame_struct (struct frame *f)
931 {
932   /* zero out all slots. */
933   f->frame_data = xnew_and_zero (struct gtk_frame);
934
935   /* yeah, except the lisp ones */
936   FRAME_GTK_ICON_PIXMAP (f) = Qnil;
937   FRAME_GTK_ICON_PIXMAP_MASK (f) = Qnil;
938 }
939
940 \f
941 /************************************************************************/
942 /*                              Lisp functions                          */
943 /************************************************************************/
944
945 static void
946 gtk_init_frame_1 (struct frame *f, Lisp_Object props)
947 {
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);
953
954   if (!NILP (popup))
955     {
956       if (EQ (popup, Qt))
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",
961                                device, popup);
962     }
963
964   initially_unmapped = Fplist_get (props, Qinitially_unmapped, Qnil);
965
966   /*
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
974    * frame properties.
975    */
976   f->visible = 1;
977
978   allocate_gtk_frame_struct (f);
979   gtk_create_widgets (f, lisp_window_id, popup);
980
981   if (!NILP (initially_unmapped))
982     {
983       gtk_object_set_data (GTK_OBJECT (FRAME_GTK_SHELL_WIDGET (f)),
984                            UNMAPPED_DATA_IDENTIFIER, (gpointer) 1);
985     }
986 }
987
988 static void
989 gtk_init_frame_2 (struct frame *f, Lisp_Object props)
990 {
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. */
993
994   update_frame_face_values (f);
995   gtk_initialize_frame_size (f);
996   /* Kyle:
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.
1001    * JV:
1002    *   It turns out it gives problems with FVWMs name based mapping.
1003    *   We'll just  need to be carefull in the modeline specs.
1004    */
1005   update_frame_title (f); 
1006 }
1007
1008 static void
1009 gtk_init_frame_3 (struct frame *f)
1010 {
1011   /* Pop up the frame. */
1012   gtk_popup_frame (f);
1013 }
1014
1015 static void
1016 gtk_mark_frame (struct frame *f)
1017 {
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]);
1023 }
1024
1025 static void
1026 gtk_set_frame_icon (struct frame *f)
1027 {
1028   GdkPixmap *gtk_pixmap = NULL, *gtk_mask = NULL;
1029
1030   if (IMAGE_INSTANCEP (f->icon)
1031       && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (f->icon)))
1032     {
1033       gtk_pixmap = XIMAGE_INSTANCE_GTK_PIXMAP (f->icon);
1034       gtk_mask = XIMAGE_INSTANCE_GTK_MASK (f->icon);
1035     }
1036   else
1037     {
1038       gtk_pixmap = 0;
1039       gtk_mask = 0;
1040     }
1041
1042   gdk_window_set_icon (GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f)), NULL, gtk_pixmap, gtk_mask);
1043 }
1044
1045 static void
1046 gtk_set_frame_pointer (struct frame *f)
1047 {
1048   GtkWidget *w = FRAME_GTK_TEXT_WIDGET (f);
1049   GdkCursor *c = XIMAGE_INSTANCE_GTK_CURSOR (f->pointer);
1050
1051   if (POINTER_IMAGE_INSTANCEP (f->pointer))
1052     {
1053       gdk_window_set_cursor (GET_GTK_WIDGET_WINDOW (w), c);
1054       gdk_flush ();
1055     }
1056   else
1057     {
1058       /* abort()? */
1059       stderr_out ("POINTER_IMAGE_INSTANCEP (f->pointer) failed!\n");
1060     }
1061 }
1062
1063 static Lisp_Object
1064 gtk_get_frame_parent (struct frame *f)
1065 {
1066     GtkWidget *parentwid = gtk_object_get_data (GTK_OBJECT (FRAME_GTK_SHELL_WIDGET (f)),
1067                                                 TRANSIENT_DATA_IDENTIFIER);
1068
1069     /* find the frame whose wid is parentwid */
1070     if (parentwid)
1071     {
1072         Lisp_Object frmcons;
1073         DEVICE_FRAME_LOOP (frmcons, XDEVICE (FRAME_DEVICE (f)))
1074             {
1075                 Lisp_Object frame = XCAR (frmcons);
1076                 if (FRAME_GTK_SHELL_WIDGET (XFRAME (frame)) == parentwid)
1077                     return frame;
1078             }
1079     }
1080     return Qnil;
1081 }
1082
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
1088 a string.
1089 */
1090        (frame))
1091 {
1092   char str[255];
1093   struct frame *f = decode_gtk_frame (frame);
1094
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);
1098 }
1099 #endif
1100
1101 \f
1102 /************************************************************************/
1103 /*                      manipulating the X window                       */
1104 /************************************************************************/
1105
1106 static void
1107 gtk_set_frame_position (struct frame *f, int xoff, int yoff)
1108 {
1109     gtk_widget_set_uposition (FRAME_GTK_SHELL_WIDGET (f), xoff, yoff);
1110 }
1111
1112 /* Call this to change the size of frame S's x-window. */
1113
1114 static void
1115 gtk_set_frame_size (struct frame *f, int cols, int rows)
1116 {
1117   GtkWidget *shell = FRAME_GTK_SHELL_WIDGET (f);
1118   GdkGeometry geometry;
1119   GdkWindowHints geometry_mask = 0x00;
1120
1121   if (GTK_IS_WINDOW (shell))
1122     {
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;
1126
1127       gtk_window_set_geometry_hints (GTK_WINDOW (shell),
1128                                      FRAME_GTK_TEXT_WIDGET (f), &geometry, geometry_mask);
1129     }
1130
1131   change_frame_size (f, rows, cols, 0);
1132
1133   {
1134     GtkRequisition req;
1135
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);
1138   }
1139 }
1140
1141 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
1142 /* There is NO equivalent to XWarpPointer under Gtk */
1143 static void
1144 gtk_set_mouse_position (struct window *w, int x, int y)
1145 {
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);
1151 }
1152 #endif /* STUPID_X_SPECIFIC_GTK_STUFF */
1153
1154 static int
1155 gtk_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y)
1156 {
1157     /* Returns the pixel position within the editor text widget */
1158     gint win_x, win_y;
1159     GdkWindow *w = gdk_window_at_pointer (&win_x, &win_y);
1160     struct frame *f = NULL;
1161
1162     if (!w) return (0);
1163
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.
1166     */
1167     f = gtk_any_window_to_frame (d, w);
1168
1169     if (!f) return (0);
1170
1171     XSETFRAME (*frame, f);
1172
1173     gdk_window_get_pointer (GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f)),
1174                             &win_x, &win_y, NULL);
1175
1176     *x = win_x;
1177     *y = win_y;
1178
1179     return (1);
1180 }
1181
1182 static void
1183 gtk_cant_notify_wm_error (void)
1184 {
1185   error ("Can't notify window manager of iconification.");
1186 }
1187
1188 /* Raise frame F.  */
1189 static void
1190 gtk_raise_frame_1 (struct frame *f, int force)
1191 {
1192   if (FRAME_VISIBLE_P (f) || force)
1193     {
1194       GdkWindow *emacs_window = GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f));
1195
1196       gdk_window_raise (emacs_window);
1197     }
1198 }
1199
1200 static void
1201 gtk_raise_frame (struct frame *f)
1202 {
1203   gtk_raise_frame_1 (f, 1);
1204 }
1205
1206 /* Lower frame F.  */
1207 static void
1208 gtk_lower_frame (struct frame *f)
1209 {
1210   if (FRAME_VISIBLE_P (f))
1211     {
1212         gdk_window_lower (GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f)));
1213     }
1214 }
1215
1216 /* Change from withdrawn state to mapped state. */
1217 static void
1218 gtk_make_frame_visible (struct frame *f)
1219 {
1220     gtk_widget_show_all (FRAME_GTK_SHELL_WIDGET (f));
1221     gtk_raise_frame_1 (f, 0);
1222 }
1223
1224 /* Change from mapped state to withdrawn state. */
1225 static void
1226 gtk_make_frame_invisible (struct frame *f)
1227 {
1228     gtk_widget_hide (FRAME_GTK_SHELL_WIDGET (f));
1229 }
1230
1231 static int
1232 gtk_frame_visible_p (struct frame *f)
1233 {
1234     GtkWidget *w = FRAME_GTK_SHELL_WIDGET (f);
1235
1236     f->visible = (GTK_OBJECT_FLAGS (w) & GTK_VISIBLE);
1237
1238     return f->visible;
1239 }
1240
1241 static int
1242 gtk_frame_totally_visible_p (struct frame *f)
1243 {
1244   return FRAME_GTK_TOTALLY_VISIBLE_P (f);
1245 }
1246
1247 /* Change window state from mapped to iconified. */
1248 static void
1249 gtk_iconify_frame (struct frame *f)
1250 {
1251   GdkWindow *w = GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f));
1252
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 ();
1258
1259   f->iconified = 1;
1260 }
1261
1262 /* Sets the X focus to frame f. */
1263 static void
1264 gtk_focus_on_frame (struct frame *f)
1265 {
1266   GtkWidget *shell_widget;
1267
1268   assert (FRAME_GTK_P (f));
1269
1270   shell_widget = FRAME_GTK_SHELL_WIDGET (f);
1271   if (!GET_GTK_WIDGET_WINDOW (shell_widget))
1272     return;
1273
1274   gtk_widget_grab_focus (shell_widget);
1275 }
1276
1277 /* Destroy the window of frame S.  */
1278 static void
1279 gtk_delete_frame (struct frame *f)
1280 {
1281     GtkWidget *w = FRAME_GTK_SHELL_WIDGET (f);
1282
1283     gtk_widget_destroy (w);
1284
1285     if (FRAME_GTK_GEOM_FREE_ME_PLEASE (f))
1286         xfree (FRAME_GTK_GEOM_FREE_ME_PLEASE (f));
1287     xfree (f->frame_data);
1288     f->frame_data = 0;
1289 }
1290
1291 static void
1292 gtk_recompute_cell_sizes (struct frame *frm)
1293 {
1294   if (GTK_IS_WINDOW (FRAME_GTK_SHELL_WIDGET (frm)))
1295     {
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;
1301
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;
1306
1307       gtk_window_set_geometry_hints (w, FRAME_GTK_TEXT_WIDGET (frm), &geometry, geometry_mask);
1308     }
1309 }
1310
1311 static void
1312 gtk_update_frame_external_traits (struct frame* frm, Lisp_Object name)
1313 {
1314   Lisp_Object frame = Qnil;
1315
1316   XSETFRAME(frame, frm);
1317
1318   if (EQ (name, Qforeground))
1319    {
1320      Lisp_Object color = FACE_FOREGROUND (Vdefault_face, frame);
1321      GdkColor *fgc;
1322
1323      if (!EQ (color, Vthe_null_color_instance))
1324        {
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. */
1330        }
1331    }
1332   else if (EQ (name, Qbackground))
1333    {
1334      Lisp_Object color = FACE_BACKGROUND (Vdefault_face, frame);
1335      GdkColor *bgc;
1336
1337      if (!EQ (color, Vthe_null_color_instance))
1338        {
1339          bgc = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (color));
1340          if (FRAME_GTK_SHELL_WIDGET (frm)->window)
1341            {
1342              gdk_window_set_background (FRAME_GTK_SHELL_WIDGET (frm)->window, bgc);
1343            }
1344          if (FRAME_GTK_TEXT_WIDGET (frm)->window)
1345            {
1346              gdk_window_set_background (FRAME_GTK_TEXT_WIDGET (frm)->window, bgc);
1347            }
1348        }
1349
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);
1354    }
1355   else if (EQ (name, Qfont))
1356    {
1357      Lisp_Object font = FACE_FONT (Vdefault_face, frame, Vcharset_ascii);
1358
1359      if (!EQ (font, Vthe_null_font_instance))
1360      {
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. */
1365      }
1366    }
1367   else
1368    abort ();
1369
1370 #ifdef HAVE_TOOLBARS
1371   /* Setting the background clears the entire frame area
1372     including the toolbar so we force an immediate redraw of
1373     it. */
1374   if (EQ (name, Qbackground))
1375     MAYBE_DEVMETH (XDEVICE (frm->device), redraw_frame_toolbars, (frm));
1376 #endif /* HAVE_TOOLBARS */
1377
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);
1382 }
1383
1384 \f
1385 /************************************************************************/
1386 /*                            initialization                            */
1387 /************************************************************************/
1388
1389 void
1390 syms_of_frame_gtk (void)
1391 {
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");
1397
1398 #ifdef HAVE_DRAGNDROP
1399   staticpro (&Vcurrent_drag_object);
1400   Vcurrent_drag_object = Qnil;
1401   DEFSUBR (Fgtk_start_drag_internal);
1402 #endif
1403 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
1404   DEFSUBR (Fgtk_window_id);
1405 #endif
1406 }
1407
1408 void
1409 console_type_create_frame_gtk (void)
1410 {
1411   /* frame methods */
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);
1421 #endif
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);
1442 }
1443
1444 void
1445 vars_of_frame_gtk (void)
1446 {
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'.
1452
1453 Note: In many cases, properties of a frame are available as specifiers
1454 instead of through the frame-properties mechanism.
1455
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):
1459
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
1463                                 the frame appear.
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
1484                                 decorations).
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
1488                                 decorations).
1489   border-color                  Color of external border around text area.
1490   cursor-color                  Color of text cursor.
1491
1492 See also `default-frame-plist', which specifies properties which apply
1493 to all frames, not just Gtk frames.
1494 */ );
1495   Vdefault_gtk_frame_plist = Qnil;
1496
1497   gtk_console_methods->device_specific_frame_props = &Vdefault_gtk_frame_plist;
1498 }