<h3 dir="auto">Preflight Checklist</h3>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I have read the <a href="https://github.com/electron/electron/blob/master/CONTRIBUTING.md">Contributing Guidelines</a> for this project.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I agree to follow the <a href="https://github.com/electron/electron/blob/master/CODE_OF_CONDUCT.md">Code of Conduct</a> that this project adheres to.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I have searched the <a href="https://www.github.com/electron/electron/issues">issue tracker</a> for a feature request that matches the one I want to file, without success.</li>
</ul>
<h3 dir="auto">Electron Version</h3>
<p dir="auto">11.3.0</p>
<h3 dir="auto">What operating system are you using?</h3>
<p dir="auto">macOS</p>
<h3 dir="auto">Operating System Version</h3>
<p dir="auto">macOS Big Sur 11.5.1</p>
<h3 dir="auto">What arch are you using?</h3>
<p dir="auto">arm64 (including Apple Silicon)</p>
<h3 dir="auto">Last Known Working Electron version</h3>
<p dir="auto"><em>No response</em></p>
<h3 dir="auto">Expected Behavior</h3>
<p dir="auto">When the <code class="notranslate">frame: false</code> option is passed to the <code class="notranslate">new BrowserWindow()</code> options, all of the window is a canvas for HTML that is clickable.</p>
<h3 dir="auto">Actual Behavior</h3>
<p dir="auto">The top ~20 pixels of the frameless window is not clickable, and doesn't have events. It's as if the title bar was there, but invisible. This is the code:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="const { app, BrowserWindow } = require(&quot;electron&quot;);

