]> code.delx.au - gnu-emacs/blobdiff - src/w32term.c
accept-process-output fix
[gnu-emacs] / src / w32term.c
index 251c46c73cf2c864603c8a37607900c1897398a3..fbd31b15de2de8c4dbc8f4777053d964e255623c 100644 (file)
@@ -401,7 +401,13 @@ w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y,
   oldhb = SelectObject (hdc, hb);
   oldhp = SelectObject (hdc, hp);
 
-  Rectangle (hdc, x, y, x + width, y + height);
+  /* We enlarge WIDTH and HEIGHT by 1 to be bug-compatible to the
+     brain-dead design of XDrawRectangle, which draws a rectangle that
+     is 1 pixel wider and higher than its arguments WIDTH and HEIGHT.
+     This allows us to keep the code that calls this function similar
+     to the corresponding code in xterm.c.  For the details, see
+     http://lists.gnu.org/archives/html/emacs-devel/2014-10/msg00546.html.  */
+  Rectangle (hdc, x, y, x + width + 1, y + height + 1);
 
   SelectObject (hdc, oldhb);
   SelectObject (hdc, oldhp);
@@ -1212,7 +1218,12 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
        }
       else
 #endif
-        if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
+           if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
+              /* When xdisp.c ignores FONT_HEIGHT, we cannot trust
+                 font dimensions, since the actual glyphs might be
+                 much smaller.  So in that case we always clear the
+                 rectangle with background color.  */
+              || FONT_TOO_HIGH (s->font)
               || s->font_not_found_p
               || s->extends_to_end_of_line_p
               || force_p)
@@ -1410,7 +1421,7 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
 
       if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)
        {
-         if (len > 1
+         if (len > 0
              && CHAR_TABLE_P (Vglyphless_char_display)
              && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display))
                  >= 1))
