unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#25818: 25.2; frame moved off display does not return (OS X)
@ 2017-02-20 20:04 Charles A. Roelli
  2017-02-23  8:49 ` martin rudalics
  0 siblings, 1 reply; 34+ messages in thread
From: Charles A. Roelli @ 2017-02-20 20:04 UTC (permalink / raw)
  To: 25818

After looking into a possible bug in Ediff on OS X
(https://debbugs.gnu.org/cgi/bugreport.cgi?bug=25057) it looks like
there may be a bug in the frame handling code for OS X.

You can evaluate this code from emacs -Q to have a frame gradually moved
in steps of 200 px from position ((top . 1) (left . 1)) until it's just
past the right edge of the display (more or less), and then come back
again:

(let ((display-width (display-pixel-width))
      (dx            200)
      (frame-x       1))
  (setq frame-test (make-frame
		    `((top . 1) (left . ,frame-x))))
  (sleep-for 0.5)
  ;; 1. Move it until it's off-screen.
  (while (< frame-x display-width)
    (setq frame-x (+ frame-x dx))
    (modify-frame-parameters frame-test
			     `((left . ,frame-x)))
    (sleep-for 0.5))
  (sleep-for 1)
  ;; 2. Bring it back.
  (while (> frame-x dx)
    (setq frame-x (- frame-x dx))
    (modify-frame-parameters frame-test
			     `((left . ,frame-x)))
    (sleep-for 0.5))
  (sleep-for 1)
  (delete-frame frame-test))

On GNU/Linux and MS Windows the frame behaves as expected: when the
frame parameters are changed to bring it back onscreen (step 2), the
frame becomes visible again.  On OS X 10.6 the frame stays off screen,
however, and I can't find any way to put it back on screen.  You can
change the frame parameters for `top' and `left', and they'll stick, but
they don't actually seem to have any effect.

Can someone reproduce this on a more recent OS X?  Maybe the problem is
fixed in newer versions.

In GNU Emacs 25.2.1 (x86_64-apple-darwin10.8.0, NS appkit-1038.36 Version 10.6.8 (Build 10K549))
 of 2017-02-07 built on gray
Windowing system distributor 'Apple', version 10.3.1038
Configured using:
 'configure --with-modules'

Configured features:
JPEG RSVG NOTIFY ACL GNUTLS LIBXML2 ZLIB TOOLKIT_SCROLL_BARS NS MODULES





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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-02-20 20:04 bug#25818: 25.2; frame moved off display does not return (OS X) Charles A. Roelli
@ 2017-02-23  8:49 ` martin rudalics
  2017-02-26 11:26   ` Charles A. Roelli
  0 siblings, 1 reply; 34+ messages in thread
From: martin rudalics @ 2017-02-23  8:49 UTC (permalink / raw)
  To: Charles A. Roelli, 25818

 > You can evaluate this code from emacs -Q to have a frame gradually moved
 > in steps of 200 px from position ((top . 1) (left . 1)) until it's just
 > past the right edge of the display (more or less), and then come back
 > again:
...
 > On GNU/Linux and MS Windows the frame behaves as expected: when the
 > frame parameters are changed to bring it back onscreen (step 2), the
 > frame becomes visible again.  On OS X 10.6 the frame stays off screen,
 > however, and I can't find any way to put it back on screen.  You can
 > change the frame parameters for `top' and `left', and they'll stick, but
 > they don't actually seem to have any effect.
 >
 > Can someone reproduce this on a more recent OS X?  Maybe the problem is
 > fixed in newer versions.

FWIW this seems OS X specific behavior.  Compare

http://superuser.com/questions/55341/move-an-off-screen-window-back-on-screen-on-mac-os-x

http://osxdaily.com/2013/08/14/move-window-back-on-screen-mac-os-x/

http://www.gottabemobile.com/how-to-move-an-os-x-window-thats-stuck-off-screen/

http://apple.stackexchange.com/questions/709/how-to-retrieve-windows-that-have-moved-off-screen

https://www.cnet.com/forums/discussions/bring-misplaced-off-screen-applications-back-to-your-desktop-380285/

martin





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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-02-23  8:49 ` martin rudalics
@ 2017-02-26 11:26   ` Charles A. Roelli
  2017-02-26 15:40     ` Charles A. Roelli
  0 siblings, 1 reply; 34+ messages in thread
From: Charles A. Roelli @ 2017-02-26 11:26 UTC (permalink / raw)
  To: martin rudalics; +Cc: 25818

See also https://debbugs.gnu.org/cgi/bugreport.cgi?bug=18801.  It's
possible that the problem was introduced from 24.3 to 24.4.





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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-02-26 11:26   ` Charles A. Roelli
@ 2017-02-26 15:40     ` Charles A. Roelli
  2017-02-26 16:45       ` martin rudalics
  0 siblings, 1 reply; 34+ messages in thread
From: Charles A. Roelli @ 2017-02-26 15:40 UTC (permalink / raw)
  To: martin rudalics; +Cc: 25818

On Sun, Feb 26 2017 at 12:26:46 pm, Charles A. Roelli wrote:

> See also https://debbugs.gnu.org/cgi/bugreport.cgi?bug=18801.  It's
> possible that the problem was introduced from 24.3 to 24.4.

I built 24.3 and 24.4 from source, and it is correct that a regression
with Emacs' handling of the window system in OS X happened between those
two releases.

The form I suggested to show the issue,

