emacsomancer / equake

A drop-down console written in Emacs Lisp, designed for eshell and terminal emulation.
GNU General Public License v3.0
2 stars 0 forks source link

Can't run without an existing frame. #4

Closed emacsomancer closed 2 months ago

emacsomancer commented 4 years ago

In GitLab by @artemyurchenko on May 11, 2020, 14:34

I'm attaching a somewhat minimal config file to reproduce the problem:.emacs.

The steps to reproduce are:

Expected behaviour: equake frame pops up.

Actual behaviour: *ERROR*: Unknown terminal type

I suspect that the issue is with 'make-frame' call. It might be connected to this, although the proposed solution didn't work for me.

I would be very glad if you could help.

emacsomancer commented 4 years ago

yeah, that's a problem. I inevitably have an emacsclient frame open somewhere.

Here's a complicated workaround:

instead of emacsclient -n -e '(equake-invoke)', try (as your run command):

if [ $(emacsclient -n -e '(length (frame-list))') -lt 2 ]; then emacsclient -n -e '(make-frame-on-display ":0")'; emacsclient -n -e '(progn (sleep-for 1) (equake-invoke) (sleep-for 1) (delete-frame (cadr (frame-list))))'; else emacsclient -n -e '(equake-invoke)'; fi

(the other issue is that equake takes a moment to initialise the first time; but you might try playing with the exact sleep-for times)

emacsomancer commented 4 years ago

(see also here for related discussion.)

emacsomancer commented 4 years ago

In GitLab by @artemyurchenko on May 13, 2020, 01:11

It appears that emacs hangs on sleep-for before finishing creating a frame, so I get the same error. I don't know how concurrency works in emacs, so I have no idea why it's happening. However, I found that doing sleep 1 before the second command solves the problem:

if [ $(emacsclient -n -e '(length (frame-list))') -lt 2 ]; then
    emacsclient -n -e '(make-frame-on-display ":0")';
    sleep 0.1
    emacsclient -n -e '(progn
        (equake-invoke)
        (delete-frame (cadr (frame-list))))';
else
    emacsclient -n -e '(equake-invoke)';
fi

That works perfectly, thanks for the workaround!

emacsomancer commented 4 years ago

In GitLab by @artemyurchenko on May 13, 2020, 01:51

Or it doesn't. After creating and closing another emacs GUI frame it throws the same error, although the equake frame has been created.

I guess, we need to subtract number of equake frames from the total number frames.

emacsomancer commented 4 years ago

What error are you getting? *ERROR*: Mouse pointer location out of range ? Or *ERROR*: Unknown terminal type ? Or something else?

Or it doesn't. After creating and closing another emacs GUI frame it throws the same error, although the equake frame has been created.

On my machine, the problem is only when no frames exist. If I open an Emacs frame, and then invoke equake for the first time, and then close the first Emacs frame, then I can toggle equake with no issue.

What is your GUI environment? (Which DE or WM?) (The other thing to try, if you're in X11, is to turn on (setq equake-use-xdotool-probe 't) and see if that affects the behaviour [when used with the workaround].)

emacsomancer commented 4 years ago

In GitLab by @artemyurchenko on May 21, 2020, 13:43

Sorry, for the delay. It is *ERROR*: Unknown terminal type. If I do what you described, the problem doesn't arise as well.

However, if I do the following:

  1. restart emacs server
  2. toggle equake on and off with the suggested workaround
  3. open and close an emacs client frame
  4. try to toggle equake

I get the error.