app.on(&quot;ready&quot;, () =&gt; {
  const child = new BrowserWindow({ frame: false });
  child.loadURL(&quot;https://github.com&quot;);
  child.once(&quot;ready-to-show&quot;, () =&gt; {
    child.show();
  });
});"><pre class="notranslate"><span class="pl-k">const</span> <span class="pl-kos">{</span> app<span class="pl-kos">,</span> BrowserWindow <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">"electron"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-s1">app</span><span class="pl-kos">.</span><span class="pl-en">on</span><span class="pl-kos">(</span><span class="pl-s">"ready"</span><span class="pl-kos">,</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">const</span> <span class="pl-s1">child</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">BrowserWindow</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">frame</span>: <span class="pl-c1">false</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-s1">child</span><span class="pl-kos">.</span><span class="pl-en">loadURL</span><span class="pl-kos">(</span><span class="pl-s">"https://github.com"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-s1">child</span><span class="pl-kos">.</span><span class="pl-en">once</span><span class="pl-kos">(</span><span class="pl-s">"ready-to-show"</span><span class="pl-kos">,</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-s1">child</span><span class="pl-kos">.</span><span class="pl-en">show</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">See a recording of the bug in action, expected the whole icon/button to be hoverable+clickable but seems like something is "covering" them:</p>
<details open="" class="details-reset border rounded-2">
  <summary class="px-3 py-2">
    <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-device-camera-video">
    <path d="M16 3.75v8.5a.75.75 0 0 1-1.136.643L11 10.575v.675A1.75 1.75 0 0 1 9.25 13h-7.5A1.75 1.75 0 0 1 0 11.25v-6.5C0 3.784.784 3 1.75 3h7.5c.966 0 1.75.784 1.75 1.75v.675l3.864-2.318A.75.75 0 0 1 16 3.75Zm-6.5 1a.25.25 0 0 0-.25-.25h-7.5a.25.25 0 0 0-.25.25v6.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-6.5ZM11 8.825l3.5 2.1v-5.85l-3.5 2.1Z"></path>
</svg>
    <span aria-label="Video description electron-bug.mp4" class="m-1">electron-bug.mp4</span>
    <span class="dropdown-caret"></span>
  </summary>

  <video src="https://user-images.githubusercontent.com/2801252/130335574-d3c9b9a4-e949-4af2-8150-6bde52196cf2.mp4" data-canonical-src="https://user-images.githubusercontent.com/2801252/130335574-d3c9b9a4-e949-4af2-8150-6bde52196cf2.mp4" controls="controls" muted="muted" class="d-block rounded-bottom-2 border-top width-fit" style="max-height:640px; min-height: 200px">

  </video>
</details>

<h3 dir="auto">Testcase Gist URL</h3>
<p dir="auto"><a href="https://gist.github.com/franciscop/20a6fbd380ad10678e512f14c76be125">https://gist.github.com/franciscop/20a6fbd380ad10678e512f14c76be125</a></p>
<h3 dir="auto">Additional Information</h3>
<p dir="auto">Something interesting is that, playing with the option <code class="notranslate">titleBarStyle</code> you can get one version where this particular issue is fixed (BUT it requires you to show the buttons on hover, which of course it's an impossible requirement in many cases, so it's still a bug):</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="const { app, BrowserWindow } = require(&quot;electron&quot;);

app.on(&quot;ready&quot;, () =&gt; {
  const child = new BrowserWindow({
    frame: false,
    // We don't want the buttons, but at least this makes more real estate clickable?
    titleBarStyle: &quot;customButtonsOnHover&quot;
  });
  child.loadURL(&quot;https://github.com&quot;);
  child.once(&quot;ready-to-show&quot;, () =&gt; {
    child.show();
  });
});"><pre class="notranslate"><span class="pl-k">const</span> <span class="pl-kos">{</span> app<span class="pl-kos">,</span> BrowserWindow <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">"electron"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-s1">app</span><span class="pl-kos">.</span><span class="pl-en">on</span><span class="pl-kos">(</span><span class="pl-s">"ready"</span><span class="pl-kos">,</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">const</span> <span class="pl-s1">child</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">BrowserWindow</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
    <span class="pl-c1">frame</span>: <span class="pl-c1">false</span><span class="pl-kos">,</span>
    <span class="pl-c">// We don't want the buttons, but at least this makes more real estate clickable?</span>
    <span class="pl-c1">titleBarStyle</span>: <span class="pl-s">"customButtonsOnHover"</span>
  <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-s1">child</span><span class="pl-kos">.</span><span class="pl-en">loadURL</span><span class="pl-kos">(</span><span class="pl-s">"https://github.com"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-s1">child</span><span class="pl-kos">.</span><span class="pl-en">once</span><span class="pl-kos">(</span><span class="pl-s">"ready-to-show"</span><span class="pl-kos">,</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-s1">child</span><span class="pl-kos">.</span><span class="pl-en">show</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">See how now you can hover on all the elements, BUT it also displays the buttons on hover:</p>
<details open="" class="details-reset border rounded-2">
  <summary class="px-3 py-2">
    <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-device-camera-video">
    <path d="M16 3.75v8.5a.75.75 0 0 1-1.136.643L11 10.575v.675A1.75 1.75 0 0 1 9.25 13h-7.5A1.75 1.75 0 0 1 0 11.25v-6.5C0 3.784.784 3 1.75 3h7.5c.966 0 1.75.784 1.75 1.75v.675l3.864-2.318A.75.75 0 0 1 16 3.75Zm-6.5 1a.25.25 0 0 0-.25-.25h-7.5a.25.25 0 0 0-.25.25v6.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-6.5ZM11 8.825l3.5 2.1v-5.85l-3.5 2.1Z"></path>
</svg>
    <span aria-label="Video description electron-almost-fixed.mp4" class="m-1">electron-almost-fixed.mp4</span>
    <span class="dropdown-caret"></span>
  </summary>

  <video src="https://user-images.githubusercontent.com/2801252/130335667-7106286f-2203-417f-99c9-68e8a832abdc.mp4" data-canonical-src="https://user-images.githubusercontent.com/2801252/130335667-7106286f-2203-417f-99c9-68e8a832abdc.mp4" controls="controls" muted="muted" class="d-block rounded-bottom-2 border-top width-fit" style="max-height:640px; min-height: 200px">

  </video>
</details>

<p dir="auto">I tried <code class="notranslate">hidden</code> and <code class="notranslate">hiddenInset</code> but they oddly enough do show the controls and they still have the previous issue as the commented here originally (or even worse in the case of <code class="notranslate">hiddenInset</code>).</p>
<p dir="auto">Related bugs:</p>
<ul dir="auto">
<li><a href="https://github.com/maxogden/menubar/issues/172" data-hovercard-type="issue" data-hovercard-url="/maxogden/menubar/issues/172/hovercard">This bug in menubar</a> is definitely the same thing.</li>
<li>I found <a href="https://github.com/electron/electron/issues/26720" data-hovercard-type="issue" data-hovercard-url="/electron/electron/issues/26720/hovercard">another slightly related</a> but probably different bug since it's in a different platform, so I believe it might be a different thing (the video linked is dead so cannot verify).</li>
</ul>
<h3 dir="auto">Code dive-in</h3>
<p dir="auto">I'm way out of my depth here, but it seems <a href="https://github.com/electron/electron/blob/main/shell/browser/native_window_mac.mm#L357">this line of code</a> is the one making the title bar transparent when <code class="notranslate">frame: false</code>:</p>
<div class="highlight highlight-source-c++ notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="  if (transparent() || !has_frame()) {
    // Don't show title bar.
    [window_ setTitlebarAppearsTransparent:YES];
    [window_ setTitleVisibility:NSWindowTitleHidden];"><pre class="notranslate">  <span class="pl-k">if</span> (transparent() || !has_frame()) {
    <span class="pl-c"><span class="pl-c">//</span> Don't show title bar.</span>
    [window_ setTitlebarAppearsTransparent:YES];
    [window_ setTitleVisibility:NSWindowTitleHidden];</pre></div>
<p dir="auto">And then <a href="https://github.com/electron/electron/blob/main/shell/browser/native_window_mac.mm#L1479">this conditional</a> makes it "visible" if it's not <code class="notranslate">customButtonsOnHover</code>? Maybe? (as I said, unfortunately I can report the bug but not sure if I follow the correct code for the bug here):</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="  if (title_bar_style_ == TitleBarStyle::kCustomButtonsOnHover)
    [buttons_proxy_ setVisible:visible];
  else
    InternalSetWindowButtonVisibility(visible);"><pre class="notranslate"><code class="notranslate">  if (title_bar_style_ == TitleBarStyle::kCustomButtonsOnHover)
    [buttons_proxy_ setVisible:visible];
  else
    InternalSetWindowButtonVisibility(visible);
</code></pre></div>
<h3 dir="auto">Preflight Checklist</h3>

<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I have read the <a href="https://github.com/electron/electron/blob/master/CONTRIBUTING.md">Contributing Guidelines</a> for this project.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I agree to follow the <a href="https://github.com/electron/electron/blob/master/CODE_OF_CONDUCT.md">Code of Conduct</a> that this project adheres to.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I have searched the issue tracker for a feature request that matches the one I want to file, without success.</li>
</ul>
<h3 dir="auto">Problem Description</h3>
<p dir="auto">IIUC, when using the <code class="notranslate">app.requestSingleInstanceLock();</code> function in our electron main process, when it returns <code class="notranslate">false</code> we would usually exit the second created process, since the event will be forwarded to the first instance. My issue here is that when exiting the second process, I may want to get feedback from the main instance to know what exit code to return with. Say I wanted to open a resource but it failed, I would like my second process to exit with code != 0. Maybe a CLI argument passed was bogus as well, which case I'd like to exit with code != 0 again.</p>
<h3 dir="auto">Proposed Solution</h3>
<p dir="auto">Since it would be weird to change the return type of <code class="notranslate">app.requestSingleInstanceLock()</code>, maybe add a new <code class="notranslate">app.waitSingleInstanceResponse()</code> that would return a promise with the value set from a new callback function in the <code class="notranslate">second-instance</code> event: <code class="notranslate">event.setResponse(data)</code>. Data type is left to implementers to decide what is easier/better. String is fine with me, or serialization could be done by the framework, I don't know what's best.</p>
<h3 dir="auto">Alternatives Considered</h3>
<p dir="auto">I would have liked to tap into any already involved IPC mechanism used for that feature, but I don't know where to look for that, and it feels a bit hacky IMO.</p>
<h3 dir="auto">Additional Information</h3>
<p dir="auto">This new flow would allow to put most argument parsing into the main single instance process, and avoid thinking about how to break the processing in the temporary second process and then maybe duplicate parsing again in the main instance. Please tell me if I just approach the issue from the wrong angle as well.</p>