@@ -3223,7 +3234,7 @@ queue_notifications (struct input_event *event, W32Msg *msg, struct frame *f,
   if (notification_buffer_in_use)
     {
       DWORD info_size = notifications_size;
-      Lisp_Object cs = intern ("utf-16le");
+      Lisp_Object cs = Qutf_16le;
       Lisp_Object obj = w32_get_watch_object (notifications_desc);
 
       /* notifications_size could be zero when the buffer of
@@ -3344,8 +3355,6 @@ static void x_horizontal_scroll_bar_report_motion (struct frame **, Lisp_Object
                                                   enum scroll_bar_part *,
                                                   Lisp_Object *, Lisp_Object *,
                                                   Time *);
-static void x_check_fullscreen (struct frame *);
-
 static void
 w32_define_cursor (Window window, Cursor cursor)
 {
@@ -4989,8 +4998,12 @@ w32_read_socket (struct terminal *terminal,
                 sets the WAIT flag.  */
              if ((msg.msg.message == WM_WINDOWPOSCHANGED || msg.msg.wParam)
                  && (f->want_fullscreen & FULLSCREEN_WAIT))
-               w32fullscreen_hook (f);
-             x_check_fullscreen (f);
+               {
+                 /* Must set visibility right here since otherwise
+                    w32fullscreen_hook returns immediately.  */
+                 SET_FRAME_VISIBLE (f, 1);
+                 w32fullscreen_hook (f);
+               }
            }
          check_visibility = 1;
          break;
@@ -5050,6 +5063,7 @@ w32_read_socket (struct terminal *terminal,
                case SIZE_MAXIMIZED:
                  {
                    bool iconified = FRAME_ICONIFIED_P (f);
+                   Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
 
                    SET_FRAME_VISIBLE (f, 1);
                    SET_FRAME_ICONIFIED (f, false);
@@ -5080,12 +5094,22 @@ w32_read_socket (struct terminal *terminal,
                         to update the frame titles
                         in case this is the second frame.  */
                      record_asynch_buffer_change ();
-                 }
 
-                 if (EQ (get_frame_param (f, Qfullscreen), Qnil))
-                   set_frame_param (f, Qfullscreen, Qmaximized);
-                 else if (! EQ (get_frame_param (f, Qfullscreen), Qmaximized))
-                   set_frame_param (f, Qmaximized, Qmaximized);
+                 /* Windows can send us a SIZE_MAXIMIZED message even
+                    when fullscreen is fullboth.  The following is a
+                    simple hack to check that based on the fact that
+                    only a maximized fullscreen frame should have both
+                    top/left outside the screen.  */
+                 if (EQ (fullscreen, Qfullwidth) || EQ (fullscreen, Qfullheight)
+                     || NILP (fullscreen))
+                     {
+                       int x, y;
+
+                       x_real_positions (f, &x, &y);
+                       if (x < 0 && y < 0)
+                         store_frame_param (f, Qfullscreen, Qmaximized);
+                     }
+                 }
 
                  break;
 
@@ -5126,9 +5150,7 @@ w32_read_socket (struct terminal *terminal,
                  }
 
                  if (EQ (get_frame_param (f, Qfullscreen), Qmaximized))
-                   set_frame_param (f, Qfullscreen, Qnil);
-                 else if (! EQ (get_frame_param (f, Qmaximized), Qnil))
-                   set_frame_param (f, Qmaximized, Qnil);
+                   store_frame_param (f, Qfullscreen, Qnil);
 
                  break;
                }
@@ -5269,11 +5291,18 @@ w32_read_socket (struct terminal *terminal,
 
          if (f)
            {
+             Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
+
              dpyinfo->n_cbits = msg.msg.wParam;
              /* The new display could have a different resolution, in
-                which case we must reconsider what fullscreen
-                means.  */
-             x_check_fullscreen (f);
+                which case we must reconsider what fullscreen means.
+                The following code is untested yet.  */
+             if (!NILP (fullscreen))
+               {
+                 x_set_fullscreen (f, fullscreen, fullscreen);
+                 w32fullscreen_hook (f);
+               }
+
              DebPrint (("display change: %d %d\n",
                         (short) LOWORD (msg.msg.lParam),
                         (short) HIWORD (msg.msg.lParam)));
@@ -5803,7 +5832,7 @@ Lisp_Object
 x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
 {
   struct font *font = XFONT_OBJECT (font_object);
-  int unit;
+  int unit, font_ascent, font_descent;
 
   if (fontset < 0)
     fontset = fontset_from_font (font_object);
@@ -5816,7 +5845,8 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
   FRAME_FONT (f) = font;
   FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
   FRAME_COLUMN_WIDTH (f) = unit = font->average_width;
-  FRAME_LINE_HEIGHT (f) = font->height;
+  get_font_ascent_descent (font, &font_ascent, &font_descent);
+  FRAME_LINE_HEIGHT (f) = font_ascent + font_descent;
 
   /* Compute number of scrollbar columns.  */
   unit = FRAME_COLUMN_WIDTH (f);
@@ -5959,75 +5989,6 @@ x_set_offset (struct frame *f, register int xoff, register int yoff,
   unblock_input ();
 }
 
-/* Calculate fullscreen size.  Return in *TOP_POS and *LEFT_POS the
-   wanted positions of the WM window (not Emacs window).
-   Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
-   window (FRAME_X_WINDOW).
- */
-
-static void
-x_fullscreen_adjust (struct frame *f, int *width, int *height, int *top_pos, int *left_pos)
-{
-  int newwidth = FRAME_COLS (f);
-  int newheight = FRAME_LINES (f);
-  Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
-
-  *top_pos = f->top_pos;
-  *left_pos = f->left_pos;
-
-  if (f->want_fullscreen & FULLSCREEN_HEIGHT)
-    {
-      int ph;
-
-      ph = x_display_pixel_height (dpyinfo);
-      newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
-      ph = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, newheight) - f->y_pixels_diff;
-      newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
-      *top_pos = 0;
-    }
-
-  if (f->want_fullscreen & FULLSCREEN_WIDTH)
-    {
-      int pw;
-
-      pw = x_display_pixel_width (dpyinfo);
-      newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
-      pw = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, newwidth) - f->x_pixels_diff;
-      newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
-      *left_pos = 0;
-    }
-
-  *width = newwidth;
-  *height = newheight;
-}
-
-/* Check if we need to resize the frame due to a fullscreen request.
-   If so needed, resize the frame.  */
-static void
-x_check_fullscreen (struct frame *f)
-{
-  if (f->want_fullscreen & FULLSCREEN_BOTH)
-    {
-      int width, height, ign;
-
-      x_real_positions (f, &f->left_pos, &f->top_pos);
-
-      x_fullscreen_adjust (f, &width, &height, &ign, &ign);
-
-      /* We do not need to move the window, it shall be taken care of
-         when setting WM manager hints.  */
-      if (FRAME_COLS (f) != width || FRAME_LINES (f) != height)
-        {
-          change_frame_size (f, width, height, 0, 1, 0, 0);
-          SET_FRAME_GARBAGED (f);
-          cancel_mouse_face (f);
-
-          /* Wait for the change of frame size to occur.  */
-          f->want_fullscreen |= FULLSCREEN_WAIT;
-        }
-    }
-}
-
 static void
 w32fullscreen_hook (struct frame *f)
 {
@@ -6068,12 +6029,19 @@ w32fullscreen_hook (struct frame *f)
        }
       else if (f->want_fullscreen == FULLSCREEN_BOTH)
         {
+         int menu_bar_height = GetSystemMetrics (SM_CYMENU);
+
          w32_fullscreen_rect (hwnd, f->want_fullscreen,
                               FRAME_NORMAL_PLACEMENT (f).rcNormalPosition, &rect);
           SetWindowLong (hwnd, GWL_STYLE, dwStyle & ~WS_OVERLAPPEDWINDOW);
           SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
                         rect.right - rect.left, rect.bottom - rect.top,
                         SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
+         change_frame_size
+           (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, rect.right - rect.left),
+            FRAME_PIXEL_TO_TEXT_HEIGHT (f, (rect.bottom - rect.top
+                                            - menu_bar_height)),
+            0, 1, 0, 1);
         }
       else
         {
@@ -6082,10 +6050,39 @@ w32fullscreen_hook (struct frame *f)
                               FRAME_NORMAL_PLACEMENT (f).rcNormalPosition, &rect);
           SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
                         rect.right - rect.left, rect.bottom - rect.top, 0);
