]> code.delx.au - gnu-emacs/blobdiff - src/w32term.c
Remove now-inaccurate bytecode comments
[gnu-emacs] / src / w32term.c
index f764e250aa812fc643758f3f3d579def9edcad6e..5a11e2a871a74730aa8f8716efbb8b52e8374d67 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,6 +23,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "lisp.h"
 #include "blockinput.h"
 #include "w32term.h"
+#include "w32common.h" /* for OS version info */
 
 #include <ctype.h>
 #include <errno.h>
@@ -82,8 +83,6 @@ static int any_help_event_p;
 
 extern unsigned int msh_mousewheel;
 
-extern void free_frame_menubar (struct frame *);
-
 extern int w32_codepage_for_font (char *fontname);
 extern Cursor w32_load_cursor (LPCTSTR name);
 
@@ -177,9 +176,7 @@ static void w32_define_cursor (Window, Cursor);
 
 void x_lower_frame (struct frame *);
 void x_scroll_bar_clear (struct frame *);
-void x_wm_set_size_hint (struct frame *, long, bool);
 void x_raise_frame (struct frame *);
-void x_set_window_size (struct frame *, bool, int, int, bool);
 void x_wm_set_window_state (struct frame *, int);
 void x_wm_set_icon_pixmap (struct frame *, int);
 static void w32_initialize (void);
@@ -247,7 +244,7 @@ record_event (char *locus, int type)
 #endif /* 0 */
 \f
 
-void
+static void
 XChangeGC (void *ignore, XGCValues *gc, unsigned long mask,
           XGCValues *xgcv)
 {
@@ -269,12 +266,14 @@ XCreateGC (void *ignore, Window window, unsigned long mask, XGCValues *xgcv)
   return gc;
 }
 
-void
+#if 0  /* unused for now, see x_draw_image_glyph_string below */
+static void
 XGetGCValues (void *ignore, XGCValues *gc,
              unsigned long mask, XGCValues *xgcv)
 {
   XChangeGC (ignore, xgcv, mask, gc);
 }
+#endif
 
 static void
 w32_set_clip_rectangle (HDC hdc, RECT *rect)
@@ -320,7 +319,7 @@ w32_restore_glyph_string_clip (struct glyph_string *s)
 
 */
 
-void
+static void
 w32_draw_underwave (struct glyph_string *s, COLORREF color)
 {
   int wave_height = 3, wave_length = 2;
@@ -383,7 +382,7 @@ w32_draw_underwave (struct glyph_string *s, COLORREF color)
 }
 
 /* Draw a hollow rectangle at the specified position.  */
-void
+static void
 w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y,
                     int width, int height)
 {
@@ -612,7 +611,7 @@ w32_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
   r.bottom = y1;
 
   hdc = get_frame_dc (f);
-  face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
+  face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID);
   if (face)
     w32_fill_rect (f, hdc, face->foreground, &r);
   else
@@ -629,9 +628,11 @@ w32_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   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);
+  struct face *face = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FACE_ID);
+  struct face *face_first
+    = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
+  struct face *face_last
+    = FACE_FROM_ID_OR_NULL (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
@@ -990,7 +991,7 @@ x_set_mouse_face_gc (struct glyph_string *s)
 
   /* What face has to be used last for the mouse face?  */
   face_id = MOUSE_HL_INFO (s->f)->mouse_face_face_id;
-  face = FACE_FROM_ID (s->f, face_id);
+  face = FACE_FROM_ID_OR_NULL (s->f, face_id);
   if (face == NULL)
     face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
 
@@ -1433,7 +1434,7 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
        {
          sprintf ((char *) buf, "%0*X",
                   glyph->u.glyphless.ch < 0x10000 ? 4 : 6,
-                  glyph->u.glyphless.ch);
+                  (unsigned int) glyph->u.glyphless.ch);
          str = buf;
        }
 
@@ -2576,7 +2577,7 @@ x_draw_glyph_string (struct glyph_string *s)
 
 /* Shift display to make room for inserted glyphs.   */
 
