comparison src/frame-gtk.c @ 462:0784d089fdc9 r21-2-46

Import from CVS: tag r21-2-46
author cvs
date Mon, 13 Aug 2007 11:44:37 +0200
parents
children 183866b06e0b
comparison
equal deleted inserted replaced
461:120ed4009e51 462:0784d089fdc9
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
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
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
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
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
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
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
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
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 }