Fix regression introduced by patch for Bug#10500.
[bpt/emacs.git] / src / w32term.c
index 3d6b653..15b502b 100644 (file)
@@ -1,6 +1,6 @@
 /* Implementation of GUI terminal on the Microsoft Windows API.
 
-Copyright (C) 1989, 1993-2013 Free Software Foundation, Inc.
+Copyright (C) 1989, 1993-2014 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -628,26 +628,38 @@ static void
 w32_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
-  RECT r;
-  HDC hdc;
-  struct face *face;
-
-  r.left = x0;
-  r.right = x1;
-  r.top = y0;
-  r.bottom = y1;
-
-  hdc = get_frame_dc (f);
-  face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
-  if (face)
-    w32_fill_rect (f, hdc, face->foreground, &r);
+  HDC hdc = get_frame_dc (f);
+  struct face *face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
+  struct face *face_first = FACE_FROM_ID (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
+  struct face *face_last = FACE_FROM_ID (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
+  unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f);
+  unsigned long color_first = (face_first
+                              ? face_first->foreground
+                              : FRAME_FOREGROUND_PIXEL (f));
+  unsigned long color_last = (face_last
+                             ? face_last->foreground
+                             : FRAME_FOREGROUND_PIXEL (f));
+
+  if (y1 - y0 > x1 - x0 && x1 - x0 > 2)
+    /* Vertical.  */
+    {
+      w32_fill_area_abs (f, hdc, color_first, x0, y0, x0 + 1, y1);
+      w32_fill_area_abs (f, hdc, color, x0 + 1, y0, x1 - 1, y1);
+      w32_fill_area_abs (f, hdc, color_last, x1 - 1, y0, x1, y1);
+    }
+  else if (x1 - x0 > y1 - y0 && y1 - y0 > 3)
+    /* Horizontal.  */
+    {
+      w32_fill_area_abs (f, hdc, color_first, x0, y0, x1, y0 + 1);
+      w32_fill_area_abs (f, hdc, color, x0, y0 + 1, x1, y1 - 1);
+      w32_fill_area_abs (f, hdc, color_last, x0, y1 - 1, x1, y1);
+    }
   else
-    w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r);
+    w32_fill_area_abs (f, hdc, color, x0, y0, x1, y1);
 
   release_frame_dc (f, hdc);
 }
 
-
 /* End update of window W.
 
    Draw vertical borders between horizontally adjacent windows, and
@@ -792,62 +804,13 @@ w32_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
 
   hdc = get_frame_dc (f);
 
-  if (!p->overlay_p)
-    {
-      int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
-
-      /* If the fringe is adjacent to the left (right) scroll bar of a
-        leftmost (rightmost, respectively) window, then extend its
-        background to the gap between the fringe and the bar.  */
-      if ((WINDOW_LEFTMOST_P (w)
-          && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
-         || (WINDOW_RIGHTMOST_P (w)
-             && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
-       {
-         int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
-
-         if (sb_width > 0)
-           {
-             int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
-             int bar_area_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
-
-             if (bx < 0)
-               {
-                 /* Bitmap fills the fringe.  */
-                 if (bar_area_x + bar_area_width == p->x)
-                   bx = bar_area_x + sb_width;
-                 else if (p->x + p->wd == bar_area_x)
-                   bx = bar_area_x;
-                 if (bx >= 0)
-                   {
-                     int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
-
-                     nx = bar_area_width - sb_width;
-                     by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
-                                                           row->y));
-                     ny = row->visible_height;
-                   }
-               }
-             else
-               {
-                 if (bar_area_x + bar_area_width == bx)
-                   {
-                     bx = bar_area_x + sb_width;
-                     nx += bar_area_width - sb_width;
-                   }
-                 else if (bx + nx == bar_area_x)
-                   nx += bar_area_width - sb_width;
-               }
-           }
-       }
-
-      if (bx >= 0 && nx > 0)
-       w32_fill_area (f, hdc, face->background, bx, by, nx, ny);
-    }
-
   /* Must clip because of partially visible lines.  */
   w32_clip_to_row (w, row, ANY_AREA, hdc);
 
