Subject: bug#5864: 23.1; [PATCH] emacsclient support for setting frame parameters

From: Andreas Rottmann <[email-masked]>
Date: Thu, 08 Apr 2010 17:50:46 +0200

The attached patch (against recent HEAD) adds a new option
`--frame-parameters' to emacsclient, which allows to set the frame
parameter alist for the to-be-created frame.

This feature is useful for window managers that allow matching on X
properties. Without this patch, it is not possible to influence those
at /frame creation time/, they could only be set after the frame was
already created. This is to late for windowmanagers who match, and
typically do so at frame creation time.

diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c
index 1e7ec7d..c4aeb68 100644
--- a/lib-src/emacsclient.c
+++ b/lib-src/emacsclient.c
@@ -154,6 +154,10 @@ char *server_file = NULL;
 /* PID of the Emacs server process.  */
 int emacs_pid = 0;
 
+/* If non-NULL, a string that should form a frame parameter alist to
+   be used for the new frame */
+const char *frame_parameters = NULL;
+
 void print_help_and_exit () NO_RETURN;
 
 struct option longopts[] =
@@ -166,6 +170,7 @@ struct option longopts[] =
   { "nw",	no_argument,       NULL, 't' },
   { "create-frame", no_argument,   NULL, 'c' },
   { "alternate-editor", required_argument, NULL, 'a' },
+  { "frame-parameters", required_argument, NULL, 'F' },
 #ifndef NO_SOCKETS_IN_FILE_SYSTEM
   { "socket-name",	required_argument, NULL, 's' },
 #endif
@@ -587,6 +592,10 @@ decode_options (argc, argv)
 	  print_help_and_exit ();
 	  break;
 
+        case 'F':
+          frame_parameters = optarg;
+          break;
+
 	default:
 	  message (TRUE, "Try `%s --help' for more information\n", progname);
 	  exit (EXIT_FAILURE);
@@ -1620,6 +1629,13 @@ main (argc, argv)
       send_to_emacs (emacs_socket, " ");
     }
 
+  if (frame_parameters && !current_frame)
+    {
+      send_to_emacs (emacs_socket, "-frame-parameters ");
+      quote_argument (emacs_socket, frame_parameters);
+      send_to_emacs (emacs_socket, " ");
+    }
+
   /* If using the current frame, send tty information to Emacs anyway.
      In daemon mode, Emacs may need to occupy this tty if no other
      frame is available.  */
diff --git a/lisp/server.el b/lisp/server.el
index d36b99c..9a7b4c8 100644
--- a/lisp/server.el
+++ b/lisp/server.el
@@ -708,7 +708,10 @@ Server mode runs a process that accepts commands from the
                                      (number-to-string (emacs-pid)) "\n"))
     frame))
 
-(defun server-create-window-system-frame (display nowait proc)
+(defun server-create-window-system-frame (display 
+                                          nowait
+                                          proc
+                                          &optional parameters)
   (add-to-list 'frame-inherited-parameters 'client)
   (if (not (fboundp 'make-frame-on-display))
       (progn
@@ -723,7 +726,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))
            (frame (make-frame-on-display
                    (or display
                        (frame-parameter nil 'display)
@@ -803,6 +807,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.
@@ -904,6 +911,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
@@ -926,6 +934,13 @@ The following commands are accepted by the client:
 		 ;; -current-frame:  Don't create frames.
 		 ((equal "-current-frame" arg) (setq use-current-frame t))
 
+                 ;; -frame-parameters: Set frame parameters
+                 ((equal "-frame-parameters" arg)
+                  (lexical-let ((alist (pop command-line-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.
 		 ((and (equal "-display" arg) command-line-args-left)
@@ -1036,7 +1051,11 @@ The following commands are accepted by the client:
 		    (setq tty-name nil tty-type nil)
 		    (if display (server-select-display display)))
 		   ((eq tty-name 'window-system)
-		    (server-create-window-system-frame display nowait proc))
+		    (server-create-window-system-frame
+                     display
+                     nowait
+                     proc
+                     frame-parameters))
 		   ;; When resuming on a tty, tty-name is nil.
 		   (tty-name
 		    (server-create-tty-frame tty-name tty-type proc))))

Regards, Rotty
-- 
Andreas Rottmann -- <http://rotty.yi.org/>