unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* make-pointer-invisible on Windows
@ 2015-06-24  9:17 martin rudalics
  2015-06-24 14:50 ` Eli Zaretskii
  0 siblings, 1 reply; 22+ messages in thread
From: martin rudalics @ 2015-06-24  9:17 UTC (permalink / raw)
  To: emacs-devel

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

I intend to apply the attached patch in order to fix this problem for
the Windows build (see Bug#6105 and Bug#12922).  Comments welcome.

Thanks, martin

[-- Attachment #2: make-pointer-invisible.diff --]
[-- Type: text/plain, Size: 2639 bytes --]

--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -3974,11 +3974,17 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
       if (LOWORD (lParam) == HTCLIENT)
 	{
 	  f = x_window_to_frame (dpyinfo, hwnd);
-	  if (f && f->output_data.w32->hourglass_p
-	      && !menubar_in_use && !current_popup_menu)
-	    SetCursor (f->output_data.w32->hourglass_cursor);
-	  else if (f)
-	    SetCursor (f->output_data.w32->current_cursor);
+	  if (f)
+	    {
+	      if (f->output_data.w32->hourglass_p
+		  && !menubar_in_use && !current_popup_menu)
+		SetCursor (f->output_data.w32->hourglass_cursor);
+	      else if (f->pointer_invisible)
+		SetCursor (NULL);
+	      else
+		SetCursor (f->output_data.w32->current_cursor);
+	    }
+
 	  return 0;
 	}
       goto dflt;
@@ -3991,7 +3997,12 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 	  {
 	    f->output_data.w32->current_cursor = cursor;
 	    if (!f->output_data.w32->hourglass_p)
-	      SetCursor (cursor);
+	      {
+		if (f->pointer_invisible)
+		  SetCursor (NULL);
+		else
+		  SetCursor (cursor);
+	      }
 	  }
 	return 0;
       }
diff --git a/src/w32term.c b/src/w32term.c
index b7c6e13..7c5f2db 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -6590,7 +6590,10 @@ w32_hide_hourglass (struct frame *f)
   struct w32_output *w32 = FRAME_X_OUTPUT (f);
 
   w32->hourglass_p = 0;
-  SetCursor (w32->current_cursor);
+  if (f->pointer_invisible)
+    SetCursor (NULL);
+  else
+    SetCursor (w32->current_cursor);
 }
 
 /* FIXME: old code did that, but I don't know why.  Anyway,
@@ -6602,6 +6605,25 @@ w32_arrow_cursor (void)
   SetCursor (w32_load_cursor (IDC_ARROW));
 }
 
+static void
+w32_toggle_invisible_pointer (struct frame *f, bool invisible)
+{
+  block_input ();
+
+  if (f->pointer_invisible != invisible)
+    {
+      f->pointer_invisible = invisible;
+      SET_FRAME_GARBAGED (f);
+    }
+
+  if (invisible)
+    SetCursor (NULL);
+  else
+    SetCursor (f->output_data.w32->current_cursor);
+
+  unblock_input ();
+}
+
 /***********************************************************************
 			    Initialization
  ***********************************************************************/
@@ -6741,6 +6763,7 @@ w32_create_terminal (struct w32_display_info *dpyinfo)
   terminal->ins_del_lines_hook = x_ins_del_lines;
   terminal->delete_glyphs_hook = x_delete_glyphs;
   terminal->ring_bell_hook = w32_ring_bell;
+  terminal->toggle_invisible_pointer_hook = w32_toggle_invisible_pointer;
   terminal->update_begin_hook = x_update_begin;
   terminal->update_end_hook = x_update_end;
   terminal->read_socket_hook = w32_read_socket;


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

* Re: make-pointer-invisible on Windows
  2015-06-24  9:17 make-pointer-invisible on Windows martin rudalics
@ 2015-06-24 14:50 ` Eli Zaretskii
  2015-06-24 17:40   ` martin rudalics
  0 siblings, 1 reply; 22+ messages in thread
From: Eli Zaretskii @ 2015-06-24 14:50 UTC (permalink / raw)
  To: martin rudalics; +Cc: emacs-devel

> Date: Wed, 24 Jun 2015 11:17:58 +0200
> From: martin rudalics <rudalics@gmx.at>
> 
> I intend to apply the attached patch in order to fix this problem for
> the Windows build (see Bug#6105 and Bug#12922).  Comments welcome.

Thanks.

> +static void
> +w32_toggle_invisible_pointer (struct frame *f, bool invisible)
> +{
> +  block_input ();
> +
> +  if (f->pointer_invisible != invisible)
> +    {
> +      f->pointer_invisible = invisible;
> +      SET_FRAME_GARBAGED (f); <<<<<<<<<<<<<<<<<<<<<<<
> +    }

That sounds excessive: I think it means that every self-inserting
character will trigger thorough redisplay of the frame.  Why do you
need this?  Is there any problem without marking the frame garbaged?

Also, what about the equivalent of the X code that makes the pointer
visible on focus-in events -- don't we need that on MS-Windows?



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

* Re: make-pointer-invisible on Windows
  2015-06-24 14:50 ` Eli Zaretskii