+
+         if (f->want_fullscreen == FULLSCREEN_WIDTH)
+           {
+             int border_width = GetSystemMetrics (SM_CXFRAME);
+
+             change_frame_size
+               (f, (FRAME_PIXEL_TO_TEXT_WIDTH
+                    (f, rect.right - rect.left - 2 * border_width)),
+                0, 0, 1, 0, 1);
+           }
+         else
+           {
+             int border_height = GetSystemMetrics (SM_CYFRAME);
+             /* Won't work for wrapped menu bar.  */
+             int menu_bar_height = GetSystemMetrics (SM_CYMENU);
+             int title_height = GetSystemMetrics (SM_CYCAPTION);
+
+             change_frame_size
+               (f, 0, (FRAME_PIXEL_TO_TEXT_HEIGHT
+                       (f, rect.bottom - rect.top - 2 * border_height
+                        - title_height - menu_bar_height)),
+                0, 1, 0, 1);
+           }
         }
 
       f->want_fullscreen = FULLSCREEN_NONE;
       unblock_input ();
+
+      if (f->want_fullscreen == FULLSCREEN_BOTH
+         || f->want_fullscreen == FULLSCREEN_WIDTH
+         || f->want_fullscreen == FULLSCREEN_HEIGHT)
+       do_pending_window_change (0);
+
     }
   else
     f->want_fullscreen |= FULLSCREEN_WAIT;