(let ((display-width (display-pixel-width))
      (dx            200)
      (frame-x       1))
  (setq frame-test (make-frame
		    `((top . 1) (left . ,frame-x))))
  (sleep-for 0.5)
  ;; 1. Move it until it's off-screen.
  (while (< frame-x display-width)
    (setq frame-x (+ frame-x dx))
    (modify-frame-parameters frame-test
			     `((left . ,frame-x)))
    (sleep-for 0.5))
  (sleep-for 1)
  ;; 2. Bring it back.
  (while (> frame-x dx)
    (setq frame-x (- frame-x dx))
    (modify-frame-parameters frame-test
			     `((left . ,frame-x)))
    (sleep-for 0.5))
  (sleep-for 1)
  (delete-frame frame-test))

works correctly on 24.3 but not on 24.4 (24.4 has the same behavior as
25.1 and 25.2, detailed in my first message).  I guess the regression
would be in src/nsterm.m, or maybe src/nsfns.m.





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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-02-26 15:40     ` Charles A. Roelli
@ 2017-02-26 16:45       ` martin rudalics
  2017-02-26 19:42         ` Charles A. Roelli
  0 siblings, 1 reply; 34+ messages in thread
From: martin rudalics @ 2017-02-26 16:45 UTC (permalink / raw)
  To: Charles A. Roelli; +Cc: 25818

 >> See also https://debbugs.gnu.org/cgi/bugreport.cgi?bug=18801.  It's
 >> possible that the problem was introduced from 24.3 to 24.4.
 >
 > I built 24.3 and 24.4 from source, and it is correct that a regression
 > with Emacs' handling of the window system in OS X happened between those
 > two releases.
 >
 > The form I suggested to show the issue,
[...]
 > works correctly on 24.3 but not on 24.4 (24.4 has the same behavior as
 > 25.1 and 25.2, detailed in my first message).  I guess the regression
 > would be in src/nsterm.m, or maybe src/nsfns.m.

So something seems to have happened that Emacs fell into the same trap
as other applications (which, in my understanding, is that the frame
gets displayed on another, probably non-existent, monitor).  I'm afraid
that my only suggestion is to bisect the sources until you've found the
culprit.

(I suppose you verified that the value returned by ‘display-pixel-width’
is the same in 24.3 and 24.4.)

martin






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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-02-26 16:45       ` martin rudalics
@ 2017-02-26 19:42         ` Charles A. Roelli
  2017-02-27  8:05           ` martin rudalics
  0 siblings, 1 reply; 34+ messages in thread
From: Charles A. Roelli @ 2017-02-26 19:42 UTC (permalink / raw)
  To: martin rudalics; +Cc: 25818

On Sun, Feb 26 2017 at 05:45:40 pm, martin rudalics wrote:

>>> See also https://debbugs.gnu.org/cgi/bugreport.cgi?bug=18801.  It's
>>> possible that the problem was introduced from 24.3 to 24.4.
>>
>> I built 24.3 and 24.4 from source, and it is correct that a regression
>> with Emacs' handling of the window system in OS X happened between those
>> two releases.
>>
>> The form I suggested to show the issue,
> [...]
>> works correctly on 24.3 but not on 24.4 (24.4 has the same behavior as
>> 25.1 and 25.2, detailed in my first message).  I guess the regression
>> would be in src/nsterm.m, or maybe src/nsfns.m.
>
> So something seems to have happened that Emacs fell into the same trap
> as other applications (which, in my understanding, is that the frame
> gets displayed on another, probably non-existent, monitor).  I'm afraid
> that my only suggestion is to bisect the sources until you've found the
> culprit.
>
> (I suppose you verified that the value returned by ‘display-pixel-width’
> is the same in 24.3 and 24.4.)

No, I did not; thanks for the reminder.  In 24.3, with a second monitor
plugged in, (display-pixel-width) returns 1280, i.e. the width only of
my primary monitor.  In 24.4, in the same situation,
(display-pixel-width) returns 2330 = (+ 1280 1050).  Second monitor is
1050 pixels wide.

In both the case of 24.3 and 24.4 with no external monitor attached,
(display-pixel-width) returns 1280.

So it seems that the code for `display-pixel-width' (or code that it
calls) was changed between those releases, maybe to support multiple
monitors.

I notice now that when running the test form on 24.3, the created frame
never actually leaves the visible portion of the screen.  For example,
when the code calls (sleep-for 1) with the frame supposedly being
offscreen according to its frame parameters (right before step 2), the
frame is in reality maybe 50 pixels left of the screen's right edge.
This is with just one monitor.  When I run the example with two
monitors, the frame just spills into the second monitor but does not go
further (since 24.3 does not seem to give correct values for
`display-pixel-width' with multiple monitors).

So it seems like there used to be code in Emacs that prevented a frame
from programmatically leaving the screen area in OS X.  For example, in
24.3, if I call (modify-frame-parameters nil '((left . 10000))), the
frame is put, as above, about 50 pixels left of the screen's right edge.





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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-02-26 19:42         ` Charles A. Roelli
@ 2017-02-27  8:05           ` martin rudalics
  2017-02-27 10:34             ` Charles A. Roelli
  2017-02-27 20:47             ` Charles A. Roelli
  0 siblings, 2 replies; 34+ messages in thread
From: martin rudalics @ 2017-02-27  8:05 UTC (permalink / raw)
  To: Charles A. Roelli; +Cc: 25818

 > No, I did not; thanks for the reminder.  In 24.3, with a second monitor
 > plugged in, (display-pixel-width) returns 1280, i.e. the width only of
 > my primary monitor.  In 24.4, in the same situation,
 > (display-pixel-width) returns 2330 = (+ 1280 1050).  Second monitor is
 > 1050 pixels wide.

So the problem occurs only with the second monitor plugged in?

 > In both the case of 24.3 and 24.4 with no external monitor attached,
 > (display-pixel-width) returns 1280.

And there is no problem in this case with 24.4?

 > So it seems that the code for `display-pixel-width' (or code that it
 > calls) was changed between those releases, maybe to support multiple
 > monitors.

The code was changed in two tranches

2013-05-20  YAMAMOTO Mitsuharu  <mituharu@math.s.chiba-u.ac.jp>

2013-07-04  YAMAMOTO Mitsuharu  <mituharu@math.s.chiba-u.ac.jp>

I'll CC him - maybe he can help us solving this issue in a more general
way.

 > I notice now that when running the test form on 24.3, the created frame
 > never actually leaves the visible portion of the screen.  For example,
 > when the code calls (sleep-for 1) with the frame supposedly being
 > offscreen according to its frame parameters (right before step 2), the
 > frame is in reality maybe 50 pixels left of the screen's right edge.
 > This is with just one monitor.  When I run the example with two
 > monitors, the frame just spills into the second monitor but does not go
 > further (since 24.3 does not seem to give correct values for
 > `display-pixel-width' with multiple monitors).

Do you mean that the value is already wrong for the primary monitor or
that the value simply does not account for the second monitor?

 > So it seems like there used to be code in Emacs that prevented a frame
 > from programmatically leaving the screen area in OS X.  For example, in
 > 24.3, if I call (modify-frame-parameters nil '((left . 10000))), the
 > frame is put, as above, about 50 pixels left of the screen's right edge.

In any case we have to change ediff-wind.el in order to fix the issue at
hand.

martin





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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-02-27  8:05           ` martin rudalics
@ 2017-02-27 10:34             ` Charles A. Roelli
  2017-02-27 20:47             ` Charles A. Roelli
  1 sibling, 0 replies; 34+ messages in thread
From: Charles A. Roelli @ 2017-02-27 10:34 UTC (permalink / raw)
  To: martin rudalics; +Cc: 25818

On Mon, Feb 27 2017 at 09:05:14 am, martin rudalics wrote:

>> No, I did not; thanks for the reminder.  In 24.3, with a second monitor
>> plugged in, (display-pixel-width) returns 1280, i.e. the width only of
>> my primary monitor.  In 24.4, in the same situation,
>> (display-pixel-width) returns 2330 = (+ 1280 1050).  Second monitor is
>> 1050 pixels wide.
>
> So the problem occurs only with the second monitor plugged in?

The problem occurs (in 24.4) regardless of how many monitors are plugged
in, and it may not be directly related to `display-pixel-width'.

>
>> In both the case of 24.3 and 24.4 with no external monitor attached,
>> (display-pixel-width) returns 1280.
>
> And there is no problem in this case with 24.4?

No, as above, the problem always occurs with 24.4, regardless of the
number of monitors connected.

>
>> So it seems that the code for `display-pixel-width' (or code that it
>> calls) was changed between those releases, maybe to support multiple
>> monitors.
>
> The code was changed in two tranches
>
> 2013-05-20  YAMAMOTO Mitsuharu  <mituharu@math.s.chiba-u.ac.jp>
>
> 2013-07-04  YAMAMOTO Mitsuharu  <mituharu@math.s.chiba-u.ac.jp>
>
> I'll CC him - maybe he can help us solving this issue in a more general
> way.

Thanks.

>
>> I notice now that when running the test form on 24.3, the created frame
>> never actually leaves the visible portion of the screen.  For example,
>> when the code calls (sleep-for 1) with the frame supposedly being
>> offscreen according to its frame parameters (right before step 2), the
>> frame is in reality maybe 50 pixels left of the screen's right edge.
>> This is with just one monitor.  When I run the example with two
>> monitors, the frame just spills into the second monitor but does not go
>> further (since 24.3 does not seem to give correct values for
>> `display-pixel-width' with multiple monitors).
>
> Do you mean that the value is already wrong for the primary monitor or
> that the value simply does not account for the second monitor?

The value does not account for the second monitor (but is correct for
the primary monitor).  This is the behavior that was fixed in 24.4.

>> So it seems like there used to be code in Emacs that prevented a frame
>> from programmatically leaving the screen area in OS X.  For example, in
>> 24.3, if I call (modify-frame-parameters nil '((left . 10000))), the
>> frame is put, as above, about 50 pixels left of the screen's right edge.
>
> In any case we have to change ediff-wind.el in order to fix the issue at
> hand.

We could, but it would be better to restore Emacs 24.3's behavior in OS
X, where frames are effectively prevented from moving off-screen.  There
is no point in allowing a frame to be moved off-screen, IIUC, since the
frame seems to never reappear no matter what we do with it.

>
>
> martin





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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-02-27  8:05           ` martin rudalics
  2017-02-27 10:34             ` Charles A. Roelli
@ 2017-02-27 20:47             ` Charles A. Roelli
  2017-02-28 10:12               ` Charles A. Roelli
  2017-02-28 13:20               ` Anders Lindgren
  1 sibling, 2 replies; 34+ messages in thread
From: Charles A. Roelli @ 2017-02-27 20:47 UTC (permalink / raw)
  To: martin rudalics; +Cc: 25818, andlind

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

Bisecting between emacs-24.3 and emacs-24.4 led me to commit
680e6b8c5a28489733df544edb074fd29d0522a0, which introduces the
regression.  There is also a possibly related commit two hours later,
1269a680862a9bc6cd65e3d26ef05f68c7521632.

Commit 680e6b8c introduces the behavior observed in 24.4, where a frame
is not constrained to the screen area.  Also interesting is that
`display-pixel-width' works correctly (for multiple monitors as well,
that is) in the commit and the commits immediately preceding it, so it
may only be tangentially related.

I'm attaching the changeset of 680e6b8c and CCing the author.

I looked into constrainFrameRect, and it seems to have different
behavior depending on whether "Spaces" are available (introduced in OS X
10.9 apparently).  Might also have something to with the issue at hand.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 680e6b8c-2013-12-19-frame-handling.diff --]
[-- Type: text/x-patch, Size: 6027 bytes --]

diff --git a/src/ChangeLog b/src/ChangeLog
index d6db5b3..e7f30f2 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,16 @@
 2013-12-19  Anders Lindgren <andlind@gmail.com>
 
+	* nsterm.m (NSTRACE_SIZE, NSTRACE_RECT): New macros.
+	(ns_constrain_all_frames, x_set_offset): Remove assignment to
+	dont_constrain.
+	(updateFrameSize:, windowWillResize:toSize:): Add trace.
+	(constrainFrameRect): Remove special case nr_screens == 1.
+	Don't constrain size to size of view.
+
+	* nsterm.h (ns_output): Remove dont_constrain.
+
+2013-12-19  Anders Lindgren <andlind@gmail.com>
+
 	* nsterm.m (mouseDown:): Generate HORIZ_WHEEL_EVENT.
 
 2013-12-18  Paul Eggert  <eggert@cs.ucla.edu>
diff --git a/src/nsterm.h b/src/nsterm.h
index 0215f13..faf8271 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -687,9 +687,6 @@ struct ns_output
   /* This is the Emacs structure for the NS display this frame is on.  */
   struct ns_display_info *display_info;
 
-  /* Non-zero if we want to constrain the frame to the screen.  */
-  int dont_constrain;
-
   /* Non-zero if we are zooming (maximizing) the frame.  */
   int zooming;
 };
diff --git a/src/nsterm.m b/src/nsterm.m
index 99c061d..d7c2f38 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -79,6 +79,28 @@ int term_trace_num = 0;
 #define NSTRACE(x)
 #endif
 
+/* Detailed tracing. "S" means "size" and "LL" stands for "lower left". */
+#if 1
+int term_trace_num = 0;
+#define NSTRACE_SIZE(str,size) fprintf (stderr,                         \
+                                   "%s:%d: [%d]   " str                 \
+                                   " (S:%.0f x %.0f)\n", \
+                                   __FILE__, __LINE__, ++term_trace_num,\
+                                   size.height,                       \
+                                   size.width)
+#define NSTRACE_RECT(s,r) fprintf (stderr,                              \
+                                   "%s:%d: [%d]   " s                   \
+                                   " (LL:%.0f x %.0f -> S:%.0f x %.0f)\n", \
+                                   __FILE__, __LINE__, ++term_trace_num,\
+                                   r.origin.x,                          \
+                                   r.origin.y,                          \
+                                   r.size.height,                       \
+                                   r.size.width)
+#else
+#define NSTRACE_SIZE(str,size)
+#define NSTRACE_RECT(s,r)
+#endif
+
 extern NSString *NSMenuDidBeginTrackingNotification;
 
 /* ==========================================================================
@@ -605,7 +627,6 @@ ns_constrain_all_frames (void)
           NSView *view = FRAME_NS_VIEW (f);
           /* This no-op will trigger the default window placing
            * constraint system. */
-          f->output_data.ns->dont_constrain = 0;
           [[view window] setFrameOrigin:[[view window] frame].origin];
         }
     }
@@ -1225,7 +1246,6 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_grav)
 #endif
       /* Constrain the setFrameTopLeftPoint so we don't move behind the
          menu bar.  */
-      f->output_data.ns->dont_constrain = 0;
       [[view window] setFrameTopLeftPoint:
                        NSMakePoint (SCREENMAXBOUND (f->left_pos),
                                     SCREENMAXBOUND ([fscreen frame].size.height
@@ -5684,10 +5704,13 @@ not_in_argv (NSString *arg)
   NSRect wr = [window frame];
   int extra = 0;
   int oldc = cols, oldr = rows;
-  int oldw = FRAME_PIXEL_WIDTH (emacsframe),
-    oldh = FRAME_PIXEL_HEIGHT (emacsframe);
+  int oldw = FRAME_PIXEL_WIDTH (emacsframe);
+  int oldh = FRAME_PIXEL_HEIGHT (emacsframe);
   int neww, newh;
 
+  NSTRACE (updateFrameSize);
+  NSTRACE_SIZE ("Original size", NSMakeSize (oldw, oldh));
+
   if (! [self isFullscreen])
     {
 #ifdef NS_IMPL_GNUSTEP
@@ -5731,6 +5754,8 @@ not_in_argv (NSString *arg)
           sz.width = FRAME_COLUMN_WIDTH (emacsframe);
           sz.height = FRAME_LINE_HEIGHT (emacsframe);
           [win setResizeIncrements: sz];
+
+          NSTRACE_SIZE ("New size", NSMakeSize (neww, newh));
         }
 
       [view setFrame: NSMakeRect (0, 0, neww, newh)];
@@ -5744,6 +5769,7 @@ not_in_argv (NSString *arg)
   int extra = 0;
 
   NSTRACE (windowWillResize);
+  NSTRACE_SIZE ("Original size", frameSize);
 /*fprintf (stderr,"Window will resize: %.0f x %.0f\n",frameSize.width,frameSize.height); */
 
   if (fs_state == FULLSCREEN_MAXIMIZED
@@ -6903,19 +6929,39 @@ if (cols > 0 && rows > 0)
   NSUInteger nr_screens = [[NSScreen screens] count];
   struct frame *f = ((EmacsView *)[self delegate])->emacsframe;
   NSTRACE (constrainFrameRect);
+  NSTRACE_RECT ("input", frameRect);
 
-  if (nr_screens == 1)
-    {
-      NSRect r = [super constrainFrameRect:frameRect toScreen:screen];
-      return r;
-    }
-
-  if (f->output_data.ns->dont_constrain
-      || ns_menu_bar_should_be_hidden ())
+  if (ns_menu_bar_should_be_hidden ())
     return frameRect;
 
-  f->output_data.ns->dont_constrain = 1;
-  return [super constrainFrameRect:frameRect toScreen:screen];
+  /* The default implementation does two things 1) ensure that the top
+     of the rectangle is below the menu bar (or below the top of the
+     screen) and 2) resizes windows larger than the screen. As we
+     don't want the latter, a smaller rectangle is used. */
+#define FAKE_HEIGHT 64
+  float old_top = frameRect.origin.y + frameRect.size.height;
+  NSRect r;
+  r.size.height = FAKE_HEIGHT;
+  r.size.width = frameRect.size.width;
+  r.origin.x = frameRect.origin.x;
+  r.origin.y = old_top - FAKE_HEIGHT;
+
+  NSTRACE_RECT ("input to super", r);
+
+  r = [super constrainFrameRect:r toScreen:screen];
+
+  NSTRACE_RECT ("output from super", r);
+
+  float new_top = r.origin.y + FAKE_HEIGHT;
+  if (new_top < old_top)
+  {
+    frameRect.origin.y = new_top - frameRect.size.height;
+  }
+
+  NSTRACE_RECT ("output", frameRect);
+
+  return frameRect;
+#undef FAKE_HEIGHT
 }
 
 @end /* EmacsWindow */

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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-02-27 20:47             ` Charles A. Roelli
@ 2017-02-28 10:12               ` Charles A. Roelli
  2017-02-28 13:20               ` Anders Lindgren
  1 sibling, 0 replies; 34+ messages in thread
From: Charles A. Roelli @ 2017-02-28 10:12 UTC (permalink / raw)
  To: martin rudalics; +Cc: 25818, jan.h.d, andlind

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

The attached patch against master fixes the issue on OS X 10.6 by
constraining frames to the visible area.  Behavior with OS X 10.9+ (and
"Spaces") still needs testing.  The patch also fixes
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=14713, which has
reappeared since it was fixed (at least it has reappeared on 10.6).

Also CCing Jan Djärv who worked on this area of the code previously (see
e61a31bf999b37f32616e5159196d179657ad788).


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-nsterm.m-constrainFrameRect-toScreen-Constrain-frame.patch --]
[-- Type: text/x-patch, Size: 1320 bytes --]

From cdc3c31ef47bad37899575c78aa888b4f0bf24f2 Mon Sep 17 00:00:00 2001
From: Charles A. Roelli <charles@aurox.ch>
Date: Tue, 28 Feb 2017 10:58:25 +0100
Subject: [PATCH] Constrain frames in all versions of OS X

* nsterm.m (constrainFrameRect:toScreen:): Constrain
  frames in all versions of OS X.

Fixes: debbugs:25818
---
 src/nsterm.m |   14 +++-----------
 1 files changed, 3 insertions(+), 11 deletions(-)

diff --git a/src/nsterm.m b/src/nsterm.m
index 28764c8..9b479ad 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -7841,17 +7841,9 @@ - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
              NSTRACE_ARG_RECT (frameRect));
 
 #ifdef NS_IMPL_COCOA
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
-  // If separate spaces is on, it is like each screen is independent.  There is
-  // no spanning of frames across screens.
-  if ([NSScreen screensHaveSeparateSpaces])
-    {
-      NSTRACE_MSG ("Screens have separate spaces");
-      frameRect = [super constrainFrameRect:frameRect toScreen:screen];
-      NSTRACE_RETURN_RECT (frameRect);
-      return frameRect;
-    }
-#endif
+  frameRect = [super constrainFrameRect:frameRect toScreen:screen];
+  NSTRACE_RETURN_RECT (frameRect);
+  return frameRect;
 #endif
 
   return constrain_frame_rect(frameRect,
--
1.7.4.4


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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-02-27 20:47             ` Charles A. Roelli
  2017-02-28 10:12               ` Charles A. Roelli
@ 2017-02-28 13:20               ` Anders Lindgren
  2017-02-28 15:05                 ` Charles A. Roelli
  1 sibling, 1 reply; 34+ messages in thread
From: Anders Lindgren @ 2017-02-28 13:20 UTC (permalink / raw)
  To: Charles A. Roelli; +Cc: 25818


[-- Attachment #1.1: Type: text/plain, Size: 2272 bytes --]

Hi!

I'm the author behind the changes you are discussing.

Emacs 24.3 demonstrates a number of problems when you want to stretch Emacs
across two screens and also when placing the title bar above the top of the
screen (which is very useful when `ns-auto-hide-menu-bar' is non-nil).
Applying the suggested patch would only reintroduce those problems.

A better solution would be to add to code to check if the Emacs frame is
outside any monitor, and then (and only then) call the constrainFrameRect
method of the parent class.

Also, if I remember correctly, 24.3 behaved differently when you had one
monitor compared to multiple monitors. I removed this, as I didn't see the
point of it, and because if introduced an extra level of complexity when it
came to testing.

When it comes to `display-pixel-width', it should return the combined width
of side-by-side monitors, so 24.4 and newer Emacs versions behave correctly.

I have attached a test file I used when I worked with the NS port.

Anyway, I'm glad that you have looked into this. The number of people
actively working on the NS port are close to zero (I threw in the towel
about a year ago, simply because I couldn't find the time I needed to spend
on it). If you are interested in contributing, you can look at the
"NeXTstep port" section of the "TODO" file.

    -- Anders


On Mon, Feb 27, 2017 at 9:47 PM, Charles A. Roelli <charles@aurox.ch> wrote:

> Bisecting between emacs-24.3 and emacs-24.4 led me to commit
> 680e6b8c5a28489733df544edb074fd29d0522a0, which introduces the
> regression.  There is also a possibly related commit two hours later,
> 1269a680862a9bc6cd65e3d26ef05f68c7521632.
>
> Commit 680e6b8c introduces the behavior observed in 24.4, where a frame
> is not constrained to the screen area.  Also interesting is that
> `display-pixel-width' works correctly (for multiple monitors as well,
> that is) in the commit and the commits immediately preceding it, so it
> may only be tangentially related.
>
> I'm attaching the changeset of 680e6b8c and CCing the author.
>
> I looked into constrainFrameRect, and it seems to have different
> behavior depending on whether "Spaces" are available (introduced in OS X
> 10.9 apparently).  Might also have something to with the issue at hand.
>
>

[-- Attachment #1.2: Type: text/html, Size: 2903 bytes --]

[-- Attachment #2: ns-frame-test.el --]
[-- Type: application/octet-stream, Size: 3839 bytes --]

;; ns-frame-test.el --- test for NextStep (Mac OS X) frame positioning.

;; Author: Anders Lindgren

;; This file is *not* intended to be loaded into Emacs. Instead, it
;; contains individual expressions that should be evaluated one by
;; one, with accompanying manual test steps.

;; Future development:
;;
;; * Add more test cases, like resolution change, frame stretching
;;   multiple screens, and dragging between different sized screens.
;;
;; * Automatic testing using a unit test framework, for example ert.
;;
(error "You should not load this file, read the file comments for details")

;; ----------------------------------------
;; Basics
;;

;; Initially, Emacs should be placed under the menu bar.

;; After each test in this section, it should be possible to drag the
;; frame around, but it should not be possible to drag it in under the
;; menu bar.

;; The following should not place the window under the menu bar.
(set-frame-position (selected-frame) 0 -10)

;; The following will create a frame taller than screen. (90 is
;; suitable for a 1200 pixel display, you mileage may wary.)
;;
;; The frame should not be resized to fit the screen.
(set-frame-size (selected-frame) 80 90)

;; The following should move the frame down a bit. It should not be
;; resized to fit the screen.
(set-frame-position (selected-frame) 0 50)


;; ----------------------------------------
;; Auto hide menu
;;

;; In this section, the auto-hide feature of the menu bar is
;; tested. After each step it should be possible do drag the window
;; around. It should not be possible to drag the window from within
;; the screen to above the screen. However, if it already is above the
;; screen, it should be possible to drag it around there.

;; Start with a frame smaller than the screen.
(set-frame-size (selected-frame) 80 50)

;; After this, the menu bar should be hidden (unless the mouse pointer
;; is at the top of the screen).
(setq ns-auto-hide-menu-bar t)

;; This will place the window title *above* the top of the screen (as
;; intended).
(set-frame-position (selected-frame) 0 -10)

;; Frame will be higher than screen.
(set-frame-size (selected-frame) 80 90)


;; ----------------------------------------
;; Exit auto hide menu
;;

;; Redisplay the menu bar. After this, the frame should be placed
;; *below* the menu bar.
(setq ns-auto-hide-menu-bar nil)


;; ----------------------------------------
;; Pixelwise resize.
;;

;; The following tests assums that the Dock is configured to be on the
;; bottom of the screen and in auto-hide mode.


;; ----------
;; Restart Emacs.
;;
;; Evaluate the following. The frame should stretch from the menu bar
;; to four pixels from the bottom.

(progn
  (setq frame-resize-pixelwise t)
  (set-frame-parameter (selected-frame) 'fullscreen 'fullheight))


;; ----------
;; Restart Emcas
;;
;; Evaluate the following. The frame should stretch from the top of
;; the screen to four pixels from the bottom.

(progn
  (setq frame-resize-pixelwise t)
  (setq ns-auto-hide-menu-bar t)
  (set-frame-parameter (selected-frame) 'fullscreen 'fullheight))


;; ----------
;; Restart Emcas
;;
;; Evaluate the following and press the alt-click the green button (it
;; should display a plus). The frame should stretch from the menu bar
;; to four pixels from the bottom.
;;
;; Click again, the frame should conver the entire screen, except the
;; menu bar and four pixels from the bottom.
;;
;; Click again, the frame return to its original size and place.

(setq frame-resize-pixelwise t)


;; ----------
;; Restart Emcas
;;
;; Evaluate the following and press the alt-click the green button (it
;; should display a plus). The frame should stretch from the top to
;; four pixels from the bottom.

(progn
  (setq frame-resize-pixelwise t)
  (setq ns-auto-hide-menu-bar t))

;; ns-frame-test.el ends here.

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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-02-28 13:20               ` Anders Lindgren
@ 2017-02-28 15:05                 ` Charles A. Roelli
  2017-02-28 20:35                   ` Anders Lindgren
  0 siblings, 1 reply; 34+ messages in thread
From: Charles A. Roelli @ 2017-02-28 15:05 UTC (permalink / raw)
  To: Anders Lindgren; +Cc: 25818

Thanks for the quick response.

On Tue, Feb 28 2017 at 02:20:55 pm, Anders Lindgren wrote:

> Hi!
>
> I'm the author behind the changes you are discussing.
>
> Emacs 24.3 demonstrates a number of problems when you want to stretch Emacs
> across two screens and also when placing the title bar above the top of the
> screen (which is very useful when `ns-auto-hide-menu-bar' is non-nil).
> Applying the suggested patch would only reintroduce those problems.

I've tested my patched version of Emacs master and I can stretch one
frame across both screens (seemingly) without any problem.  It is
possible that my patched version would not do the right thing on OS X
10.9+, though, if the interaction with "Spaces" and constrainFrameRect
is different there.

[BTW, if I understand right, "Spaces" in Mac OS X 10.9+ prevent you from
having any frame spanning multiple monitors.  Does the current Emacs
code (without my patch) remove that limitation?]

Also, thank you for pointing out `ns-auto-hide-menu-bar'.  I did not
know about that variable.  But I do not understand why you would want to
place a frame above the top of the screen when the menu bar is hidden.
It might give you an extra row of text, at the cost of obscuring the
close/iconify/maximize buttons, and the frame title.  You could get more
bang for your buck by turning off `tool-bar-mode', IMO.  And I don't
think OS X natively allows a user to place a frame above the top of the
screen anyway.

> A better solution would be to add to code to check if the Emacs frame is
> outside any monitor, and then (and only then) call the constrainFrameRect
> method of the parent class.

Your use case above for a frame (placing it above the top of the screen,
as with `(set-frame-position (selected-frame) 0 -10)' in your test
code), would (I think) count as bringing the frame outside of a screen,
and therefore constrainFrameRect would kick in, bringing the frame back
to ((top . 0) (left . 0)) -- as my patched version does.  But this is
apparently not what you want.  So we would need to allow some leeway in
the calculation to allow a frame to be only slightly outside of a
monitor?  This sounds complicated to me.

> Also, if I remember correctly, 24.3 behaved differently when you had one
> monitor compared to multiple monitors. I removed this, as I didn't see the
> point of it, and because if introduced an extra level of complexity when it
> came to testing.

In my recently built emacs-24.3, I can't see any different behavior with
a second monitor (except, of course, that `display-pixel-width' only
accounts for the first monitor, which must ultimately have some
consequences).

> When it comes to `display-pixel-width', it should return the combined width
> of side-by-side monitors, so 24.4 and newer Emacs versions behave correctly.
>
> I have attached a test file I used when I worked with the NS port.

Thank you, it's a good start for testing out the frame handling code on
different versions.

> Anyway, I'm glad that you have looked into this. The number of people
> actively working on the NS port are close to zero (I threw in the towel
> about a year ago, simply because I couldn't find the time I needed to spend
> on it). If you are interested in contributing, you can look at the
> "NeXTstep port" section of the "TODO" file.

Will do.  Do you know of any good resources for tinkering in this area?
I have some old Apple docsets available which I haven't really gotten
around to reading yet, but that's about it.

>
> On Mon, Feb 27, 2017 at 9:47 PM, Charles A. Roelli <charles@aurox.ch> wrote:
>
>> Bisecting between emacs-24.3 and emacs-24.4 led me to commit
>> 680e6b8c5a28489733df544edb074fd29d0522a0, which introduces the
>> regression.  There is also a possibly related commit two hours later,
>> 1269a680862a9bc6cd65e3d26ef05f68c7521632.
>>
>> Commit 680e6b8c introduces the behavior observed in 24.4, where a frame
>> is not constrained to the screen area.  Also interesting is that
>> `display-pixel-width' works correctly (for multiple monitors as well,
>> that is) in the commit and the commits immediately preceding it, so it
>> may only be tangentially related.
>>
>> I'm attaching the changeset of 680e6b8c and CCing the author.
>>
>> I looked into constrainFrameRect, and it seems to have different
>> behavior depending on whether "Spaces" are available (introduced in OS X
>> 10.9 apparently).  Might also have something to with the issue at hand.





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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-02-28 15:05                 ` Charles A. Roelli
@ 2017-02-28 20:35                   ` Anders Lindgren
  2017-02-28 22:05                     ` Drew Adams
  2017-03-19 19:38                     ` Charles A. Roelli
  0 siblings, 2 replies; 34+ messages in thread
From: Anders Lindgren @ 2017-02-28 20:35 UTC (permalink / raw)
  To: Charles A. Roelli; +Cc: 25818

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

Hi!


> I've tested my patched version of Emacs master and I can stretch one
> frame across both screens (seemingly) without any problem.  It is
> possible that my patched version would not do the right thing on OS X
> 10.9+, though, if the interaction with "Spaces" and constrainFrameRect
> is different there.
>
> [BTW, if I understand right, "Spaces" in Mac OS X 10.9+ prevent you from
> having any frame spanning multiple monitors.  Does the current Emacs
> code (without my patch) remove that limitation?]
>

In 10.9, a "space" is a dedicated full-frame area. I don't think your patch
will affect this.

It took quite a lot of work to get the current implementation to work for a
variety of scenarios. To throw in a "quick fix" for another scenario will
most likely break things that work today. It would be better to identify
some situations when the function should behave differently and fix those
specific cases.


> A better solution would be to add to code to check if the Emacs frame is
> > outside any monitor, and then (and only then) call the constrainFrameRect
> > method of the parent class.
>
> Your use case above for a frame (placing it above the top of the screen,
> as with `(set-frame-position (selected-frame) 0 -10)' in your test
> code), would (I think) count as bringing the frame outside of a screen,
> and therefore constrainFrameRect would kick in, bringing the frame back
> to ((top . 0) (left . 0)) -- as my patched version does.  But this is
> apparently not what you want.  So we would need to allow some leeway in
> the calculation to allow a frame to be only slightly outside of a
> monitor?  This sounds complicated to me.
>

I think it is acceptable if a frame is partially outside the display. What
I suggested was to check if the frame was ENTIRELY outside any monitor, and
in that case call the parent function to bring it in. This test should be
trivial to implement.

You can find a lot of the recent design decisions of the NS port in the
epic discussion thread of bug 21415.


Also, thank you for pointing out `ns-auto-hide-menu-bar'.  I did not
> know about that variable.  But I do not understand why you would want to
> place a frame above the top of the screen when the menu bar is hidden.
> It might give you an extra row of text, at the cost of obscuring the
> close/iconify/maximize buttons, and the frame title.  You could get more
> bang for your buck by turning off `tool-bar-mode', IMO.  And I don't
> think OS X natively allows a user to place a frame above the top of the
> screen anyway.
>

By placing the title bar above the top of the screen, I'm able to use the
entire height of the monitor for text, while having access to the menu by
moving the mouse pointer to the top of the screen. I don't need the buttons
and the frame title is of little use.

Admittedly, I'm a bit crazy when it comes to screen real estate -- with a
small font, six side-by-side windows, and Follow mode enabled, I get 888
consecutive lines of text.


> Anyway, I'm glad that you have looked into this. The number of people
> > actively working on the NS port are close to zero (I threw in the towel
> > about a year ago, simply because I couldn't find the time I needed to
> spend
> > on it). If you are interested in contributing, you can look at the
> > "NeXTstep port" section of the "TODO" file.
>
> Will do.  Do you know of any good resources for tinkering in this area?
> I have some old Apple docsets available which I haven't really gotten
> around to reading yet, but that's about it.


I mostly look at the reference documentation like
https://developer.apple.com/reference/appkit/nswindow

There are tons of introductory text on macOS (which, internally, is similar
for iOS). You have to look for one which suit your background knowledge.
You can, however, skip anything related to the "Interface Builder", since
it's not used by Emacs. If you don't know Objective-C, I would recommend
you to start with an introduction to that, and go from there.

    -- Anders

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

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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-02-28 20:35                   ` Anders Lindgren
@ 2017-02-28 22:05                     ` Drew Adams
  2017-03-01 10:48                       ` Anders Lindgren
  2017-03-19 19:38                     ` Charles A. Roelli
  1 sibling, 1 reply; 34+ messages in thread
From: Drew Adams @ 2017-02-28 22:05 UTC (permalink / raw)
  To: Anders Lindgren, Charles A. Roelli; +Cc: 25818

Excuse me for chiming in without really following this
thread.  I don't use OS X, for one thing, and I'm not
following this particular bug.

But if one of the questions is whether an Emacs user
(or code) should _be able_ to position a frame off
screen then I emphatically say yes, s?he should.

I have code that lets you incrementally move a frame
up/down/left/right, including wraparound or including
the possibility of not wrapping but continuing till
the frame is entirely off screen.

I don't see anything wrong with _allowing_ someone
to position a frame off screen.  Why they might want
to do that is up to them.

If that question is not in fact being raised in this
bug discussion, then please ignore this intrusion,
and sorry for the noise.





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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-02-28 22:05                     ` Drew Adams
@ 2017-03-01 10:48                       ` Anders Lindgren
  2017-03-01 16:10                         ` Drew Adams
  0 siblings, 1 reply; 34+ messages in thread
From: Anders Lindgren @ 2017-03-01 10:48 UTC (permalink / raw)
  To: Drew Adams; +Cc: 25818, Charles A. Roelli

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

Hi!

On Tue, Feb 28, 2017 at 11:05 PM, Drew Adams <drew.adams@oracle.com> wrote:

> But if one of the questions is whether an Emacs user
> (or code) should _be able_ to position a frame off
> screen then I emphatically say yes, s?he should.
>
> I have code that lets you incrementally move a frame
> up/down/left/right, including wraparound or including
> the possibility of not wrapping but continuing till
> the frame is entirely off screen.
>
> I don't see anything wrong with _allowing_ someone
> to position a frame off screen.  Why they might want
> to do that is up to them.
>

I can see the point of your argument. After all, this is how Emacs work
today, and most people have been fine with it.

However, I don't feel 100% comfortable with the current situation.

The main issue is people with laptops connected to an extern monitor. When
the external monitor is disconnected, Emacs might land off screen. I would
imagine that most people would prefer that Emacs would be moved and resized
to fit in the screen of the laptop (as I imagine, most macOS application
behave).

Secondly, I miss an easy accessible method to move off-screen frames into
the visible parts of the display. On macOS, the menu is always accessible
even if the window isn't, so the obvious place would be a menu item like
"Collect Frame" (I noticed that "C-x 5 c" is unbound) -- it could be placed
after "Delete Frame" in the "File" menu.


If that question is not in fact being raised in this
> bug discussion, then please ignore this intrusion,
> and sorry for the noise.
>

No need to apologize, your input is always welcome!

    -- Anders

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

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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-03-01 10:48                       ` Anders Lindgren
@ 2017-03-01 16:10                         ` Drew Adams
  0 siblings, 0 replies; 34+ messages in thread
From: Drew Adams @ 2017-03-01 16:10 UTC (permalink / raw)
  To: Anders Lindgren; +Cc: 25818, Charles A. Roelli

> I can see the point of your argument. After all, this is how Emacs
> work today, and most people have been fine with it.
> 
> However, I don't feel 100% comfortable with the current situation.
> 
> The main issue is people with laptops connected to an extern monitor.
> When the external monitor is disconnected, Emacs might land off screen.
> I would imagine that most people would prefer that Emacs would be
> moved and resized to fit in the screen of the laptop (as I imagine,
> most macOS application behave).

> Secondly, I miss an easy accessible method to move off-screen frames
> into the visible parts of the display. On macOS, the menu is always
> accessible even if the window isn't, so the obvious place would be
> a menu item like "Collect Frame" (I noticed that "C-x 5 c" is unbound)
> -- it could be placed after "Delete Frame" in the "File" menu.

I think I agree with everything you wrote.

Users & Emacs-Lisp code should be able to position a frame partially
or fully off-screen.

But users should have simple ways to bring a given frame or all
frames that are completely off screen on screen.

And I agree with Martin's observation that such things should be
available from Emacs, but when a window mgr does something we don't
want wrt positioning users (and Emacs code) should be able to try
to compensate in some way (change the position to something that is
acceptable by the window mgr).  And our doc should make clear to
users that Emacs doesn't get the last word, so that some behavior
they see may be imposed by the window mgr, i.e., beyond Emacs's
control.





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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-02-28 20:35                   ` Anders Lindgren
  2017-02-28 22:05                     ` Drew Adams
@ 2017-03-19 19:38                     ` Charles A. Roelli
  2017-03-27 18:22                       ` Anders Lindgren
  1 sibling, 1 reply; 34+ messages in thread
From: Charles A. Roelli @ 2017-03-19 19:38 UTC (permalink / raw)
  To: Anders Lindgren; +Cc: 25818

Hi again,

Sorry for taking a while to get back on this.

Looking at this issue again, it would be helpful to know what version of
OS X you use and whether you see the issue that I described in the first
message of this thread (*), and also whether the patch I suggested stops
frames from being placed above the top of the screen.  Because from what
I can see, I don't see how the patch will prevent you from doing so,
unless you have "Spaces" turned off.

(*) One quick way of finding out is running something like
    `(set-frame-position (selected-frame) 0 10000)' (best done from
    `emacs -Q').  If the moved frame cannot be returned on-screen
    programmatically, then you have the issue.  If it stays on-screen,
    then you don't.

My patch got rid of these lines:

-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
-  // If separate spaces is on, it is like each screen is independent.  There is
-  // no spanning of frames across screens.
-  if ([NSScreen screensHaveSeparateSpaces])
-    {
-      NSTRACE_MSG ("Screens have separate spaces");
-      frameRect = [super constrainFrameRect:frameRect toScreen:screen];
-      NSTRACE_RETURN_RECT (frameRect);
-      return frameRect;
-    }
-#endif

According to the Apple documentation, screensHaveSeparateSpaces()
"returns a Boolean value that indicates whether each screen can have its
own set of spaces.  This method reflects whether the “Displays have
separate Spaces” option is enabled in Mission Control system
preference. You might use the return value to determine how to present
your app when in fullscreen mode."

So the idea of this code was to constrain a frame only if "Spaces" is
enabled, right?  I assume then, that if you have "Spaces" turned on (but
even if you don't necessarily use the feature), then frames are
prevented from going entirely off-screen (which is a must for OS X).

The reason I ask this is because I have no idea whether the problem
exists in Emacs on newer versions of OS X.  If it doesn't, then the fix
can be added only for OS X < 10.9.





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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-03-19 19:38                     ` Charles A. Roelli
@ 2017-03-27 18:22                       ` Anders Lindgren
  2017-04-02 14:14                         ` Charles A. Roelli
  0 siblings, 1 reply; 34+ messages in thread
From: Anders Lindgren @ 2017-03-27 18:22 UTC (permalink / raw)
  To: Charles A. Roelli; +Cc: 25818

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

Hi!

Sorry for not getting back to you immediately.

Anyway, I did try your original patch. Unfortunately, the effect is as I
anticipated. When the patch is applied, if a frame is placed slightly
outside the display area, it will be moved back inside the borders.
Effectively, this means that you can't place the title bar above the top of
the display, which is possible (by design) with an unpatched Emacs. (By the
way, this is possible in Emacs on Windows as well.)

I use OS X 10.10.5 (Yosemite). I have "spaces" disabled, which allows an
Emacs frame to be stretched across multiple monitors.

To solve your problem, and to ensure that we don't break anything for my
use case, we would need to call "[super constrainFrameRect:frameRect
toScreen:screen];" only when the frame is determined to be fully outside
any monitor. This is not rocket science -- just iterate over all monitors
and check that the frame overlap at least one.

Sincerely,
    Anders Lindgren

On Sun, Mar 19, 2017 at 8:38 PM, Charles A. Roelli <charles@aurox.ch> wrote:

> Hi again,
>
> Sorry for taking a while to get back on this.
>
> Looking at this issue again, it would be helpful to know what version of
> OS X you use and whether you see the issue that I described in the first
> message of this thread (*), and also whether the patch I suggested stops
> frames from being placed above the top of the screen.  Because from what
> I can see, I don't see how the patch will prevent you from doing so,
> unless you have "Spaces" turned off.
>
> (*) One quick way of finding out is running something like
>     `(set-frame-position (selected-frame) 0 10000)' (best done from
>     `emacs -Q').  If the moved frame cannot be returned on-screen
>     programmatically, then you have the issue.  If it stays on-screen,
>     then you don't.
>
> My patch got rid of these lines:
>
> -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
> -  // If separate spaces is on, it is like each screen is independent.
> There is
> -  // no spanning of frames across screens.
> -  if ([NSScreen screensHaveSeparateSpaces])
> -    {
> -      NSTRACE_MSG ("Screens have separate spaces");
> -      frameRect = [super constrainFrameRect:frameRect toScreen:screen];
> -      NSTRACE_RETURN_RECT (frameRect);
> -      return frameRect;
> -    }
> -#endif
>
> According to the Apple documentation, screensHaveSeparateSpaces()
> "returns a Boolean value that indicates whether each screen can have its
> own set of spaces.  This method reflects whether the “Displays have
> separate Spaces” option is enabled in Mission Control system
> preference. You might use the return value to determine how to present
> your app when in fullscreen mode."
>
> So the idea of this code was to constrain a frame only if "Spaces" is
> enabled, right?  I assume then, that if you have "Spaces" turned on (but
> even if you don't necessarily use the feature), then frames are
> prevented from going entirely off-screen (which is a must for OS X).
>
> The reason I ask this is because I have no idea whether the problem
> exists in Emacs on newer versions of OS X.  If it doesn't, then the fix
> can be added only for OS X < 10.9.
>

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

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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-03-27 18:22                       ` Anders Lindgren
@ 2017-04-02 14:14                         ` Charles A. Roelli
  2017-04-03  8:33                           ` Anders Lindgren
  0 siblings, 1 reply; 34+ messages in thread
From: Charles A. Roelli @ 2017-04-02 14:14 UTC (permalink / raw)
  To: Anders Lindgren; +Cc: 25818

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

Hi Anders,

Does the attached patch work for you?  It's still a bit rough around the
edges, but seems to do the right thing.

A quick test on 10.6:

(setq ns-auto-hide-menu-bar t)

;; Places the frame just above the top of the screen.
(set-frame-position (selected-frame) 0 -20)

;; Frame would be completely offscreen; so it's constrained and brought
;; back.
(set-frame-position (selected-frame) 0 -10000)

Cheers,
Charles


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Constrain-frames-to-visible-area-of-screens-in-OS-X.patch --]
[-- Type: text/x-patch, Size: 2420 bytes --]

From 60db513f5283525c3adacb29f1bc6ad4461a11b0 Mon Sep 17 00:00:00 2001
From: Charles A. Roelli <charles@aurox.ch>
Date: Sun, 2 Apr 2017 15:51:24 +0200
Subject: [PATCH] Constrain frames to visible area of screens in OS X

* nsterm.m (constrainFrameRect:toScreen:): Constrain
  frames in OS X, if they would otherwise go offscreen.

Fixes: debbugs:25818
---
 src/nsterm.m |   33 ++++++++++++++++++++++++++++++++-
 1 files changed, 32 insertions(+), 1 deletions(-)

diff --git a/src/nsterm.m b/src/nsterm.m
index ebe29e4..b87b9fa 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -7846,21 +7846,52 @@ - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
   // If separate spaces is on, it is like each screen is independent.  There is
   // no spanning of frames across screens.
   if ([NSScreen screensHaveSeparateSpaces])
     {
       NSTRACE_MSG ("Screens have separate spaces");
       frameRect = [super constrainFrameRect:frameRect toScreen:screen];
       NSTRACE_RETURN_RECT (frameRect);
       return frameRect;
     }
-#endif
+  else
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 */
+    {
+      NSArray *screens = [NSScreen screens];
+      NSUInteger nr_screens = [screens count];
+
+      int i;
+      // A rectangle covering all the screen the frame is displayed in.
+      // Duplicated from constrain_frame_rect.
+      NSRect multiscreenRect = NSMakeRect(0, 0, 0, 0);
+      for (i = 0; i < nr_screens; ++i )
+	{
+	  NSScreen *s = [screens objectAtIndex: i];
+	  NSRect scrRect = [s frame];
+
+	  NSTRACE_MSG ("Screen %d: " NSTRACE_FMT_RECT,
+		       i, NSTRACE_ARG_RECT (scrRect));
+
+	  multiscreenRect = NSUnionRect (multiscreenRect, scrRect);
+	}
+
+      // Check that the proposed frameRect intersects the
+      // multiscreenRect.  If it does not, constrain the frame and
+      // return it.  See bug #25818.
+      if (!NSIntersectsRect(multiscreenRect, frameRect))
+	{
+	  NSTRACE_MSG ("Frame outside screens; constraining");
+	  frameRect = [super constrainFrameRect:frameRect toScreen:screen];
+	  NSTRACE_RETURN_RECT (frameRect);
+	  return frameRect;
+	}
+    }
 #endif
 
   return constrain_frame_rect(frameRect,
                               [(EmacsView *)[self delegate] isFullscreen]);
 }
 
 
 - (void)performZoom:(id)sender
 {
   NSTRACE ("[EmacsWindow performZoom:]");
-- 
1.7.4.4


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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-04-02 14:14                         ` Charles A. Roelli
@ 2017-04-03  8:33                           ` Anders Lindgren
  2017-04-08 20:40                             ` Charles A. Roelli
  0 siblings, 1 reply; 34+ messages in thread
From: Anders Lindgren @ 2017-04-03  8:33 UTC (permalink / raw)
  To: Charles A. Roelli; +Cc: 25818

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

Hi!

I think this is a good start. However, there is a case that your patch
miss. If you have multiple monitors arranged in, say, an L-shape, a frame
might be placed inside "multiscreenRect", without actually being visible on
any screen. (This typically occur when you have a large desktop monitor
connected to a laptop or when you have one monitor placed horizontally and
one vertically.)

Fortunately, it should be easy to fix. What about something like (in
pseudo-code):

     BOOL in_any_screen = NO;
     for (screen = /* Loop over all screens */ ...)
       {
         if (overlapping(frame, scree))
           {
              in_any_screen = YES;
              break;
           }
        }
     if ( ! in_any_screen )
       {
         /* Move the frame in */
       }

Anyway, I think that we're on the right track and I appreciate that you
have taken time to work on this!

    -- Anders

PS. I just found another, unrelated, problem, when comparing the NS and X11
versions. When passing a negative value to `set-frame-position' it is
supposed to place the frame relative to the right/bottom border of the
display, but in the NS version it doesn't. (The X11 version gets the Y
placement wrong with 48 pixels, but that is another story.)

On Sun, Apr 2, 2017 at 4:14 PM, Charles A. Roelli <charles@aurox.ch> wrote:

> Hi Anders,
>
> Does the attached patch work for you?  It's still a bit rough around the
> edges, but seems to do the right thing.
>
> A quick test on 10.6:
>
> (setq ns-auto-hide-menu-bar t)
>
> ;; Places the frame just above the top of the screen.
> (set-frame-position (selected-frame) 0 -20)
>
> ;; Frame would be completely offscreen; so it's constrained and brought
> ;; back.
> (set-frame-position (selected-frame) 0 -10000)
>
> Cheers,
> Charles
>
>

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

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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-04-03  8:33                           ` Anders Lindgren
@ 2017-04-08 20:40                             ` Charles A. Roelli
  2017-04-09 19:13                               ` Anders Lindgren
  0 siblings, 1 reply; 34+ messages in thread
From: Charles A. Roelli @ 2017-04-08 20:40 UTC (permalink / raw)
  To: Anders Lindgren; +Cc: 25818

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

Hi Anders,

Following your idea, here's an updated patch that works equivalently.
Please let me know what you think.

> Anyway, I think that we're on the right track and I appreciate that you
> have taken time to work on this!

My pleasure!

> PS. I just found another, unrelated, problem, when comparing the NS and X11
> versions. When passing a negative value to `set-frame-position' it is
> supposed to place the frame relative to the right/bottom border of the
> display, but in the NS version it doesn't. (The X11 version gets the Y
> placement wrong with 48 pixels, but that is another story.)

Hm... but what if a second display is in the negative coordinate space?
How would you place a frame on it programmatically?  In any case I'll
try to build the X11 version and see how it does it -- I wasn't aware
that it still works on Mac OS.

Cheers,
Charles

>> A quick test on 10.6:
>>
>> (setq ns-auto-hide-menu-bar t)
>>
>> ;; Places the frame just above the top of the screen.
>> (set-frame-position (selected-frame) 0 -20)
>>
>> ;; Frame would be completely offscreen; so it's constrained and brought
>> ;; back.
>> (set-frame-position (selected-frame) 0 -10000)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Constrain-frames-to-visible-area-of-screens-in-OS-X-revised.patch --]
[-- Type: text/x-patch, Size: 2206 bytes --]

From 2b95b86f8c50665bbbb62b5faae0d8d610019594 Mon Sep 17 00:00:00 2001
From: Charles A. Roelli <charles@aurox.ch>
Date: Sat, 8 Apr 2017 22:15:17 +0200
Subject: [PATCH] Constrain frames to visible area of screens in OS X

* nsterm.m (constrainFrameRect:toScreen:): Constrain
  frames in OS X, if they would otherwise go offscreen.

Fixes: debbugs:25818
---
 src/nsterm.m |   33 ++++++++++++++++++++++++++++++++-
 1 files changed, 32 insertions(+), 1 deletions(-)

diff --git a/src/nsterm.m b/src/nsterm.m
index ebe29e4..b1429f4 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -7846,21 +7846,52 @@ - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
   // If separate spaces is on, it is like each screen is independent.  There is
   // no spanning of frames across screens.
   if ([NSScreen screensHaveSeparateSpaces])
     {
       NSTRACE_MSG ("Screens have separate spaces");
       frameRect = [super constrainFrameRect:frameRect toScreen:screen];
       NSTRACE_RETURN_RECT (frameRect);
       return frameRect;
     }
-#endif
+  else
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 */
+    // Check that the proposed frameRect intersects at least one
+    // screen rectangle.  If it does not, constrain the frame and
+    // return it.  See bug #25818.
+    {
+      NSArray *screens = [NSScreen screens];
+      NSUInteger nr_screens = [screens count];
+
+      int i;
+      BOOL frame_on_screen = NO;
+
+      for (i = 0; i < nr_screens; ++i)
+	{
+	  NSScreen *s = [screens objectAtIndex: i];
+	  NSRect scrRect = [s frame];
+
+	  if (NSIntersectsRect(frameRect, scrRect))
+	    {
+	      frame_on_screen = YES;
+	      break;
+	    }
+	}
+
+      if (!frame_on_screen)
+	{
+	  NSTRACE_MSG ("Frame outside screens; constraining");
+	  frameRect = [super constrainFrameRect:frameRect toScreen:screen];
+	  NSTRACE_RETURN_RECT (frameRect);
+	  return frameRect;
+	}
+    }
 #endif
 
   return constrain_frame_rect(frameRect,
                               [(EmacsView *)[self delegate] isFullscreen]);
 }
 
 
 - (void)performZoom:(id)sender
 {
   NSTRACE ("[EmacsWindow performZoom:]");
-- 
1.7.4.4


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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-04-08 20:40                             ` Charles A. Roelli
@ 2017-04-09 19:13                               ` Anders Lindgren
  2017-04-10 19:54                                 ` Charles A. Roelli
  0 siblings, 1 reply; 34+ messages in thread
From: Anders Lindgren @ 2017-04-09 19:13 UTC (permalink / raw)
  To: Charles A. Roelli; +Cc: 25818

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

Hi!


> Following your idea, here's an updated patch that works equivalently.
> Please let me know what you think.
>

It looks really good! I've applied it and it works for my use case (placing
the menu bar above the top of the screen) and also for your (the frame
isn't visible at all). Also, I'm sure it will work with L-shaped layouts as
well, even though I haven't tried it.

I've got two minor comments. And when I say "minor" they really are minor,
feel free to disregard them if you like:

* The nsterm.m file is (almost) tab free, so I would appreciate if you
would untabify the code.

* Replace the comment with something like the following:

    // Check that the proposed frame placement is visible in at least
    // one screen.  If it is not, ask the system to reposition it.

If someone doesn't understand what the code does and why, the original
comment doesn't help as it only repeats the algorithm of the code. Also, I
don't see the need to refer to a bug number in the comment, except under
very special circumstances -- that information is available in the git
commit message.


> PS. I just found another, unrelated, problem, when comparing the NS and
> X11
> > versions. When passing a negative value to `set-frame-position' it is
> > supposed to place the frame relative to the right/bottom border of the
> > display, but in the NS version it doesn't. (The X11 version gets the Y
> > placement wrong with 48 pixels, but that is another story.)
>
> Hm... but what if a second display is in the negative coordinate space?
> How would you place a frame on it programmatically?


You can set the `left' and `top' frame parameters. If they are assigned an
integer they act like `set-frame-position' is supposed to work. However, if
they are assigned `(+ INTEGER)' or `(- INTEGER)' the value is specified
relative to the left (top) or right (bottom) edge of the display,
respectively. This allows a frame to be placed anywhere.


In any case I'll
> try to build the X11 version and see how it does it -- I wasn't aware
> that it still works on Mac OS.
>

It does. I've been using it as "the" reference implementation, whenever the
documentation isn't 100% clear.

    -- Anders

Cheers,
> Charles
>
> >> A quick test on 10.6:
> >>
> >> (setq ns-auto-hide-menu-bar t)
> >>
> >> ;; Places the frame just above the top of the screen.
> >> (set-frame-position (selected-frame) 0 -20)
> >>
> >> ;; Frame would be completely offscreen; so it's constrained and brought
> >> ;; back.
> >> (set-frame-position (selected-frame) 0 -10000)
>
>

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

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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-04-09 19:13                               ` Anders Lindgren
@ 2017-04-10 19:54                                 ` Charles A. Roelli
  2017-04-11 18:35                                   ` Anders Lindgren
  0 siblings, 1 reply; 34+ messages in thread
From: Charles A. Roelli @ 2017-04-10 19:54 UTC (permalink / raw)
  To: Anders Lindgren; +Cc: 25818

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

Hi Anders,

> Also, I'm sure it will work with L-shaped layouts as well,
> even though I haven't tried it.

I gave it a try and it worked as expected.

> I've got two minor comments. And when I say "minor" they really are minor,
> feel free to disregard them if you like:
>
> * The nsterm.m file is (almost) tab free, so I would appreciate if you
> would untabify the code.
>
> * Replace the comment with something like the following:
>
>     // Check that the proposed frame placement is visible in at least
>     // one screen.  If it is not, ask the system to reposition it.
>
> If someone doesn't understand what the code does and why, the original
> comment doesn't help as it only repeats the algorithm of the code. Also, I
> don't see the need to refer to a bug number in the comment, except under
> very special circumstances -- that information is available in the git
> commit message.

Good points, I've made these fixes in the attached patch.

>> Hm... but what if a second display is in the negative coordinate space?
>> How would you place a frame on it programmatically?
>
> You can set the `left' and `top' frame parameters. If they are assigned an
> integer they act like `set-frame-position' is supposed to work. However, if
> they are assigned `(+ INTEGER)' or `(- INTEGER)' the value is specified
> relative to the left (top) or right (bottom) edge of the display,
> respectively. This allows a frame to be placed anywhere.

I see now, thanks for this explanation.  I tried building Emacs with X
(--with-x --with-ns=no) and the configuring step picked up my installed
version of GTK3, then later failed at the linking stage for temacs due
to some GDK-related symbols not being present.  Have you seen similar
errors?

Cheers,
Charles


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Constrain-frames-to-visible-area-of-screens-in-OS-X-v2.patch --]
[-- Type: text/x-patch, Size: 1749 bytes --]

From a32609425f3aba89e1171e2dd1139876cc84051b Mon Sep 17 00:00:00 2001
From: Charles A. Roelli <charles@aurox.ch>
Date: Sat, 8 Apr 2017 22:15:17 +0200
Subject: [PATCH] Constrain frames to visible area of screens in OS X

* nsterm.m (constrainFrameRect:toScreen:): Constrain
  frames in OS X, if they would otherwise go offscreen.

Fixes: debbugs:25818
---
 src/nsterm.m |   32 +++++++++++++++++++++++++++++++-
 1 files changed, 31 insertions(+), 1 deletions(-)

diff --git a/src/nsterm.m b/src/nsterm.m
index ebe29e4..66c9d50 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -7853,7 +7853,37 @@ - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
       NSTRACE_RETURN_RECT (frameRect);
       return frameRect;
     }
-#endif
+  else
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 */
+    // Check that the proposed frameRect is visible in at least one
+    // screen.  If it is not, ask the system to reposition it.
+    {
+      NSArray *screens = [NSScreen screens];
+      NSUInteger nr_screens = [screens count];
+
+      int i;
+      BOOL frame_on_screen = NO;
+
+      for (i = 0; i < nr_screens; ++i)
+        {
+          NSScreen *s = [screens objectAtIndex: i];
+          NSRect scrRect = [s frame];
+
+          if (NSIntersectsRect(frameRect, scrRect))
+            {
+              frame_on_screen = YES;
+              break;
+            }
+        }
+
+      if (!frame_on_screen)
+        {
+          NSTRACE_MSG ("Frame outside screens; constraining");
+          frameRect = [super constrainFrameRect:frameRect toScreen:screen];
+          NSTRACE_RETURN_RECT (frameRect);
+          return frameRect;
+        }
+    }
 #endif
 
   return constrain_frame_rect(frameRect,
-- 
1.7.4.4


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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-04-10 19:54                                 ` Charles A. Roelli
@ 2017-04-11 18:35                                   ` Anders Lindgren
  2017-04-27 19:14                                     ` Charles A. Roelli
  0 siblings, 1 reply; 34+ messages in thread
From: Anders Lindgren @ 2017-04-11 18:35 UTC (permalink / raw)
  To: Charles A. Roelli; +Cc: 25818

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

Hi!

On Mon, Apr 10, 2017 at 9:54 PM, Charles A. Roelli <charles@aurox.ch> wrote:

> Good points, I've made these fixes in the attached patch.
>

Looks good!

Have you assigned copyright to FSF?

Have you commit rights to the Emacs archive? If not, would you like me to
commit it for you?


I tried building Emacs with X
> (--with-x --with-ns=no) and the configuring step picked up my installed
> version of GTK3, then later failed at the linking stage for temacs due
> to some GDK-related symbols not being present.  Have you seen similar
> errors?
>

I haven't got GTK3 libraries installed. I've used the following command
line to configure:

./configure --with-x --with-ns=no --without-dbus --with-jpeg=no
--with-gif=no --with-tiff=no
--x-includes=/Developer/SDKs/MacOSX10.6.sdk/usr/X11/include/:/Developer/SDKs/MacOSX10.6.sdk/usr/X11/include/freetype2

    -- Anders

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

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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-04-11 18:35                                   ` Anders Lindgren
@ 2017-04-27 19:14                                     ` Charles A. Roelli
  2017-04-27 20:05                                       ` Alan Third
  2017-04-29 10:30                                       ` martin rudalics
  0 siblings, 2 replies; 34+ messages in thread
From: Charles A. Roelli @ 2017-04-27 19:14 UTC (permalink / raw)
  To: Anders Lindgren; +Cc: 25818, alan

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

Hi Anders,

As discussed off-list, the copyright assignment is done.

I fixed the patch so that child frames are never constrained (after some 
testing, it seems that a child frame cannot get stuck off screen as long 
as its parent is still visible).  To test this out, evaluate the 
following from emacs -Q,

(progn
   (setq test-frame (make-frame `((parent-frame . ,(selected-frame)))))
   (set-frame-position test-frame 0 500))

