unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* How to get DISPLAY of emacsclient?
@ 2022-11-25 15:17 Max Nikulin
  2022-11-25 16:57 ` Stefan Monnier
  0 siblings, 1 reply; 19+ messages in thread
From: Max Nikulin @ 2022-11-25 15:17 UTC (permalink / raw)
  To: emacs-devel

Hi,

Is it possible to get display of an emacsclient process? I mean either 
--display option argument or the DISPLAY environment variable namely for 
the client.

Unfortunately the value of following expression is the DISPLAY 
environment of the server process

     emacsclient --eval '(getenv "DISPLAY")'

I admit, it should work in most cases, but it is not robust:

     DISPLAY= emacs --daemon --display :0

causes empty string returned by `getenv'. In general, emacsclient's 
display is not necessary the same as the server's one. If I have got it 
correctly, the value is passed from client to server and there is a 
local "display" variable in server.el hidden from evaluated expression.

The context of the question is the following. Org-capture allows to 
create notes in non-distracting way (by setting :immediate-finish t 
property of the capture template). The idea is to save text currently 
selected in some application (either PRIMARY or CLIPBOARD) using a 
global window manager shortcut invoking

      emacsclient --eval '(org-capture nil "x")'

There is a pitfall. Emacs daemon has no frame at startup, so selection 
is inaccessible:

      emacsclient --eval "(org-get-x-clipboard 'PRIMARY)"