+  if (p->bx >= 0 && !p->overlay_p)
+    w32_fill_area (f, hdc, face->background,
+                  p->bx, p->by, p->nx, p->ny);
+
   if (p->which && p->which < max_fringe_bmp)
     {
       HBITMAP pixmap = fringe_bmp[p->which];
@@ -1929,6 +1892,7 @@ static void
 x_draw_image_relief (struct glyph_string *s)
 {
   int x1, y1, thick, raised_p, top_p, bot_p, left_p, right_p;
+  int extra_x, extra_y;
   RECT r;
   int x = s->x;
   int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
@@ -1962,16 +1926,31 @@ x_draw_image_relief (struct glyph_string *s)
 
   x1 = x + s->slice.width - 1;
   y1 = y + s->slice.height - 1;
+
+  extra_x = extra_y = 0;
+  if (s->face->id == TOOL_BAR_FACE_ID)
+    {
+      if (CONSP (Vtool_bar_button_margin)
+         && INTEGERP (XCAR (Vtool_bar_button_margin))
+         && INTEGERP (XCDR (Vtool_bar_button_margin)))
+       {
+         extra_x = XINT (XCAR (Vtool_bar_button_margin));
+         extra_y = XINT (XCDR (Vtool_bar_button_margin));
+       }
+      else if (INTEGERP (Vtool_bar_button_margin))
+       extra_x = extra_y = XINT (Vtool_bar_button_margin);
+    }
+
   top_p = bot_p = left_p = right_p = 0;
 
   if (s->slice.x == 0)
-    x -= thick, left_p = 1;
+    x -= thick + extra_x, left_p = 1;
   if (s->slice.y == 0)
-    y -= thick, top_p = 1;
+    y -= thick + extra_y, top_p = 1;
   if (s->slice.x + s->slice.width == s->img->width)
-    x1 += thick, right_p = 1;
+    x1 += thick + extra_x, right_p = 1;
   if (s->slice.y + s->slice.height == s->img->height)
-    y1 += thick, bot_p = 1;
+    y1 += thick + extra_y, bot_p = 1;
 
   x_setup_relief_colors (s);
   get_glyph_string_clip_rect (s, &r);
@@ -2693,31 +2672,6 @@ x_scroll_run (struct window *w, struct run *run)
      fringes of W.  */
   window_box (w, ANY_AREA, &x, &y, &width, &height);
 
-  /* If the fringe is adjacent to the left (right) scroll bar of a
-     leftmost (rightmost, respectively) window, then extend its
-     background to the gap between the fringe and the bar.  */
-  if ((WINDOW_LEFTMOST_P (w)
-       && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
-      || (WINDOW_RIGHTMOST_P (w)
-         && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
-    {
-      int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
-
-      if (sb_width > 0)
-       {
-         int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
-         int bar_area_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
-
-         if (bar_area_x + bar_area_width == x)
-           {
-             x = bar_area_x + sb_width;
-             width += bar_area_width - sb_width;
-           }
-         else if (x + width == bar_area_x)
-           width += bar_area_width - sb_width;
-       }
-    }
-
   from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
   to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
   bottom_y = y + height;
@@ -3137,7 +3091,7 @@ construct_drag_n_drop (struct input_event *result, W32Msg *msg, struct frame *f)
   char name_a[MAX_PATH];
   char file[MAX_UTF8_PATH];
 #endif
-  int i, len;
+  int i;
 
   result->kind = DRAG_N_DROP_EVENT;
   result->code = 0;
@@ -3451,9 +3405,7 @@ w32_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
               = x_window_to_scroll_bar (WindowFromPoint (pt));
 
            if (bar)
-             {
-               f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
-             }
+             f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
          }
 
        if (f1 == 0 && insist > 0)
@@ -3560,10 +3512,10 @@ w32_set_scroll_bar_thumb (struct scroll_bar *bar,
   /* We use the whole scroll-bar height in the calculations below, to
      avoid strange effects like scrolling backwards when just clicking
      on the handle (without moving it).  */
-  double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height))
+  double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height)
                  + VERTICAL_SCROLL_BAR_MIN_HANDLE;
   int sb_page, sb_pos;
-  BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
+  BOOL draggingp = bar->dragging ? TRUE : FALSE;
   SCROLLINFO si;
 
   /* We used to change the nPage setting while dragging the handle,
@@ -3708,20 +3660,19 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
   HWND hwnd;
   SCROLLINFO si;
   struct scroll_bar *bar
-    = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, fringe_extended_p, PVEC_OTHER);
+    = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, top, PVEC_OTHER);
   Lisp_Object barobj;
 
   block_input ();
 
   XSETWINDOW (bar->window, w);
-  XSETINT (bar->top, top);
-  XSETINT (bar->left, left);
-  XSETINT (bar->width, width);
-  XSETINT (bar->height, height);
-  XSETINT (bar->start, 0);
-  XSETINT (bar->end, 0);
-  bar->dragging = Qnil;
-  bar->fringe_extended_p = 0;
+  bar->top = top;
+  bar->left = left;
+  bar->width = width;
+  bar->height = height;
+  bar->start = 0;
+  bar->end = 0;
+  bar->dragging = 0;
 
   /* Requires geometry to be set before call to create the real window */
 
@@ -3783,33 +3734,17 @@ w32_set_vertical_scroll_bar (struct window *w,
   struct frame *f = XFRAME (w->frame);
   Lisp_Object barobj;
   struct scroll_bar *bar;
-  int top, height, left, sb_left, width, sb_width;
+  int top, height, left, width;
   int window_y, window_height;
-  bool fringe_extended_p;
 
   /* Get window dimensions.  */
   window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
   top  = window_y;
-  width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
   height = window_height;
 
-  /* Compute the left edge of the scroll bar area.  */
+  /* Compute the left edge and the width of the scroll bar area.  */
   left = WINDOW_SCROLL_BAR_AREA_X (w);
-
-  /* Compute the width of the scroll bar which might be less than
-     the width of the area reserved for the scroll bar.  */
-  if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
-    sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
-  else
-    sb_width = width;
-
-  /* Compute the left edge of the scroll bar.  */
-  if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
-    sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
-  else
-    sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
-
-  fringe_extended_p = WINDOW_FRINGE_EXTENDED_P (w);
+  width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
 
   /* Does the scroll bar exist yet?  */
   if (NILP (w->vertical_scroll_bar))
@@ -3819,15 +3754,12 @@ w32_set_vertical_scroll_bar (struct window *w,
       if (width > 0 && height > 0)
        {
          hdc = get_frame_dc (f);
-         if (fringe_extended_p)
-           w32_clear_area (f, hdc, sb_left, top, sb_width, height);
-         else
-           w32_clear_area (f, hdc, left, top, width, height);
+         w32_clear_area (f, hdc, left, top, width, height);
          release_frame_dc (f, hdc);
        }
       unblock_input ();
 
-      bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
+      bar = x_scroll_bar_create (w, top, left, width, height);
     }
   else
     {
@@ -3838,11 +3770,10 @@ w32_set_vertical_scroll_bar (struct window *w,
       hwnd = SCROLL_BAR_W32_WINDOW (bar);
 
       /* If already correctly positioned, do nothing.  */
-      if (XINT (bar->left) == sb_left
-         && XINT (bar->top) == top
-         && XINT (bar->width) == sb_width
-         && XINT (bar->height) == height
-         && bar->fringe_extended_p == fringe_extended_p)
+      if (bar->left == left
+         && bar->top == top
+         && bar->width == width
+         && bar->height == height)
         {
           /* Redraw after clear_frame. */
           if (!my_show_window (f, hwnd, SW_NORMAL))
@@ -3859,17 +3790,13 @@ w32_set_vertical_scroll_bar (struct window *w,
              hdc = get_frame_dc (f);
              /* Since Windows scroll bars are smaller than the space reserved
                 for them on the frame, we have to clear "under" them.  */
-             if (fringe_extended_p)
-               w32_clear_area (f, hdc, sb_left, top, sb_width, height);
-             else
-               w32_clear_area (f, hdc, left, top, width, height);
+             w32_clear_area (f, hdc, left, top, width, height);
              release_frame_dc (f, hdc);
            }
           /* Make sure scroll bar is "visible" before moving, to ensure the
              area of the parent window now exposed will be refreshed.  */
           my_show_window (f, hwnd, SW_HIDE);
-          MoveWindow (hwnd, sb_left, top, sb_width,
-                     max (height, 1), TRUE);
+          MoveWindow (hwnd, left, top, width, max (height, 1), TRUE);
 
          si.cbSize = sizeof (si);
          si.fMask = SIF_RANGE;
@@ -3883,16 +3810,14 @@ w32_set_vertical_scroll_bar (struct window *w,
           /* InvalidateRect (w, NULL, FALSE);  */
 
           /* Remember new settings.  */
-          XSETINT (bar->left, sb_left);
-          XSETINT (bar->top, top);
-          XSETINT (bar->width, sb_width);
-          XSETINT (bar->height, height);
+          bar->left = left;
+          bar->top = top;
+          bar->width = width;
+          bar->height = height;
 
           unblock_input ();
         }
     }
-  bar->fringe_extended_p = fringe_extended_p;
-
   w32_set_scroll_bar_thumb (bar, portion, position, whole);
   XSETVECTOR (barobj, bar);
   wset_vertical_scroll_bar (w, barobj);
@@ -4026,9 +3951,9 @@ w32_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg,
   emacs_event->timestamp = msg->msg.time;
 
   {
-    int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
+    int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
     int y;
-    int dragging = !NILP (bar->dragging);
+    int dragging = bar->dragging;
     SCROLLINFO si;
 
     si.cbSize = sizeof (si);
@@ -4037,7 +3962,7 @@ w32_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg,
     GetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
     y = si.nPos;
 
-    bar->dragging = Qnil;
+    bar->dragging = 0;
     FRAME_DISPLAY_INFO (f)->last_mouse_scroll_bar_pos = msg->msg.wParam;
 
     switch (LOWORD (msg->msg.wParam))
@@ -4064,9 +3989,9 @@ w32_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg,
        break;
       case SB_THUMBTRACK:
       case SB_THUMBPOSITION:
-       if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
+       if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height) <= 0xffff)
           y = HIWORD (msg->msg.wParam);
-       bar->dragging = Qt;
+       bar->dragging = 1; /* ??????? */
        emacs_event->part = scroll_bar_handle;
 
        /* "Silently" update current position.  */
@@ -4090,8 +4015,8 @@ w32_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg,
        if (dragging)
          {
            SCROLLINFO si;
-           int start = XINT (bar->start);
-           int end = XINT (bar->end);
+           int start = bar->start;
+           int end = bar->end;
 
            si.cbSize = sizeof (si);
            si.fMask = SIF_PAGE | SIF_POS;
@@ -4126,7 +4051,7 @@ x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
   Window w = SCROLL_BAR_W32_WINDOW (bar);
   struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
   int pos;
-  int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
+  int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
   SCROLLINFO si;
 
   block_input ();
@@ -4146,7 +4071,7 @@ x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
   case SB_THUMBPOSITION:
   case SB_THUMBTRACK:
       *part = scroll_bar_handle;
-      if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
+      if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height) <= 0xffff)
        pos = HIWORD (dpyinfo->last_mouse_scroll_bar_pos);
       break;
   case SB_LINEDOWN:
@@ -4775,6 +4700,10 @@ w32_read_socket (struct terminal *terminal,
                  {
                    bool iconified = FRAME_ICONIFIED_P (f);
 
+                   /* The following was made unconditional in a
+                      pathetic attempt to fix bug#16967 in revision
+                      116716 but, considered counterproductive was made
+                      conditional again in revision 116727.  martin */
                    if (iconified)
                      SET_FRAME_VISIBLE (f, 1);
                    SET_FRAME_ICONIFIED (f, 0);
@@ -4944,6 +4873,10 @@ w32_read_socket (struct terminal *terminal,
          if (f)
            {
              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);
              DebPrint (("display change: %d %d\n",
                         (short) LOWORD (msg.msg.lParam),
                         (short) HIWORD (msg.msg.lParam)));
@@ -5464,6 +5397,7 @@ Lisp_Object
 x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
 {
   struct font *font = XFONT_OBJECT (font_object);
+  int unit;
 
   if (fontset < 0)
     fontset = fontset_from_font (font_object);
@@ -5475,22 +5409,21 @@ 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) = font->average_width;
+  FRAME_COLUMN_WIDTH (f) = unit = font->average_width;
   FRAME_LINE_HEIGHT (f) = font->height;
 
   compute_fringe_widths (f, 1);
 
-  /* Compute the scroll bar width in character columns.  */
+  /* Compute number of scrollbar columns.  */
+  unit = FRAME_COLUMN_WIDTH (f);
   if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
-    {
-      int wid = FRAME_COLUMN_WIDTH (f);
-      FRAME_CONFIG_SCROLL_BAR_COLS (f)
-       = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid;
-    }
+    FRAME_CONFIG_SCROLL_BAR_COLS (f)
+      = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
   else
     {
-      int wid = FRAME_COLUMN_WIDTH (f);
-      FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
+      FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
+      FRAME_CONFIG_SCROLL_BAR_WIDTH (f) =
+       FRAME_CONFIG_SCROLL_BAR_COLS (f) * unit;
     }
 
   /* Now make the frame display the given font.  */
@@ -5667,18 +5600,22 @@ w32fullscreen_hook (struct frame *f)
       if (FRAME_PREV_FSMODE (f) == FULLSCREEN_BOTH)
         {
           SetWindowLong (hwnd, GWL_STYLE, dwStyle | WS_OVERLAPPEDWINDOW);
-          SetWindowPos (hwnd, NULL, 0, 0, 0, 0,
-                        SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
-                        SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
-        }
+         SetWindowPlacement (hwnd, &FRAME_NORMAL_PLACEMENT (f));
+       }
+      else if (FRAME_PREV_FSMODE (f) == FULLSCREEN_HEIGHT
+              || FRAME_PREV_FSMODE (f) == FULLSCREEN_WIDTH)
+       SetWindowPlacement (hwnd, &FRAME_NORMAL_PLACEMENT (f));
 
-      w32_fullscreen_rect (hwnd, f->want_fullscreen,
-                           FRAME_NORMAL_PLACEMENT (f).rcNormalPosition, &rect);
       FRAME_PREV_FSMODE (f) = f->want_fullscreen;
-      if (f->want_fullscreen == FULLSCREEN_MAXIMIZED)
-       PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, 0xf030, 0);
+
+      if (f->want_fullscreen == FULLSCREEN_NONE)
+       ShowWindow (hwnd, SW_SHOWNORMAL);
+      else if (f->want_fullscreen == FULLSCREEN_MAXIMIZED)
+       ShowWindow (hwnd, SW_MAXIMIZE);
       else if (f->want_fullscreen == FULLSCREEN_BOTH)
         {
+         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,
@@ -5686,6 +5623,9 @@ w32fullscreen_hook (struct frame *f)
         }
       else
         {
+         ShowWindow (hwnd, SW_SHOWNORMAL);
+         w32_fullscreen_rect (hwnd, f->want_fullscreen,
+                              FRAME_NORMAL_PLACEMENT (f).rcNormalPosition, &rect);
           SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
                         rect.right - rect.left, rect.bottom - rect.top, 0);
         }
@@ -5710,8 +5650,6 @@ x_set_window_size (struct frame *f, int change_gravity, int width, int height, b
   block_input ();
 
   check_frame_size (f, &width, &height, pixelwise);
-  f->scroll_bar_actual_width
-    = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
 
   compute_fringe_widths (f, 0);
 
@@ -5726,6 +5664,21 @@ x_set_window_size (struct frame *f, int change_gravity, int width, int height, b
       pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height);
     }
 
+  if (!frame_resize_pixelwise)
+    {
+      /* If we don't resize frames pixelwise, round sizes to multiples
+        of character sizes here.  Otherwise, when enforcing size hints
+        while processing WM_WINDOWPOSCHANGING in w32_wnd_proc, we might
+        clip our frame rectangle to a multiple of the frame's character
+        size and subsequently lose our mode line or scroll bar.
+        Bug#16923 could be one possible consequence of this.  */
+      int unit_width = FRAME_COLUMN_WIDTH (f);
+      int unit_height = FRAME_LINE_HEIGHT (f);
+
+      pixelwidth = (pixelwidth / unit_width) * unit_width;
+      pixelheight = (pixelheight / unit_height) * unit_height;
+    }
+
   f->win_gravity = NorthWestGravity;
   x_wm_set_size_hint (f, (long) 0, 0);
 
@@ -5747,53 +5700,51 @@ x_set_window_size (struct frame *f, int change_gravity, int width, int height, b
                       SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
   }
 
-#if 0
-  /* 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.
+  /* 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.
 
-     -----------------------------------------------------------------
-
-     Now, strictly speaking, we can't be sure that this is accurate,
-     but the window manager will get around to dealing with the size
-     change request eventually, and we'll hear how it went when the
-     ConfigureNotify event gets here.
-
-     We could just not bother storing any of this information here,
-     and let the ConfigureNotify event set everything up, but that
-     might be kind of confusing to the Lisp code, since size changes
-     wouldn't be reported in the frame parameters until some random
-     point in the future when the ConfigureNotify event arrives.
-
-     We pass 1 for DELAY since we can't run Lisp code inside of
-     a BLOCK_INPUT.  */
-  change_frame_size (f, width, height, 0, 1, 0, 0);
-  FRAME_PIXEL_WIDTH (f) = pixelwidth;
-  FRAME_PIXEL_HEIGHT (f) = pixelheight;
-
-  /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
-     receive in the ConfigureNotify event; if we get what we asked
-     for, then the event won't cause the screen to become garbaged, so
-     we have to make sure to do it here.  */
-  SET_FRAME_GARBAGED (f);
-
-  /* If cursor was outside the new size, mark it as off.  */
-  mark_window_cursors_off (XWINDOW (f->root_window));
-
-  /* Clear out any recollection of where the mouse highlighting was,
-     since it might be in a place that's outside the new frame size.
-     Actually checking whether it is outside is a pain in the neck,
-     so don't try--just let the highlighting be done afresh with new size.  */
-  cancel_mouse_face (f);
-#endif
+     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)
+
+    {
+      change_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth),
+                        FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight),
+                        0, 1, 0, 1);
+      SET_FRAME_GARBAGED (f);
+
+      /* If cursor was outside the new size, mark it as off.  */
+      mark_window_cursors_off (XWINDOW (f->root_window));
+
+      /* Clear out any recollection of where the mouse highlighting was,
+        since it might be in a place that's outside the new frame size.
+        Actually checking whether it is outside is a pain in the neck,
+        so don't try--just let the highlighting be done afresh with new
+        size.  */
+      cancel_mouse_face (f);
+    }
 
   unblock_input ();
 }
@@ -6470,7 +6421,7 @@ static void
 w32_initialize (void)
 {
   HANDLE shell;
-  HRESULT (WINAPI * set_user_model) (wchar_t * id);
+  HRESULT (WINAPI * set_user_model) (const wchar_t * id);
 
   baud_rate = 19200;
 
@@ -6517,9 +6468,8 @@ w32_initialize (void)
   Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
 
   {
-    DWORD input_locale_id = ((DWORD_PTR) GetKeyboardLayout (0) & 0xffffffff);
-    w32_keyboard_codepage =
-      codepage_for_locale ((LCID) (input_locale_id & 0xffff));
+    LCID input_locale_id = LOWORD (GetKeyboardLayout (0));
+    w32_keyboard_codepage = codepage_for_locale (input_locale_id);
   }
 
   /* Create the window thread - it will terminate itself when the app
@@ -6673,6 +6623,16 @@ systems of the NT family, including W2K, XP, Vista, Windows 7 and
 Windows 8.  It is set to nil on Windows 9X.  */);
   w32_unicode_filenames = 0;
 
+  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);
 }