]> code.delx.au - gnu-emacs/blobdiff - src/w32term.c
In x_set_window_size restore do_pending_window_change calls
[gnu-emacs] / src / w32term.c
index 7c5f2db3a4cd8e29251daf8590527114170de5fb..51743f8f94dad77257e9db79cd2f498c07d55bc6 100644 (file)
@@ -1,13 +1,13 @@
 /* Implementation of GUI terminal on the Microsoft Windows API.
 
-Copyright (C) 1989, 1993-2015 Free Software Foundation, Inc.
+Copyright (C) 1989, 1993-2016 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -23,38 +23,29 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "lisp.h"
 #include "blockinput.h"
 #include "w32term.h"
-
-#include "systty.h"
-#include "systime.h"
+#include "w32common.h" /* for OS version info */
 
 #include <ctype.h>
 #include <errno.h>
 #include <sys/stat.h>
+#ifdef CYGWIN
+#include <fcntl.h>     /* for O_RDWR */
+#endif
 #include <imm.h>
 
-#include "charset.h"
-#include "character.h"
 #include "coding.h"
-#include "ccl.h"
 #include "frame.h"
-#include "dispextern.h"
 #include "fontset.h"
 #include "termhooks.h"
 #include "termopts.h"
 #include "termchar.h"
-#include "disptab.h"
 #include "buffer.h"
 #include "window.h"
 #include "keyboard.h"
-#include "intervals.h"
-#include "process.h"
-#include "atimer.h"
-#include "keymap.h"
-#include "menu.h"
+#include "menu.h"      /* for w32_menu_show */
 
 #ifdef WINDOWSNT
 #include "w32.h"       /* for filename_from_utf16, filename_from_ansi */
-#include "w32heap.h"
 #endif
 
 #ifndef WINDOWSNT
@@ -65,6 +56,10 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "font.h"
 #include "w32font.h"
+
+#if 0  /* TODO: stipple */
+#include "bitmaps/gray.xbm"
+#endif
 \f
 /* Fringe bitmaps.  */
 
@@ -1596,7 +1591,9 @@ w32_setup_relief_color (struct frame *f, struct relief *relief, double factor,
   unsigned long mask = GCForeground;
   COLORREF pixel;
   COLORREF background = di->relief_background;
+#if 0
   struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+#endif
 
   /* TODO: Free colors (if using palette)? */
 
@@ -3619,8 +3616,8 @@ w32_set_horizontal_scroll_bar_thumb (struct scroll_bar *bar,
   si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
   si.nMin = 0;
   si.nMax = whole;
-  /* Allow nPage to be one larger than nPos so we don't allow to scroll
-     an already fully visible buffer.  */
+  /* Allow nPage to be one larger than nPos so we don't allow the scrolling
+     of an already fully visible buffer.  */
   si.nPage = min (portion, si.nMax) + 1;
   si.nPos = min (position, si.nMax);
   SetScrollInfo (w, SB_CTL, &si, TRUE);
@@ -4350,8 +4347,6 @@ w32_horizontal_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg,
        if (dragging)
          {
            SCROLLINFO si;
-           int start = bar->start;
-           int end = bar->end;
 
            si.cbSize = sizeof (si);
            si.fMask = SIF_POS;
@@ -4509,18 +4504,6 @@ x_scroll_bar_clear (struct frame *f)
       }
 }
 
-static void
-set_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
-{
-  register Lisp_Object old_alist_elt;
-
-  old_alist_elt = Fassq (prop, f->param_alist);
-  if (EQ (old_alist_elt, Qnil))
-    fset_param_alist (f, Fcons (Fcons (prop, val), f->param_alist));
-  else
-    Fsetcdr (old_alist_elt, val);
-}
-
 /* The main W32 event-reading loop - w32_read_socket.  */
 
 /* Record the last 100 characters stored
@@ -5159,7 +5142,7 @@ w32_read_socket (struct terminal *terminal,
          if (f && !FRAME_ICONIFIED_P (f) && msg.msg.wParam != SIZE_MINIMIZED)
            {
              RECT rect;
-             int rows, columns, width, height, text_width, text_height;
+             int /* rows, columns, */ width, height, text_width, text_height;
 
              if (GetClientRect (msg.msg.hwnd, &rect)
                  /* GetClientRect evidently returns (0, 0, 0, 0) if
@@ -5931,16 +5914,49 @@ x_calc_absolute_position (struct frame *f)
       top_bottom_borders_height = 32;
     }
 
+  /* With multiple monitors, we can legitimately get negative
+     coordinates (for monitors above or to the left of the primary
+     monitor).  Find the display origin to ensure negative positions
+     are computed correctly (Bug#21173).  */
+  int display_left = 0;
+  int display_top = 0;
+  if (flags & (XNegative | YNegative))
+    {
+      Lisp_Object list;
+
+      list = Fw32_display_monitor_attributes_list (Qnil);
+      while (CONSP (list))
+        {
+          Lisp_Object attributes = CAR(list);
+          Lisp_Object geometry;
+          Lisp_Object monitor_left, monitor_top;
+
+          list = CDR(list);
+
+          geometry = Fassoc (Qgeometry, attributes);
+          if (!NILP (geometry))
+            {
+              monitor_left = Fnth (make_number (1), geometry);
+              monitor_top  = Fnth (make_number (2), geometry);
+
+              display_left = min (display_left, XINT (monitor_left));
+              display_top  = min (display_top,  XINT (monitor_top));
+            }
+        }
+    }
+
   /* Treat negative positions as relative to the rightmost bottommost
      position that fits on the screen.  */
   if (flags & XNegative)
     f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f))