-void
+static void
 w32_shift_glyphs_for_insert (struct frame *f, int x, int y,
                             int width, int height, int shift_by)
 {
@@ -2873,13 +2874,15 @@ w32_detect_focus_change (struct w32_display_info *dpyinfo, W32Msg *event,
 }
 
 
+#if 0  /* unused */
 /* Handle an event saying the mouse has moved out of an Emacs frame.  */
 
-void
+static void
 x_mouse_leave (struct w32_display_info *dpyinfo)
 {
   x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
 }
+#endif
 
 /* The focus has changed, or we have redirected a frame's focus to
    another frame (this happens when a frame uses a surrogate
@@ -3210,71 +3213,85 @@ static void
 queue_notifications (struct input_event *event, W32Msg *msg, struct frame *f,
                     int *evcount)
 {
-  BYTE *p = file_notifications;
-  FILE_NOTIFY_INFORMATION *fni = (PFILE_NOTIFY_INFORMATION)p;
-  const DWORD min_size
-    = offsetof (FILE_NOTIFY_INFORMATION, FileName) + sizeof(wchar_t);
+  struct notifications_set *ns = NULL;
   Lisp_Object frame;
+  int done = 0;
 
   /* We cannot process notification before Emacs is fully initialized,
      since we need the UTF-16LE coding-system to be set up.  */
   if (!initialized)
-    {
-      notification_buffer_in_use = 0;
-      return;
-    }
+    return;
 
   XSETFRAME (frame, f);
 
-  enter_crit ();
-  if (notification_buffer_in_use)
+  while (!done)
     {
-      DWORD info_size = notifications_size;
-      Lisp_Object cs = Qutf_16le;
-      Lisp_Object obj = w32_get_watch_object (notifications_desc);
-
-      /* notifications_size could be zero when the buffer of
-        notifications overflowed on the OS level, or when the
-        directory being watched was itself deleted.  Do nothing in
-        that case.  */
-      if (info_size
-         && !NILP (obj) && CONSP (obj))
+      ns = NULL;
+
+      /* Find out if there is a record available in the linked list of
+        notifications sets.  If so, unlink the set from the linked
+        list.  Use critical section.  */
+      enter_crit ();
+      if (notifications_set_head->next != notifications_set_head)
        {
-         Lisp_Object callback = XCDR (obj);
+         ns = notifications_set_head->next;
+         ns->prev->next = ns->next;
+         ns->next->prev = ns->prev;
+       }
+      else
+       done = 1;
+      leave_crit();
 
-         while (info_size >= min_size)
+      if (ns)
+       {
+         BYTE *p = ns->notifications;
+         FILE_NOTIFY_INFORMATION *fni = (PFILE_NOTIFY_INFORMATION)p;
+         const DWORD min_size
+           = offsetof (FILE_NOTIFY_INFORMATION, FileName) + sizeof(wchar_t);
+         DWORD info_size = ns->size;
+         Lisp_Object cs = Qutf_16le;
+         Lisp_Object obj = w32_get_watch_object (ns->desc);
+
+         /* notifications size could be zero when the buffer of
+            notifications overflowed on the OS level, or when the
+            directory being watched was itself deleted.  Do nothing in
+            that case.  */
+         if (info_size
+             && !NILP (obj) && CONSP (obj))
            {
-             Lisp_Object utf_16_fn
-               = make_unibyte_string ((char *)fni->FileName,
-                                      fni->FileNameLength);
-             /* Note: mule-conf is preloaded, so utf-16le must
-                already be defined at this point.  */
-             Lisp_Object fname
-               = code_convert_string_norecord (utf_16_fn, cs, 0);
-             Lisp_Object action = lispy_file_action (fni->Action);
-
-             event->kind = FILE_NOTIFY_EVENT;
-             event->timestamp = msg->msg.time;
-             event->modifiers = 0;
-             event->frame_or_window = callback;
-             event->arg = list3 (make_pointer_integer (notifications_desc),
-                                 action, fname);
-             kbd_buffer_store_event (event);
-             (*evcount)++;
-
-             if (!fni->NextEntryOffset)
-               break;
-             p += fni->NextEntryOffset;
-             fni = (PFILE_NOTIFY_INFORMATION)p;
-             info_size -= fni->NextEntryOffset;
+             Lisp_Object callback = XCDR (obj);
+
+             while (info_size >= min_size)
+               {
+                 Lisp_Object utf_16_fn
+                   = make_unibyte_string ((char *)fni->FileName,
+                                          fni->FileNameLength);
+                 /* Note: mule-conf is preloaded, so utf-16le must
+                    already be defined at this point.  */
+                 Lisp_Object fname
+                   = code_convert_string_norecord (utf_16_fn, cs, 0);
+                 Lisp_Object action = lispy_file_action (fni->Action);
+
+                 event->kind = FILE_NOTIFY_EVENT;
+                 event->timestamp = msg->msg.time;
+                 event->modifiers = 0;
+                 event->frame_or_window = callback;
+                 event->arg = list3 (make_pointer_integer (ns->desc),
+                                     action, fname);
+                 kbd_buffer_store_event (event);
+                 (*evcount)++;
+                 if (!fni->NextEntryOffset)
+                   break;
+                 p += fni->NextEntryOffset;
+                 fni = (PFILE_NOTIFY_INFORMATION)p;
+                 info_size -= fni->NextEntryOffset;
+               }
            }
+         /* Free this notifications set. */
+         xfree (ns->notifications);
+         xfree (ns);
        }
-      notification_buffer_in_use = 0;
     }
-  else
-    DebPrint (("We were promised notifications, but in-use flag is zero!\n"));
-  leave_crit ();
-
   /* We've stuffed all the events ourselves, so w32_read_socket shouldn't.  */
   event->kind = NO_EVENT;
 }