My environment is KDE Plasma on X11. Setting (setq equake-use-xdotool-probe 't) leads to the following error: *ERROR*: Symbol’s function definition is void: second

emacsomancer commented 4 years ago

For the *ERROR*: Symbol’s function definition is void: second error, perhaps xdotool is not installed> (I should probably add a check for that.)

emacsomancer commented 4 years ago

In GitLab by @artemyurchenko on May 21, 2020, 15:09

xdotool is installed

emacsomancer commented 4 years ago

ok, that's weird.

what output do you get if you evaluate (display-monitor-attributes-list) (in *scratch* or with M-:?

EDIT: Ok, I figured out one thing: if you start with emacs -q or emacs -Q then the subr.el internal package isn't loaded, and second, third &c. are defined there. I'm going to update those bits with a different method that shouldn't fail in that case.

emacsomancer commented 4 years ago

In GitLab by @artemyurchenko on May 22, 2020, 02:29

(((name . "eDP1") (geometry 0 0 1600 900) (workarea 0 0 1600 900) (mm-size 310 170) (frames #<frame *EQUAKE*[eDP1] 0x6754eb0> #<frame emacs@hedgehog 0x60091d0>) (source . "Gdk")))

emacsomancer commented 4 years ago

I pushed a new version that shouldn't produce the *ERROR*: Symbol’s function definition is void: second error. You can try it either from here or update via MELPA.

emacsomancer commented 4 years ago

In GitLab by @artemyurchenko on May 22, 2020, 10:47

I've updated. Now it's *ERROR*: Mouse pointer location out of range following the aforementioned steps.

emacsomancer commented 4 years ago

Yeah, that's the error I was getting before.

Let me ponder this a bit.

emacsomancer commented 4 years ago

In GitLab by @artemyurchenko on Jul 12, 2020, 06:59

Also, it seems to work weirdly in terminal frames. Also using geometry as a monitor ID breaks xprop command (fixable though). It seems, that it makes sense to just ignore every display that doesn't have a name attribute (that is, no physical display tied). Am I missing something?

emacsomancer commented 4 years ago

Unfortunately lots of things have come up since my last message and I haven't had a chance to think much about this in the meantime.

I have no idea how Equake works in terminal frames - I never tested that - I assume "not at all". (Probably shell-pop would be more appropriate for terminal use.)

Using geometry as the monitor id was a workaround I had to do for a single-screen laptop where there was no name or other identifier assigned to the display. But it sounds like it's creating some issues?

emacsomancer commented 4 years ago

In GitLab by @artemyurchenko on Jul 12, 2020, 11:07

It requires escaping when using with xprop since it includes whitespaces.

I'm trying to fix the issue in question myself and I have a few ideas that I'm implementing right now. It would be nice to have your opinion before I go to far into it.

First, I think the issue can be solved if we always create a new frame in some graphical environment (when no graphical frames are found). For that, we need to either specify window-system (x or nt or whatever) or display (e.g. ":0"). It's easy enough on X11 but I don't know a cross platform way to specify it (is it even a concern? it seems that you use quite a lot of x11-specific utilities). I would be glad if you could share you thoughts on that.

The implication of that is that frame name can not be directly tied to a monitor name (or geometry): it's not known before the frame creation. It seems logical to me, to add a unique id to the frame name (based on a counter, e.g.) and store a mapping of it to a monitor. Should concurrency be considered a problem here?

emacsomancer commented 4 years ago

Perhaps one way of addressing this is to create a new method alongside of the old method. I tried to keep the system as crossplatform as possible, but in practice I only use X11 myself. Then there could be a user-settable boolean to either use the old method or use the new method. That frees the new method of dealing with frames from the constraints of the old method.

It makes sense to me to have the method not have to be tied to the monitor name (or geometry). Though we would want to determine the geometry at some point to get the size right (unless the user has to just manually specify those?).

What concurrency concerns do you foresee?

emacsomancer commented 4 years ago

In GitLab by @artemyurchenko on Jul 12, 2020, 12:06

I don't want to completely drop reliance on geometry, I just think it's better not to use it as id.

As for concurrency issues, if I were to implement a unique id via a counter, I would want this counter to be thread-safe (to guarantee uniqueness). Unfortunately, I'm not familiar with emacs lisp memory model and I've heard that it's generally single-threaded, so that is not a concern at all (?).

emacsomancer commented 4 years ago

I see what you mean for geometry - that sounds reasonable.

For unique ids, what about using something like UUIDs - e.g. https://nullprogram.com/blog/2010/05/11/ ?

emacsomancer commented 4 years ago

In GitLab by @artemyurchenko on Jul 12, 2020, 13:37

That's an interesting idea. Though that code doesn't have a license, I wonder if it's okay to reuse it.

emacsomancer commented 4 years ago

Under "Licensing" on https://nullprogram.com/about/ it indicates that all code on the blog is released into the public domain.

emacsomancer commented 4 years ago

In GitLab by @artemyurchenko on Jul 12, 2020, 13:50

Oh, I should have payed more attention

emacsomancer commented 4 years ago

In GitLab by @artemyurchenko on Jul 13, 2020, 06:44

(getenv "DISPLAY") appears to be working cross-platformly (I tested on x11, wayland, mac os and windows), so I guess it's okay to replace the old method altogether.

emacsomancer commented 4 years ago

Excellent

emacsomancer commented 4 years ago

Solved by https://gitlab.com/emacsomancer/equake/-/merge_requests/1