+                   + display_left
                   - FRAME_PIXEL_WIDTH (f)
                   + f->left_pos
                   - (left_right_borders_width - 1));
 
   if (flags & YNegative)
     f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
+                  + display_top
                  - FRAME_PIXEL_HEIGHT (f)
                  + f->top_pos
                  - (top_bottom_borders_height - 1));
@@ -6100,9 +6116,22 @@ x_set_window_size (struct frame *f, bool change_gravity,
   int pixelwidth, pixelheight;
   Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
   RECT rect;
+  MENUBARINFO info;
+  int menu_bar_height;
 
   block_input ();
 
+  /* Get the height of the menu bar here.  It's used below to detect
+     whether the menu bar is wrapped.  It's also used to specify the
+     third argument for AdjustWindowRect.  FRAME_EXTERNAL_MENU_BAR which
+     has been used before for that reason is unreliable because it only
+     specifies whether we _want_ a menu bar for this frame and not
+     whether this frame _has_ a menu bar.  See bug#22105.  */
+  info.cbSize = sizeof (info);
+  info.rcBar.top = info.rcBar.bottom = 0;
+  GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &info);
+  menu_bar_height = info.rcBar.bottom - info.rcBar.top;
+
   if (pixelwise)
     {
       pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width);
@@ -6120,17 +6149,11 @@ x_set_window_size (struct frame *f, bool change_gravity,
         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;
       int default_menu_bar_height;
-      int menu_bar_height;
 
       /* Why is (apparently) SM_CYMENUSIZE needed here instead of
         SM_CYMENU ??  */
       default_menu_bar_height = GetSystemMetrics (SM_CYMENUSIZE);
-      info.cbSize = sizeof (info);
-      info.rcBar.top = info.rcBar.bottom = 0;
-      GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &info);
-      menu_bar_height = info.rcBar.bottom - info.rcBar.top;
 
       if ((default_menu_bar_height > 0)
          && (menu_bar_height > default_menu_bar_height)
@@ -6145,8 +6168,7 @@ x_set_window_size (struct frame *f, bool change_gravity,
   rect.right = pixelwidth;
   rect.bottom = pixelheight;
 
-  AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
-                   FRAME_EXTERNAL_MENU_BAR (f));
+  AdjustWindowRect (&rect, f->output_data.w32->dwStyle, menu_bar_height > 0);
 
   if (!(f->after_make_frame)
       && !(f->want_fullscreen & FULLSCREEN_WAIT)
@@ -6176,6 +6198,13 @@ x_set_window_size (struct frame *f, bool change_gravity,
 
   if (pixelwidth > 0 || pixelheight > 0)
     {
+      frame_size_history_add
+       (f, Qx_set_window_size_1, width, height,
+        list2 (Fcons (make_number (pixelwidth),
+                      make_number (pixelheight)),
+               Fcons (make_number (rect.right - rect.left),
+                      make_number (rect.bottom - rect.top))));
+
       my_set_window_pos (FRAME_W32_WINDOW (f), NULL,
                         0, 0,
                         rect.right - rect.left,
@@ -6203,7 +6232,7 @@ x_set_window_size (struct frame *f, bool change_gravity,
 
   unblock_input ();
 
-  do_pending_window_change (0);
+  do_pending_window_change (false);
 }
 \f
 /* Mouse warping.  */
@@ -6211,6 +6240,8 @@ x_set_window_size (struct frame *f, bool change_gravity,
 void
 frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
 {
+  UINT trail_num = 0;
+  BOOL ret = false;
   RECT rect;
   POINT pt;
 
@@ -6221,7 +6252,15 @@ frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
   pt.y = rect.top + pix_y;
   ClientToScreen (FRAME_W32_WINDOW (f), &pt);
 
+  /* When "mouse trails" are in effect, moving the mouse cursor
+     sometimes leaves behind an annoying "ghost" of the pointer.
+     Avoid that by momentarily switching off mouse trails.  */
+  if (os_subtype == OS_NT
+      && w32_major_version + w32_minor_version >= 6)
+    ret = SystemParametersInfo (SPI_GETMOUSETRAILS, 0, &trail_num, 0);
   SetCursorPos (pt.x, pt.y);
+  if (ret)
+    SystemParametersInfo (SPI_SETMOUSETRAILS, trail_num, NULL, 0);
 
   unblock_input ();
 }
@@ -6613,14 +6652,10 @@ w32_toggle_invisible_pointer (struct frame *f, bool invisible)
   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 ();
 }
 
@@ -6909,6 +6944,15 @@ x_delete_display (struct w32_display_info *dpyinfo)
 \f
 /* Set up use of W32.  */
 
+void
+w32_init_main_thread (void)
+{
+  dwMainThreadId = GetCurrentThreadId ();
+  DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
+                  GetCurrentProcess (), &hMainThread, 0, TRUE,
+                  DUPLICATE_SAME_ACCESS);
+}
+
 DWORD WINAPI w32_msg_worker (void * arg);
 
 static void
@@ -6969,10 +7013,6 @@ w32_initialize (void)
      terminates */
   init_crit ();
 
-  dwMainThreadId = GetCurrentThreadId ();
-  DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
-                  GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
-
   /* Wait for thread to start */
   {
     MSG msg;