@ 2015-06-24 17:40   ` martin rudalics
  2015-06-24 19:21     ` Eli Zaretskii
  0 siblings, 1 reply; 22+ messages in thread
From: martin rudalics @ 2015-06-24 17:40 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

 >> +static void
 >> +w32_toggle_invisible_pointer (struct frame *f, bool invisible)
 >> +{
 >> +  block_input ();
 >> +
 >> +  if (f->pointer_invisible != invisible)
 >> +    {
 >> +      f->pointer_invisible = invisible;
 >> +      SET_FRAME_GARBAGED (f); <<<<<<<<<<<<<<<<<<<<<<<
 >> +    }
 >
 > That sounds excessive: I think it means that every self-inserting
 > character will trigger thorough redisplay of the frame.

Hopefully only for the first self-inserting character typed.  After that
the f->pointer_invisible != invisible fails until the mouse is moved.

 > Why do you
 > need this?  Is there any problem without marking the frame garbaged?

Yes, unfortunately (this was the only time-consuming part of the patch).
If I don't mark the frame garbaged, the cursor sometimes disappears only
after typing at least two or maybe a couple of characters which is quite
distracting.  There must be some redisplay optimization which gets into
the way.

 > Also, what about the equivalent of the X code that makes the pointer
 > visible on focus-in events -- don't we need that on MS-Windows?

I don't know.  It's certainly not necessary on XP here.  People would
have to try though.  In general, it seems that X and Windows differ
quite substantially in their respective behaviors.  For example, on X,
when a synchronous shell operation is active, the cursor becomes visible
as soon as the mouse is moved.  On Windows, the cursor remains invisible
until the shell operation terminates and the frame gets redrawn
(obviously, the frame doesn't look very decent in that period either, so
there are worse problems).

martin



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

* Re: make-pointer-invisible on Windows
  2015-06-24 17:40   ` martin rudalics
@ 2015-06-24 19:21     ` Eli Zaretskii
  2015-06-25  6:36       ` martin rudalics
  0 siblings, 1 reply; 22+ messages in thread
From: Eli Zaretskii @ 2015-06-24 19:21 UTC (permalink / raw)
  To: martin rudalics; +Cc: emacs-devel

> Date: Wed, 24 Jun 2015 19:40:29 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: emacs-devel@gnu.org
> 
>  >> +static void
>  >> +w32_toggle_invisible_pointer (struct frame *f, bool invisible)
>  >> +{
>  >> +  block_input ();
>  >> +
>  >> +  if (f->pointer_invisible != invisible)
>  >> +    {
>  >> +      f->pointer_invisible = invisible;
>  >> +      SET_FRAME_GARBAGED (f); <<<<<<<<<<<<<<<<<<<<<<<
>  >> +    }
>  >
>  > That sounds excessive: I think it means that every self-inserting
>  > character will trigger thorough redisplay of the frame.
> 
> Hopefully only for the first self-inserting character typed.  After that
> the f->pointer_invisible != invisible fails until the mouse is moved.

In theory, yes.  But doing this makes me nervous, since inserting a
single character is something the display engine knows how to optimize
very well.  This disables all those optimizations.

>  > Why do you
>  > need this?  Is there any problem without marking the frame garbaged?
> 
> Yes, unfortunately (this was the only time-consuming part of the patch).
> If I don't mark the frame garbaged, the cursor sometimes disappears only
> after typing at least two or maybe a couple of characters which is quite
> distracting.  There must be some redisplay optimization which gets into
> the way.

There are less radical ways of triggering more thorough redisplay,
than redrawing the whole frame.  I will look into this when I have
time, if no one beats me to it.

>  > Also, what about the equivalent of the X code that makes the pointer
>  > visible on focus-in events -- don't we need that on MS-Windows?
> 
> I don't know.  It's certainly not necessary on XP here.  People would
> have to try though.  In general, it seems that X and Windows differ
> quite substantially in their respective behaviors.  For example, on X,
> when a synchronous shell operation is active, the cursor becomes visible
> as soon as the mouse is moved.  On Windows, the cursor remains invisible
> until the shell operation terminates and the frame gets redrawn
> (obviously, the frame doesn't look very decent in that period either, so
> there are worse problems).

I don't think this is related to the issue at hand.



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

* Re: make-pointer-invisible on Windows
  2015-06-24 19:21     ` Eli Zaretskii
@ 2015-06-25  6:36       ` martin rudalics
  2015-06-25 15:02         ` Eli Zaretskii
  0 siblings, 1 reply; 22+ messages in thread
From: martin rudalics @ 2015-06-25  6:36 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

 >> Hopefully only for the first self-inserting character typed.  After that
 >> the f->pointer_invisible != invisible fails until the mouse is moved.
 >
 > In theory, yes.

I'm using this for a couple of months and never had a problem in
practice either.

 > But doing this makes me nervous, since inserting a
 > single character is something the display engine knows how to optimize
 > very well.  This disables all those optimizations.

Note that the mouse cursor can appear _anywhere_ on your frame when you
type the first character.  So in order to get rid of it you do have to
redraw the entire frame IMO.

 > There are less radical ways of triggering more thorough redisplay,
 > than redrawing the whole frame.  I will look into this when I have
 > time, if no one beats me to it.

Please do that.

 >>   > Also, what about the equivalent of the X code that makes the pointer
 >>   > visible on focus-in events -- don't we need that on MS-Windows?
 >>
 >> I don't know.  It's certainly not necessary on XP here.  People would
 >> have to try though.  In general, it seems that X and Windows differ
 >> quite substantially in their respective behaviors.  For example, on X,
 >> when a synchronous shell operation is active, the cursor becomes visible
 >> as soon as the mouse is moved.  On Windows, the cursor remains invisible
 >> until the shell operation terminates and the frame gets redrawn
 >> (obviously, the frame doesn't look very decent in that period either, so
 >> there are worse problems).
 >
 > I don't think this is related to the issue at hand.

I don't think so either.  My point was that X and Windows run into
different problems when trying to make the pointer invisible.

martin



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

* Re: make-pointer-invisible on Windows
  2015-06-25  6:36       ` martin rudalics
@ 2015-06-25 15:02         ` Eli Zaretskii
  2015-06-26  6:55           ` martin rudalics
  0 siblings, 1 reply; 22+ messages in thread
From: Eli Zaretskii @ 2015-06-25 15:02 UTC (permalink / raw)
  To: martin rudalics; +Cc: emacs-devel

> Date: Thu, 25 Jun 2015 08:36:06 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: emacs-devel@gnu.org
> 
>  > There are less radical ways of triggering more thorough redisplay,
>  > than redrawing the whole frame.  I will look into this when I have
>  > time, if no one beats me to it.
> 
> Please do that.

It turns out this has nothing to do with redisplay.  Inserting a
single character is enough to turn off the mouse pointer with your
original patch, after removing the call to SET_FRAME_GARBAGED.  The
problem is that sometimes the effect is far from immediate, you need
to wait for a second or so.

Looking into this, I concluded that calling SetCursor from the main
(a.k.a. "Lisp") thread has no effect whatsoever.  For some reason,
only the input thread can do that.  And it already does, whenever it
gets an appropriate message.  So all we have to do in the main thread
is send that message to the input thread.  This is what the first hunk
below, to be applied on top of your patch, does.

>  >>   > Also, what about the equivalent of the X code that makes the pointer
>  >>   > visible on focus-in events -- don't we need that on MS-Windows?
>  >>
>  >> I don't know.  It's certainly not necessary on XP here.  People would
>  >> have to try though.  In general, it seems that X and Windows differ
>  >> quite substantially in their respective behaviors.  For example, on X,
>  >> when a synchronous shell operation is active, the cursor becomes visible
>  >> as soon as the mouse is moved.  On Windows, the cursor remains invisible
>  >> until the shell operation terminates and the frame gets redrawn
>  >> (obviously, the frame doesn't look very decent in that period either, so
>  >> there are worse problems).
>  >
>  > I don't think this is related to the issue at hand.
> 
> I don't think so either.  My point was that X and Windows run into
> different problems when trying to make the pointer invisible.

Well, actually, it _is_ related, albeit to a different aspect of this.
The code that turns the mouse pointer back on when mouse moves also
runs in the main thread.  So whenever the main thread is busy with
some long calculation, or waits for some synchronous system call, we
cannot rely on this mechanism to timely turn the pointer back on.  But
the input thread can very well do that, so the second hunk of changes
below makes that happen.

So please install your changes, followed by mine (or tell me to do the
latter).  Thanks for working on this.

As for not redrawing the frame during these synchronous operations, I
will try to see why it happens (strangely, I only see it on XP, but
not on Windows 7).

--- src/w32term.c~0	2015-06-25 12:10:25 +0300
+++ src/w32term.c	2015-06-25 17:52:04 +0300
@@ -6613,14 +6613,10 @@ w32_toggle_invisible_pointer (struct fra
   if (f->pointer_invisible != invisible)
     {
       f->pointer_invisible = invisible;
-      SET_FRAME_GARBAGED (f);
+      w32_define_cursor (FRAME_W32_WINDOW (f),
+			 f->output_data.w32->current_cursor);
     }
 
-  if (invisible)
-    SetCursor (NULL);
-  else
-    SetCursor (f->output_data.w32->current_cursor);
-
   unblock_input ();
 }
 
--- src/w32fns.c~0	2015-06-25 12:29:41 +0300
+++ src/w32fns.c	2015-06-25 17:50:19 +0300
@@ -73,6 +73,7 @@ along with GNU Emacs.  If not, see <http
 
 #include <dlgs.h>
 #include <imm.h>
+#include <windowsx.h>
 
 #include "font.h"
 #include "w32font.h"
@@ -3492,13 +3493,31 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARA
       return (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONUP);
 
     case WM_MOUSEMOVE:
-      /* Ignore mouse movements as long as the menu is active.  These
-	 movements are processed by the window manager anyway, and
-	 it's wrong to handle them as if they happened on the
-	 underlying frame.  */
       f = x_window_to_frame (dpyinfo, hwnd);
-      if (f && f->output_data.w32->menubar_active)
-	return 0;
+      if (f)
+	{
+	  /* Ignore mouse movements as long as the menu is active.
+	     These movements are processed by the window manager
+	     anyway, and it's wrong to handle them as if they happened
+	     on the underlying frame.  */
+	  if (f->output_data.w32->menubar_active)
+	    return 0;
+
+	  /* If the mouse moved, and the mouse pointer is invisible,
+	     make it visible again.  We do this here so as to be able
+	     to show the mouse pointer even when the main
+	     (a.k.a. "Lisp") thread is busy doing something.  */
+	  static int last_x, last_y;
+	  int x = GET_X_LPARAM (lParam);
+	  int y = GET_Y_LPARAM (lParam);
+
+	  if (f->pointer_invisible
+	      && (x != last_x || y != last_y))
+	    f->pointer_invisible = false;
+
+	  last_x = x;
+	  last_y = y;
+	}
 
       /* If the mouse has just moved into the frame, start tracking
 	 it, so we will be notified when it leaves the frame.  Mouse



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

* Re: make-pointer-invisible on Windows
  2015-06-25 15:02         ` Eli Zaretskii
@ 2015-06-26  6:55           ` martin rudalics
  2015-06-26  8:43             ` Eli Zaretskii
  0 siblings, 1 reply; 22+ messages in thread
From: martin rudalics @ 2015-06-26  6:55 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

 > It turns out this has nothing to do with redisplay.  Inserting a
 > single character is enough to turn off the mouse pointer with your
 > original patch, after removing the call to SET_FRAME_GARBAGED.  The
 > problem is that sometimes the effect is far from immediate, you need
 > to wait for a second or so.

This explains why I couldn't consistently trigger the misbehavior.

 > Looking into this, I concluded that calling SetCursor from the main
 > (a.k.a. "Lisp") thread has no effect whatsoever.  For some reason,
 > only the input thread can do that.  And it already does, whenever it
 > gets an appropriate message.  So all we have to do in the main thread
 > is send that message to the input thread.  This is what the first hunk
 > below, to be applied on top of your patch, does.

Seems to work here.

 > Well, actually, it _is_ related, albeit to a different aspect of this.
 > The code that turns the mouse pointer back on when mouse moves also
 > runs in the main thread.  So whenever the main thread is busy with
 > some long calculation, or waits for some synchronous system call, we
 > cannot rely on this mechanism to timely turn the pointer back on.  But
 > the input thread can very well do that, so the second hunk of changes
 > below makes that happen.
 >
 > So please install your changes, followed by mine (or tell me to do the
 > latter).  Thanks for working on this.

All changes should be in place by now.

 > As for not redrawing the frame during these synchronous operations, I
 > will try to see why it happens (strangely, I only see it on XP, but
 > not on Windows 7).

This would be fine.

Thanks for the fixes, martin



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

* Re: make-pointer-invisible on Windows
  2015-06-26  6:55           ` martin rudalics
@ 2015-06-26  8:43             ` Eli Zaretskii
  2015-06-26  9:15               ` martin rudalics
  0 siblings, 1 reply; 22+ messages in thread
From: Eli Zaretskii @ 2015-06-26  8:43 UTC (permalink / raw)
  To: martin rudalics; +Cc: emacs-devel

> Date: Fri, 26 Jun 2015 08:55:26 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: emacs-devel@gnu.org
> 
>  > As for not redrawing the frame during these synchronous operations, I
>  > will try to see why it happens (strangely, I only see it on XP, but
>  > not on Windows 7).
> 
> This would be fine.

Btw, how does this work on X?  When we wait in waitpid for a
subprocess launched via "M-!", we are not supposed to call the
read-socket hook, so the X messages that tell us to redraw portions of
our frames are not supposed to be redrawn.  If this is what happens,
then the w32 behavior seems to be consistent; if not, what am I
missing here?  Specifically, can you show a backtrace on X from calls
to expose_frame when we are waiting for a synchronous subprocess?

TIA



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

* Re: make-pointer-invisible on Windows
  2015-06-26  8:43             ` Eli Zaretskii
@ 2015-06-26  9:15               ` martin rudalics
  2015-06-26  9:39                 ` Eli Zaretskii
  0 siblings, 1 reply; 22+ messages in thread
From: martin rudalics @ 2015-06-26  9:15 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

 > Btw, how does this work on X?  When we wait in waitpid for a
 > subprocess launched via "M-!", we are not supposed to call the
 > read-socket hook, so the X messages that tell us to redraw portions of
 > our frames are not supposed to be redrawn.

.. not supposed to be processed.

 > If this is what happens,
 > then the w32 behavior seems to be consistent; if not, what am I
 > missing here?  Specifically, can you show a backtrace on X from calls
 > to expose_frame when we are waiting for a synchronous subprocess?

That was a misunderstanding.  On X the frame is not redrawn either.

The difference was that on Windows, when waiting, the mouse cursor
remained invisible while on X it became visible again.  Your patch fixed
that already.  I didn't believe you could (reasonably) redraw the frame
while waiting for a subprocess, but you somehow sounded optimistic ...

martin



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

* Re: make-pointer-invisible on Windows
  2015-06-26  9:15               ` martin rudalics
@ 2015-06-26  9:39                 ` Eli Zaretskii
  2015-06-26 10:14                   ` martin rudalics
  2015-06-28 14:51                   ` Eli Zaretskii
  0 siblings, 2 replies; 22+ messages in thread
From: Eli Zaretskii @ 2015-06-26  9:39 UTC (permalink / raw)
  To: martin rudalics; +Cc: emacs-devel

> Date: Fri, 26 Jun 2015 11:15:06 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: emacs-devel@gnu.org
> 
>  > Btw, how does this work on X?  When we wait in waitpid for a
>  > subprocess launched via "M-!", we are not supposed to call the
>  > read-socket hook, so the X messages that tell us to redraw portions of
>  > our frames are not supposed to be redrawn.
> 
> .. not supposed to be processed.

OK, thanks for confirming my understanding.

> I didn't believe you could (reasonably) redraw the frame while
> waiting for a subprocess, but you somehow sounded optimistic ...

I understand what happens on XP: Windows sens us the WM_PAINT
messages, which the input thread picks up and passes to the main
thread.  But the main thread is busy-waiting inside waitpid, so it
doesn't react to those messages until the subprocess exist.

What I don't understand is how come the frame _is_ redrawn on Windows
7, and that's something I still need to look into.  It might mean
there is a way of keeping the frame display updated after all.  But if
X doesn't, then the motivation for that gets lower, of course.



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

* Re: make-pointer-invisible on Windows
  2015-06-26  9:39                 ` Eli Zaretskii
@ 2015-06-26 10:14                   ` martin rudalics
  2015-06-26 10:24                     ` Eli Zaretskii
  2015-06-28 14:51                   ` Eli Zaretskii
  1 sibling, 1 reply; 22+ messages in thread
From: martin rudalics @ 2015-06-26 10:14 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

 > What I don't understand is how come the frame _is_ redrawn on Windows
 > 7, and that's something I still need to look into.  It might mean
 > there is a way of keeping the frame display updated after all.

Is it really redrawn?  That is, if the subprocess writes to a buffer and
the buffer is shown in a window, does redrawing reflect that?  Or does
it just redisplay the previous contents (which wouldn't be bad either)?

martin



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

* Re: make-pointer-invisible on Windows
  2015-06-26 10:14                   ` martin rudalics
@ 2015-06-26 10:24                     ` Eli Zaretskii
  2015-06-28 14:52                       ` Eli Zaretskii
  0 siblings, 1 reply; 22+ messages in thread
From: Eli Zaretskii @ 2015-06-26 10:24 UTC (permalink / raw)
  To: martin rudalics; +Cc: emacs-devel

> Date: Fri, 26 Jun 2015 12:14:31 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: emacs-devel@gnu.org
> 
>  > What I don't understand is how come the frame _is_ redrawn on Windows
>  > 7, and that's something I still need to look into.  It might mean
>  > there is a way of keeping the frame display updated after all.
> 
> Is it really redrawn?  That is, if the subprocess writes to a buffer and
> the buffer is shown in a window, does redrawing reflect that?  Or does
> it just redisplay the previous contents (which wouldn't be bad either)?

The latter; I didn't yet see if the former will also work.



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

* Re: make-pointer-invisible on Windows
  2015-06-26  9:39                 ` Eli Zaretskii
  2015-06-26 10:14                   ` martin rudalics
@ 2015-06-28 14:51                   ` Eli Zaretskii
  2015-06-29  9:45                     ` martin rudalics
  1 sibling, 1 reply; 22+ messages in thread
From: Eli Zaretskii @ 2015-06-28 14:51 UTC (permalink / raw)
  To: rudalics; +Cc: emacs-devel

> Date: Fri, 26 Jun 2015 12:39:41 +0300
> From: Eli Zaretskii <eliz@gnu.org>
> Cc: emacs-devel@gnu.org
> 
> I understand what happens on XP: Windows sens us the WM_PAINT
> messages, which the input thread picks up and passes to the main
> thread.  But the main thread is busy-waiting inside waitpid, so it
> doesn't react to those messages until the subprocess exist.
> 
> What I don't understand is how come the frame _is_ redrawn on Windows
> 7, and that's something I still need to look into.

No mystery here, it turns out.  On XP, we get the WM_ERASEBKGND
message when (portions of) the Emacs frame previously covered by other
windows are uncovered.  In response, we erase the rectangle specified
by the message, and we do that from the input thread, i.e. this works
even if the main thread is busy.  WM_ERASEBKGND is immediately
followed by WM_PAINT, but the latter is passed for execution by the
main thread, and that thread is busy.  This is why you wind up with an
empty rectangle.

On Windows 7, neither WM_ERASEBKGND nor WM_PAINT are sent, except when
the Emacs frame is moved or resized.  So we don't erase the rectangle,
and the text remains on screen.

> It might mean there is a way of keeping the frame display updated
> after all.

Not an easy one: we'd need to handle several expose events for
different rectangles at once.  Given that X doesn't support this, I
see no reason to invest any efforts there.



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

* Re: make-pointer-invisible on Windows
  2015-06-26 10:24                     ` Eli Zaretskii
@ 2015-06-28 14:52                       ` Eli Zaretskii
  2015-06-29  9:46                         ` martin rudalics
  0 siblings, 1 reply; 22+ messages in thread
From: Eli Zaretskii @ 2015-06-28 14:52 UTC (permalink / raw)
  To: rudalics; +Cc: emacs-devel

> Date: Fri, 26 Jun 2015 13:24:11 +0300
> From: Eli Zaretskii <eliz@gnu.org>
> Cc: emacs-devel@gnu.org
> 
> > Date: Fri, 26 Jun 2015 12:14:31 +0200
> > From: martin rudalics <rudalics@gmx.at>
> > CC: emacs-devel@gnu.org
> > 
> >  > What I don't understand is how come the frame _is_ redrawn on Windows
> >  > 7, and that's something I still need to look into.  It might mean
> >  > there is a way of keeping the frame display updated after all.
> > 
> > Is it really redrawn?  That is, if the subprocess writes to a buffer and
> > the buffer is shown in a window, does redrawing reflect that?  Or does
> > it just redisplay the previous contents (which wouldn't be bad either)?
> 
> The latter; I didn't yet see if the former will also work.

Come to think about that, the former is not possible: the output from
a synchronous subprocess is not inserted into a buffer until the
process exits.



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

* Re: make-pointer-invisible on Windows
  2015-06-28 14:51                   ` Eli Zaretskii
@ 2015-06-29  9:45                     ` martin rudalics
  2015-06-29 14:43                       ` Eli Zaretskii
  0 siblings, 1 reply; 22+ messages in thread
From: martin rudalics @ 2015-06-29  9:45 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

 > No mystery here, it turns out.  On XP, we get the WM_ERASEBKGND
 > message when (portions of) the Emacs frame previously covered by other
 > windows are uncovered.  In response, we erase the rectangle specified
 > by the message, and we do that from the input thread, i.e. this works
 > even if the main thread is busy.

I don't think it's worth changing this but in principle we could erase
from the main thread as well?  That is, erasing without painting doesn't
make much sense anyway.

 > WM_ERASEBKGND is immediately
 > followed by WM_PAINT, but the latter is passed for execution by the
 > main thread, and that thread is busy.  This is why you wind up with an
 > empty rectangle.
 >
 > On Windows 7, neither WM_ERASEBKGND nor WM_PAINT are sent, except when
 > the Emacs frame is moved or resized.  So we don't erase the rectangle,
 > and the text remains on screen.

So you do get a blank rectangle when you (de-)maximze the frame I
suppose.

 > Not an easy one: we'd need to handle several expose events for
 > different rectangles at once.  Given that X doesn't support this, I
 > see no reason to invest any efforts there.

Agreed.

martin



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

* Re: make-pointer-invisible on Windows
  2015-06-28 14:52                       ` Eli Zaretskii
@ 2015-06-29  9:46                         ` martin rudalics
  0 siblings, 0 replies; 22+ messages in thread
From: martin rudalics @ 2015-06-29  9:46 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

 >>> Is it really redrawn?  That is, if the subprocess writes to a buffer and
 >>> the buffer is shown in a window, does redrawing reflect that?  Or does
 >>> it just redisplay the previous contents (which wouldn't be bad either)?
 >>
 >> The latter; I didn't yet see if the former will also work.
 >
 > Come to think about that, the former is not possible: the output from
 > a synchronous subprocess is not inserted into a buffer until the
 > process exits.

Aha...  I've been too lazy to look into the logic of this.

Thanks for the explanation, martin



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

* Re: make-pointer-invisible on Windows
  2015-06-29  9:45                     ` martin rudalics
@ 2015-06-29 14:43                       ` Eli Zaretskii
  2015-06-29 17:16                         ` martin rudalics
  0 siblings, 1 reply; 22+ messages in thread
From: Eli Zaretskii @ 2015-06-29 14:43 UTC (permalink / raw)
  To: martin rudalics; +Cc: emacs-devel

> Date: Mon, 29 Jun 2015 11:45:49 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: emacs-devel@gnu.org
> 
>  > No mystery here, it turns out.  On XP, we get the WM_ERASEBKGND
>  > message when (portions of) the Emacs frame previously covered by other
>  > windows are uncovered.  In response, we erase the rectangle specified
>  > by the message, and we do that from the input thread, i.e. this works
>  > even if the main thread is busy.
> 
> I don't think it's worth changing this but in principle we could erase
> from the main thread as well?

We could, but that brings the difficulty I mentioned below, with
collecting several such redraws of different rectangles, and
repainting them all at once.  Not rocket science, but needs some work.

> That is, erasing without painting doesn't make much sense anyway.

Maybe, I really know nothing about this.

>  > On Windows 7, neither WM_ERASEBKGND nor WM_PAINT are sent, except when
>  > the Emacs frame is moved or resized.  So we don't erase the rectangle,
>  > and the text remains on screen.
> 
> So you do get a blank rectangle when you (de-)maximze the frame I
> suppose.

Of course.



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

* Re: make-pointer-invisible on Windows
  2015-06-29 14:43                       ` Eli Zaretskii
@ 2015-06-29 17:16                         ` martin rudalics
  2015-06-29 17:40                           ` Eli Zaretskii
  0 siblings, 1 reply; 22+ messages in thread
From: martin rudalics @ 2015-06-29 17:16 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

 >> I don't think it's worth changing this but in principle we could erase
 >> from the main thread as well?
 >
 > We could, but that brings the difficulty I mentioned below, with
 > collecting several such redraws of different rectangles, and
 > repainting them all at once.  Not rocket science, but needs some work.

Silly me.  It's obviously Windows who does the erasing part _before_
sending us the WM_ERASEBKGND message and not us erase after receiving
that message.

martin



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

* Re: make-pointer-invisible on Windows
  2015-06-29 17:16                         ` martin rudalics
@ 2015-06-29 17:40                           ` Eli Zaretskii
  2015-06-30  6:01                             ` martin rudalics
  0 siblings, 1 reply; 22+ messages in thread
From: Eli Zaretskii @ 2015-06-29 17:40 UTC (permalink / raw)
  To: martin rudalics; +Cc: emacs-devel

> Date: Mon, 29 Jun 2015 19:16:00 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: emacs-devel@gnu.org
> 
> Silly me.  It's obviously Windows who does the erasing part _before_
> sending us the WM_ERASEBKGND message and not us erase after receiving
> that message.

Maybe I'm missing something, but this:

    case WM_ERASEBKGND:
      f = x_window_to_frame (dpyinfo, hwnd);
      if (f)
	{
          HDC hdc = get_frame_dc (f);
	  GetUpdateRect (hwnd, &wmsg.rect, FALSE);
	  w32_clear_rect (f, hdc, &wmsg.rect); <<<<<<<<<<<<<<<<<<<<
          release_frame_dc (f, hdc);

looks to me like us erasing the rectangle.



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

* Re: make-pointer-invisible on Windows
  2015-06-29 17:40                           ` Eli Zaretskii
@ 2015-06-30  6:01                             ` martin rudalics
  2015-06-30 15:09                               ` Eli Zaretskii
  0 siblings, 1 reply; 22+ messages in thread
From: martin rudalics @ 2015-06-30  6:01 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

 > Maybe I'm missing something, but this:
 >
 >      case WM_ERASEBKGND:
 >        f = x_window_to_frame (dpyinfo, hwnd);
 >        if (f)
 > 	{
 >            HDC hdc = get_frame_dc (f);
 > 	  GetUpdateRect (hwnd, &wmsg.rect, FALSE);
 > 	  w32_clear_rect (f, hdc, &wmsg.rect); <<<<<<<<<<<<<<<<<<<<
 >            release_frame_dc (f, hdc);
 >
 > looks to me like us erasing the rectangle.

Then if we didn't erase here there would be no gaps.  Would it be a
silly idea to pass the erase call to the main thread?

martin



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

* Re: make-pointer-invisible on Windows
  2015-06-30  6:01                             ` martin rudalics
@ 2015-06-30 15:09                               ` Eli Zaretskii
  2015-07-02 13:21                                 ` martin rudalics
  0 siblings, 1 reply; 22+ messages in thread
From: Eli Zaretskii @ 2015-06-30 15:09 UTC (permalink / raw)
  To: martin rudalics; +Cc: emacs-devel

> Date: Tue, 30 Jun 2015 08:01:53 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: emacs-devel@gnu.org
> 
>  > Maybe I'm missing something, but this:
>  >
>  >      case WM_ERASEBKGND:
>  >        f = x_window_to_frame (dpyinfo, hwnd);
>  >        if (f)
>  > 	{
>  >            HDC hdc = get_frame_dc (f);
>  > 	  GetUpdateRect (hwnd, &wmsg.rect, FALSE);
>  > 	  w32_clear_rect (f, hdc, &wmsg.rect); <<<<<<<<<<<<<<<<<<<<
>  >            release_frame_dc (f, hdc);
>  >
>  > looks to me like us erasing the rectangle.
> 
> Then if we didn't erase here there would be no gaps.  Would it be a
> silly idea to pass the erase call to the main thread?

We've been through this: it's not silly, but implementing that will
have to be able to compact several such redraw pairs into one, because
by the time the main thread wakes up, we could have received several
different expose events, and handling them one by one will cause
flickering.

And after all that, we are still left with the use case of resizing
the frame.



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

* Re: make-pointer-invisible on Windows
  2015-06-30 15:09                               ` Eli Zaretskii
@ 2015-07-02 13:21                                 ` martin rudalics
  0 siblings, 0 replies; 22+ messages in thread
From: martin rudalics @ 2015-07-02 13:21 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

 > We've been through this: it's not silly, but implementing that will
 > have to be able to compact several such redraw pairs into one, because
 > by the time the main thread wakes up, we could have received several
 > different expose events, and handling them one by one will cause
 > flickering.

This sounds like too much work for such a minor improvement.

 > And after all that, we are still left with the use case of resizing
 > the frame.

Indeed.

Thanks for the patience, martin



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

end of thread, other threads:[~2015-07-02 13:21 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-06-24  9:17 make-pointer-invisible on Windows martin rudalics
2015-06-24 14:50 ` Eli Zaretskii
2015-06-24 17:40   ` martin rudalics
2015-06-24 19:21     ` Eli Zaretskii
2015-06-25  6:36       ` martin rudalics
2015-06-25 15:02         ` Eli Zaretskii
2015-06-26  6:55           ` martin rudalics
2015-06-26  8:43             ` Eli Zaretskii
2015-06-26  9:15               ` martin rudalics
2015-06-26  9:39                 ` Eli Zaretskii
2015-06-26 10:14                   ` martin rudalics
2015-06-26 10:24                     ` Eli Zaretskii
2015-06-28 14:52                       ` Eli Zaretskii
2015-06-29  9:46                         ` martin rudalics
2015-06-28 14:51                   ` Eli Zaretskii
2015-06-29  9:45                     ` martin rudalics
2015-06-29 14:43                       ` Eli Zaretskii
2015-06-29 17:16                         ` martin rudalics
2015-06-29 17:40                           ` Eli Zaretskii
2015-06-30  6:01                             ` martin rudalics
2015-06-30 15:09                               ` Eli Zaretskii
2015-07-02 13:21                                 ` 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).