@@ -3615,8 +3632,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);
@@ -4181,6 +4198,7 @@ w32_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg,
       y = si.nPos;
 
     bar->dragging = 0;
+    struct frame *f;           /* Value is not used.  */
     FRAME_DISPLAY_INFO (f)->last_mouse_scroll_bar_pos = msg->msg.wParam;
 
     switch (sb_event)
@@ -4296,6 +4314,7 @@ w32_horizontal_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg,
     y = si.nMax - si.nPage;
 
     bar->dragging = 0;
+    struct frame *f;           /* Value is not used.  */
     FRAME_DISPLAY_INFO (f)->last_mouse_scroll_bar_pos = msg->msg.wParam;
 
     switch (sb_event)
@@ -4533,6 +4552,8 @@ static char dbcs_lead = 0;
    recursively with different messages by the system.
 */
 
+extern void menubar_selection_callback (struct frame *, void *);
+
 static int
 w32_read_socket (struct terminal *terminal,
                 struct input_event *hold_quit)
@@ -5245,6 +5266,10 @@ w32_read_socket (struct terminal *terminal,
            }
          break;
 
+       case WM_ENDSESSION:
+         inev.kind = END_SESSION_EVENT;
+         break;
+
        case WM_INITMENU:
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
 
@@ -5260,8 +5285,6 @@ w32_read_socket (struct terminal *terminal,
 
          if (f)
            {
-             extern void menubar_selection_callback
-               (struct frame *f, void * client_data);
              menubar_selection_callback (f, (void *)msg.msg.wParam);
            }
 
@@ -5878,7 +5901,7 @@ xim_close_dpy (dpyinfo)
 /* Calculate the absolute position in frame F
    from its current recorded position values and gravity.  */
 
-void
+static void
 x_calc_absolute_position (struct frame *f)
 {
   int flags = f->size_hint_flags;
@@ -6115,9 +6138,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);
@@ -6135,17 +6171,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)
@@ -6160,8 +6190,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)
@@ -6224,6 +6253,8 @@ x_set_window_size (struct frame *f, bool change_gravity,
     }
 
   unblock_input ();
+
+  do_pending_window_change (false);
 }
 \f
 /* Mouse warping.  */
@@ -6231,6 +6262,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;
 
@@ -6241,7 +6274,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 ();
 }
@@ -6536,7 +6577,7 @@ x_free_frame_resources (struct frame *f)
 
 
 /* Destroy the window of frame F.  */
-void
+static void
 x_destroy_window (struct frame *f)
 {
   struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
@@ -6925,6 +6966,17 @@ 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
@@ -6985,10 +7037,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;