masm11 / emacs

Mirror of GNU Emacs
http://www.gnu.org/software/emacs/
GNU General Public License v3.0
198 stars 14 forks source link

Is pgtk fork suppose to support macOS? #95

Open declantsien opened 3 years ago

declantsien commented 3 years ago

Since Gtk support Linux/macOS/Windows, https://www.gtk.org/docs/installations/macos/#features which means pgtk Emacs can built on multi platform?

Just built(--without-ns --with-pgtk) on macOS, But I got a frame with spinning cursor and not responsive.

Also the font looks bigger than ns one(the bottom frame in screen) https://imgur.com/aps7jqo

I run pgtk Emacs under sway on Linux daily, it works perfect. Thanks for this awesome work.

masm11 commented 3 years ago

Thank you for testing on macOS. I have never tested on macOS since I don't have mac.

In your terminal, you ran emacs -Q but some config file was loaded?

fejfighter commented 3 years ago

@declanqian just tested this off savannah, and although it stalls on startup for me, it somewhat works.

however it seems to lock up when it loses and regains focus.

it looks like it is stuck in select

(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
  * frame #0: 0x00007fff6fe0e87e libsystem_kernel.dylib`__pselect + 10
    frame #1: 0x00007fff6fe0e79b libsystem_kernel.dylib`pselect$DARWIN_EXTSN + 42
    frame #2: 0x00000001001c47e8 emacs`really_call_select(arg=0x00007ffeefbfe518) at thread.c:592:16 [opt]
    frame #3: 0x00000001001c4770 emacs`thread_select [inlined] flush_stack_call_func(func=<unavailable>, arg=0x00007ffeefbfe518) at lisp.h:3797:3 [opt]
    frame #4: 0x00000001001c4760 emacs`thread_select(func=<unavailable>, max_fds=16, rfds=0x00007ffeefbfe5a0, wfds=<unavailable>, efds=0x0000000000000000, timeout=0x00007ffeefbfee30, sigmask=0x0000000000000000) at thread.c:624 [opt]
    frame #5: 0x00000001001cd88e emacs`pgtk_select(fds_lim=16, rfds=<unavailable>, wfds=<unavailable>, efds=0x0000000000000000, timeout=<unavailable>, sigmask=0x0000000000000000) at pgtkterm.c:3978:10 [opt]
    frame #6: 0x00000001001a2360 emacs`wait_reading_process_output(time_limit=<unavailable>, nsecs=<unavailable>, read_kbd=-1, do_display=true, wait_for_cell=<unavailable>, wait_proc=<unavailable>, just_wait_proc=0) at process.c:5561:11 [opt]
    frame #7: 0x0000000100007bbb emacs`sit_for(timeout=<unavailable>, reading=true, display_option=<unavailable>) at dispnew.c:6121:7 [opt]
    frame #8: 0x00000001000d29fd emacs`read_char(commandflag=1, map=0x000000010f877d23, prev_event=0x0000000000000000, used_mouse_menu=0x00007ffeefbff5af, end_time=0x0000000000000000) at keyboard.c:2741:11 [opt]
    frame #9: 0x00000001000cfad2 emacs`read_key_sequence(keybuf=<unavailable>, prompt=0x0000000000000000, dont_downcase_last=false, can_return_switch_frame=true, fix_current_buffer=true, prevent_redisplay=<unavailable>) at keyboard.c:9492:12 [opt]
    frame #10: 0x00000001000ce33c emacs`command_loop_1 at keyboard.c:1353:15 [opt]
    frame #11: 0x0000000100153517 emacs`internal_condition_case(bfun=(emacs`command_loop_1 at keyboard.c:1239), handlers=0x0000000000000090, hfun=(emacs`cmd_error at keyboard.c:922)) at eval.c:1443:25 [opt]
    frame #12: 0x00000001000de120 emacs`command_loop_2(ignore=<unavailable>) at keyboard.c:1094:11 [opt]
    frame #13: 0x0000000100152ce2 emacs`internal_catch(tag=0x000000000000d140, func=(emacs`command_loop_2 at keyboard.c:1090), arg=0x0000000000000000) at eval.c:1187:25 [opt]
    frame #14: 0x000000010020aef5 emacs`recursive_edit_1.cold.1 at keyboard.c:1073:2 [opt]
    frame #15: 0x00000001000cd409 emacs`recursive_edit_1 [inlined] command_loop at keyboard.c:1070:5 [opt]
    frame #16: 0x00000001000cd404 emacs`recursive_edit_1 at keyboard.c:720 [opt]
    frame #17: 0x00000001000cd59b emacs`Frecursive_edit at keyboard.c:789:3 [opt]
    frame #18: 0x00000001000cc622 emacs`main(argc=<unavailable>, argv=<unavailable>) at emacs.c:2065:3 [opt]
    frame #19: 0x00007fff6fcc8cc9 libdyld.dylib`start + 1
    frame #20: 0x00007fff6fcc8cc9 libdyld.dylib`start + 1
declantsien commented 3 years ago

it somewhat works. however it seems to lock up when it loses and regains focus.

True.

Just tested it again with and without -Q. Behaved the same way.

fejfighter commented 3 years ago

I finally carved out an hour to investigate,

essentially Pselect for pgtk/macOS is receiving a high timeout value, this is always 0 on an ns build, ( I'll need to look at pgtk/linux later and see what values it gets)

pgtk_select might be receiving different output between Mac and linux which could be causing the stuttering

if you want a hack fix setting the time out fallback value in process.c wait_reading_process_output to something lower like 1 rather than 1000000

fejfighter commented 3 years ago

some notes:

I'm getting inconsistent results on macos, sometimes it's quite usable, then the same binary will run poorly the next time.

testing on linux I never get a time out of 1000000, an it will always return quickly, macos seems to hang onto events for a little while before dumping them all at once

Atemu commented 3 years ago

I've been using the version packaged in the https://github.com/nix-community/emacs-overlay for a few months on Catalina.

There has been a bit of glitchyness but it works pretty well and has noticably lower input lag than the native Cocoa renderer which is why I've stuck with it.
There have been long pauses but they rarely happened and I'm not even 100% sure they're caused by the pgtk patches.

It's gotten a lot more glitchy with Big Sur though, particularly when scrolling or when switching buffers.

dsdshcym commented 3 years ago

Hi @Atemu!

Are you still using EmacsPgtk on macOS? Could you share your nix config? I tried with nix-build --expr 'with (import <nixpkgs> { overlays = [ (import ./.) ]; }); emacsPgtkGcc' in emacs-overlay project. But it failed with these errors:

checking whether the C compiler works... no
configure: error: in `/private/tmp/nix-build-emacs-pgtk-20210425.0.drv-0/source':
configure: error: C compiler cannot create executables
Atemu commented 3 years ago

Your expression instantiates, realises and runs just fine for me with nixos/nixpkgs@32f7980afb5e33f1e078a51e715b9f102f396a69 and nix-community/emacs-overlay@d1fbf6d39f3a0869c5fb0cc7f9ba7c9033e35cf9.

I currently don't actively use any 28.5-based emacs on mac though as there is an unbearable performance regression in large org-mode files.

dsdshcym commented 3 years ago

@Atemu Thanks for checking! I switched to nixpkgs-unstable and then the expression above works.

But it doesn't seem to be using pgtk at all: The output of ./configure suggested that it's still using Cocoa (ns). What window system should Emacs use? nextstep

I have to override the configure arguments to make it use gtk3:

      configureFlags = (super.lib.remove "--with-ns" (super.lib.remove "--with-xft" old.configureFlags))
        ++ super.lib.singleton "--with-pgtk"
        ++ super.lib.singleton "--with-cairo"
        ++ super.lib.singleton "--without-ns";

Then it complained gtk3 was missing (in the nix environment)

dsdshcym commented 3 years ago

Hi @fejfighter I successfully built emacs-pgtk in my macos environment with gtk+3. But it also stuck very often (spinning cursor). The font looked normal though.

I tried to apply the hack you mentioned above, but the performance was still bad Or did I change the wrong place? since I didn't find the fallback value 1000000 in process.c

  1. first patch I tried:

    1 file changed, 2 insertions(+), 2 deletions(-)
    src/process.c | 4 ++--
    
    modified   src/process.c
    @@ -5267,7 +5267,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
       timeout = timespec_sub (end_time, now);
     }
         else
    -    timeout = make_timespec (wait < TIMEOUT ? 0 : 100000, 0);
    +    timeout = make_timespec (wait < TIMEOUT ? 0 : 1, 0);
    
         /* Normally we run timers here.
     But not if wait_for_cell; in those cases,
    @@ -7802,7 +7802,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
       timeout = timespec_sub (end_time, now);
     }
         else
    -    timeout = make_timespec (wait < TIMEOUT ? 0 : 100000, 0);
    +    timeout = make_timespec (wait < TIMEOUT ? 0 : 1, 0);
    
         /* If our caller will not immediately handle keyboard events,
  2. second patch I tried:

    1 file changed, 4 insertions(+), 4 deletions(-)
    src/process.c | 8 ++++----
    
    modified   src/process.c
    @@ -5050,7 +5050,7 @@ wait_for_socket_fds (Lisp_Object process, char const *name)
     && connecting_status (XPROCESS (process)->status))
       {
         add_to_log ("Waiting for socket from %s...", build_string (name));
    -      wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0);
    +      wait_reading_process_output (0, 20, 0, 0, Qnil, NULL, 0);
       }
    }
    
    @@ -5060,7 +5060,7 @@ wait_while_connecting (Lisp_Object process)
     while (connecting_status (XPROCESS (process)->status))
       {
         add_to_log ("Waiting for connection...");
    -      wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0);
    +      wait_reading_process_output (0, 20, 0, 0, Qnil, NULL, 0);
       }
    }
    
    @@ -5072,7 +5072,7 @@ wait_for_tls_negotiation (Lisp_Object process)
     && XPROCESS (process)->gnutls_initstage != GNUTLS_STAGE_READY)
       {
         add_to_log ("Waiting for TLS...");
    -      wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0);
    +      wait_reading_process_output (0, 20, 0, 0, Qnil, NULL, 0);
       }
    #endif
    }
    @@ -6554,7 +6554,7 @@ send_process (Lisp_Object proc, const char *buf, ptrdiff_t len,
    
         /* Put what we should have written in write_queue.  */
         write_queue_push (p, cur_object, cur_buf, cur_len, 1);
    -          wait_reading_process_output (0, 20 * 1000 * 1000,
    +          wait_reading_process_output (0, 20,
                   0, 0, Qnil, NULL, 0);
         /* Reread queue, to see what is left.  */
         break;

I hope that the emacs-pgtk version can out perform the cocoa version, since I've heard some good news from linux users..

Thaodan commented 3 years ago

I hope that the emacs-pgtk version can out perform the cocoa version, since I've heard some good news from linux users.. Has GTK on macOS gotten better? That depends on how good the GTK support for that OS is I think.

fejfighter commented 3 years ago

Sorry for not responding sooner, real life has been smashing me lately

This is mostly outside the gtk specific code, but likely on a codepath that ns emacs does not hit.

I wonder if it's related to the primary thread requirements for input of MacOS

dsdshcym commented 3 years ago

@Thaodan Here's what I found: https://blogs.gnome.org/chergert/2020/12/15/gtk-4-got-a-new-macos-backend-now-with-opengl/ Sounds like GTK4 has improved a lot on macOS. (Anyway, I'm diving into nsterm now to see if I can improve the performance of Cocoa version for Emacs 28)

dsdshcym commented 3 years ago

@fejfighter Thanks for the reply! I've stopped trying to make emacs-pgtk work on macOS. (Instead, I'm trying to figure out why NS Emacs 28 performs worse than 27, and probably fix the issue) Maybe I'll come back to this pgtk issue later.

fejfighter commented 3 years ago

With any luck the two may be related

masm11 commented 2 years ago

Hi, all I bought a macbook air. And I debugged PGTK on my macOS Monterey.

Here are some patches.

pgtkmac-patches.tar.gz

My configuration is as follows:

CFLAGS='-O0 -g3 -no-pie' CPPFLAGS='-I/usr/local/include' LDFLAGS='-L/usr/local/lib' \
../configure --with-pgtk --without-x --without-ns \
--with-cairo --with-modules --with-gif=yes --with-tiff=yes \
--without-imagemagick --with-gnutls=yes --without-pop \
--enable-gcc-warnings=warn-only --enable-checking='yes,glyphs' \
--enable-check-lisp-object-type=yes
pgtkmac

There is a problem: command key is recognized as meta key. I'll debug it.

declantsien commented 2 years ago

Just tried it out. UI is working indeed, just

Oh, the command key. I think the mac port had some solution

Screenshot 2022-01-27 at 17 16 54 Screenshot 2022-01-27 at 17 12 12 Screenshot 2022-01-27 at 17 11 39
masm11 commented 2 years ago

Thanks for the try and the screenshots.

The font rendering is different from ns port. Feels not native.

PGTK doesn't use NS native font renderer by design.

And the menu, shouldn't it be located on the macOS Menu Bar?

I agree. I found GtkosxApplication. I'm trying it.

Oh, the command key. I think the mac port had some solution

Thanks for the information!

masm11 commented 2 years ago

And the menu, shouldn't it be located on the macOS Menu Bar?

I agree. I found GtkosxApplication. I'm trying it

Partially done. (When I select from the application menu, a non-focused frame is often targeted. I couldn't find the reason.)

Oh, the command key. I think the mac port had some solution

Thanks for the information!

I tried to support some keys.

Could you try this patch instead of previous four patches?

macos.diff.gz

You need gtk-mac-integration to use this patch.

brew install gtk-mac-integration
declantsien commented 2 years ago

I tried to support some keys.

Command key is working, and some macOS shortcut is working with this version. I've tried cmd-c/v.

However I can't find the key for meta, option from my keyboard isn't.

When I select from the application menu, a non-focused frame is often targeted.

Not sure what you mean by that

gtk-mac-integration seems work fine for me. Except app name emacs should be in capitalized as Emacs I think.

Screenshot 2022-01-29 at 12 16 05
declantsien commented 2 years ago

(emacs:99301): GLib-GObject-WARNING **: 12:47:27.602: g_object_get_is_valid_property: object class 'GtkLabel' has no property named 'accel-closure'

(emacs:99301): GLib-GObject-WARNING **: 12:47:27.602: g_object_get_is_valid_property: object class 'GtkLabel' has no property named 'accel-closure'

(emacs:99301): GLib-GObject-WARNING **: 12:47:27.602: g_object_get_is_valid_property: object class 'GtkLabel' has no property named 'accel-closure'

Forgot to mention that my terminal got flooded by this message.

masm11 commented 2 years ago

Not sure what you mean by that

Open 2 frames. Focus one of them. Select "About Emacs" in the application menu. Focus another one. Select "About Emacs" in the application menu. Focus first frame, and switch to another buffer. Select "About Emacs" in the application menu. ...

*About Emacs* should be shown in the focused frame, but sometimes in another one.

declantsien commented 2 years ago

Emm.., confirmed. Also happens to me when using menu bar. But it always works when using keyboard shortcut c-h c-a.