and drag the parent frame down until its child is off screen. When the 
parent is moved back up, the child should reappear with it.  (Assuming 
Spaces is off; not sure what would happen in OS X 10.9+ in this case 
when Spaces is on... I guess the child would be constrained before it is 
placed off screen?).

I've also CC'ed Alan since this change is related to the new frame 
parameters.

Cheers,

Charles



[-- Attachment #2: 0001-Constrain-non-child-frames-to-screen-area-in-OS-X.patch --]
[-- Type: text/x-patch, Size: 1876 bytes --]

From d2ed9a7bed8872bd89c32d3475607a6e5a271198 Mon Sep 17 00:00:00 2001
From: Charles A. Roelli <charles@aurox.ch>
Date: Thu, 27 Apr 2017 20:44:09 +0200
Subject: [PATCH] Constrain non-child frames to screen area in OS X

* src/nsterm.m (constrainFrameRect:toScreen:): Constrain non-child
frames in OS X, if they would otherwise go offscreen.

Fixes: debbugs:25818
---
 src/nsterm.m |   35 ++++++++++++++++++++++++++++++++++-
 1 files changed, 34 insertions(+), 1 deletions(-)

diff --git a/src/nsterm.m b/src/nsterm.m
index 8c5eb06..f0495c4 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -8011,8 +8011,40 @@ - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
       NSTRACE_RETURN_RECT (frameRect);
       return frameRect;
     }
