X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/275a5dd65098a2d6fcc14c21f805fc8d5e4479ee..1dba6978b8c3ee884576f5c45884fd3cf7257c60:/lisp/server.el diff --git a/lisp/server.el b/lisp/server.el index 04d35695c5..34ac5d7ba2 100644 --- a/lisp/server.el +++ b/lisp/server.el @@ -1,6 +1,6 @@ ;;; server.el --- Lisp code for GNU Emacs running as server process -*- lexical-binding: t -*- -;; Copyright (C) 1986-1987, 1992, 1994-2011 Free Software Foundation, Inc. +;; Copyright (C) 1986-1987, 1992, 1994-2012 Free Software Foundation, Inc. ;; Author: William Sommerfeld ;; Maintainer: FSF @@ -112,7 +112,10 @@ If set, the server accepts remote connections; otherwise it is local." (put 'server-host 'risky-local-variable t) (defcustom server-port nil - "The port number that the server process should listen on." + "The port number that the server process should listen on. +This variable only takes effect when the Emacs server is using +TCP instead of local sockets. A nil value means to use a random +port number." :group 'server :type '(choice (string :tag "Port number") @@ -123,6 +126,8 @@ If set, the server accepts remote connections; otherwise it is local." (defcustom server-auth-dir (locate-user-emacs-file "server/") "Directory for server authentication files. +We only use this if `server-use-tcp' is non-nil. +Otherwise we use `server-socket-dir'. NOTE: On FAT32 filesystems, directories are not secure; files can be read and modified by any user or process. @@ -304,11 +309,13 @@ Updates `server-clients'." (setq server-clients (delq proc server-clients)) - ;; Delete the client's tty. - (let ((terminal (process-get proc 'terminal))) - ;; Only delete the terminal if it is non-nil. - (when (and terminal (eq (terminal-live-p terminal) t)) - (delete-terminal terminal))) + ;; Delete the client's tty, except on Windows (both GUI and console), + ;; where there's only one terminal and does not make sense to delete it. + (unless (eq system-type 'windows-nt) + (let ((terminal (process-get proc 'terminal))) + ;; Only delete the terminal if it is non-nil. + (when (and terminal (eq (terminal-live-p terminal) t)) + (delete-terminal terminal)))) ;; Delete the client's process. (if (eq (process-status proc) 'open) @@ -392,16 +399,19 @@ If CLIENT is non-nil, add a description of it to the logged message." ;; visible. If not (which can happen if the user's customizations call ;; pop-to-buffer etc.), delete it to avoid preserving the connection after ;; the last real frame is deleted. - (if (and (eq (frame-first-window frame) - (next-window (frame-first-window frame) 'nomini)) - (eq (window-buffer (frame-first-window frame)) - (frame-parameter frame 'server-dummy-buffer))) - ;; The temp frame still only shows one buffer, and that is the - ;; internal temp buffer. - (delete-frame frame) - (set-frame-parameter frame 'visibility t)) - (kill-buffer (frame-parameter frame 'server-dummy-buffer)) - (set-frame-parameter frame 'server-dummy-buffer nil))) + + ;; Rewritten to avoid inadvertently killing the current buffer after + ;; `delete-frame' removed FRAME (Bug#10729). + (let ((buffer (frame-parameter frame 'server-dummy-buffer))) + (if (and (one-window-p 'nomini frame) + (eq (window-buffer (frame-first-window frame)) buffer)) + ;; The temp frame still only shows one buffer, and that is the + ;; internal temp buffer. + (delete-frame frame) + (set-frame-parameter frame 'visibility t) + (set-frame-parameter frame 'server-dummy-buffer nil)) + (when (buffer-live-p buffer) + (kill-buffer buffer))))) (defun server-handle-delete-frame (frame) "Delete the client connection when the emacsclient frame is deleted. @@ -666,9 +676,13 @@ Return values: ;;;###autoload (define-minor-mode server-mode "Toggle Server mode. -With ARG, turn Server mode on if ARG is positive, off otherwise. +With a prefix argument ARG, enable Server mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +Server mode if ARG is omitted or nil. + Server mode runs a process that accepts commands from the -`emacsclient' program. See `server-start' and Info node `Emacs server'." +`emacsclient' program. See Info node `Emacs server' and +`server-start' for details." :global t :group 'server :version "22.1" @@ -678,8 +692,15 @@ Server mode runs a process that accepts commands from the (defun server-eval-and-print (expr proc) "Eval EXPR and send the result back to client PROC." - (let ((v (eval (car (read-from-string expr))))) - (when (and v proc) + ;; While we're running asynchronously (from a process filter), it is likely + ;; that the emacsclient command was run in response to a user + ;; action, so the user probably knows that Emacs is processing this + ;; emacsclient request, so if we get a C-g it's likely that the user + ;; intended it to interrupt us rather than interrupt whatever Emacs + ;; was doing before it started handling the process filter. + ;; Hence `with-local-quit' (bug#6585). + (let ((v (with-local-quit (eval (car (read-from-string expr)))))) + (when proc (with-temp-buffer (let ((standard-output (current-buffer))) (pp v) @@ -736,7 +757,8 @@ Server mode runs a process that accepts commands from the frame)) -(defun server-create-window-system-frame (display nowait proc parent-id) +(defun server-create-window-system-frame (display nowait proc parent-id + &optional parameters) (add-to-list 'frame-inherited-parameters 'client) (if (not (fboundp 'make-frame-on-display)) (progn @@ -751,7 +773,8 @@ Server mode runs a process that accepts commands from the ;; killing emacs on that frame. (let* ((params `((client . ,(if nowait 'nowait proc)) ;; This is a leftover, see above. - (environment . ,(process-get proc 'env)))) + (environment . ,(process-get proc 'env)) + ,@parameters)) (display (or display (frame-parameter nil 'display) (getenv "DISPLAY") @@ -832,6 +855,9 @@ The following commands are accepted by the server: `-current-frame' Forbid the creation of new frames. +`-frame-parameters ALIST' + Set the parameters of the created frame. + `-nowait' Request that the next frame created should not be associated with this client. @@ -940,6 +966,7 @@ The following commands are accepted by the client: commands dir use-current-frame + frame-parameters ;parameters for newly created frame tty-name ; nil, `window-system', or the tty name. tty-type ; string. files @@ -960,6 +987,13 @@ The following commands are accepted by the client: ;; -current-frame: Don't create frames. (`"-current-frame" (setq use-current-frame t)) + ;; -frame-parameters: Set frame parameters + (`"-frame-parameters" + (let ((alist (pop args-left))) + (if coding-system + (setq alist (decode-coding-string alist coding-system))) + (setq frame-parameters (car (read-from-string alist))))) + ;; -display DISPLAY: ;; Open X frames on the given display instead of the default. (`"-display" @@ -1008,7 +1042,11 @@ The following commands are accepted by the client: (setq tty-name (pop args-left) tty-type (pop args-left) dontkill (or dontkill - (not use-current-frame)))) + (not use-current-frame))) + ;; On Windows, emacsclient always asks for a tty frame. + ;; If running a GUI server, force the frame type to GUI. + (when (eq window-system 'w32) + (push "-window-system" args-left))) ;; -position LINE[:COLUMN]: Set point to the given ;; position in the next file. @@ -1075,7 +1113,8 @@ The following commands are accepted by the client: (if display (server-select-display display))) ((eq tty-name 'window-system) (server-create-window-system-frame display nowait proc - parent-id)) + parent-id + frame-parameters)) ;; When resuming on a tty, tty-name is nil. (tty-name (server-create-tty-frame tty-name tty-type proc)))) @@ -1139,7 +1178,10 @@ The following commands are accepted by the client: "When done with a buffer, type \\[server-edit]"))))) (when (and frame (null tty-name)) (server-unselect-display frame))) - (error (server-return-error proc err))))) + ((quit error) + (when (eq (car err) 'quit) + (message "Quit emacsclient request")) + (server-return-error proc err))))) (defun server-return-error (proc err) (ignore-errors @@ -1186,12 +1228,12 @@ so don't mark these buffers specially, just visit them normally." (add-to-history 'file-name-history filen) (if (null obuf) (progn - (run-hooks 'pre-command-hook) + (run-hooks 'pre-command-hook) (set-buffer (find-file-noselect filen))) (set-buffer obuf) ;; separately for each file, in sync with post-command hooks, ;; with the new buffer current: - (run-hooks 'pre-command-hook) + (run-hooks 'pre-command-hook) (cond ((file-exists-p filen) (when (not (verify-visited-file-modtime obuf)) (revert-buffer t nil))) @@ -1205,7 +1247,7 @@ so don't mark these buffers specially, just visit them normally." (server-goto-line-column (cdr file)) (run-hooks 'server-visit-hook) ;; hooks may be specific to current buffer: - (run-hooks 'post-command-hook)) + (run-hooks 'post-command-hook)) (unless nowait ;; When the buffer is killed, inform the clients. (add-hook 'kill-buffer-hook 'server-kill-buffer nil t) @@ -1488,7 +1530,14 @@ only these files will be asked to be saved." nil) (defun server-eval-at (server form) - "Eval FORM on Emacs Server SERVER." + "Contact the Emacs server named SERVER and evaluate FORM there. +Returns the result of the evaluation, or signals an error if it +cannot contact the specified server. For example: + \(server-eval-at \"server\" '(emacs-pid)) +returns the process ID of the Emacs instance running \"server\". +This function requires the use of TCP sockets. " + (or server-use-tcp + (error "This function requires TCP sockets")) (let ((auth-file (expand-file-name server server-auth-dir)) (coding-system-for-read 'binary) (coding-system-for-write 'binary)