(U+5364-itaiji-002): New character.
[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 "elhash.h"
31 #include "console-gtk.h"
32 #include "ui-gtk.h"
33 #include "glyphs-gtk.h"
34 #include "objects-gtk.h"
35 #include "scrollbar-gtk.h"
36
37 #include "gtk-xemacs.h"
38
39 #include "buffer.h"
40 #include "events.h"
41 #include "extents.h"
42 #include "faces.h"
43 #include "frame.h"
44 #include "window.h"
45
46 #ifdef HAVE_GNOME
47 #include <libgnomeui/libgnomeui.h>
48 #endif
49
50 #ifdef HAVE_DRAGNDROP
51 #include "dragdrop.h"
52 #endif
53
54 #define BORDER_WIDTH 0
55 #define INTERNAL_BORDER_WIDTH 0
56
57 #define TRANSIENT_DATA_IDENTIFIER "xemacs::transient_for"
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 which contains the given widget. */
102 struct frame *
103 gtk_widget_to_frame (GtkWidget *w)
104 {
105   struct frame *f = NULL;
106
107   for (; w; w = w->parent)
108     {
109       if ((f = (struct frame *) gtk_object_get_data (GTK_OBJECT (w),
110                                                      GTK_DATA_FRAME_IDENTIFIER)))
111         return (f);
112     }
113
114   return (selected_frame());
115 }
116
117
118 /* Return the Emacs frame-object corresponding to an X window */
119 struct frame *
120 gtk_window_to_frame (struct device *d, GdkWindow *wdesc)
121 {
122   Lisp_Object tail, frame;
123   struct frame *f;
124
125   /* This function was previously written to accept only a window argument
126      (and to loop over all devices looking for a matching window), but
127      that is incorrect because window ID's are not unique across displays. */
128
129   for (tail = DEVICE_FRAME_LIST (d); CONSP (tail); tail = XCDR (tail))
130     {
131       frame = XCAR (tail);
132       if (!FRAMEP (frame))
133         continue;
134       f = XFRAME (frame);
135       if (FRAME_GTK_P (f) && GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f)) == wdesc)
136         return f;
137     }
138   return 0;
139 }
140
141 /* Like gtk_window_to_frame but also compares the window with the widget's
142    windows */
143 struct frame *
144 gtk_any_window_to_frame (struct device *d, GdkWindow *w)
145 {
146     do
147     {
148         Lisp_Object frmcons;
149
150         DEVICE_FRAME_LOOP (frmcons, d)
151             {
152                 struct frame *fr = XFRAME (XCAR (frmcons));
153                 if ((w == GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (fr))) ||
154                     (w == GET_GTK_WIDGET_WINDOW (FRAME_GTK_CONTAINER_WIDGET (fr))) ||
155 #ifdef HAVE_MENUBARS
156                     (w == GET_GTK_WIDGET_WINDOW (FRAME_GTK_MENUBAR_WIDGET (fr))) ||
157 #endif
158                     (w == GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (fr))))
159                 {
160                     return (fr);
161                 }
162             }
163         w = gdk_window_get_parent (w);
164     } while (w);
165
166     return (0);
167 }
168
169 struct frame *
170 gtk_any_widget_or_parent_to_frame (struct device *d, GtkWidget *widget)
171 {
172     return (gtk_any_window_to_frame (d, GET_GTK_WIDGET_WINDOW (widget)));
173 }
174
175 struct device *
176 gtk_any_window_to_device (GdkWindow *w)
177 {
178         struct device *d = NULL;
179         Lisp_Object devcons, concons;
180
181         DEVICE_LOOP_NO_BREAK (devcons, concons)
182                 {
183                         d = XDEVICE (XCAR (devcons));
184                         if (!DEVICE_GTK_P (d)) continue;
185                         if (gtk_any_window_to_frame (d, w))
186                                 return (d);
187                 }
188         return (NULL);
189 }
190
191 struct frame *
192 decode_gtk_frame (Lisp_Object frame)
193 {
194   if (NILP (frame))
195     XSETFRAME (frame, selected_frame ());
196   CHECK_LIVE_FRAME (frame);
197   /* this will also catch dead frames, but putting in the above check
198      results in a more useful error */
199   CHECK_GTK_FRAME (frame);
200   return XFRAME (frame);
201 }
202
203 \f
204 /************************************************************************/
205 /*                      window-manager interactions                     */
206 /************************************************************************/
207 static int
208 gtk_frame_iconified_p (struct frame *f)
209 {
210     return (f->iconified);
211 }
212
213 \f
214 /************************************************************************/
215 /*                          frame properties                            */
216 /************************************************************************/
217
218 static Lisp_Object
219 gtk_frame_property (struct frame *f, Lisp_Object property)
220 {
221   GtkWidget *shell = FRAME_GTK_SHELL_WIDGET (f);
222
223   if (EQ (Qleft, property) || EQ (Qtop, property))
224     {
225       gint x, y;
226       if (!GET_GTK_WIDGET_WINDOW(shell))
227         return Qzero;
228       gdk_window_get_deskrelative_origin (GET_GTK_WIDGET_WINDOW (shell), &x, &y);
229       if (EQ (Qleft, property)) return make_int (x);
230       if (EQ (Qtop,  property)) return make_int (y);
231     }
232   if (EQ (Qshell_widget, property))
233     {
234       return (FRAME_GTK_LISP_WIDGETS (f)[0]);
235     }
236   if (EQ (Qcontainer_widget, property))
237     {
238       return (FRAME_GTK_LISP_WIDGETS (f)[1]);
239     }
240   if (EQ (Qtext_widget, property))
241     {
242       return (FRAME_GTK_LISP_WIDGETS (f)[2]);
243     }
244 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
245   if (EQ (Qwindow_id, property))
246     return Fgtk_window_id (make_frame (f));
247 #endif
248
249   return Qunbound;
250 }
251
252 static int
253 gtk_internal_frame_property_p (struct frame *f, Lisp_Object property)
254 {
255   return EQ (property, Qleft)
256     || EQ (property, Qtop)
257     || EQ (Qshell_widget, property)
258     || EQ (Qcontainer_widget, property)
259     || EQ (Qtext_widget, property)
260     || EQ (property, Qwindow_id)
261     || STRINGP (property);
262 }
263
264 static Lisp_Object
265 gtk_frame_properties (struct frame *f)
266 {
267   Lisp_Object props = Qnil;
268   GtkWidget *shell = FRAME_GTK_SHELL_WIDGET (f);
269   gint x, y;
270
271   props = cons3 (Qshell_widget, FRAME_GTK_LISP_WIDGETS (f)[0], props);
272   props = cons3 (Qcontainer_widget, FRAME_GTK_LISP_WIDGETS (f)[1], props);
273   props = cons3 (Qtext_widget, FRAME_GTK_LISP_WIDGETS (f)[2], props);
274
275 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
276   props = cons3 (Qwindow_id, Fgtk_window_id (make_frame (f)), props);
277 #endif
278
279   if (!GET_GTK_WIDGET_WINDOW (shell))
280     x = y = 0;
281   else
282     gdk_window_get_deskrelative_origin (GET_GTK_WIDGET_WINDOW (shell), &x, &y);
283
284   props = cons3 (Qtop,  make_int (y), props);
285   props = cons3 (Qleft, make_int (x), props);
286
287   return props;
288 }
289
290 \f
291 /* Functions called only from `gtk_set_frame_properties' to set
292    individual properties. */
293
294 static void
295 gtk_set_frame_text_value (struct frame *f, Bufbyte *value,
296                           void (*func) (gpointer, gchar *),
297                           gpointer arg)
298 {
299   gchar *the_text = (gchar *) value;
300
301   /* Programmer fuckup or window is not realized yet. */
302   if (!func || !arg) return;
303
304 #ifdef MULE
305   {
306     Bufbyte *ptr;
307     
308     /* Optimize for common ASCII case */
309     for (ptr = value; *ptr; ptr++)
310       if (!BYTE_ASCII_P (*ptr))
311         {
312           char *tmp;
313           C_STRING_TO_EXTERNAL (value, tmp, Qctext);
314           the_text = tmp;
315           break;
316         }
317   }
318 #endif /* MULE */
319
320   (*func) (arg, (gchar *) the_text);
321 }
322
323 static void
324 gtk_set_title_from_bufbyte (struct frame *f, Bufbyte *name)
325 {
326   if (GTK_IS_WINDOW (FRAME_GTK_SHELL_WIDGET (f)))
327     gtk_set_frame_text_value (f, name,
328                               (void (*)(gpointer, gchar *))
329                               gtk_window_set_title, FRAME_GTK_SHELL_WIDGET (f));
330 }
331
332 static void
333 gtk_set_icon_name_from_bufbyte (struct frame *f, Bufbyte *name)
334 {
335   gtk_set_frame_text_value (f, name,
336                             (void (*)(gpointer, gchar *))
337                             gdk_window_set_icon_name, FRAME_GTK_SHELL_WIDGET (f)->window);
338 }
339
340 /* Set the initial frame size as specified.  This function is used
341    when the frame's widgets have not yet been realized.
342 */
343 static void
344 gtk_set_initial_frame_size (struct frame *f, int x, int y,
345                             unsigned int w, unsigned int h)
346 {
347   GtkWidget *shell = FRAME_GTK_SHELL_WIDGET (f);
348   GdkGeometry geometry;
349   GdkWindowHints geometry_mask = 0x00;
350
351   if (GTK_IS_WINDOW (shell))
352     {
353       /* Deal with the cell size */
354       default_face_height_and_width (make_frame (f), &geometry.height_inc, &geometry.width_inc);
355       geometry_mask |= GDK_HINT_RESIZE_INC;
356
357       gtk_window_set_geometry_hints (GTK_WINDOW (shell),
358                                      FRAME_GTK_TEXT_WIDGET (f), &geometry, geometry_mask);
359       gdk_window_set_hints (GET_GTK_WIDGET_WINDOW (shell), x, y, 0, 0, 0, 0, GDK_HINT_POS);
360       gtk_window_set_policy (GTK_WINDOW (shell), TRUE, TRUE, FALSE);
361     }
362
363   FRAME_HEIGHT (f) = h;
364   FRAME_WIDTH (f) = w;
365
366   change_frame_size (f, h, w, 0);
367   {
368     GtkRequisition req;
369  
370     gtk_widget_size_request (FRAME_GTK_SHELL_WIDGET (f), &req);
371     gtk_widget_set_usize (FRAME_GTK_SHELL_WIDGET (f), req.width, req.height);
372   }
373 }
374
375 /* Report that a frame property of frame S is being set or changed.
376    If the property is not specially recognized, do nothing.
377  */
378
379 static void
380 gtk_set_frame_properties (struct frame *f, Lisp_Object plist)
381 {
382   gint x, y;
383   gint width = 0, height = 0;
384   gboolean width_specified_p = FALSE;
385   gboolean height_specified_p = FALSE;
386   gboolean x_position_specified_p = FALSE;
387   gboolean y_position_specified_p = FALSE;
388   Lisp_Object tail;
389
390   for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
391     {
392       Lisp_Object prop = Fcar (tail);
393       Lisp_Object val = Fcar (Fcdr (tail));
394
395       if (SYMBOLP (prop))
396         {
397           if (EQ (prop, Qfont))
398           {
399               /* If the value is not a string we silently ignore it. */
400               if (STRINGP (val))
401               {
402                   Lisp_Object frm, font_spec;
403
404                   XSETFRAME (frm, f);
405                   font_spec = Fget (Fget_face (Qdefault), Qfont, Qnil);
406
407                   Fadd_spec_to_specifier (font_spec, val, frm, Qnil, Qnil);
408                   update_frame_face_values (f);
409               }
410               continue;
411           }
412           else if (EQ (prop, Qwidth))
413           {
414               CHECK_INT (val);
415               width = XINT (val);
416               width_specified_p = TRUE;
417               continue;
418           }
419           else if (EQ (prop, Qheight))
420           {
421               CHECK_INT (val);
422               height = XINT (val);
423               height_specified_p = TRUE;
424               continue;
425           }
426           /* Further kludge the x/y. */
427           else if (EQ (prop, Qx))
428           {
429               CHECK_INT (val);
430               x = (gint) XINT (val);
431               x_position_specified_p = TRUE;
432               continue;
433           }
434           else if (EQ (prop, Qy))
435           {
436               CHECK_INT (val);
437               y = (gint) XINT (val);
438               y_position_specified_p = TRUE;
439               continue;
440           }
441         }
442     }
443
444   /* Kludge kludge kludge.   We need to deal with the size and position
445    specially. */
446   {
447     int size_specified_p = width_specified_p || height_specified_p;
448     int position_specified_p = x_position_specified_p || y_position_specified_p;
449
450     if (!width_specified_p)
451       width = 80;
452     if (!height_specified_p)
453       height = 30;
454
455     /* Kludge kludge kludge kludge. */
456     if (position_specified_p &&
457         (!x_position_specified_p || !y_position_specified_p))
458       {
459         gint dummy;
460         GtkWidget *shell = FRAME_GTK_SHELL_WIDGET (f);
461         gdk_window_get_deskrelative_origin (GET_GTK_WIDGET_WINDOW (shell),
462                                             (x_position_specified_p ? &dummy : &x),
463                                             (y_position_specified_p ? &dummy : &y));
464       }
465
466     if (!f->init_finished)
467       {
468         if (size_specified_p || position_specified_p)
469           gtk_set_initial_frame_size (f, x, y, width, height);
470       }
471     else
472       {
473         if (size_specified_p)
474           {
475             Lisp_Object frame;
476             XSETFRAME (frame, f);
477             Fset_frame_size (frame, make_int (width), make_int (height), Qnil);
478           }
479         if (position_specified_p)
480           {
481             Lisp_Object frame;
482             XSETFRAME (frame, f);
483             Fset_frame_position (frame, make_int (x), make_int (y));
484           }
485       }
486   }
487 }
488
489 \f
490 /************************************************************************/
491 /*                              widget creation                         */
492 /************************************************************************/
493 /* Figure out what size the shell widget should initially be,
494    and set it.  Should be called after the default font has been
495    determined but before the widget has been realized. */
496
497 extern Lisp_Object Vgtk_initial_geometry;
498
499 #ifndef HAVE_GNOME
500 static int
501 get_number (const char **geometry)
502 {
503   int value = 0;
504   int mult  = 1;
505         
506   if (**geometry == '-'){
507     mult = -1;
508     (*geometry)++;
509   }
510   while (**geometry && isdigit (**geometry)){
511     value = value * 10 + (**geometry - '0');
512     (*geometry)++;
513   }
514   return value * mult;
515 }
516
517 /*
518  */
519
520 /**
521  * gnome_parse_geometry
522  * @geometry: geometry string to be parsed
523  * @xpos: X position geometry component
524  * @ypos: Y position geometry component
525  * @width: pixel width geometry component
526  * @height: pixel height geometry component
527  *
528  * Description:
529  * Parses the geometry string passed in @geometry, and fills
530  * @xpos, @ypos, @width, and @height with
531  * the corresponding values upon completion of the parse.
532  * If the parse fails, it should be assumed that @xpos, @ypos, @width,
533  * and @height contain undefined values.
534  *
535  * Returns:
536  * %TRUE if the geometry was successfully parsed, %FALSE otherwise.
537  **/
538
539 static gboolean
540 gnome_parse_geometry (const gchar *geometry, gint *xpos, 
541                       gint *ypos, gint *width, gint *height)
542 {
543   int subtract;
544
545   g_return_val_if_fail (xpos != NULL, FALSE);
546   g_return_val_if_fail (ypos != NULL, FALSE);
547   g_return_val_if_fail (width != NULL, FALSE);
548   g_return_val_if_fail (height != NULL, FALSE);
549         
550   *xpos = *ypos = *width = *height = -1;
551
552   if (!geometry)
553     return FALSE;
554
555   if (*geometry == '=')
556     geometry++;
557   if (!*geometry)
558     return FALSE;
559   if (isdigit (*geometry))
560     *width = get_number (&geometry);
561   if (!*geometry)
562     return TRUE;
563   if (*geometry == 'x' || *geometry == 'X'){
564     geometry++;
565     *height = get_number (&geometry);
566   }
567   if (!*geometry)
568     return 1;
569   if (*geometry == '+'){
570     subtract = 0;
571     geometry++;
572   } else if (*geometry == '-'){
573     subtract = gdk_screen_width ();
574     geometry++;
575   } else
576     return FALSE;
577   *xpos = get_number (&geometry);
578   if (subtract)
579     *xpos = subtract - *xpos;
580   if (!*geometry)
581     return TRUE;
582   if (*geometry == '+'){
583     subtract = 0;
584     geometry++;
585   } else if (*geometry == '-'){
586     subtract = gdk_screen_height ();
587     geometry++;
588   } else
589     return FALSE;
590   *ypos = get_number (&geometry);
591   if (subtract)
592     *ypos = subtract - *ypos;
593   return TRUE;
594 }
595 #endif
596
597 static void
598 gtk_initialize_frame_size (struct frame *f)
599 {
600   gint x = 10, y = 10, w = 80, h = 30;
601
602   if (STRINGP (Vgtk_initial_geometry))
603     {
604       if (!gnome_parse_geometry (XSTRING_DATA (Vgtk_initial_geometry), &x,&y,&w,&h))
605         {
606           x = y = 10;
607           w = 80;
608           h = 30;
609         }
610     }
611
612   /* set the position of the frame's root window now.  When the
613      frame was created, the position was initialized to (0,0). */
614   {
615     struct window *win = XWINDOW (f->root_window);
616
617     WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f);
618     WINDOW_TOP (win) = FRAME_TOP_BORDER_END (f);
619
620     if (!NILP (f->minibuffer_window))
621       {
622         win = XWINDOW (f->minibuffer_window);
623         WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f);
624       }
625   }
626
627   gtk_set_initial_frame_size (f, x, y, w, h);
628 }
629
630 static gboolean
631 resize_event_cb (GtkWidget *w, GtkAllocation *allocation, gpointer user_data)
632 {
633   struct frame *f = (struct frame *) user_data;
634
635   f->pixwidth = allocation->width;
636   f->pixheight = allocation->height;
637
638   if (FRAME_GTK_TEXT_WIDGET (f)->window)
639     {
640       Lisp_Object frame;
641       XSETFRAME (frame, f);
642       Fredraw_frame (frame, Qt);
643     }
644
645   return (FALSE);
646 }
647
648 static gboolean
649 delete_event_cb (GtkWidget *w, GdkEvent *ev, gpointer user_data)
650 {
651     struct frame *f = (struct frame *) user_data;
652     Lisp_Object frame;
653
654     XSETFRAME (frame, f);
655     enqueue_misc_user_event (frame, Qeval, list3 (Qdelete_frame, frame, Qt));
656
657     /* See if tickling the event queue helps us with our delays when
658        clicking 'close' */
659     signal_fake_event ();
660
661     return (TRUE);
662 }
663
664 extern gboolean emacs_shell_event_handler (GtkWidget *wid, GdkEvent *event, gpointer closure);
665 extern Lisp_Object build_gtk_object (GtkObject *obj);
666
667 #ifndef GNOME_IS_APP
668 #define GNOME_IS_APP(x) 0
669 #define gnome_app_set_contents(x,y) 0
670 #endif
671
672 static void
673 cleanup_deleted_frame (gpointer data)
674 {
675   struct frame *f = (struct frame *) data;
676   Lisp_Object frame;
677
678   XSETFRAME (frame, f);
679   Fdelete_frame (frame, Qt);
680 }
681
682 #ifdef HAVE_DRAGNDROP
683 extern void
684 dragndrop_data_received (GtkWidget          *widget,
685                          GdkDragContext     *context,
686                          gint                x,
687                          gint                y,
688                          GtkSelectionData   *data,
689                          guint               info,
690                          guint               time);
691
692 extern gboolean
693 dragndrop_dropped (GtkWidget *widget,
694                    GdkDragContext *drag_context,
695                    gint x,
696                    gint y,
697                    guint time,
698                    gpointer user_data);
699
700 Lisp_Object Vcurrent_drag_object;
701
702 #define DRAG_SELECTION_DATA_ERROR "Error converting drag data to external format"
703 static void
704 dragndrop_get_drag (GtkWidget *widget,
705                     GdkDragContext *drag_context,
706                     GtkSelectionData *data,
707                     guint info,
708                     guint time,
709                     gpointer user_data)
710 {
711   gtk_selection_data_set (data, GDK_SELECTION_TYPE_STRING, 8,
712                           DRAG_SELECTION_DATA_ERROR,
713                           strlen (DRAG_SELECTION_DATA_ERROR));
714
715   switch (info)
716     {
717     case TARGET_TYPE_STRING:
718       {
719         Lisp_Object string = Vcurrent_drag_object;
720         
721         if (!STRINGP (Vcurrent_drag_object))
722           {
723             string = Fprin1_to_string (string, Qnil);
724             /* Convert to a string */
725           }
726         
727         gtk_selection_data_set (data, GDK_SELECTION_TYPE_STRING,
728                                 8, XSTRING_DATA (string), XSTRING_LENGTH (string));
729       }
730       break;
731     case TARGET_TYPE_URI_LIST:
732       break;
733     default:
734       break;
735     }
736   Vcurrent_drag_object = Qnil;
737 }
738
739 DEFUN ("gtk-start-drag-internal", Fgtk_start_drag_internal, 2, 3, 0, /*
740 Start a GTK drag from a buffer.
741 First arg is the event that started the drag,
742 second arg should be some string, and the third
743 is the type of the data (this should be a MIME type as a string (ie: text/plain)).
744 The type defaults to text/plain.
745 */
746        (event, data, dtyp))
747 {
748   if (EVENTP(event))
749     {
750       struct frame *f = decode_gtk_frame (Fselected_frame (Qnil));
751       GtkWidget *wid = FRAME_GTK_TEXT_WIDGET (f);
752       struct Lisp_Event *lisp_event = XEVENT(event);
753       GdkAtom dnd_typ;
754       GtkTargetList *tl = gtk_target_list_new (dnd_target_table, dnd_n_targets);
755
756       /* only drag if this is really a press */
757       if (EVENT_TYPE(lisp_event) != button_press_event)
758         return Qnil;
759
760       /* get the desired type */
761       if (!NILP (dtyp) && STRINGP (dtyp))
762         dnd_typ = gdk_atom_intern (XSTRING_DATA (dtyp), FALSE);
763
764       gtk_drag_begin (wid, tl, GDK_ACTION_COPY, lisp_event->event.button.button, NULL);
765
766       Vcurrent_drag_object = data;
767
768       gtk_target_list_unref (tl);
769     }
770   return Qnil;
771 }
772 #endif
773
774 /* Creates the widgets for a frame.
775    lisp_window_id is a Lisp description of an X window or Xt
776    widget to parse.
777
778    This function does not map the windows.  (That is
779    done by gtk_popup_frame().)
780 */
781 static void
782 gtk_create_widgets (struct frame *f, Lisp_Object lisp_window_id, Lisp_Object parent)
783 {
784   const char *name;
785   GtkWidget *text, *container, *shell;
786   gboolean embedded_p = !NILP (lisp_window_id);
787 #ifdef HAVE_MENUBARS
788   int menubar_visible;
789 #endif
790
791   if (STRINGP (f->name))
792     TO_EXTERNAL_FORMAT (LISP_STRING, f->name, C_STRING_ALLOCA, name, Qctext);
793   else
794     name = "emacs";
795
796   FRAME_GTK_TOP_LEVEL_FRAME_P (f) = 1;
797
798   if (embedded_p)
799     {
800       CHECK_GTK_OBJECT (lisp_window_id);
801
802       if (!GTK_IS_CONTAINER (XGTK_OBJECT (lisp_window_id)->object))
803         {
804           signal_simple_error ("Window ID must be a GtkContainer subclass", lisp_window_id);
805         }
806
807       shell = gtk_vbox_new (FALSE, 0);
808
809       gtk_object_weakref (GTK_OBJECT (shell), cleanup_deleted_frame, f);
810       gtk_container_add (GTK_CONTAINER (XGTK_OBJECT (lisp_window_id)->object), shell);
811     }
812   else
813     {
814 #ifdef HAVE_GNOME
815       shell = GTK_WIDGET (gnome_app_new ("XEmacs", "XEmacs/GNOME"));
816 #else
817       shell = GTK_WIDGET (gtk_window_new (GTK_WINDOW_TOPLEVEL));
818 #endif
819     }
820
821   if (!NILP (parent))
822   {
823       /* If this is a transient window, keep the parent info around */
824       GtkWidget *parentwid = FRAME_GTK_SHELL_WIDGET (XFRAME (parent));
825       gtk_object_set_data (GTK_OBJECT (shell), TRANSIENT_DATA_IDENTIFIER, parentwid);
826       gtk_window_set_transient_for (GTK_WINDOW (shell), GTK_WINDOW (parentwid));
827   }
828
829   gtk_container_set_border_width (GTK_CONTAINER (shell), 0);
830
831   gtk_object_set_data (GTK_OBJECT (shell), GTK_DATA_FRAME_IDENTIFIER, f);
832
833   FRAME_GTK_SHELL_WIDGET (f) = shell;
834
835   text = GTK_WIDGET (gtk_xemacs_new (f));
836
837   if (!GNOME_IS_APP (shell))
838     container = GTK_WIDGET (gtk_vbox_new (FALSE, INTERNAL_BORDER_WIDTH));
839   else
840     container = shell;
841
842   FRAME_GTK_CONTAINER_WIDGET (f) = container;
843   FRAME_GTK_TEXT_WIDGET (f) = text;
844
845 #ifdef HAVE_DRAGNDROP
846   gtk_drag_dest_set (text, GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT,
847                      dnd_target_table, dnd_n_targets,
848                      GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_ASK);
849   gtk_signal_connect (GTK_OBJECT (text), "drag_drop",
850                       GTK_SIGNAL_FUNC (dragndrop_dropped), text);
851   gtk_signal_connect (GTK_OBJECT (text), "drag_data_received",
852                       GTK_SIGNAL_FUNC (dragndrop_data_received), text);
853   gtk_signal_connect (GTK_OBJECT (text), "drag_data_get",
854                       GTK_SIGNAL_FUNC (dragndrop_get_drag), NULL);
855 #endif
856
857 #ifdef HAVE_MENUBARS
858   /* Create the initial menubar widget. */
859   menubar_visible = gtk_initialize_frame_menubar (f);
860
861   if (menubar_visible)
862     {
863       gtk_widget_show_all (FRAME_GTK_MENUBAR_WIDGET (f));
864     }
865 #endif /* HAVE_MENUBARS */
866
867 #ifdef HAVE_GNOME
868   if (GNOME_IS_APP (shell))
869     gnome_app_set_contents (GNOME_APP (shell), text);
870   else
871 #endif
872     /* Now comes the drawing area, which should fill the rest of the
873     ** frame completely.
874     */
875     gtk_box_pack_end (GTK_BOX (container), text, TRUE, TRUE, 0);
876
877   /* Connect main event handler */
878   gtk_signal_connect (GTK_OBJECT (shell), "delete-event", GTK_SIGNAL_FUNC (delete_event_cb), f);
879
880   {
881     static char *events_to_frob[] = { "focus-in-event",
882                                       "focus-out-event",
883                                       "enter-notify-event",
884                                       "leave-notify-event",
885                                       "map-event",
886                                       "unmap-event",
887                                       "property-notify-event",
888                                       "selection-clear-event",
889                                       "selection-request-event",
890                                       "selection-notify-event",
891                                       "client-event",
892                                       /* "configure-event", */
893                                       "visibility-notify-event",
894                                       NULL };
895     int i;
896
897     for (i = 0; events_to_frob[i]; i++)
898       {
899         gtk_signal_connect (GTK_OBJECT (shell), events_to_frob[i],
900                             GTK_SIGNAL_FUNC (emacs_shell_event_handler), f);
901       }
902   }
903
904   gtk_signal_connect (GTK_OBJECT (shell), "size-allocate", GTK_SIGNAL_FUNC (resize_event_cb), f);
905
906   /* This might be safe to call now... */
907   /* gtk_signal_connect (GTK_OBJECT (shell), "event", GTK_SIGNAL_FUNC (emacs_shell_event_handler), f); */
908
909   /* Let's make sure we get all the events we can */
910   gtk_widget_set_events (text, GDK_ALL_EVENTS_MASK);
911
912   if (shell != container)
913     gtk_container_add (GTK_CONTAINER (shell), container);
914
915   gtk_widget_set_name (shell, "XEmacs::shell");
916   gtk_widget_set_name (container, "XEmacs::container");
917   gtk_widget_set_name (text, "XEmacs::text");
918
919   FRAME_GTK_LISP_WIDGETS(f)[0] = build_gtk_object (GTK_OBJECT (shell));
920   FRAME_GTK_LISP_WIDGETS(f)[1] = build_gtk_object (GTK_OBJECT (container));
921   FRAME_GTK_LISP_WIDGETS(f)[2] = build_gtk_object (GTK_OBJECT (text));
922
923   gtk_widget_realize (shell);
924 }
925
926 /* create the windows for the specified frame and display them.
927    Note that the widgets have already been created, and any
928    necessary geometry calculations have already been done. */
929 static void
930 gtk_popup_frame (struct frame *f)
931 {
932   /* */
933
934   if (gtk_object_get_data (GTK_OBJECT (FRAME_GTK_SHELL_WIDGET (f)), UNMAPPED_DATA_IDENTIFIER))
935     {
936       FRAME_GTK_TOTALLY_VISIBLE_P (f) = 0;
937       f->visible = 0;
938       gtk_widget_realize (FRAME_GTK_SHELL_WIDGET (f));
939       gtk_widget_realize (FRAME_GTK_TEXT_WIDGET (f));
940       gtk_widget_hide_all (FRAME_GTK_SHELL_WIDGET (f));
941     }
942   else
943     {
944       gtk_widget_show_all (FRAME_GTK_SHELL_WIDGET (f));
945     }
946 }
947
948 static void
949 allocate_gtk_frame_struct (struct frame *f)
950 {
951   /* zero out all slots. */
952   f->frame_data = xnew_and_zero (struct gtk_frame);
953
954   /* yeah, except the lisp ones */
955   FRAME_GTK_ICON_PIXMAP (f) = Qnil;
956   FRAME_GTK_ICON_PIXMAP_MASK (f) = Qnil;
957
958   /*
959     Hashtables of callback data for glyphs on the frame.  Make them EQ because
960     we only use ints as keys.  Otherwise we run into stickiness in redisplay
961     because internal_equal() can QUIT.  See enter_redisplay_critical_section().
962   */
963   FRAME_GTK_WIDGET_INSTANCE_HASH_TABLE (f) =
964     make_lisp_hash_table (50, HASH_TABLE_VALUE_WEAK, HASH_TABLE_EQ);
965   FRAME_GTK_WIDGET_CALLBACK_HASH_TABLE (f) =
966     make_lisp_hash_table (50, HASH_TABLE_VALUE_WEAK, HASH_TABLE_EQ);
967   FRAME_GTK_WIDGET_CALLBACK_EX_HASH_TABLE (f) =
968     make_lisp_hash_table (50, HASH_TABLE_VALUE_WEAK, HASH_TABLE_EQ);
969 }
970
971 \f
972 /************************************************************************/
973 /*                              Lisp functions                          */
974 /************************************************************************/
975
976 static void
977 gtk_init_frame_1 (struct frame *f, Lisp_Object props)
978 {
979   /* This function can GC */
980   Lisp_Object initially_unmapped;
981   Lisp_Object device = FRAME_DEVICE (f);
982   Lisp_Object lisp_window_id = Fplist_get (props, Qwindow_id, Qnil);
983   Lisp_Object popup = Fplist_get (props, Qpopup, Qnil);
984
985   if (!NILP (popup))
986     {
987       if (EQ (popup, Qt))
988         popup = Fselected_frame (device);
989       CHECK_LIVE_FRAME (popup);
990       if (!EQ (device, FRAME_DEVICE (XFRAME (popup))))
991         signal_simple_error_2 ("Parent must be on same device as frame",
992                                device, popup);
993     }
994
995   initially_unmapped = Fplist_get (props, Qinitially_unmapped, Qnil);
996
997   /*
998    * Previously we set this only if NILP (DEVICE_SELECTED_FRAME (d))
999    * to make sure that messages were displayed as soon as possible
1000    * if we're creating the first frame on a device.  But it is
1001    * better to just set this all the time, so that when a new frame
1002    * is created that covers the selected frame, echo area status
1003    * messages can still be seen.  f->visible is reset later if the
1004    * initially-unmapped property is found to be non-nil in the
1005    * frame properties.
1006    */
1007   f->visible = 1;
1008
1009   allocate_gtk_frame_struct (f);
1010   gtk_create_widgets (f, lisp_window_id, popup);
1011
1012   if (!NILP (initially_unmapped))
1013     {
1014       gtk_object_set_data (GTK_OBJECT (FRAME_GTK_SHELL_WIDGET (f)),
1015                            UNMAPPED_DATA_IDENTIFIER, (gpointer) 1);
1016     }
1017 }
1018
1019 static void
1020 gtk_init_frame_2 (struct frame *f, Lisp_Object props)
1021 {
1022   /* Set up the values of the widget/frame.  A case could be made for putting
1023      this inside of the widget's initialize method. */
1024
1025   update_frame_face_values (f);
1026   gtk_initialize_frame_size (f);
1027   /* Kyle:
1028    *   update_frame_title() can't be done here, because some of the
1029    *   modeline specs depend on the frame's device having a selected
1030    *   frame, and that may not have been set up yet.  The redisplay
1031    *   will update the frame title anyway, so nothing is lost.
1032    * JV:
1033    *   It turns out it gives problems with FVWMs name based mapping.
1034    *   We'll just  need to be carefull in the modeline specs.
1035    */
1036   update_frame_title (f); 
1037 }
1038
1039 static void
1040 gtk_init_frame_3 (struct frame *f)
1041 {
1042   /* Pop up the frame. */
1043   gtk_popup_frame (f);
1044 }
1045
1046 static void
1047 gtk_mark_frame (struct frame *f)
1048 {
1049   mark_object (FRAME_GTK_ICON_PIXMAP (f));
1050   mark_object (FRAME_GTK_ICON_PIXMAP_MASK (f));
1051   mark_object (FRAME_GTK_LISP_WIDGETS (f)[0]);
1052   mark_object (FRAME_GTK_LISP_WIDGETS (f)[1]);
1053   mark_object (FRAME_GTK_LISP_WIDGETS (f)[2]);
1054   mark_object (FRAME_GTK_WIDGET_INSTANCE_HASH_TABLE (f));
1055   mark_object (FRAME_GTK_WIDGET_CALLBACK_HASH_TABLE (f));
1056   mark_object (FRAME_GTK_WIDGET_CALLBACK_EX_HASH_TABLE (f));
1057 }
1058
1059 static void
1060 gtk_set_frame_icon (struct frame *f)
1061 {
1062   GdkPixmap *gtk_pixmap = NULL, *gtk_mask = NULL;
1063
1064   if (IMAGE_INSTANCEP (f->icon)
1065       && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (f->icon)))
1066     {
1067       gtk_pixmap = XIMAGE_INSTANCE_GTK_PIXMAP (f->icon);
1068       gtk_mask = XIMAGE_INSTANCE_GTK_MASK (f->icon);
1069     }
1070   else
1071     {
1072       gtk_pixmap = 0;
1073       gtk_mask = 0;
1074     }
1075
1076   gdk_window_set_icon (GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f)), NULL, gtk_pixmap, gtk_mask);
1077 }
1078
1079 static void
1080 gtk_set_frame_pointer (struct frame *f)
1081 {
1082   GtkWidget *w = FRAME_GTK_TEXT_WIDGET (f);
1083   GdkCursor *c = XIMAGE_INSTANCE_GTK_CURSOR (f->pointer);
1084
1085   if (POINTER_IMAGE_INSTANCEP (f->pointer))
1086     {
1087       gdk_window_set_cursor (GET_GTK_WIDGET_WINDOW (w), c);
1088       gdk_flush ();
1089     }
1090   else
1091     {
1092       /* ABORT()? */
1093       stderr_out ("POINTER_IMAGE_INSTANCEP (f->pointer) failed!\n");
1094     }
1095 }
1096
1097 static Lisp_Object
1098 gtk_get_frame_parent (struct frame *f)
1099 {
1100     GtkWidget *parentwid = gtk_object_get_data (GTK_OBJECT (FRAME_GTK_SHELL_WIDGET (f)),
1101                                                 TRANSIENT_DATA_IDENTIFIER);
1102
1103     /* find the frame whose wid is parentwid */
1104     if (parentwid)
1105     {
1106         Lisp_Object frmcons;
1107         DEVICE_FRAME_LOOP (frmcons, XDEVICE (FRAME_DEVICE (f)))
1108             {
1109                 Lisp_Object frame = XCAR (frmcons);
1110                 if (FRAME_GTK_SHELL_WIDGET (XFRAME (frame)) == parentwid)
1111                     return frame;
1112             }
1113     }
1114     return Qnil;
1115 }
1116
1117 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
1118 DEFUN ("gtk-window-id", Fgtk_window_id, 0, 1, 0, /*
1119 Get the ID of the Gtk window.
1120 This gives us a chance to manipulate the Emacs window from within a
1121 different program.  Since the ID is an unsigned long, we return it as
1122 a string.
1123 */
1124        (frame))
1125 {
1126   char str[255];
1127   struct frame *f = decode_gtk_frame (frame);
1128
1129   /* Arrrrggghhh... this defeats the whole purpose of using Gdk... do we really need this? */
1130   sprintf (str, "%lu", GDK_WINDOW_XWINDOW( GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f))));
1131   return build_string (str);
1132 }
1133 #endif
1134
1135 \f
1136 /************************************************************************/
1137 /*                      manipulating the X window                       */
1138 /************************************************************************/
1139
1140 static void
1141 gtk_set_frame_position (struct frame *f, int xoff, int yoff)
1142 {
1143     gtk_widget_set_uposition (FRAME_GTK_SHELL_WIDGET (f), xoff, yoff);
1144 }
1145
1146 /* Call this to change the size of frame S's x-window. */
1147
1148 static void
1149 gtk_set_frame_size (struct frame *f, int cols, int rows)
1150 {
1151   GtkWidget *shell = FRAME_GTK_SHELL_WIDGET (f);
1152   GdkGeometry geometry;
1153   GdkWindowHints geometry_mask = 0x00;
1154
1155   if (GTK_IS_WINDOW (shell))
1156     {
1157       /* Update the cell size */
1158       default_face_height_and_width (make_frame (f), &geometry.height_inc, &geometry.width_inc);
1159       geometry_mask |= GDK_HINT_RESIZE_INC;
1160
1161       gtk_window_set_geometry_hints (GTK_WINDOW (shell),
1162                                      FRAME_GTK_TEXT_WIDGET (f), &geometry, geometry_mask);
1163     }
1164
1165   change_frame_size (f, rows, cols, 0);
1166
1167   {
1168     GtkRequisition req;
1169
1170     gtk_widget_size_request (FRAME_GTK_SHELL_WIDGET (f), &req);
1171     gtk_widget_set_usize (FRAME_GTK_SHELL_WIDGET (f), req.width, req.height);
1172   }
1173 }
1174
1175 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
1176 /* There is NO equivalent to XWarpPointer under Gtk */
1177 static void
1178 gtk_set_mouse_position (struct window *w, int x, int y)
1179 {
1180   struct frame *f = XFRAME (w->frame);
1181   Display *display = GDK_DISPLAY ();
1182   XWarpPointer (display, None,
1183                 GDK_WINDOW_XWINDOW (GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f))),
1184                 0, 0, 0, 0, w->pixel_left + x, w->pixel_top + y);
1185 }
1186 #endif /* STUPID_X_SPECIFIC_GTK_STUFF */
1187
1188 static int
1189 gtk_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y)
1190 {
1191     /* Returns the pixel position within the editor text widget */
1192     gint win_x, win_y;
1193     GdkWindow *w = gdk_window_at_pointer (&win_x, &win_y);
1194     struct frame *f = NULL;
1195
1196     if (!w) return (0);
1197
1198     /* At this point, w is the innermost GdkWindow containing the
1199     ** pointer and win_x and win_y are the coordinates of that window.
1200     */
1201     f = gtk_any_window_to_frame (d, w);
1202
1203     if (!f) return (0);
1204
1205     XSETFRAME (*frame, f);
1206
1207     gdk_window_get_pointer (GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f)),
1208                             &win_x, &win_y, NULL);
1209
1210     *x = win_x;
1211     *y = win_y;
1212
1213     return (1);
1214 }
1215
1216 static void
1217 gtk_cant_notify_wm_error (void)
1218 {
1219   error ("Can't notify window manager of iconification.");
1220 }
1221
1222 /* Raise frame F.  */
1223 static void
1224 gtk_raise_frame_1 (struct frame *f, int force)
1225 {
1226   if (FRAME_VISIBLE_P (f) || force)
1227     {
1228       GdkWindow *emacs_window = GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f));
1229
1230       gdk_window_raise (emacs_window);
1231     }
1232 }
1233
1234 static void
1235 gtk_raise_frame (struct frame *f)
1236 {
1237   gtk_raise_frame_1 (f, 1);
1238 }
1239
1240 /* Lower frame F.  */
1241 static void
1242 gtk_lower_frame (struct frame *f)
1243 {
1244   if (FRAME_VISIBLE_P (f))
1245     {
1246         gdk_window_lower (GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f)));
1247     }
1248 }
1249
1250 /* Change from withdrawn state to mapped state. */
1251 static void
1252 gtk_make_frame_visible (struct frame *f)
1253 {
1254     gtk_widget_map (FRAME_GTK_SHELL_WIDGET (f));
1255     gtk_raise_frame_1 (f, 0);
1256 }
1257
1258 /* Change from mapped state to withdrawn state. */
1259 static void
1260 gtk_make_frame_invisible (struct frame *f)
1261 {
1262     gtk_widget_unmap(FRAME_GTK_SHELL_WIDGET (f));
1263 }
1264
1265 static int
1266 gtk_frame_visible_p (struct frame *f)
1267 {
1268     GtkWidget *w = FRAME_GTK_SHELL_WIDGET (f);
1269
1270     f->visible = (GTK_OBJECT_FLAGS (w) & GTK_VISIBLE);
1271
1272     return f->visible;
1273 }
1274
1275 static int
1276 gtk_frame_totally_visible_p (struct frame *f)
1277 {
1278   return FRAME_GTK_TOTALLY_VISIBLE_P (f);
1279 }
1280
1281 /* Change window state from mapped to iconified. */
1282 static void
1283 gtk_iconify_frame (struct frame *f)
1284 {
1285   GdkWindow *w = GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f));
1286
1287   /* There is no equivalent to XIconifyWindow in Gtk/Gdk. */
1288   if (!XIconifyWindow (GDK_WINDOW_XDISPLAY (w),
1289                        GDK_WINDOW_XWINDOW (w),
1290                        DefaultScreen (GDK_WINDOW_XDISPLAY (w))))
1291     gtk_cant_notify_wm_error ();
1292
1293   f->iconified = 1;
1294 }
1295
1296 /* Sets the X focus to frame f. */
1297 static void
1298 gtk_focus_on_frame (struct frame *f)
1299 {
1300   GtkWidget *shell_widget;
1301
1302   assert (FRAME_GTK_P (f));
1303
1304   shell_widget = FRAME_GTK_SHELL_WIDGET (f);
1305   if (!GET_GTK_WIDGET_WINDOW (shell_widget))
1306     return;
1307
1308   gtk_widget_grab_focus (shell_widget);
1309 }
1310
1311 /* Destroy the window of frame S.  */
1312 static void
1313 gtk_delete_frame (struct frame *f)
1314 {
1315     GtkWidget *w = FRAME_GTK_SHELL_WIDGET (f);
1316
1317     gtk_widget_destroy (w);
1318
1319     if (FRAME_GTK_GEOM_FREE_ME_PLEASE (f))
1320         xfree (FRAME_GTK_GEOM_FREE_ME_PLEASE (f));
1321     xfree (f->frame_data);
1322     f->frame_data = 0;
1323 }
1324
1325 static void
1326 gtk_recompute_cell_sizes (struct frame *frm)
1327 {
1328   if (GTK_IS_WINDOW (FRAME_GTK_SHELL_WIDGET (frm)))
1329     {
1330       GtkWindow *w = GTK_WINDOW (FRAME_GTK_SHELL_WIDGET (frm));
1331       GdkGeometry geometry;
1332       GdkWindowHints geometry_mask;
1333       gint width_inc = 10;
1334       gint height_inc = 10;
1335
1336       default_face_height_and_width (make_frame (frm), &height_inc, &width_inc);
1337       geometry_mask = GDK_HINT_RESIZE_INC;
1338       geometry.width_inc = width_inc;
1339       geometry.height_inc = height_inc;
1340
1341       gtk_window_set_geometry_hints (w, FRAME_GTK_TEXT_WIDGET (frm), &geometry, geometry_mask);
1342     }
1343 }
1344
1345 static void
1346 gtk_update_frame_external_traits (struct frame* frm, Lisp_Object name)
1347 {
1348   Lisp_Object frame = Qnil;
1349
1350   XSETFRAME(frame, frm);
1351
1352   if (EQ (name, Qforeground))
1353    {
1354      Lisp_Object color = FACE_FOREGROUND (Vdefault_face, frame);
1355      GdkColor *fgc;
1356
1357      if (!EQ (color, Vthe_null_color_instance))
1358        {
1359          fgc = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (color));
1360          /* #### BILL!!! The X code set the XtNforeground property of
1361             the text widget here.  Why did they bother?  All that type
1362             of thing is done down in the guts of the redisplay code,
1363             not in the Emacs* widgets. */
1364        }
1365    }
1366   else if (EQ (name, Qbackground))
1367    {
1368      Lisp_Object color = FACE_BACKGROUND (Vdefault_face, frame);
1369      GdkColor *bgc;
1370
1371      if (!EQ (color, Vthe_null_color_instance))
1372        {
1373          bgc = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (color));
1374          if (FRAME_GTK_SHELL_WIDGET (frm)->window)
1375            {
1376              gdk_window_set_background (FRAME_GTK_SHELL_WIDGET (frm)->window, bgc);
1377            }
1378          if (FRAME_GTK_TEXT_WIDGET (frm)->window)
1379            {
1380              gdk_window_set_background (FRAME_GTK_TEXT_WIDGET (frm)->window, bgc);
1381            }
1382        }
1383
1384      /* Really crappy way to force the modeline shadows to be
1385         redrawn.  But effective. */
1386      MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (frm);
1387      MARK_FRAME_CHANGED (frm);
1388    }
1389   else if (EQ (name, Qfont))
1390    {
1391      Lisp_Object font = FACE_FONT (Vdefault_face, frame, Vcharset_ascii);
1392
1393      if (!EQ (font, Vthe_null_font_instance))
1394      {
1395          /* #### BILL!!! The X code set the XtNfont property of the
1396             text widget here.  Why did they bother?  All that type of
1397             thing is done down in the guts of the redisplay code, not
1398             in the Emacs* widgets. */
1399      }
1400    }
1401   else
1402    ABORT ();
1403
1404 #ifdef HAVE_TOOLBARS
1405   /* Setting the background clears the entire frame area
1406     including the toolbar so we force an immediate redraw of
1407     it. */
1408   if (EQ (name, Qbackground))
1409     MAYBE_DEVMETH (XDEVICE (frm->device), redraw_frame_toolbars, (frm));
1410 #endif /* HAVE_TOOLBARS */
1411
1412   /* Set window manager resize increment hints according to
1413      the new character size */
1414   if (EQ (name, Qfont) && FRAME_GTK_TOP_LEVEL_FRAME_P (frm))
1415           gtk_recompute_cell_sizes (frm);
1416 }
1417
1418 \f
1419 /************************************************************************/
1420 /*                            initialization                            */
1421 /************************************************************************/
1422
1423 void
1424 syms_of_frame_gtk (void)
1425 {
1426   defsymbol (&Qwindow_id, "window-id");
1427   defsymbol (&Qtext_widget, "text-widget");
1428   defsymbol (&Qcontainer_widget, "container-widget");
1429   defsymbol (&Qshell_widget, "shell-widget");
1430   defsymbol (&Qdetachable_menubar, "detachable-menubar");
1431
1432 #ifdef HAVE_DRAGNDROP
1433   staticpro (&Vcurrent_drag_object);
1434   Vcurrent_drag_object = Qnil;
1435   DEFSUBR (Fgtk_start_drag_internal);
1436 #endif
1437 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
1438   DEFSUBR (Fgtk_window_id);
1439 #endif
1440 }
1441
1442 void
1443 console_type_create_frame_gtk (void)
1444 {
1445   /* frame methods */
1446   CONSOLE_HAS_METHOD (gtk, init_frame_1);
1447   CONSOLE_HAS_METHOD (gtk, init_frame_2);
1448   CONSOLE_HAS_METHOD (gtk, init_frame_3);
1449   CONSOLE_HAS_METHOD (gtk, mark_frame);
1450   CONSOLE_HAS_METHOD (gtk, focus_on_frame);
1451   CONSOLE_HAS_METHOD (gtk, delete_frame);
1452   CONSOLE_HAS_METHOD (gtk, get_mouse_position);
1453 #ifdef STUPID_X_SPECIFIC_GTK_STUFF
1454   CONSOLE_HAS_METHOD (gtk, set_mouse_position);
1455 #endif
1456   CONSOLE_HAS_METHOD (gtk, raise_frame);
1457   CONSOLE_HAS_METHOD (gtk, lower_frame);
1458   CONSOLE_HAS_METHOD (gtk, make_frame_visible);
1459   CONSOLE_HAS_METHOD (gtk, make_frame_invisible);
1460   CONSOLE_HAS_METHOD (gtk, iconify_frame);
1461   CONSOLE_HAS_METHOD (gtk, set_frame_size);
1462   CONSOLE_HAS_METHOD (gtk, set_frame_position);
1463   CONSOLE_HAS_METHOD (gtk, frame_property);
1464   CONSOLE_HAS_METHOD (gtk, internal_frame_property_p);
1465   CONSOLE_HAS_METHOD (gtk, frame_properties);
1466   CONSOLE_HAS_METHOD (gtk, set_frame_properties);
1467   CONSOLE_HAS_METHOD (gtk, set_title_from_bufbyte);
1468   CONSOLE_HAS_METHOD (gtk, set_icon_name_from_bufbyte);
1469   CONSOLE_HAS_METHOD (gtk, frame_visible_p);
1470   CONSOLE_HAS_METHOD (gtk, frame_totally_visible_p);
1471   CONSOLE_HAS_METHOD (gtk, frame_iconified_p);
1472   CONSOLE_HAS_METHOD (gtk, set_frame_pointer);
1473   CONSOLE_HAS_METHOD (gtk, set_frame_icon);
1474   CONSOLE_HAS_METHOD (gtk, get_frame_parent);
1475   CONSOLE_HAS_METHOD (gtk, update_frame_external_traits);
1476 }
1477
1478 void
1479 vars_of_frame_gtk (void)
1480 {
1481   DEFVAR_LISP ("default-gtk-frame-plist", &Vdefault_gtk_frame_plist /*
1482 Plist of default frame-creation properties for Gtk frames.
1483 These override what is specified in the resource database and in
1484 `default-frame-plist', but are overridden by the arguments to the
1485 particular call to `make-frame'.
1486
1487 Note: In many cases, properties of a frame are available as specifiers
1488 instead of through the frame-properties mechanism.
1489
1490 Here is a list of recognized frame properties, other than those
1491 documented in `set-frame-properties' (they can be queried and
1492 set at any time, except as otherwise noted):
1493
1494   initially-unmapped            If non-nil, the frame will not be visible
1495                                 when it is created.  In this case, you
1496                                 need to call `make-frame-visible' to make
1497                                 the frame appear.
1498   popup                         If non-nil, it should be a frame, and this
1499                                 frame will be created as a "popup" frame
1500                                 whose parent is the given frame.  This
1501                                 will make the window manager treat the
1502                                 frame as a dialog box, which may entail
1503                                 doing different things (e.g. not asking
1504                                 for positioning, and not iconifying
1505                                 separate from its parent).
1506   inter-line-space              Not currently implemented.
1507   toolbar-shadow-thickness      Thickness of toolbar shadows.
1508   background-toolbar-color      Color of toolbar background.
1509   bottom-toolbar-shadow-color   Color of bottom shadows on toolbars.
1510                                 (*Not* specific to the bottom-toolbar.)
1511   top-toolbar-shadow-color      Color of top shadows on toolbars.
1512                                 (*Not* specific to the top-toolbar.)
1513   internal-border-width         Width of internal border around text area.
1514   border-width                  Width of external border around text area.
1515   top                           Y position (in pixels) of the upper-left
1516                                 outermost corner of the frame (i.e. the
1517                                 upper-left of the window-manager
1518                                 decorations).
1519   left                          X position (in pixels) of the upper-left
1520                                 outermost corner of the frame (i.e. the
1521                                 upper-left of the window-manager
1522                                 decorations).
1523   border-color                  Color of external border around text area.
1524   cursor-color                  Color of text cursor.
1525
1526 See also `default-frame-plist', which specifies properties which apply
1527 to all frames, not just Gtk frames.
1528 */ );
1529   Vdefault_gtk_frame_plist = Qnil;
1530
1531   gtk_console_methods->device_specific_frame_props = &Vdefault_gtk_frame_plist;
1532 }