diff options
Diffstat (limited to 'src/frame.c')
-rw-r--r-- | src/frame.c | 352 |
1 files changed, 301 insertions, 51 deletions
diff --git a/src/frame.c b/src/frame.c index 9a176a67741..660b9db4316 100644 --- a/src/frame.c +++ b/src/frame.c @@ -42,6 +42,7 @@ Boston, MA 02111-1307, USA. */ #include "fontset.h" #endif #include "blockinput.h" +#include "termchar.h" #include "termhooks.h" #include "dispextern.h" #include "window.h" @@ -75,6 +76,8 @@ Lisp_Object Qinhibit_default_face_x_resources; Lisp_Object Qx_frame_parameter; Lisp_Object Qx_resource_name; +Lisp_Object Qdisplay_id; +Lisp_Object Qdisplay_live_p; /* Frame parameters (set or reported). */ @@ -106,12 +109,13 @@ Lisp_Object Qmenu_bar_lines, Qtool_bar_lines; Lisp_Object Qleft_fringe, Qright_fringe; Lisp_Object Qbuffer_predicate, Qbuffer_list; Lisp_Object Qtty_color_mode; +Lisp_Object Qtty, Qtty_type; +Lisp_Object Qwindow_system; Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth; Lisp_Object Qface_set_after_frame_default; - Lisp_Object Vterminal_frame; Lisp_Object Vdefault_frame_alist; Lisp_Object Vdefault_frame_scroll_bars; @@ -121,8 +125,8 @@ Lisp_Object Vdelete_frame_functions; static void set_menu_bar_lines_1 (window, n) - Lisp_Object window; - int n; + Lisp_Object window; + int n; { struct window *w = XWINDOW (window); @@ -180,8 +184,6 @@ set_menu_bar_lines (f, value, oldval) Lisp_Object Vemacs_iconified; Lisp_Object Vframe_list; -struct x_output tty_display; - extern Lisp_Object Vminibuffer_list; extern Lisp_Object get_minibuffer (); extern Lisp_Object Fhandle_switch_frame (); @@ -203,6 +205,7 @@ See also `frame-live-p'. */) return Qnil; switch (XFRAME (object)->output_method) { + case output_initial: /* The initial frame is like a termcap frame. */ case output_termcap: return Qt; case output_x_window: @@ -233,6 +236,30 @@ return values. */) : Qnil); } +DEFUN ("window-system", Fwindow_system, Swindow_system, 0, 1, 0, + doc: /* The name of the window system that FRAME is displaying through. +The value is a symbol---for instance, 'x' for X windows. +The value is nil if Emacs is using a text-only terminal. + +FRAME defaults to the currently selected frame. */) + (frame) + Lisp_Object frame; +{ + Lisp_Object type; + if (NILP (frame)) + frame = selected_frame; + + type = Fframep (frame); + + if (NILP (type)) + wrong_type_argument (Qframep, frame); + + if (EQ (type, Qt)) + return Qnil; + else + return type; +} + struct frame * make_frame (mini_p) int mini_p; @@ -475,18 +502,19 @@ make_minibuffer_frame () } #endif /* HAVE_WINDOW_SYSTEM */ -/* Construct a frame that refers to the terminal (stdin and stdout). */ +/* Construct a frame that refers to a terminal. */ static int terminal_frame_count; struct frame * -make_terminal_frame () +make_initial_frame (void) { - register struct frame *f; + struct frame *f; + struct display *display; Lisp_Object frame; - char name[20]; #ifdef MULTI_KBOARD + /* Create the initial keyboard. */ if (!initial_kboard) { initial_kboard = (KBOARD *) xmalloc (sizeof (KBOARD)); @@ -500,6 +528,45 @@ make_terminal_frame () if (! (NILP (Vframe_list) || CONSP (Vframe_list))) Vframe_list = Qnil; + display = init_initial_display (); + + f = make_frame (1); + XSETFRAME (frame, f); + + Vframe_list = Fcons (frame, Vframe_list); + + terminal_frame_count = 1; + f->name = build_string ("F1"); + + f->visible = 1; + f->async_visible = 1; + + f->output_method = display->type; + f->display = display; + f->display->reference_count++; + f->output_data.nothing = 0; + + FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR; + FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR; + + FRAME_CAN_HAVE_SCROLL_BARS (f) = 0; + FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none; + +#ifdef MULTI_KBOARD + f->kboard = initial_kboard; +#endif + + return f; +} + + +struct frame * +make_terminal_frame (struct display *display) +{ + register struct frame *f; + Lisp_Object frame; + char name[20]; + f = make_frame (1); XSETFRAME (frame, f); @@ -538,12 +605,35 @@ make_terminal_frame () #else #ifdef WINDOWSNT f->output_method = output_termcap; - f->output_data.x = &tty_display; + f->output_data.x = &tty_display; /* XXX ??? */ #else #ifdef MAC_OS8 make_mac_terminal_frame (f); #else - f->output_data.x = &tty_display; + { + f->output_method = output_termcap; + f->display = display; + f->display->reference_count++; + create_tty_output (f); + + FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR; + FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR; + + FRAME_CAN_HAVE_SCROLL_BARS (f) = 0; + FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none; + +#ifdef MULTI_KBOARD + f->kboard = FRAME_TTY (f)->kboard; +#endif + + /* Set the top frame to the newly created frame. */ + if (FRAME_TTY (f)->top_frame + && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame))) + XFRAME (FRAME_TTY (f)->top_frame)->async_visible = 2; /* obscured */ + + FRAME_TTY (f)->top_frame = frame; + } + #ifdef CANNOT_DUMP FRAME_FOREGROUND_PIXEL(f) = FACE_TTY_DEFAULT_FG_COLOR; FRAME_BACKGROUND_PIXEL(f) = FACE_TTY_DEFAULT_BG_COLOR; @@ -560,16 +650,26 @@ make_terminal_frame () DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame, 1, 1, 0, - doc: /* Create an additional terminal frame. -You can create multiple frames on a text-only terminal in this way. -Only the selected terminal frame is actually displayed. + doc: /* Create an additional terminal frame, possibly on another terminal. This function takes one argument, an alist specifying frame parameters. -In practice, generally you don't need to specify any parameters. -Note that changing the size of one terminal frame automatically affects all. */) + +You can create multiple frames on a single text-only terminal, but +only one of them (the selected terminal frame) is actually displayed. + +In practice, generally you don't need to specify any parameters, +except when you want to create a new frame on another terminal. +In that case, the `tty' parameter specifies the device file to open, +and the `tty-type' parameter specifies the terminal type. Example: + + (make-terminal-frame '((tty . "/dev/pts/5") (tty-type . "xterm"))) + +Note that changing the size of one terminal frame automatically +affects all frames on the same terminal device. */) (parms) Lisp_Object parms; { struct frame *f; + struct display *d = NULL; Lisp_Object frame, tem; struct frame *sf = SELECTED_FRAME (); @@ -583,20 +683,89 @@ Note that changing the size of one terminal frame automatically affects all. */ if (sf->output_method != output_mac) error ("Not running on a Macintosh screen; cannot make a new Macintosh frame"); #else +#if 0 /* This should work now! */ if (sf->output_method != output_termcap) error ("Not using an ASCII terminal now; cannot make a new ASCII frame"); #endif +#endif #endif /* not MSDOS */ + + { + Lisp_Object display_device; - f = make_terminal_frame (); + display_device = Fassq (Qdisplay_id, parms); + if (!NILP (display_device)) + { + display_device = XCDR (display_device); + CHECK_NUMBER (display_device); + d = get_display (XINT (display_device)); + if (!d) + wrong_type_argument (Qdisplay_live_p, display_device); + } + } + + if (!d) + { + Lisp_Object tty, tty_type; + char *name = 0, *type = 0; + + tty = Fassq (Qtty, parms); + if (EQ (tty, Qnil)) + tty = Fassq (Qtty, XFRAME (selected_frame)->param_alist); + if (EQ (tty, Qnil) && FRAME_TERMCAP_P (XFRAME (selected_frame)) + && FRAME_TTY (XFRAME (selected_frame))->name) + tty = build_string (FRAME_TTY (XFRAME (selected_frame))->name); + if (EQ (tty, Qnil)) + tty = Fassq (Qtty, Vdefault_frame_alist); + if (! EQ (tty, Qnil) && ! STRINGP (tty)) + tty = XCDR (tty); + if (EQ (tty, Qnil) || !STRINGP (tty)) + tty = Qnil; + + tty_type = Fassq (Qtty_type, parms); + if (EQ (tty_type, Qnil)) + tty_type = Fassq (Qtty, XFRAME (selected_frame)->param_alist); + if (EQ (tty_type, Qnil) && FRAME_TERMCAP_P (XFRAME (selected_frame)) + && FRAME_TTY (XFRAME (selected_frame))->type) + tty_type = build_string (FRAME_TTY (XFRAME (selected_frame))->type); + if (EQ (tty_type, Qnil)) + tty_type = Fassq (Qtty_type, Vdefault_frame_alist); + if (! EQ (tty_type, Qnil) && ! STRINGP (tty_type)) + tty_type = XCDR (tty_type); + if (EQ (tty_type, Qnil) || !STRINGP (tty_type)) + tty_type = Qnil; + + if (! EQ (tty, Qnil)) + { + name = (char *) alloca (SBYTES (tty) + 1); + strncpy (name, SDATA (tty), SBYTES (tty)); + name[SBYTES (tty)] = 0; + } + + if (! EQ (tty_type, Qnil)) + { + type = (char *) alloca (SBYTES (tty_type) + 1); + strncpy (type, SDATA (tty_type), SBYTES (tty_type)); + type[SBYTES (tty_type)] = 0; + } + + d = term_init (name, type, 0); /* Errors are not fatal. */ + } - change_frame_size (f, FRAME_LINES (sf), - FRAME_COLS (sf), 0, 0, 0); + f = make_terminal_frame (d); + + { + int width, height; + get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height); + change_frame_size (f, height, width, 0, 0, 0); + } + adjust_glyphs (f); calculate_costs (f); XSETFRAME (frame, f); Fmodify_frame_parameters (frame, Vdefault_frame_alist); Fmodify_frame_parameters (frame, parms); + Fmodify_frame_parameters (frame, Fcons (Fcons (Qwindow_system, Qnil), Qnil)); /* Make the frame face alist be frame-specific, so that each frame could change its face definitions independently. */ @@ -695,6 +864,15 @@ do_switch_frame (frame, track, for_deletion) if (!for_deletion && FRAME_HAS_MINIBUF_P (sf)) resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1); + if (FRAME_TERMCAP_P (XFRAME (selected_frame)) + && FRAME_TERMCAP_P (XFRAME (frame)) + && FRAME_TTY (XFRAME (selected_frame)) == FRAME_TTY (XFRAME (frame))) + { + XFRAME (selected_frame)->async_visible = 2; /* obscured */ + XFRAME (frame)->async_visible = 1; + FRAME_TTY (XFRAME (frame))->top_frame = frame; + } + selected_frame = frame; if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame))) last_nonminibuf_frame = XFRAME (selected_frame); @@ -888,6 +1066,31 @@ If FRAME is the selected frame, this makes WINDOW the selected window. */) return XFRAME (frame)->selected_window = window; } + +DEFUN ("frame-display", Fframe_display, Sframe_display, 0, 1, 0, + doc: /* Return the display device that FRAME is displayed on. +If FRAME is nil, the selected frame is used. + +The display device is represented by its integer identifier. */) + (frame) + Lisp_Object frame; +{ + struct display *d; + + if (NILP (frame)) + frame = selected_frame; + + CHECK_LIVE_FRAME (frame); + + d = get_display (frame); + + if (!d) + return Qnil; + else + return make_number (d->id); +} + + DEFUN ("frame-list", Fframe_list, Sframe_list, 0, 0, 0, doc: /* Return a list of all frames. */) @@ -934,7 +1137,10 @@ next_frame (frame, minibuf) f = XCAR (tail); if (passed - && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame))) + && ((!FRAME_TERMCAP_P (XFRAME (f)) && !FRAME_TERMCAP_P (XFRAME (frame)) + && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame))) + || (FRAME_TERMCAP_P (XFRAME (f)) && FRAME_TERMCAP_P (XFRAME (frame)) + && FRAME_TTY (XFRAME (f)) == FRAME_TTY (XFRAME (frame))))) { /* Decide whether this frame is eligible to be returned. */ @@ -1011,7 +1217,10 @@ prev_frame (frame, minibuf) if (EQ (frame, f) && !NILP (prev)) return prev; - if (FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame))) + if ((!FRAME_TERMCAP_P (XFRAME (f)) && !FRAME_TERMCAP_P (XFRAME (frame)) + && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame))) + || (FRAME_TERMCAP_P (XFRAME (f)) && FRAME_TERMCAP_P (XFRAME (frame)) + && FRAME_TTY (XFRAME (f)) == FRAME_TTY (XFRAME (frame)))) { /* Decide whether this frame is eligible to be returned, according to minibuf. */ @@ -1223,6 +1432,10 @@ The functions are run with one arg, the frame to be deleted. */) Frun_hook_with_args (2, args); } + /* The hook may sometimes (indirectly) cause the frame to be deleted. */ + if (! FRAME_LIVE_P (f)) + return Qnil; + minibuffer_selected = EQ (minibuf_window, selected_window); /* Don't let the frame remain selected. */ @@ -1238,7 +1451,7 @@ The functions are run with one arg, the frame to be deleted. */) { FOR_EACH_FRAME (tail, frame1) { - if (! EQ (frame, frame1)) + if (! EQ (frame, frame1) && FRAME_LIVE_P (XFRAME (frame1))) break; } } @@ -1305,13 +1518,26 @@ The functions are run with one arg, the frame to be deleted. */) promise that the display of the frame must be valid until we have called the window-system-dependent frame destruction routine. */ - /* I think this should be done with a hook. */ -#ifdef HAVE_WINDOW_SYSTEM - if (FRAME_WINDOW_P (f)) - x_destroy_window (f); -#endif + if (FRAME_DISPLAY (f)->delete_frame_hook) + (*FRAME_DISPLAY (f)->delete_frame_hook) (f); + + { + struct display *display = FRAME_DISPLAY (f); - f->output_data.nothing = 0; + f->output_data.nothing = 0; + f->display = 0; /* Now the frame is dead. */ + + /* If needed, delete the device that this frame was on. + (This must be done after the frame is killed.) */ + display->reference_count--; + if (display->reference_count == 0) + { + if (display->delete_display_hook) + (*display->delete_display_hook) (display); + else + delete_display (display); + } + } /* If we've deleted the last_nonminibuf_frame, then try to find another one. */ @@ -1456,11 +1682,11 @@ and returns whatever that function returns. */) #ifdef HAVE_MOUSE /* It's okay for the hook to refrain from storing anything. */ - if (mouse_position_hook) - (*mouse_position_hook) (&f, -1, - &lispy_dummy, &party_dummy, - &x, &y, - &long_dummy); + if (FRAME_DISPLAY (f)->mouse_position_hook) + (*FRAME_DISPLAY (f)->mouse_position_hook) (&f, -1, + &lispy_dummy, &party_dummy, + &x, &y, + &long_dummy); if (! NILP (x)) { col = XINT (x); @@ -1499,11 +1725,11 @@ and nil for X and Y. */) #ifdef HAVE_MOUSE /* It's okay for the hook to refrain from storing anything. */ - if (mouse_position_hook) - (*mouse_position_hook) (&f, -1, - &lispy_dummy, &party_dummy, - &x, &y, - &long_dummy); + if (FRAME_DISPLAY (f)->mouse_position_hook) + (*FRAME_DISPLAY (f)->mouse_position_hook) (&f, -1, + &lispy_dummy, &party_dummy, + &x, &y, + &long_dummy); #endif XSETFRAME (lispy_dummy, f); return Fcons (lispy_dummy, Fcons (x, y)); @@ -1769,16 +1995,19 @@ doesn't support multiple overlapping frames, this function does nothing. */) (frame) Lisp_Object frame; { + struct frame *f; if (NILP (frame)) frame = selected_frame; CHECK_LIVE_FRAME (frame); + f = XFRAME (frame); + /* Do like the documentation says. */ Fmake_frame_visible (frame); - if (frame_raise_lower_hook) - (*frame_raise_lower_hook) (XFRAME (frame), 1); + if (FRAME_DISPLAY (f)->frame_raise_lower_hook) + (*FRAME_DISPLAY (f)->frame_raise_lower_hook) (f, 1); return Qnil; } @@ -1792,13 +2021,17 @@ doesn't support multiple overlapping frames, this function does nothing. */) (frame) Lisp_Object frame; { + struct frame *f; + if (NILP (frame)) frame = selected_frame; CHECK_LIVE_FRAME (frame); - if (frame_raise_lower_hook) - (*frame_raise_lower_hook) (XFRAME (frame), 0); + f = XFRAME (frame); + + if (FRAME_DISPLAY (f)->frame_raise_lower_hook) + (*FRAME_DISPLAY (f)->frame_raise_lower_hook) (f, 0); return Qnil; } @@ -1832,6 +2065,8 @@ The redirection lasts until `redirect-frame-focus' is called to change it. */) (frame, focus_frame) Lisp_Object frame, focus_frame; { + struct frame *f; + /* Note that we don't check for a live frame here. It's reasonable to redirect the focus of a frame you're about to delete, if you know what other frame should receive those keystrokes. */ @@ -1840,10 +2075,12 @@ The redirection lasts until `redirect-frame-focus' is called to change it. */) if (! NILP (focus_frame)) CHECK_LIVE_FRAME (focus_frame); - XFRAME (frame)->focus_frame = focus_frame; + f = XFRAME (frame); + + f->focus_frame = focus_frame; - if (frame_rehighlight_hook) - (*frame_rehighlight_hook) (XFRAME (frame)); + if (FRAME_DISPLAY (f)->frame_rehighlight_hook) + (*FRAME_DISPLAY (f)->frame_rehighlight_hook) (f); return Qnil; } @@ -2732,8 +2969,8 @@ x_set_frame_parameters (f, alist) if (NATNUMP (param_index) && (XFASTINT (param_index) < sizeof (frame_parms)/sizeof (frame_parms[0])) - && rif->frame_parm_handlers[XINT (param_index)]) - (*(rif->frame_parm_handlers[XINT (param_index)])) (f, val, old_value); + && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)]) + (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value); } } } @@ -2776,8 +3013,8 @@ x_set_frame_parameters (f, alist) if (NATNUMP (param_index) && (XFASTINT (param_index) < sizeof (frame_parms)/sizeof (frame_parms[0])) - && rif->frame_parm_handlers[XINT (param_index)]) - (*(rif->frame_parm_handlers[XINT (param_index)])) (f, val, old_value); + && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)]) + (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value); } } @@ -3978,7 +4215,13 @@ syms_of_frame () staticpro (&Qbackground_mode); Qtty_color_mode = intern ("tty-color-mode"); staticpro (&Qtty_color_mode); - + Qtty = intern ("tty"); + staticpro (&Qtty); + Qtty_type = intern ("tty-type"); + staticpro (&Qtty_type); + Qwindow_system = intern ("window-system"); + staticpro (&Qwindow_system); + Qface_set_after_frame_default = intern ("face-set-after-frame-default"); staticpro (&Qface_set_after_frame_default); @@ -3994,6 +4237,11 @@ syms_of_frame () Qx_frame_parameter = intern ("x-frame-parameter"); staticpro (&Qx_frame_parameter); + Qdisplay_id = intern ("display-id"); + staticpro (&Qdisplay_id); + Qdisplay_live_p = intern ("display-live-p"); + staticpro (&Qdisplay_live_p); + { int i; @@ -4067,7 +4315,7 @@ Setting this variable does not affect existing frames, only new ones. */); staticpro (&Qinhibit_default_face_x_resources); DEFVAR_LISP ("terminal-frame", &Vterminal_frame, - doc: /* The initial frame-object, which represents Emacs's stdout. */); + doc: /* The initial frame-object, which represents Emacs's stdout. */); DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified, doc: /* Non-nil if all of emacs is iconified and frame updates are not needed. */); @@ -4115,6 +4363,7 @@ This variable is local to the current terminal and cannot be buffer-local. */); defsubr (&Sactive_minibuffer_window); defsubr (&Sframep); defsubr (&Sframe_live_p); + defsubr (&Swindow_system); defsubr (&Smake_terminal_frame); defsubr (&Shandle_switch_frame); defsubr (&Signore_event); @@ -4125,6 +4374,7 @@ This variable is local to the current terminal and cannot be buffer-local. */); defsubr (&Sframe_first_window); defsubr (&Sframe_selected_window); defsubr (&Sset_frame_selected_window); + defsubr (&Sframe_display); defsubr (&Sframe_list); defsubr (&Snext_frame); defsubr (&Sprevious_frame); |