unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: "Mattias Engdegård" <mattiase@acm.org>
To: Alan Third <alan@idiocy.org>
Cc: 44333@debbugs.gnu.org,
	Viktor Kharitonovich <viktor.kharitonovich@gmail.com>
Subject: bug#44333: 27.1; macOS menu bar 2-clicks
Date: Sun, 27 Dec 2020 18:14:25 +0100	[thread overview]
Message-ID: <A4CDFBE9-02AA-401F-8A14-120E7B9EB41D@acm.org> (raw)
In-Reply-To: <X+ewiv9xczTPCKDh@breton.holly.idiocy.org>

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

26 dec. 2020 kl. 22.52 skrev Alan Third <alan@idiocy.org>:

> It's actually almost possible to copy the Mac port code in verbatim,
> the NS port's code is based on it after all, but I feel it may be
> neater to use a custom view for the NSMenuItems. That would give us
> complete control over the layout.

We should, but because I was lazy and impatient, I wrote the attached (terrible) hack just to see what right-justification would look like.

The right margin is slightly ragged because I'm using plain spaces to offset the key binding from the menu text, but I still think it's better than what we have now. I tried using U+2009 THIN SPACE and even U+200A HAIR SPACE instead but somehow the result became worse; no doubt a silly mistake somewhere.

I also removed the special hack for s- bindings because it broke the nice alignment. If we want, we could translate modifiers into the standard symbols (⌘, ⌃, ⇧ and ⌥) depending on these are assigned, or just keep using the Emacs notation. We could also translate <right> into → and so on.


[-- Attachment #2: right-justify-keys.diff --]
[-- Type: application/octet-stream, Size: 4151 bytes --]

diff --git a/src/nsmenu.m b/src/nsmenu.m
index b5d0821323..f985234643 100644
--- a/src/nsmenu.m
+++ b/src/nsmenu.m
@@ -498,9 +498,16 @@ - (NSMenuItem *)addItemWithWidgetValue: (void *)wvptr
       keyEq = [self parseKeyEquiv: wv->key];
 #ifdef NS_IMPL_COCOA
       /* macOS mangles modifier strings longer than one character.  */
-      if (keyEquivModMask == 0)
+      if (1 || keyEquivModMask == 0)
         {
-          title = [title stringByAppendingFormat: @" (%@)", keyEq];
+          if (wv->key)
+            {
+              const char *k = wv->key;
+              while (*k == ' ') k++;
+              title = [title stringByAppendingString:
+                               [NSString stringWithUTF8String: k]];
+            }
+          //title = [title stringByAppendingString: keyEq];
           item = [self addItemWithTitle: (NSString *)title
                                  action: @selector (menuDown:)
                           keyEquivalent: @""];
@@ -514,7 +521,7 @@ - (NSMenuItem *)addItemWithWidgetValue: (void *)wvptr
 #ifdef NS_IMPL_COCOA
         }
 #endif
-      [item setKeyEquivalentModifierMask: keyEquivModMask];
+      //[item setKeyEquivalentModifierMask: keyEquivModMask];
 
       [item setEnabled: wv->enabled];
 
@@ -556,14 +563,67 @@ - (void)fillWithWidgetValue: (void *)wvptr
 
 - (void)fillWithWidgetValue: (void *)wvptr
 {
-  widget_value *wv = (widget_value *)wvptr;
+  widget_value *first_wv = (widget_value *)wvptr;
+  NSFont *menuFont = [NSFont menuFontOfSize:0];
+  NSDictionary <NSString *, id> *attributes =
+    [NSDictionary dictionaryWithObject:menuFont forKey:NSFontAttributeName];
+  const char space_str[] = " ";
+  int space_bytes = sizeof space_str - 1;
+  NSSize spaceSize = [[NSString stringWithUTF8String: space_str]
+                       sizeWithAttributes:attributes];
+  CGFloat spaceWidth = spaceSize.width;
+  CGFloat maxNameWidth = 0;
+  CGFloat maxKeyWidth = 0;
+
+  for (widget_value *wv = first_wv; wv != NULL; wv = wv->next)
+    if (!menu_separator_name_p (wv->name))
+      {
+        NSString *name = [NSString stringWithUTF8String: wv->name];
+        NSSize nameSize = [name sizeWithAttributes: attributes];
+        CGFloat nameWidth = nameSize.width;
+        maxNameWidth = MAX(maxNameWidth, nameWidth);
+        if (wv->key)
+          {
+            const char *k = wv->key;
+            while (*k == ' ') k++;
+            NSString *key = [NSString stringWithUTF8String: k];
+            NSSize keySize = [key sizeWithAttributes: attributes];
+            CGFloat keyWidth = keySize.width;
+            maxKeyWidth = MAX(maxKeyWidth, keyWidth);
+          }
+      }
 
   /* clear existing contents */
   [self removeAllItems];
 
   /* add new contents */
-  for (; wv != NULL; wv = wv->next)
+  for (widget_value *wv = first_wv; wv != NULL; wv = wv->next)
     {
+      if (wv->key && !menu_separator_name_p (wv->name))
+        {
+          NSString *name = [NSString stringWithUTF8String: wv->name];
+          NSSize nameSize = [name sizeWithAttributes: attributes];
+          CGFloat nameWidth = nameSize.width;
+          const char *k = wv->key;
+          while (*k == ' ') k++;
+          NSString *key = [NSString stringWithUTF8String: k];
+          NSSize keySize = [key sizeWithAttributes: attributes];
+          CGFloat keyWidth = keySize.width;
+          CGFloat padWidth = (maxNameWidth - nameWidth)
+                             + (maxKeyWidth - keyWidth);
+          int name_len = strlen (wv->name);
+          int extra_spaces = 7;
+          int pad_len = lround(padWidth / spaceWidth + extra_spaces);
+          Lisp_Object s = make_uninit_string (name_len + pad_len * space_bytes);
+          memcpy (SSDATA (s), wv->name, name_len);
+          if (space_bytes == 1)
+            memset (SDATA (s) + name_len, space_str[0], pad_len);
+          else
+            for (int i = 0; i < pad_len; i++)
+              memcpy (SDATA (s) + name_len + i * space_bytes, space_str,
+                      space_bytes);
+          wv->name = SSDATA (s);
+        }
       NSMenuItem *item = [self addItemWithWidgetValue: wv];
 
       if (wv->contents)

      parent reply	other threads:[~2020-12-27 17:14 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-30 17:53 bug#44333: 27.1; macOS menu bar 2-clicks Viktor Kharitonovich
2020-10-30 22:42 ` Alan Third
2020-10-31 14:08 ` Mattias Engdegård
2020-10-31 15:01   ` Alan Third
2020-11-01 10:50     ` Mattias Engdegård
2020-11-01 17:28       ` Alan Third
2020-12-23 20:33         ` Alan Third
2020-12-25 16:06           ` Mattias Engdegård
2020-12-25 17:26             ` Alan Third
2020-12-25 19:20               ` Alan Third
2020-12-25 22:28                 ` Mattias Engdegård
2020-12-26 17:07                   ` Alan Third
2020-12-26 17:42                     ` Mattias Engdegård
2020-12-26 21:52                       ` Alan Third
2020-12-27 16:56                         ` Alan Third
2020-12-27 17:14                         ` Mattias Engdegård [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=A4CDFBE9-02AA-401F-8A14-120E7B9EB41D@acm.org \
    --to=mattiase@acm.org \
    --cc=44333@debbugs.gnu.org \
    --cc=alan@idiocy.org \
    --cc=viktor.kharitonovich@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).