-#endif
+  else
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 */
+    // Check that the proposed frameRect is visible in at least one
+    // screen.  If it is not, ask the system to reposition it (only
+    // for non-child frames).
+
+    if (!FRAME_PARENT_FRAME (((EmacsView *)[self delegate])->emacsframe))
+    {
+      NSArray *screens = [NSScreen screens];
+      NSUInteger nr_screens = [screens count];
+
+      int i;
+      BOOL frame_on_screen = NO;
+
+      for (i = 0; i < nr_screens; ++i)
+        {
+          NSScreen *s = [screens objectAtIndex: i];
+          NSRect scrRect = [s frame];
+
+          if (NSIntersectsRect(frameRect, scrRect))
+            {
+              frame_on_screen = YES;
+              break;
+            }
+        }
+
+      if (!frame_on_screen)
+        {
+          NSTRACE_MSG ("Frame outside screens; constraining");
+          frameRect = [super constrainFrameRect:frameRect toScreen:screen];
+          NSTRACE_RETURN_RECT (frameRect);
+          return frameRect;
+        }
+    }
 #endif
 
   return constrain_frame_rect(frameRect,
-- 
1.7.4.4


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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-04-27 19:14                                     ` Charles A. Roelli
@ 2017-04-27 20:05                                       ` Alan Third
  2017-04-28 17:33                                         ` Charles A. Roelli
  2017-04-29 10:30                                       ` martin rudalics
  1 sibling, 1 reply; 34+ messages in thread
From: Alan Third @ 2017-04-27 20:05 UTC (permalink / raw)
  To: Charles A. Roelli; +Cc: 25818, Anders Lindgren

On Thu, Apr 27, 2017 at 09:14:05PM +0200, Charles A. Roelli wrote:
> I fixed the patch so that child frames are never constrained (after some
> testing, it seems that a child frame cannot get stuck off screen as long as
> its parent is still visible).

Looks good to me. It doesn’t actually apply here, so I did it
manually. I suspect it just needs rebased onto a more recent commit or
something.

> and drag the parent frame down until its child is off screen. When the
> parent is moved back up, the child should reappear with it.

If you put the top of the child frame off the top of the screen, then
click on it, it jumps back down so the titlebar is visible again. Is
this intentional?

> * src/nsterm.m (constrainFrameRect:toScreen:): Constrain non-child
> frames in OS X, if they would otherwise go offscreen.

I can’t find this in CONTRIBUTE, but you’re allowed to specify
#ifdef’d code with something like:

* src/nsterm.m (constrainFrameRect:toScreen:) [NS_IMPL_COCOA]:
Constrain non-child frames if they would otherwise go offscreen.

Thanks for working on this. :)
-- 
Alan Third





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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-04-27 20:05                                       ` Alan Third
@ 2017-04-28 17:33                                         ` Charles A. Roelli
  2017-05-02 20:33                                           ` Alan Third
  0 siblings, 1 reply; 34+ messages in thread
From: Charles A. Roelli @ 2017-04-28 17:33 UTC (permalink / raw)
  To: Alan Third; +Cc: 25818, Anders Lindgren

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

On 27/04/2017 22:05, Alan Third wrote:
> Looks good to me. It doesn’t actually apply here, so I did it
> manually. I suspect it just needs rebased onto a more recent commit or
> something.
You're right: attached is the rebased version.
>> and drag the parent frame down until its child is off screen. When the
>> parent is moved back up, the child should reappear with it.
> If you put the top of the child frame off the top of the screen, then
> click on it, it jumps back down so the titlebar is visible again. Is
> this intentional?
For me, this can be prevented by setting variable 
`ns-auto-hide-menu-bar' to t.  And on OS X 10.9+, the behavior may 
change if you have Spaces enabled (I haven't tested it).
>> * src/nsterm.m (constrainFrameRect:toScreen:): Constrain non-child
>> frames in OS X, if they would otherwise go offscreen.
> I can’t find this in CONTRIBUTE, but you’re allowed to specify
> #ifdef’d code with something like:
>
> * src/nsterm.m (constrainFrameRect:toScreen:) [NS_IMPL_COCOA]:
> Constrain non-child frames if they would otherwise go offscreen.
>
> Thanks for working on this. :)
My pleasure, and thank you for your work on the NS port.