returns nil (it is merely a convenient way to call `gui-get-selection'). 
A workaround is to call `server-select-display', but to do so it is 
necessary to know display. That is why I am asking how to obtain display 
of emacsclient.




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: How to get DISPLAY of emacsclient?
  2022-11-25 15:17 How to get DISPLAY of emacsclient? Max Nikulin
@ 2022-11-25 16:57 ` Stefan Monnier
  2022-11-26  3:36   ` Max Nikulin
  0 siblings, 1 reply; 19+ messages in thread
From: Stefan Monnier @ 2022-11-25 16:57 UTC (permalink / raw)
  To: Max Nikulin; +Cc: emacs-devel

> Unfortunately the value of following expression is the DISPLAY environment
> of the server process
>
>     emacsclient --eval '(getenv "DISPLAY")'

There are different ways which will give you different answers in
different cases:

- you can check the `display` parameter of the selected frame (should
  handle the `emacsclient --display` case).
- you can check the `environment` parameter of the selected frame
  (probably not very useful).
- You can check the `env` parameter (with `process-get`) of the proc
  object that represents (on Emacs's side) the emacsclient connection.
  For that you'll need to get access to this proc object, but I don't
  know offhand how to.


-- Stefan




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: How to get DISPLAY of emacsclient?
  2022-11-25 16:57 ` Stefan Monnier
@ 2022-11-26  3:36   ` Max Nikulin
  2022-11-26 21:33     ` chad
  2022-11-27 20:36     ` Jim Porter
  0 siblings, 2 replies; 19+ messages in thread
From: Max Nikulin @ 2022-11-26  3:36 UTC (permalink / raw)
  To: emacs-devel

On 25/11/2022 23:57, Stefan Monnier wrote:
>> Unfortunately the value of following expression is the DISPLAY environment
>> of the server process
>>
>>      emacsclient --eval '(getenv "DISPLAY")'
> 
> There are different ways which will give you different answers in
> different cases:
> 
> - you can check the `display` parameter of the selected frame (should
>    handle the `emacsclient --display` case).

     emacsclient --display "$DISPLAY" \
         --eval "(frame-parameter (selected-frame) 'display)"

may be a workaround, thank you for the idea. A caveat is that --display 
parameter becomes mandatory, DISPLAY environment is not enough:

     emacsclient --eval "(frame-parameter (selected-frame) 'display)"
     nil

Emacs daemon may have no x frames yet at the moment of emacsclient 
invocation.

> - you can check the `environment` parameter of the selected frame
>    (probably not very useful).

      emacsclient --display :0 \
           --eval "(frame-parameter (selected-frame) 'environment)"
      nil

> - You can check the `env` parameter (with `process-get`) of the proc
>    object that represents (on Emacs's side) the emacsclient connection.
>    For that you'll need to get access to this proc object, but I don't
>    know offhand how to.

I am unsure that -display argument is added to the `env` parameter. I do 
not like the following approach since I am afraid of races. Anyway it 
does not work

      emacsclient --eval "(process-get (car server-clients) 'env)"

So I have no idea how to access `proc` passed to a process filter as well.

Though it does not answer to the question how to get DISPLAY, the 
following is at least a workaround:

       DISPLAY= emacs -q --daemon
       emacsclient --display "$DISPLAY" \
           --eval "(require 'org)" \
           --eval "(org-get-x-clipboard 'PRIMARY)"




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: How to get DISPLAY of emacsclient?
  2022-11-26  3:36   ` Max Nikulin
@ 2022-11-26 21:33     ` chad
  2022-11-27 11:34       ` Max Nikulin
  2022-11-27 20:36     ` Jim Porter
  1 sibling, 1 reply; 19+ messages in thread
From: chad @ 2022-11-26 21:33 UTC (permalink / raw)
  To: Max Nikulin; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 174 bytes --]

Have you considered just adding a server hook that opens a gui frame on
daemon start if there is a usable display? (Apologies if you've
already explored this avenue.)

~Chad

[-- Attachment #2: Type: text/html, Size: 256 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: How to get DISPLAY of emacsclient?
  2022-11-26 21:33     ` chad
@ 2022-11-27 11:34       ` Max Nikulin
  2022-11-27 13:42         ` Gregory Heytings
  0 siblings, 1 reply; 19+ messages in thread
From: Max Nikulin @ 2022-11-27 11:34 UTC (permalink / raw)
  To: emacs-devel

On 27/11/2022 04:33, chad wrote:
> Have you considered just adding a server hook that opens a gui frame on 
> daemon start if there is a usable display?

The question is how to determine the display for which emacsclient is 
invoked. It is possible to create a hidden frame by e.g. calling 
`server-select-display', but it is necessary to know display.

> (Apologies if you've 
> already explored this avenue.)

Personally, I have a shell script that works for me, but I would not 
recommend it to others. It adds emacsclient option to create an x frame 
if there is no it yet.

This particular question originates from an emacs-orgmode thread. It was 
explicitly asked that emacs should not pop up hiding currently active 
maximized window of another application (or emacs should disappear 
without additional user action, in this case its behavior should be 
similar to a notification window). Another participant insisted on using 
xsel utility and a temporary file (in a way that is not safe) because 
getting X selection from emacs does not work. I started current thread 
because Ihor Radchenko asked if `org-get-x-clipboard' could be improved 
and I realized that my recipe (getenv "DISPLAY") may work incorrectly in 
some cases.





^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: How to get DISPLAY of emacsclient?
  2022-11-27 11:34       ` Max Nikulin
@ 2022-11-27 13:42         ` Gregory Heytings
  2022-11-27 14:23           ` Max Nikulin
  0 siblings, 1 reply; 19+ messages in thread
From: Gregory Heytings @ 2022-11-27 13:42 UTC (permalink / raw)
  To: Max Nikulin; +Cc: emacs-devel


>
> Personally, I have a shell script that works for me, but I would not 
> recommend it to others. It adds emacsclient option to create an x frame 
> if there is no it yet.
>

Note that emacsclient now has a '--reuse-frame' options, which creates a 
new frame if none exists, and uses the current Emacs frame otherwise.



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: How to get DISPLAY of emacsclient?
  2022-11-27 13:42         ` Gregory Heytings
@ 2022-11-27 14:23           ` Max Nikulin
  2022-11-27 14:38             ` Gregory Heytings
  2022-11-28  1:19             ` Po Lu
  0 siblings, 2 replies; 19+ messages in thread
From: Max Nikulin @ 2022-11-27 14:23 UTC (permalink / raw)
  To: emacs-devel

On 27/11/2022 20:42, Gregory Heytings wrote:
> 
>> Personally, I have a shell script that works for me, but I would not 
>> recommend it to others. It adds emacsclient option to create an x 
>> frame if there is no it yet.
> 
> Note that emacsclient now has a '--reuse-frame' options, which creates a 
> new frame if none exists, and uses the current Emacs frame otherwise.

Thank you for adding such option. I mentioned my script mostly to show 
that requirements of different users are not the same. Since I have a 
solution working for me, I considered the priority of my issue as rather 
low. Moreover the emacs-help mailing list may be more suitable to 
discuss it. Perhaps the new option solves it.

Currently I prefer to concentrate on the case of accessing X selection 
or getting DISPLAY without creation of visible frames.

P.S. My script notifies me that emacs server is not running, so it is 
unlikely that I will completely remove it. It is off-topic in this 
thread however.




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: How to get DISPLAY of emacsclient?
  2022-11-27 14:23           ` Max Nikulin
@ 2022-11-27 14:38             ` Gregory Heytings
  2022-11-27 15:26               ` Max Nikulin
  2022-11-28  1:19             ` Po Lu
  1 sibling, 1 reply; 19+ messages in thread
From: Gregory Heytings @ 2022-11-27 14:38 UTC (permalink / raw)
  To: Max Nikulin; +Cc: emacs-devel


>
> Currently I prefer to concentrate on the case of accessing X selection 
> or getting DISPLAY without creation of visible frames.
>

Sorry, I don't understand what "getting DISPLAY without creation of 
visible frames" means.  Is the $DISPLAY environment variable not enough?



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: How to get DISPLAY of emacsclient?
  2022-11-27 14:38             ` Gregory Heytings
@ 2022-11-27 15:26               ` Max Nikulin
  2022-11-27 16:12                 ` Gregory Heytings
  0 siblings, 1 reply; 19+ messages in thread
From: Max Nikulin @ 2022-11-27 15:26 UTC (permalink / raw)
  To: emacs-devel

On 27/11/2022 21:38, Gregory Heytings wrote:
> 
>> Currently I prefer to concentrate on the case of accessing X selection 
>> or getting DISPLAY without creation of visible frames.
> 
> Sorry, I don't understand what "getting DISPLAY without creation of 
> visible frames" means.  Is the $DISPLAY environment variable not enough?

I do not see a way to get the value of the DISPLAY environment variable 
specific to the emacsclient process. In some corner cases in may differ 
from emacs server display. For testing purposes the following may be used:

     DISPLAY= emacs --daemon

A workaround I have found so far is to specify display explicitly

     emacsclient --display "$DISPLAY" ...




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: How to get DISPLAY of emacsclient?
  2022-11-27 15:26               ` Max Nikulin
@ 2022-11-27 16:12                 ` Gregory Heytings
  0 siblings, 0 replies; 19+ messages in thread
From: Gregory Heytings @ 2022-11-27 16:12 UTC (permalink / raw)
  To: Max Nikulin; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 868 bytes --]


>>> Currently I prefer to concentrate on the case of accessing X selection 
>>> or getting DISPLAY without creation of visible frames.
>> 
>> Sorry, I don't understand what "getting DISPLAY without creation of 
>> visible frames" means.  Is the $DISPLAY environment variable not 
>> enough?
>
> I do not see a way to get the value of the DISPLAY environment variable 
> specific to the emacsclient process.
>

But where do you need that value, and what do you mean by "without 
creation of visible frames"?  Not all emacsclient processes have a 
corresponding display, e.g. if you just do

emacsclient --eval '(+ 1 1)'

there is no display involved.  If you create an emacsclient process with 
-c or -r, then in Elisp you can get the display on which the frame is 
displayed with (getenv "DISPLAY"), or (cdr (assq 'display 
(frame-parameters))).

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: How to get DISPLAY of emacsclient?
  2022-11-26  3:36   ` Max Nikulin
  2022-11-26 21:33     ` chad
@ 2022-11-27 20:36     ` Jim Porter
  2022-11-28 15:33       ` Max Nikulin
  1 sibling, 1 reply; 19+ messages in thread
From: Jim Porter @ 2022-11-27 20:36 UTC (permalink / raw)
  To: Max Nikulin, emacs-devel

On 11/25/2022 7:36 PM, Max Nikulin wrote:
> On 25/11/2022 23:57, Stefan Monnier wrote:
>> - you can check the `display` parameter of the selected frame (should
>>    handle the `emacsclient --display` case).
> 
>      emacsclient --display "$DISPLAY" \
>          --eval "(frame-parameter (selected-frame) 'display)"
> 
> may be a workaround, thank you for the idea. A caveat is that --display 
> parameter becomes mandatory, DISPLAY environment is not enough...

Looking through the emacsclient.c code, I think this is intentional, and 
if you want to do something like this, the above workaround is exactly 
what you're supposed to do:

      If the -c option is used (without -t) and no --display argument
      is provided, try $DISPLAY.
      Without the -c option, we used to set 'display' to $DISPLAY by
      default, but this changed the default behavior and is sometimes
      inconvenient.  So we force users to use "--display $DISPLAY" if
      they want Emacs to connect to their current display.



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: How to get DISPLAY of emacsclient?
  2022-11-27 14:23           ` Max Nikulin
  2022-11-27 14:38             ` Gregory Heytings
@ 2022-11-28  1:19             ` Po Lu
  1 sibling, 0 replies; 19+ messages in thread
From: Po Lu @ 2022-11-28  1:19 UTC (permalink / raw)
  To: Max Nikulin; +Cc: emacs-devel

Max Nikulin <manikulin@gmail.com> writes:

> Thank you for adding such option. I mentioned my script mostly to show
> that requirements of different users are not the same. Since I have a
> solution working for me, I considered the priority of my issue as
> rather low. Moreover the emacs-help mailing list may be more suitable
> to discuss it. Perhaps the new option solves it.
>
> Currently I prefer to concentrate on the case of accessing X selection
> or getting DISPLAY without creation of visible frames.

`x-open-connection' is your friend.



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: How to get DISPLAY of emacsclient?
  2022-11-27 20:36     ` Jim Porter
@ 2022-11-28 15:33       ` Max Nikulin
  2022-11-28 17:15         ` Gregory Heytings
  2022-11-28 18:19         ` Stefan Monnier
  0 siblings, 2 replies; 19+ messages in thread
From: Max Nikulin @ 2022-11-28 15:33 UTC (permalink / raw)
  To: emacs-devel

On 28/11/2022 03:36, Jim Porter wrote:
> 
> Looking through the emacsclient.c code, I think this is intentional, and 
> if you want to do something like this, the above workaround is exactly 
> what you're supposed to do:
> 
>       If the -c option is used (without -t) and no --display argument
>       is provided, try $DISPLAY.
>       Without the -c option, we used to set 'display' to $DISPLAY by
>       default, but this changed the default behavior and is sometimes
>       inconvenient.  So we force users to use "--display $DISPLAY" if
>       they want Emacs to connect to their current display.

Thank you, I have reread emacsclinet code and have realized that I did 
not expect such behavior. At first I missed that environment is sent to 
server only if -c option is specified and the DISPLAY environment may be 
ignored. I believed that display value is always received, but can not 
be obtained because it is assigned to a local variable. Actually it is 
not sent for simple eval.

It is not stressed in the manual that emacsclient uses the --display 
option and the DISPLAY environment in a rather unusual way in comparison 
to other X application. I considered --display option as a way to 
override $DISPLAY and nothing more.

     emacsclient --display "$DISPLAY" --eval ...

behaves as required despite it looks a bit strange. It reuses existing X 
connection or creates a new hidden frame. As a result X selection 
becomes available without additional function calls.

On 28/11/2022 08:19, Po Lu wrote:
> `x-open-connection' is your friend.

The problem was to determine DISPLAY argument for this function. 
Moreover it is not enough and (gui-get-selection) return nil if just 
`x-open-connection' is called from emacsclient. In this sense 
`server-select-display' is better, but it requires DISPLAY as well.

On 27/11/2022 23:12, Gregory Heytings wrote:
> there is no display involved.  If you create an emacsclient process with
> -c or -r, then in Elisp you can get the display on which the frame is
> displayed with (getenv "DISPLAY"), or (cdr (assq 'display
> (frame-parameters))).

I was seeking a way to avoid creation a visible frame and to call a 
function that does not work without X connection.

So I should thank Jim again for drawing my attention why the effect of 
the --display option is stronger than for the DISPLAY environment. This 
option indirectly solves the problem.




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: How to get DISPLAY of emacsclient?
  2022-11-28 15:33       ` Max Nikulin
@ 2022-11-28 17:15         ` Gregory Heytings
  2022-11-28 18:19         ` Stefan Monnier
  1 sibling, 0 replies; 19+ messages in thread
From: Gregory Heytings @ 2022-11-28 17:15 UTC (permalink / raw)
  To: Max Nikulin; +Cc: emacs-devel


>
> I was seeking a way to avoid creation a visible frame and to call a 
> function that does not work without X connection.
>
> So I should thank Jim again for drawing my attention why the effect of 
> the --display option is stronger than for the DISPLAY environment. This 
> option indirectly solves the problem.
>

I still think this is an ill-posed problem, so here are a few additional 
thoughs, in case you find them useful.  There are at least three cases:

1. "emacsclient --eval '(+ 1 1)'" does NOT use a display: it is evaluated 
in the server process.  You can use '(getenv DISPLAY)' there, but it will 
not return any useful information, it will return the value of DISPLAY 
that was current when the Emacs daemon was created.

2. "emacsclient -c", which creates a frame on the display specified in the 
environment variable DISPLAY (if DISPLAY is unset, "emacsclient -c" is 
equivalent to "emacsclient -nw").

3. "emacsclient --display <DISPLAY> -c", which creates a frame on the 
specified display <DISPLAY>; it is equivalent to "env DISPLAY=<DISPLAY> 
emacsclient -c".

If you want to know the value if the environment variable DISPLAY in case 
1, the best way to do that is to explicitly include "$DISPLAY" in the form 
you evaluate, e.g. like this:

emacsclient --eval '(progn (setq display "'$DISPLAY'") (princ display))'



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: How to get DISPLAY of emacsclient?
  2022-11-28 15:33       ` Max Nikulin
  2022-11-28 17:15         ` Gregory Heytings
@ 2022-11-28 18:19         ` Stefan Monnier
  2022-11-29 16:23           ` Max Nikulin
  1 sibling, 1 reply; 19+ messages in thread
From: Stefan Monnier @ 2022-11-28 18:19 UTC (permalink / raw)
  To: Max Nikulin; +Cc: emacs-devel

> Thank you, I have reread emacsclinet code and have realized that I did not
> expect such behavior. At first I missed that environment is sent to server
> only if -c option is specified and the DISPLAY environment may be
> ignored.

IIRC there is no good reason other than a historical accident (and the
fact that there was no clear need for it) why the environment isn't sent
in all cases.  IOW, we could change it without breaking
backward compatibility, AFAIK.


        Stefan




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: How to get DISPLAY of emacsclient?
  2022-11-28 18:19         ` Stefan Monnier
@ 2022-11-29 16:23           ` Max Nikulin
  2022-11-30  0:41             ` chad
  0 siblings, 1 reply; 19+ messages in thread
From: Max Nikulin @ 2022-11-29 16:23 UTC (permalink / raw)
  To: emacs-devel

On 29/11/2022 01:19, Stefan Monnier wrote:
>> Thank you, I have reread emacsclinet code and have realized that I did not
>> expect such behavior. At first I missed that environment is sent to server
>> only if -c option is specified and the DISPLAY environment may be
>> ignored.
> 
> IIRC there is no good reason other than a historical accident (and the
> fact that there was no clear need for it) why the environment isn't sent
> in all cases.  IOW, we could change it without breaking
> backward compatibility, AFAIK.

I agree with Gregory that --eval often does not need display. Certainly 
there are enough cases when X connection is undesired. If a frame is not 
ensured then display value is inaccessible from elisp code even 
indirectly. That is why there is a little point in sending display 
without exposing it through a variable. I do not mind to have such 
variable though.

I think, the problem is that the --display option is overloaded as an 
interface familiar for X11 users. I have not tried other OSes, but the 
issue may be even more severe. I have an idea to mention "emacsclient 
--display ..." in the Org manual e,g, in info "(org) Protocols" and 
maybe in info "(org) Capture" sections
https://orgmode.org/manual/Protocols.html
https://orgmode.org/manual/Capture.html
I do not like too verbose details related to special display values for 
Windows and macOS.

Perhaps a boolean flag like --force-display would be easier to discover 
and --display DISPLAY may assume --force-display. I hope it will be 
easier to discover and its effect will be more clear.

At least I would consider changing of documentation:
info "(emacs) emacsclient Options"
https://www.gnu.org/software/emacs/manual/html_node/emacs/emacsclient-Options.html
"Ensure connection to the specified display (X11 or OS-specific). Notice 
that without this option the DISPLAY environment is used to create a new 
frame, but it is ignored for --eval expressions when frame-related 
options are omitted."
instead of current

> Tell Emacs to open the given files on the X display display (assuming
> there is more than one X display available)

I have no idea of a concise variant to replace emacsclient --help:

> Visit the file in the given display

On 29/11/2022 00:15, Gregory Heytings wrote:
> I still think this is an ill-posed problem, so here are a few additional
> thoughs, in case you find them useful.

I agree that it is not really common, but I see no reason why the 
following cases are ill-posed:

Add to user notes content of X selection when emacs is started as 
daemong with no frames and the user prefers to avoid distraction due to 
creation of a new frame.

User connected to another machine through ssh (e.g. from a laptop to a 
desktop). In this case DISPLAY is different for the client and for the 
server process. (gui-get-selection) should be executed for client's DISPLAY.

> 1. "emacsclient --eval '(+ 1 1)'" does NOT use a display: it is
> evaluated in the server process.  You can use '(getenv DISPLAY)' there,
> but it will not return any useful information, it will return the value
> of DISPLAY that was current when the Emacs daemon was created.

Sometimes (getenv "DISPLAY") gives wrong result and I tried to highlight 
it in my first message and above.

> 2. "emacsclient -c", which creates a frame on the display specified in
> the environment variable DISPLAY (if DISPLAY is unset, "emacsclient -c"
> is equivalent to "emacsclient -nw").

Terminal frame may still be associated with DISPLAY as well. The 
challenge is to get something useful from `gui-get-selection' (may be 
called by `org-capture') in the absence of a visible frame.

> 3. "emacsclient --display <DISPLAY> -c", which creates a frame on the
> specified display <DISPLAY>; it is equivalent to "env DISPLAY=<DISPLAY>
> emacsclient -c".

A subtle point is that the DISPLAY environment affects only -c while 
--display forces X11 connection even for --eval.

> If you want to know the value if the environment variable DISPLAY in
> case 1, the best way to do that is to explicitly include "$DISPLAY" in
> the form you evaluate, e.g. like this:

I saw that display value is sent as a part of environment and as a 
dedicated message. I had a hope that it is possible to access these 
values, so adding it once more inside --eval expression is redundant. I 
missed that it is sent *conditionally*.

> emacsclient --eval '(progn (setq display "'$DISPLAY'") (princ display))' 

Unfortunately it is unsafe way to pass external values to elisp. It is 
unlikely, but if accidentally DISPLAY is set to some value with spaces 
and various shell special characters then arbitrary commands may be 
executed unexpectedly. I hope, some day I will summarize a discussion 
with Jim as a feature request to support a kind of 
`command-line-args-left' in expressions passed from emacsclient.

Max Nikulin to emacs-orgmode. Re: Lazy load of org-protocol. Wed, 9 Feb 
2022 23:46:26 +0700. https://list.orgmode.org/su0r54$f42$1@ciao.gmane.io

Another pair of double quotes around $DISPLAY will deactivate shell 
special characters, but it is still necessary to escape double quotes 
and backslashes to keep elisp expression well formed. Consider

     DISPLAY=':0") (do-something-else) (ignore "'




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: How to get DISPLAY of emacsclient?
  2022-11-29 16:23           ` Max Nikulin
@ 2022-11-30  0:41             ` chad
  2022-11-30  2:44               ` Stefan Monnier
  0 siblings, 1 reply; 19+ messages in thread
From: chad @ 2022-11-30  0:41 UTC (permalink / raw)
  To: Max Nikulin; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1963 bytes --]

On Tue, Nov 29, 2022 at 1:11 PM Max Nikulin <manikulin@gmail.com> wrote:

> [...]
> Add to user notes content of X selection when emacs is started as
> daemong with no frames and the user prefers to avoid distraction due to
> creation of a new frame.
>

In general, you seem to assume that there's no way for emacs to create a
new X11 frame object without it being immediately visible to the user. In
my experience, that's only true in the limited subset of cases where the
user has chosen a window manager that enforces that choice. Further, that
wasn't the default when I last looked -- but that was quite some time ago,
and I don't know about the current options/defaults for common X11-based
display systems of today. Can anyone shed some light on this?

On Tue, Nov 29, 2022 at 1:11 PM Max Nikulin <manikulin@gmail.com> wrote:

> [...]

User connected to another machine through ssh (e.g. from a laptop to a
> desktop). In this case DISPLAY is different for the client and for the
> server process. (gui-get-selection) should be executed for client's
> DISPLAY.
>

In the past, I have regularly seen both varieties of this: where the user
was logged into two machines, with an emacs server running on one, X
displays on both, and wanted a new emacs frame on either one, depending on
circumstances. As near as I can tell, there is no "right" choice here; the
user needs to (be able to) provide input on which display to use.

This is a fundamentally different case from "the user wants to use a
non-graphical X11-based mechanism that emacs normally doesn't enable until
emacs actually connects to a working X11 display", and I think it should be
possible to get emacs to make that connection without necessarily popping
up a window that the user doesn't want.

I hope that helps,
~Chad
P.S. Now that I've said it "out loud", I expect to learn that either the
Wayland people now consider that a security hole and will disallow it, or
that they already did so.

[-- Attachment #2: Type: text/html, Size: 2859 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: How to get DISPLAY of emacsclient?
  2022-11-30  0:41             ` chad
@ 2022-11-30  2:44               ` Stefan Monnier
  2022-11-30 12:47                 ` Max Nikulin
  0 siblings, 1 reply; 19+ messages in thread
From: Stefan Monnier @ 2022-11-30  2:44 UTC (permalink / raw)
  To: chad; +Cc: Max Nikulin, emacs-devel

chad [2022-11-29 19:41:11] wrote:
> On Tue, Nov 29, 2022 at 1:11 PM Max Nikulin <manikulin@gmail.com> wrote:
>> [...]
>> Add to user notes content of X selection when emacs is started as
>> daemong with no frames and the user prefers to avoid distraction due to
>> creation of a new frame.
> In general, you seem to assume that there's no way for emacs to create a
> new X11 frame object without it being immediately visible to the user. In
> my experience, that's only true in the limited subset of cases where the
> user has chosen a window manager that enforces that choice. Further, that
> wasn't the default when I last looked -- but that was quite some time ago,
> and I don't know about the current options/defaults for common X11-based
> display systems of today. Can anyone shed some light on this?

`xclip.el` (from GNU ELPA) uses:

    (defun xclip--hidden-frame ()
      (or xclip--hidden-frame
          (setq xclip--hidden-frame
                (make-frame-on-display (getenv "DISPLAY")
                                       '((visibility . nil)
                                         (user-position . t)
                                         (left . 0)
                                         (top . 0)
                                         (no-other-frame . t))))))

I haven't heard of a problem with that yet, but it probably hasn't been
widely tested (and it is specific to X11).

> This is a fundamentally different case from "the user wants to use a
> non-graphical X11-based mechanism that emacs normally doesn't enable until
> emacs actually connects to a working X11 display", and I think it should be
> possible to get emacs to make that connection without necessarily popping
> up a window that the user doesn't want.

server.el also does something similar to xclip-mode, tho with simpler
code:

    (defun server-select-display (display)
      ;; If the current frame is on `display' we're all set.
      ;; Similarly if we are unable to open frames on other displays, there's
      ;; nothing more we can do.
      (unless (or (not (fboundp 'make-frame-on-display))
                  (server--on-display-p (selected-frame) display))
        ;; Otherwise, look for an existing frame there and select it.
        (dolist (frame (frame-list))
          (when (server--on-display-p frame display)
    	(select-frame frame)))
        ;; If there's no frame on that display yet, create and select one.
        (unless (server--on-display-p (selected-frame) display)
          (let* ((buffer (generate-new-buffer " *server-dummy*"))
                 (frame (make-frame-on-display
                         display
                         ;; Make it display (and remember) some dummy buffer, so
                         ;; we can detect later if the frame is in use or not.
                         `((server-dummy-buffer . ,buffer)
                           ;; This frame may be deleted later (see
                           ;; server-unselect-display) so we want it to be as
                           ;; unobtrusive as possible.
                           (visibility . nil)))))
            (select-frame frame)
            (set-window-buffer (selected-window) buffer)
            frame))))

This code has been used a lot more widely, but in many/most cases we end
up making that frame visible soon after, so there might be cases where
it is not 100% unobtrusive but users don't notice it.


        Stefan




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: How to get DISPLAY of emacsclient?
  2022-11-30  2:44               ` Stefan Monnier
@ 2022-11-30 12:47                 ` Max Nikulin
  0 siblings, 0 replies; 19+ messages in thread
From: Max Nikulin @ 2022-11-30 12:47 UTC (permalink / raw)
  To: emacs-devel

To avoid misunderstanding,
     emacsclient --display "$DISPLAY" --eval ...
solves the problem (on Linux). For me, reasons to continue the 
discussion is that Stefan considered changes in Emacs code and that some 
suggestions was oversimplified.

On 30/11/2022 09:44, Stefan Monnier wrote:
> chad [2022-11-29 19:41:11] wrote:
>> On Tue, Nov 29, 2022 at 1:11 PM Max Nikulin wrote:
>>> [...]
>>> Add to user notes content of X selection when emacs is started as
>>> daemong with no frames and the user prefers to avoid distraction due to
>>> creation of a new frame.
>> In general, you seem to assume that there's no way for emacs to create a
>> new X11 frame object without it being immediately visible to the user. In
>> my experience, that's only true in the limited subset of cases where the
>> user has chosen a window manager that enforces that choice.

No, I did not assume it, it the starting message I mentioned 
`server-select-display' that creates a hidden frame. I have not tested 
various window managers though, I hope it just works. I was aware of 
info "(elisp) Visibility of Frames" 
https://www.gnu.org/software/emacs/manual/html_node/elisp/Visibility-of-Frames.html 
The problem is how to determine proper display from an expression passed 
to emacsclient --eval.

> `xclip.el` (from GNU ELPA) uses:

Interesting, I had an impression that the main reason to invoke 
xclip/pbcopy/etc from Emacs is an alternative MIME type (selection 
target), e.g. text/html in the case of https://github.com/jkitchin/ox-clip

>            (setq xclip--hidden-frame
>                  (make-frame-on-display (getenv "DISPLAY")

It is appropriate for Emacs compiled with no X11 support, but in 
general, when overridden by --display, it may cause connection to a 
wrong display. Another case
     DISPLAY= emacs --daemon --display :0

>                                         '((visibility . nil)
>                                           (user-position . t)
>                                           (left . 0)
>                                           (top . 0)
>                                           (no-other-frame . t))))))

I consider it as another argument that `x-open-connection' is not enough 
to get selection and a frame is required.

> I haven't heard of a problem with that yet, but it probably hasn't been
> widely tested (and it is specific to X11).

I would say that, accordingly to the code, it is specific to 
(eq xclip-method 'emacs), not to X11.

>> This is a fundamentally different case from "the user wants to use a
>> non-graphical X11-based mechanism that emacs normally doesn't enable until
>> emacs actually connects to a working X11 display"

I never expected getting selection without opening of an X connection. I 
think an X11 window (frame in Emacs parlance) is not strictly necessary, 
but I am quite happy with a hidden frame.

> server.el also does something similar to xclip-mode, tho with simpler
> code:

Despite server.el sets less frame properties, it skips creation a frame 
if another one already exists on the specified display. That is why I 
would not call its code simpler.

> This code has been used a lot more widely, but in many/most cases we end
> up making that frame visible soon after, so there might be cases where
> it is not 100% unobtrusive but users don't notice it.

I have not noticed any problem with this code (besides tightly 
encapsulated value of display), but I have tried only Linux.

chad [2022-11-29 19:41:11] wrote:
> On Tue, Nov 29, 2022 at 1:11 PM Max Nikulin wrote:
> 
>> User connected to another machine through ssh (e.g. from a laptop to a
>> desktop). In this case DISPLAY is different for the client and for the
>> server process. (gui-get-selection) should be executed for client's DISPLAY.
> 
> In the past, I have regularly seen both varieties of this: where the
> user was logged into two machines, with an emacs server running on one,
> X displays on both, and wanted a new emacs frame on either one,
> depending on circumstances. As near as I can tell, there is no "right"
> choice here; the user needs to (be able to) provide input on which
> display to use.

I agree with you in general but in the case of accessing selected text 
it is almost certainly display where emacsclient is called.

Such choice is a reason that I did not consider the --display option at 
first. Usually its purpose is solely to override "$DISPLAY" value 
without additional effects.




^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2022-11-30 12:47 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-11-25 15:17 How to get DISPLAY of emacsclient? Max Nikulin
2022-11-25 16:57 ` Stefan Monnier
2022-11-26  3:36   ` Max Nikulin
2022-11-26 21:33     ` chad
2022-11-27 11:34       ` Max Nikulin
2022-11-27 13:42         ` Gregory Heytings
2022-11-27 14:23           ` Max Nikulin
2022-11-27 14:38             ` Gregory Heytings
2022-11-27 15:26               ` Max Nikulin
2022-11-27 16:12                 ` Gregory Heytings
2022-11-28  1:19             ` Po Lu
2022-11-27 20:36     ` Jim Porter
2022-11-28 15:33       ` Max Nikulin
2022-11-28 17:15         ` Gregory Heytings
2022-11-28 18:19         ` Stefan Monnier
2022-11-29 16:23           ` Max Nikulin
2022-11-30  0:41             ` chad
2022-11-30  2:44               ` Stefan Monnier
2022-11-30 12:47                 ` Max Nikulin

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).