1 /* Generic frame functions.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3 Copyright (C) 1995, 1996 Ben Wing.
4 Copyright (C) 1995 Sun Microsystems, Inc.
6 This file is part of SXEmacs
8 SXEmacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 SXEmacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 /* Synched up with: FSF 19.30. */
24 /* This file has been Mule-ized. */
29 #include "buffer.h" /* for Vbuffer_alist */
31 #define INCLUDE_EVENTS_H_PRIVATE_SPHERE
32 #include "events/events.h"
39 #include "redisplay.h"
40 #include "scrollbar.h"
43 Lisp_Object Vselect_frame_hook, Qselect_frame_hook;
44 Lisp_Object Vdeselect_frame_hook, Qdeselect_frame_hook;
45 Lisp_Object Vcreate_frame_hook, Qcreate_frame_hook;
46 Lisp_Object Vdelete_frame_hook, Qdelete_frame_hook;
47 Lisp_Object Vmouse_enter_frame_hook, Qmouse_enter_frame_hook;
48 Lisp_Object Vmouse_leave_frame_hook, Qmouse_leave_frame_hook;
49 Lisp_Object Vmap_frame_hook, Qmap_frame_hook;
50 Lisp_Object Vunmap_frame_hook, Qunmap_frame_hook;
51 int allow_deletion_of_last_visible_frame;
52 Lisp_Object Vadjust_frame_function;
53 Lisp_Object Vmouse_motion_handler;
54 Lisp_Object Vsynchronize_minibuffers;
55 Lisp_Object Qsynchronize_minibuffers;
56 Lisp_Object Qbuffer_predicate;
57 Lisp_Object Qmake_initial_minibuffer_frame;
58 Lisp_Object Qcustom_initialize_frame;
60 /* We declare all these frame properties here even though many of them
61 are currently only used in frame-x.c, because we should generalize
64 Lisp_Object Qminibuffer;
65 Lisp_Object Qunsplittable;
66 Lisp_Object Qinternal_border_width;
67 Lisp_Object Qtop_toolbar_shadow_color;
68 Lisp_Object Qbottom_toolbar_shadow_color;
69 Lisp_Object Qbackground_toolbar_color;
70 Lisp_Object Qtop_toolbar_shadow_pixmap;
71 Lisp_Object Qbottom_toolbar_shadow_pixmap;
72 Lisp_Object Qtoolbar_shadow_thickness;
73 Lisp_Object Qscrollbar_placement;
74 Lisp_Object Qinter_line_space;
75 Lisp_Object Qvisual_bell;
76 Lisp_Object Qbell_volume;
77 Lisp_Object Qpointer_background;
78 Lisp_Object Qpointer_color;
79 Lisp_Object Qtext_pointer;
80 Lisp_Object Qspace_pointer;
81 Lisp_Object Qmodeline_pointer;
82 Lisp_Object Qgc_pointer;
83 Lisp_Object Qinitially_unmapped;
84 Lisp_Object Quse_backing_store;
85 Lisp_Object Qborder_color;
86 Lisp_Object Qborder_width;
88 Lisp_Object Qframep, Qframe_live_p;
89 Lisp_Object Qdelete_frame;
91 Lisp_Object Qframe_title_format, Vframe_title_format;
92 Lisp_Object Qframe_icon_title_format, Vframe_icon_title_format;
94 Lisp_Object Vdefault_frame_name;
95 Lisp_Object Vdefault_frame_plist;
97 Lisp_Object Vframe_icon_glyph;
101 Lisp_Object Qvisible, Qiconic, Qinvisible, Qvisible_iconic, Qinvisible_iconic;
102 Lisp_Object Qnomini, Qvisible_nomini, Qiconic_nomini, Qinvisible_nomini;
103 Lisp_Object Qvisible_iconic_nomini, Qinvisible_iconic_nomini;
105 Lisp_Object Qset_specifier, Qset_face_property;
106 Lisp_Object Qface_property_instance;
108 Lisp_Object Qframe_property_alias;
110 /* If this is non-nil, it is the frame that make-frame is currently
111 creating. We can't set the current frame to this in case the
112 debugger goes off because it would try and display to it. However,
113 there are some places which need to reference it which have no
114 other way of getting it if it isn't the selected frame. */
115 Lisp_Object Vframe_being_created;
116 Lisp_Object Qframe_being_created;
118 static void store_minibuf_frame_prop(struct frame *f, Lisp_Object val);
119 static void frame_conversion_internal(struct frame *f, int pixel_to_char,
120 int *pixel_width, int *pixel_height,
121 int *char_width, int *char_height,
123 static struct display_line title_string_display_line;
124 /* Used by generate_title_string. Global because they get used so much that
125 the dynamic allocation time adds up. */
126 static Emchar_dynarr *title_string_emchar_dynarr;
128 static Lisp_Object mark_frame(Lisp_Object obj)
130 struct frame *f = XFRAME(obj);
132 #define MARKED_SLOT(x) mark_object (f->x)
133 #include "frameslots.h"
135 if (FRAME_LIVE_P(f)) /* device is nil for a dead frame */
136 MAYBE_FRAMEMETH(f, mark_frame, (f));
142 print_frame(Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
144 struct frame *frm = XFRAME(obj);
147 error("printing unreadable object #<frame %s 0x%x>",
148 XSTRING_DATA(frm->name), frm->header.uid);
150 write_fmt_string(printcharfun, "#<%s-frame ",
151 (!FRAME_LIVE_P(frm) ? "dead" : FRAME_TYPE_NAME(frm)));
152 print_internal(frm->name, printcharfun, 1);
153 write_fmt_str(printcharfun, " 0x%x>", frm->header.uid);
156 DEFINE_LRECORD_IMPLEMENTATION("frame", frame,
157 mark_frame, print_frame, 0, 0, 0, 0,
160 static void nuke_all_frame_slots(struct frame *f)
162 #define MARKED_SLOT(x) f->x = Qnil
163 #include "frameslots.h"
166 /* Allocate a new frame object and set all its fields to reasonable
167 values. The root window is created but the minibuffer will be done
170 static struct frame *allocate_frame_core(Lisp_Object device)
172 /* This function can GC */
174 Lisp_Object root_window;
175 struct frame *f = alloc_lcrecord_type(struct frame, &lrecord_frame);
178 nuke_all_frame_slots(f);
182 f->framemeths = XDEVICE(device)->devmeths;
183 f->buffer_alist = Fcopy_sequence(Vbuffer_alist);
185 root_window = allocate_window();
186 XWINDOW(root_window)->frame = frame;
189 Just so that there is "something there."
190 Correct size will be set up later with change_frame_size. */
195 XWINDOW(root_window)->pixel_width = 10;
196 XWINDOW(root_window)->pixel_height = 9;
198 f->root_window = root_window;
199 f->selected_window = root_window;
200 f->last_nonminibuf_window = root_window;
202 /* cache of subwindows visible on frame */
203 f->subwindow_instance_cache = make_weak_list(WEAK_LIST_SIMPLE);
205 /* associated exposure ignore list */
206 f->subwindow_exposures = 0;
207 f->subwindow_exposures_tail = 0;
209 FRAME_SET_PAGENUMBER(f, 1);
211 /* Choose a buffer for the frame's root window. */
212 XWINDOW(root_window)->buffer = Qt;
214 Lisp_Object buf = Fcurrent_buffer();
215 Lisp_Object tmp = Fbuffer_name(buf);
217 /* If buf is a 'hidden' buffer (i.e. one whose name starts with
218 a space), try to find another one. */
219 if (string_char(XSTRING(tmp), 0) == ' ') {
220 buf = Fother_buffer(buf, Qnil, Qnil);
222 Fset_window_buffer(root_window, buf, Qnil);
228 static void setup_normal_frame(struct frame *f)
230 Lisp_Object mini_window;
235 mini_window = allocate_window();
236 XWINDOW(f->root_window)->next = mini_window;
237 XWINDOW(mini_window)->prev = f->root_window;
238 XWINDOW(mini_window)->mini_p = Qt;
239 XWINDOW(mini_window)->frame = frame;
240 f->minibuffer_window = mini_window;
241 f->has_minibuffer = 1;
243 XWINDOW(mini_window)->buffer = Qt;
244 Fset_window_buffer(mini_window, Vminibuffer_zero, Qt);
247 /* Make a frame using a separate minibuffer window on another frame.
248 MINI_WINDOW is the minibuffer window to use. nil means use the
249 default-minibuffer-frame. */
252 setup_frame_without_minibuffer(struct frame *f, Lisp_Object mini_window)
254 /* This function can GC */
255 Lisp_Object device = f->device;
257 if (!NILP(mini_window))
258 CHECK_LIVE_WINDOW(mini_window);
260 if (!NILP(mini_window)
261 && !EQ(DEVICE_CONSOLE(XDEVICE(device)),
262 FRAME_CONSOLE(XFRAME(XWINDOW(mini_window)->frame))))
263 error("frame and minibuffer must be on the same console");
265 /* Do not create a default minibuffer frame on printer devices. */
266 if (NILP(mini_window)
267 && DEVICE_DISPLAY_P(XDEVICE(FRAME_DEVICE(f)))) {
268 struct console *con = XCONSOLE(FRAME_CONSOLE(f));
269 /* Use default-minibuffer-frame if possible. */
270 if (!FRAMEP(con->default_minibuffer_frame)
271 || !FRAME_LIVE_P(XFRAME(con->default_minibuffer_frame))) {
272 /* If there's no minibuffer frame to use, create one. */
273 con->default_minibuffer_frame
274 = call1(Qmake_initial_minibuffer_frame, device);
277 XFRAME(con->default_minibuffer_frame)->minibuffer_window;
280 /* Install the chosen minibuffer window, with proper buffer. */
281 if (!NILP(mini_window)) {
282 store_minibuf_frame_prop(f, mini_window);
283 Fset_window_buffer(mini_window, Vminibuffer_zero, Qt);
285 f->minibuffer_window = Qnil;
288 /* Make a frame containing only a minibuffer window. */
290 static void setup_minibuffer_frame(struct frame *f)
292 /* This function can GC */
293 /* First make a frame containing just a root window, no minibuffer. */
294 Lisp_Object mini_window;
300 f->has_minibuffer = 1;
302 /* Now label the root window as also being the minibuffer.
303 Avoid infinite looping on the window chain by marking next pointer
306 mini_window = f->minibuffer_window = f->root_window;
307 XWINDOW(mini_window)->mini_p = Qt;
308 XWINDOW(mini_window)->next = Qnil;
309 XWINDOW(mini_window)->prev = Qnil;
310 XWINDOW(mini_window)->frame = frame;
312 /* Put the proper buffer in that window. */
314 Fset_window_buffer(mini_window, Vminibuffer_zero, Qt);
317 static Lisp_Object make_sure_its_a_fresh_plist(Lisp_Object foolist)
319 Lisp_Object tmp = Fcar(foolist);
321 /* looks like an alist to me. */
322 foolist = Fcopy_alist(foolist);
323 foolist = Fdestructive_alist_to_plist(foolist);
325 foolist = Fcopy_sequence(foolist);
330 DEFUN("make-frame", Fmake_frame, 0, 2, "", /*
331 Create and return a new frame, displaying the current buffer.
332 Runs the functions listed in `create-frame-hook' after frame creation.
334 Optional argument PROPS is a property list (a list of alternating
335 keyword-value specifications) of properties for the new frame.
336 \(An alist is accepted for backward compatibility but should not
339 See `set-frame-properties', `default-x-frame-plist', and
340 `default-tty-frame-plist' for the specially-recognized properties.
346 Lisp_Object frame = Qnil, name = Qnil, minibuf;
347 struct gcpro gcpro1, gcpro2, gcpro3;
348 int speccount = specpdl_depth();
349 int first_frame_on_device = 0;
350 int first_frame_on_console = 0;
352 d = decode_device(device);
353 XSETDEVICE(device, d);
355 /* PROPS and NAME may be freshly-created, so make sure to GCPRO. */
356 GCPRO3(frame, props, name);
358 props = make_sure_its_a_fresh_plist(props);
359 if (DEVICE_SPECIFIC_FRAME_PROPS(d))
360 /* Put the device-specific props before the more general ones so
361 that they override them. */
362 props = nconc2(props,
363 make_sure_its_a_fresh_plist
364 (*DEVICE_SPECIFIC_FRAME_PROPS(d)));
366 nconc2(props, make_sure_its_a_fresh_plist(Vdefault_frame_plist));
367 Fcanonicalize_lax_plist(props, Qnil);
369 name = Flax_plist_get(props, Qname, Qnil);
372 else if (STRINGP(Vdefault_frame_name))
373 name = Vdefault_frame_name;
375 name = build_string("SXEmacs");
377 if (!NILP(Fstring_match(make_string((const Bufbyte *)"\\.", 2), name,
379 signal_simple_error(". not allowed in frame names", name);
381 f = allocate_frame_core(device);
384 specbind(Qframe_being_created, name);
387 FRAMEMETH(f, init_frame_1, (f, props));
389 minibuf = Flax_plist_get(props, Qminibuffer, Qunbound);
390 if (UNBOUNDP(minibuf)) {
391 /* If minibuf is unspecified, then look for a minibuffer X resource. */
392 /* #### Not implemented any more. We need to fix things up so
393 that we search out all X resources and append them to the end of
394 props, above. This is the only way in general to assure
395 coherent behavior for all frame properties/resources/etc. */
397 props = Flax_plist_remprop(props, Qminibuffer);
399 if (EQ(minibuf, Qnone) || NILP(minibuf))
400 setup_frame_without_minibuffer(f, Qnil);
401 else if (EQ(minibuf, Qonly))
402 setup_minibuffer_frame(f);
403 else if (WINDOWP(minibuf))
404 setup_frame_without_minibuffer(f, minibuf);
405 else if (EQ(minibuf, Qt) || UNBOUNDP(minibuf))
406 setup_normal_frame(f);
408 signal_simple_error("Invalid value for `minibuffer'", minibuf);
410 update_frame_window_mirror(f);
412 if (initialized && !DEVICE_STREAM_P(d)) {
413 if (!NILP(f->minibuffer_window))
414 reset_face_cachels(XWINDOW(f->minibuffer_window));
415 reset_face_cachels(XWINDOW(f->root_window));
418 /* If no frames on this device formerly existed, say this is the
419 first frame. It kind of assumes that frameless devices don't
420 exist, but it shouldn't be too harmful. */
421 if (NILP(DEVICE_FRAME_LIST(d)))
422 first_frame_on_device = 1;
424 /* This *must* go before the init_*() methods. Those functions
425 call Lisp code, and if any of them causes a warning to be displayed
426 and the *Warnings* buffer to be created, it won't get added to
427 the frame-specific version of the buffer-alist unless the frame
428 is accessible from the device. */
431 DEVICE_FRAME_LIST(d) = nconc2(DEVICE_FRAME_LIST(d), Fcons(frame, Qnil));
433 DEVICE_FRAME_LIST(d) = Fcons(frame, DEVICE_FRAME_LIST(d));
434 RESET_CHANGED_SET_FLAGS;
436 /* Now make sure that the initial cached values are set correctly.
437 Do this after the init_frame method is called because that may
438 do things (e.g. create widgets) that are necessary for the
439 specifier value-changed methods to work OK. */
440 recompute_all_cached_specifiers_in_frame(f);
442 if (!DEVICE_STREAM_P(d)) {
445 #ifdef HAVE_SCROLLBARS
446 /* Finish up resourcing the scrollbars. */
447 init_frame_scrollbars(f);
451 /* Create the initial toolbars. We have to do this after the frame
452 methods are called because it may potentially call some things itself
453 which depend on the normal frame methods having initialized
455 init_frame_toolbars(f);
457 reset_face_cachels(XWINDOW(FRAME_SELECTED_WINDOW(f)));
458 reset_glyph_cachels(XWINDOW(FRAME_SELECTED_WINDOW(f)));
460 change_frame_size(f, f->height, f->width, 0);
463 MAYBE_FRAMEMETH(f, init_frame_2, (f, props));
464 Fset_frame_properties(frame, props);
465 MAYBE_FRAMEMETH(f, init_frame_3, (f));
467 /* Hallelujah, praise the lord. */
468 f->init_finished = 1;
470 /* If this is the first frame on the device, make it the selected one. */
471 if (first_frame_on_device && NILP(DEVICE_SELECTED_FRAME(d)))
472 set_device_selected_frame(d, frame);
474 /* If at startup or if the current console is a stream console
475 (usually also at startup), make this console the selected one
476 so that messages show up on it. */
478 Lisp_Object tmp = Fselected_console();
479 if (NILP(tmp) || CONSOLE_STREAM_P(XCONSOLE(tmp))) {
480 Fselect_console(DEVICE_CONSOLE(d));
484 first_frame_on_console =
485 (first_frame_on_device &&
486 XINT(Flength(CONSOLE_DEVICE_LIST(XCONSOLE(DEVICE_CONSOLE(d)))))
489 /* #### all this calling of frame methods at various odd times
490 is somewhat of a mess. It's necessary to do it this way due
491 to strange console-type-specific things that need to be done. */
492 MAYBE_FRAMEMETH(f, after_init_frame, (f, first_frame_on_device,
493 first_frame_on_console));
495 if (!DEVICE_STREAM_P(d)) {
496 /* Now initialise the gutters. This won't change the frame size,
497 but is needed as input to the layout that change_frame_size
498 will eventually do. Unfortunately gutter sizing code relies
499 on the frame in question being visible so we can't do this
501 init_frame_gutters(f);
503 change_frame_size(f, f->height, f->width, 0);
506 if (first_frame_on_device) {
507 if (first_frame_on_console)
508 va_run_hook_with_args(Qcreate_console_hook, 1,
510 va_run_hook_with_args(Qcreate_device_hook, 1, device);
512 va_run_hook_with_args(Qcreate_frame_hook, 1, frame);
514 /* Initialize custom-specific stuff. */
515 if (!UNBOUNDP(symbol_function(XSYMBOL(Qcustom_initialize_frame))))
516 call1(Qcustom_initialize_frame, frame);