[-- Attachment #2: 0001-Constrain-non-child-frames-to-screen-area-in-OS-X.patch --]
[-- Type: text/x-patch, Size: 1877 bytes --]

From 6a68480187916af3136e36596f50226f3544ded4 Mon Sep 17 00:00:00 2001
From: Charles A. Roelli <charles@aurox.ch>
Date: Thu, 27 Apr 2017 20:44:09 +0200
Subject: [PATCH] Constrain non-child frames to screen area in OS X

* src/nsterm.m (constrainFrameRect:toScreen:): Constrain non-child
frames in OS X, if they would otherwise go offscreen.

Fixes: debbugs:25818
---
 src/nsterm.m |   35 ++++++++++++++++++++++++++++++++++-
 1 files changed, 34 insertions(+), 1 deletions(-)

diff --git a/src/nsterm.m b/src/nsterm.m
index f75a9fe..c22c5a7 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -8040,7 +8040,40 @@ - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
       NSTRACE_RETURN_RECT (frameRect);
       return frameRect;
     }
-#endif
+  else
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 */
+    // Check that the proposed frameRect is visible in at least one
+    // screen.  If it is not, ask the system to reposition it (only
+    // for non-child windows).
+
+    if (!FRAME_PARENT_FRAME (((EmacsView *)[self delegate])->emacsframe))
+    {
+      NSArray *screens = [NSScreen screens];
+      NSUInteger nr_screens = [screens count];
+
+      int i;
+      BOOL frame_on_screen = NO;
+
+      for (i = 0; i < nr_screens; ++i)
+        {
+          NSScreen *s = [screens objectAtIndex: i];
+          NSRect scrRect = [s frame];
+
+          if (NSIntersectsRect(frameRect, scrRect))
+            {
+              frame_on_screen = YES;
+              break;
+            }
+        }
+
+      if (!frame_on_screen)
+        {
+          NSTRACE_MSG ("Frame outside screens; constraining");
+          frameRect = [super constrainFrameRect:frameRect toScreen:screen];
+          NSTRACE_RETURN_RECT (frameRect);
+          return frameRect;
+        }
+    }
 #endif
 
   return constrain_frame_rect(frameRect,
-- 
1.7.4.4


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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-04-27 19:14                                     ` Charles A. Roelli
  2017-04-27 20:05                                       ` Alan Third
@ 2017-04-29 10:30                                       ` martin rudalics
  2017-04-29 11:15                                         ` Charles A. Roelli
  1 sibling, 1 reply; 34+ messages in thread
From: martin rudalics @ 2017-04-29 10:30 UTC (permalink / raw)
  To: Charles A. Roelli, Anders Lindgren; +Cc: 25818, alan

 > I fixed the patch so that child frames are never constrained (after
 > some testing, it seems that a child frame cannot get stuck off screen
 > as long as its parent is still visible).  To test this out, evaluate
 > the following from emacs -Q,
 >
 > (progn
 >    (setq test-frame (make-frame `((parent-frame . ,(selected-frame)))))
 >    (set-frame-position test-frame 0 500))
 >
 > and drag the parent frame down until its child is off screen.

Does this mean that the child frame does _not_ move together with its
parent frame?  That would constitute a major deviation from the other
platforms.

martin





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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-04-29 10:30                                       ` martin rudalics
@ 2017-04-29 11:15                                         ` Charles A. Roelli
  2017-04-29 14:51                                           ` Alan Third
                                                             ` (2 more replies)
  0 siblings, 3 replies; 34+ messages in thread
From: Charles A. Roelli @ 2017-04-29 11:15 UTC (permalink / raw)
  To: martin rudalics, Anders Lindgren; +Cc: 25818, alan

With the current master branch, a child frame might be constrained on OS 
X 10.9+ with the "Spaces" windowing feature turned on, meaning that a 
child frame could be forced back into the screen area -- so yes, there 
could be a case where a child frame doesn't move together with its 
parent.  Maybe that will have to be fixed too; I'm on 10.6 though so I 
can't test.

Otherwise, though, when child/parent frames are not brought off screen, 
a child frame always moves with its parent.

My updated patch takes into account the case where "Spaces" is off or 
unavailable -- if you read the part above what I added:

#ifdef NS_IMPL_COCOA
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
   // If separate spaces is on, it is like each screen is independent.  
There is
   // no spanning of frames across screens.
   if ([NSScreen screensHaveSeparateSpaces])
     {
       NSTRACE_MSG ("Screens have separate spaces");
       frameRect = [super constrainFrameRect:frameRect toScreen:screen];
       NSTRACE_RETURN_RECT (frameRect);
       return frameRect;
     }
#endif

there is nothing there to prevent a child frame from being constrained 
-- so I will need input from somebody else on that.


On 29/04/2017 12:30, martin rudalics wrote:
> > I fixed the patch so that child frames are never constrained (after
> > some testing, it seems that a child frame cannot get stuck off screen
> > as long as its parent is still visible).  To test this out, evaluate
> > the following from emacs -Q,
> >
> > (progn
> >    (setq test-frame (make-frame `((parent-frame . ,(selected-frame)))))
> >    (set-frame-position test-frame 0 500))
> >
> > and drag the parent frame down until its child is off screen.
>
> Does this mean that the child frame does _not_ move together with its
> parent frame?  That would constitute a major deviation from the other
> platforms.
>
> martin






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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-04-29 11:15                                         ` Charles A. Roelli
@ 2017-04-29 14:51                                           ` Alan Third
  2017-04-29 17:23                                           ` Anders Lindgren
  2017-04-30  8:32                                           ` martin rudalics
  2 siblings, 0 replies; 34+ messages in thread
From: Alan Third @ 2017-04-29 14:51 UTC (permalink / raw)
  To: Charles A. Roelli; +Cc: Anders Lindgren, 25818

On Sat, Apr 29, 2017 at 01:15:10PM +0200, Charles A. Roelli wrote:
> My updated patch takes into account the case where "Spaces" is off or
> unavailable -- if you read the part above what I added:
> 
> #ifdef NS_IMPL_COCOA
> #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
>   // If separate spaces is on, it is like each screen is independent.  There
> is
>   // no spanning of frames across screens.
>   if ([NSScreen screensHaveSeparateSpaces])
>     {
>       NSTRACE_MSG ("Screens have separate spaces");
>       frameRect = [super constrainFrameRect:frameRect toScreen:screen];
>       NSTRACE_RETURN_RECT (frameRect);
>       return frameRect;
>     }
> #endif
> 
> there is nothing there to prevent a child frame from being constrained -- so
> I will need input from somebody else on that.

I think the screensHaveSeparateSpaces setting makes each monitor a
completely independent screen, so you won’t run into the problems you
have in the normal set‐up where a frame might span two monitors.

Therefore I think we could just add a check for whether it’s a child
frame, and if so, don’t constrain it at all.

-- 
Alan Third





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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-04-29 11:15                                         ` Charles A. Roelli
  2017-04-29 14:51                                           ` Alan Third
@ 2017-04-29 17:23                                           ` Anders Lindgren
  2017-04-30  8:32                                           ` martin rudalics
  2 siblings, 0 replies; 34+ messages in thread
From: Anders Lindgren @ 2017-04-29 17:23 UTC (permalink / raw)
  To: Charles A. Roelli; +Cc: Alan Third, 25818

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

Hi!

If I understand correctly, when the menu bar is visible, macOS will force
any window down below it. It's not something one can do about it, as far as
I know.

However, when the menu bar is hidden, or on secondary monitors (i.e. one
that don't have a menu bar), a window can be placed above the top
programmatically (but it's not possible for a user to drag it there).

The reason the Emacs code checks if spaces are enabled is historical. The
original NS code in Emacs 23 didn't support stretching a frame across two
monitors (whereas Emacs 22 supported this). When this was fixed for Emacs
23 the maintainer of the time, Jan Djärv, decided to retain the original
behaviour when spaces are enabled (since a frame can't be stretched across
multiple monitors). Maybe this is something we could revisit now. (One
thing I'm curious about is if it is possible to hide the menu bar and place
the frame above the top of the display, if spaces are enabled -- I suspect
that it's not possible but I haven't tested.)

    -- Anders

On Sat, Apr 29, 2017 at 1:15 PM, Charles A. Roelli <charles@aurox.ch> wrote:

> With the current master branch, a child frame might be constrained on OS X
> 10.9+ with the "Spaces" windowing feature turned on, meaning that a child
> frame could be forced back into the screen area -- so yes, there could be a
> case where a child frame doesn't move together with its parent.  Maybe that
> will have to be fixed too; I'm on 10.6 though so I can't test.
>
> Otherwise, though, when child/parent frames are not brought off screen, a
> child frame always moves with its parent.
>
> My updated patch takes into account the case where "Spaces" is off or
> unavailable -- if you read the part above what I added:
>
> #ifdef NS_IMPL_COCOA
> #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
>   // If separate spaces is on, it is like each screen is independent.
> There is
>   // no spanning of frames across screens.
>   if ([NSScreen screensHaveSeparateSpaces])
>     {
>       NSTRACE_MSG ("Screens have separate spaces");
>       frameRect = [super constrainFrameRect:frameRect toScreen:screen];
>       NSTRACE_RETURN_RECT (frameRect);
>       return frameRect;
>     }
> #endif
>
> there is nothing there to prevent a child frame from being constrained --
> so I will need input from somebody else on that.
>
>
>
> On 29/04/2017 12:30, martin rudalics wrote:
>
>> > I fixed the patch so that child frames are never constrained (after
>> > some testing, it seems that a child frame cannot get stuck off screen
>> > as long as its parent is still visible).  To test this out, evaluate
>> > the following from emacs -Q,
>> >
>> > (progn
>> >    (setq test-frame (make-frame `((parent-frame . ,(selected-frame)))))
>> >    (set-frame-position test-frame 0 500))
>> >
>> > and drag the parent frame down until its child is off screen.
>>
>> Does this mean that the child frame does _not_ move together with its
>> parent frame?  That would constitute a major deviation from the other
>> platforms.
>>
>> martin
>>
>
>

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

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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-04-29 11:15                                         ` Charles A. Roelli
  2017-04-29 14:51                                           ` Alan Third
  2017-04-29 17:23                                           ` Anders Lindgren
@ 2017-04-30  8:32                                           ` martin rudalics
  2 siblings, 0 replies; 34+ messages in thread
From: martin rudalics @ 2017-04-30  8:32 UTC (permalink / raw)
  To: Charles A. Roelli, Anders Lindgren; +Cc: 25818, alan

 > Otherwise, though, when child/parent frames are not brought off
 > screen, a child frame always moves with its parent.

Thanks for this clarification, martin





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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-04-28 17:33                                         ` Charles A. Roelli
@ 2017-05-02 20:33                                           ` Alan Third
  2017-05-05 18:30                                             ` Charles A. Roelli
  0 siblings, 1 reply; 34+ messages in thread
From: Alan Third @ 2017-05-02 20:33 UTC (permalink / raw)
  To: Charles A. Roelli; +Cc: 25818, Anders Lindgren

On Fri, Apr 28, 2017 at 07:33:00PM +0200, Charles A. Roelli wrote:
> On 27/04/2017 22:05, Alan Third wrote:
> > Looks good to me. It doesn’t actually apply here, so I did it
> > manually. I suspect it just needs rebased onto a more recent commit or
> > something.
> You're right: attached is the rebased version.

I’ve pushed this up to master.

Should I close this bug report, or do we want to look into the case
where screens have individual spaces?
-- 
Alan Third





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

* bug#25818: 25.2; frame moved off display does not return (OS X)
  2017-05-02 20:33                                           ` Alan Third
@ 2017-05-05 18:30                                             ` Charles A. Roelli
  0 siblings, 0 replies; 34+ messages in thread
From: Charles A. Roelli @ 2017-05-05 18:30 UTC (permalink / raw)
  To: Alan Third; +Cc: 25818, Anders Lindgren

I'm ok with closing.  The behavior with "Spaces" turned on seems 
reasonable at the moment, and if there's any indication that child 
frames do get constrained as a result of it, we can fix that.







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

end of thread, other threads:[~2017-05-05 18:30 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-20 20:04 bug#25818: 25.2; frame moved off display does not return (OS X) Charles A. Roelli
2017-02-23  8:49 ` martin rudalics
2017-02-26 11:26   ` Charles A. Roelli
2017-02-26 15:40     ` Charles A. Roelli
2017-02-26 16:45       ` martin rudalics
2017-02-26 19:42         ` Charles A. Roelli
2017-02-27  8:05           ` martin rudalics
2017-02-27 10:34             ` Charles A. Roelli
2017-02-27 20:47             ` Charles A. Roelli
2017-02-28 10:12               ` Charles A. Roelli
2017-02-28 13:20               ` Anders Lindgren
2017-02-28 15:05                 ` Charles A. Roelli
2017-02-28 20:35                   ` Anders Lindgren
2017-02-28 22:05                     ` Drew Adams
2017-03-01 10:48                       ` Anders Lindgren
2017-03-01 16:10                         ` Drew Adams
2017-03-19 19:38                     ` Charles A. Roelli
2017-03-27 18:22                       ` Anders Lindgren
2017-04-02 14:14                         ` Charles A. Roelli
2017-04-03  8:33                           ` Anders Lindgren
2017-04-08 20:40                             ` Charles A. Roelli
2017-04-09 19:13                               ` Anders Lindgren
2017-04-10 19:54                                 ` Charles A. Roelli
2017-04-11 18:35                                   ` Anders Lindgren
2017-04-27 19:14                                     ` Charles A. Roelli
2017-04-27 20:05                                       ` Alan Third
2017-04-28 17:33                                         ` Charles A. Roelli
2017-05-02 20:33                                           ` Alan Third
2017-05-05 18:30                                             ` Charles A. Roelli
2017-04-29 10:30                                       ` martin rudalics
2017-04-29 11:15                                         ` Charles A. Roelli
2017-04-29 14:51                                           ` Alan Third
2017-04-29 17:23                                           ` Anders Lindgren
2017-04-30  8:32                                           ` martin rudalics

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).