@@ -6101,6 +6098,7 @@ x_set_window_size (struct frame *f, bool change_gravity,
                   int width, int height, bool pixelwise)
 {
   int pixelwidth, pixelheight;
+  Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
   RECT rect;
 
   block_input ();
@@ -6119,7 +6117,7 @@ x_set_window_size (struct frame *f, bool change_gravity,
   if (w32_add_wrapped_menu_bar_lines)
     {
       /* When the menu bar wraps sending a SetWindowPos shrinks the
-        height of the frame when the wrapped menu bar lines are not
+        height of the frame then the wrapped menu bar lines are not
         accounted for (Bug#15174 and Bug#18720).  Here we add these
         extra lines to the frame height.  */
       MENUBARINFO info;
@@ -6143,9 +6141,6 @@ x_set_window_size (struct frame *f, bool change_gravity,
   f->win_gravity = NorthWestGravity;
   x_wm_set_size_hint (f, (long) 0, false);
 
-  f->want_fullscreen = FULLSCREEN_NONE;
-  w32fullscreen_hook (f);
-
   rect.left = rect.top = 0;
   rect.right = pixelwidth;
   rect.bottom = pixelheight;
@@ -6153,45 +6148,45 @@ x_set_window_size (struct frame *f, bool change_gravity,
   AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
                    FRAME_EXTERNAL_MENU_BAR (f));
 
-  my_set_window_pos (FRAME_W32_WINDOW (f),
-                    NULL,
-                    0, 0,
-                    rect.right - rect.left,
-                    rect.bottom - rect.top,
-                    SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
-
-  /* If w32_enable_frame_resize_hack is non-nil, immediately apply the
-     new pixel sizes to the frame and its subwindows.
-
-     Jason Rumney earlier refused to call change_frame_size right here
-     with the following argument:
-
-     The following mirrors what is done in xterm.c. It appears to be for
-     informing lisp of the new size immediately, while the actual resize
-     will happen asynchronously. But on Windows, the menu bar
-     automatically wraps when the frame is too narrow to contain it, and
-     that causes any calculations made here to come out wrong.  The end
-     is some nasty buggy behavior, including the potential loss of the
-     minibuffer.
-
-     Disabling this code is either not sufficient to fix the problems
-     completely, or it causes fresh problems, but at least it removes
-     the most problematic symptom of the minibuffer becoming unusable.
-
-     However, as the discussion about how to handle frame size
-     parameters on Windows (Bug#1348, Bug#16028) shows, that cure seems
-     worse than the disease.  In particular, menu bar wrapping looks
-     like a non-issue - maybe so because Windows eventually gets back to
-     us with the correct client rectangle anyway.  But we have to avoid
-     calling change_frame_size with a delta of less than one canoncial
-     character size when frame_resize_pixelwise is nil, as explained in
-     the comment above.  */
-
-  if (w32_enable_frame_resize_hack)
+  if (!(f->after_make_frame)
+      && !(f->want_fullscreen & FULLSCREEN_WAIT)
+      && FRAME_VISIBLE_P (f))
+    {
+      RECT window_rect;
 
+      GetWindowRect (FRAME_W32_WINDOW (f), &window_rect);
+
+      if (EQ (fullscreen, Qmaximized)
+         || EQ (fullscreen, Qfullboth)
+         || EQ (fullscreen, Qfullwidth))
+       {
+         rect.left = window_rect.left;
+         rect.right = window_rect.right;
+         pixelwidth = 0;
+       }
+      if (EQ (fullscreen, Qmaximized)
+         || EQ (fullscreen, Qfullboth)
+         || EQ (fullscreen, Qfullheight))
+       {
+         rect.top = window_rect.top;
+         rect.bottom = window_rect.bottom;
+         pixelheight = 0;
+       }
+    }
+
+  if (pixelwidth > 0 || pixelheight > 0)
     {
-      change_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth),
-                        FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight),
+      my_set_window_pos (FRAME_W32_WINDOW (f), NULL,
+                        0, 0,
+                        rect.right - rect.left,
+                        rect.bottom - rect.top,
+                        SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
+
+      change_frame_size (f,
+                        ((pixelwidth == 0)
+                            ? 0 : FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth)),
+                        ((pixelheight == 0)
+                         ? 0 : FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight)),
                         0, 1, 0, 1);
       SET_FRAME_GARBAGED (f);
 
@@ -6595,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,
@@ -6607,6 +6605,21 @@ 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;
+      w32_define_cursor (FRAME_W32_WINDOW (f),
+                        f->output_data.w32->current_cursor);
+    }
+
+  unblock_input ();
+}
+
 /***********************************************************************
                            Initialization
  ***********************************************************************/
@@ -6746,6 +6759,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;
@@ -7102,7 +7116,7 @@ Windows 8.  It is set to nil on Windows 9X.  */);
   w32_unicode_filenames = 0;
 
 
-  /* FIXME: The following two variables will be (hopefully) removed
+  /* FIXME: The following variable will be (hopefully) removed
      before Emacs 25.1 gets released.  */
 
   DEFVAR_BOOL ("w32-add-wrapped-menu-bar-lines",
@@ -7116,16 +7130,6 @@ wrapped menu bar lines when sending frame resize requests to the Windows
 API.  */);
   w32_add_wrapped_menu_bar_lines = 1;
 
-  DEFVAR_BOOL ("w32-enable-frame-resize-hack",
-              w32_enable_frame_resize_hack,
-     doc: /* Non-nil means enable hack for frame resizing on Windows.
-A value of nil means to resize frames by sending a corresponding request
-to the Windows API and changing the pixel sizes of the frame and its
-windows after the latter calls back.  If this is non-nil, Emacs changes
-the pixel sizes of the frame and its windows at the time it sends the
-resize request to the API.  */);
-  w32_enable_frame_resize_hack = 1;
-
   /* Tell Emacs about this window system.  */
   Fprovide (Qw32, Qnil);
 }