]> code.delx.au - gnu-emacs/blobdiff - src/xfns.c
; Revert "Ensure undo-boundary after insert-file-contents."
[gnu-emacs] / src / xfns.c
index 9d90b7ba35fced94965074c07acfad342a8e998b..7c1bb1c2819d1a39304d99c22e382769e4804dc4 100644 (file)
@@ -1,13 +1,13 @@
 /* Functions for the X window system.
 
-Copyright (C) 1989, 1992-2015 Free Software Foundation, Inc.
+Copyright (C) 1989, 1992-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
@@ -273,7 +273,7 @@ x_real_pos_and_offsets (struct frame *f,
       XFree (tmp_children);
 #endif
 
-      if (wm_window == rootw || had_errors)
+      if (had_errors || wm_window == rootw)
         break;
 
       win = wm_window;
@@ -450,10 +450,11 @@ x_real_pos_and_offsets (struct frame *f,
           if (prop)
             {
               if (prop->type == target_type
-                  && xcb_get_property_value_length (prop) == 4
-                  && prop->format == 32)
+                  && prop->format == 32
+                  && (xcb_get_property_value_length (prop)
+                     == 4 * sizeof (int32_t)))
                 {
-                  long *fe = xcb_get_property_value (prop);
+                  int32_t *fe = xcb_get_property_value (prop);
 
                   outer_x = -fe[0];
                   outer_y = -fe[2];
@@ -3669,7 +3670,7 @@ x_focus_frame (struct frame *f)
 \f
 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
        doc: /* Internal function called by `color-defined-p', which see.
-(Note that the Nextstep version of this function ignores FRAME.)  */)
+\(Note that the Nextstep version of this function ignores FRAME.)  */)
   (Lisp_Object color, Lisp_Object frame)
 {
   XColor foo;
@@ -3836,7 +3837,7 @@ If omitted or nil, that stands for the selected frame's display.  */)
 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
        doc: /* Return the "vendor ID" string of the GUI software on TERMINAL.
 
-(Labeling every distributor as a "vendor" embodies the false assumption
+\(Labeling every distributor as a "vendor" embodies the false assumption
 that operating systems cannot be developed and distributed noncommercially.)
 The optional argument TERMINAL specifies which display to ask about.
 
@@ -4261,8 +4262,19 @@ x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo)
   RROutput pxid = None;
   struct MonitorInfo *monitors;
 
-#ifdef HAVE_XRRGETSCREENRESOURCESCURRENT
-  resources = XRRGetScreenResourcesCurrent (dpy, dpyinfo->root_window);
+#define RANDR13_LIBRARY \
+  (RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3))
+
+#if RANDR13_LIBRARY
+  /* Check if the display supports 1.3 too.  */
+  bool randr13_avail = (dpyinfo->xrandr_major_version > 1
+                       || (dpyinfo->xrandr_major_version == 1
+                           && dpyinfo->xrandr_minor_version >= 3));
+
+  if (randr13_avail)
+    resources = XRRGetScreenResourcesCurrent (dpy, dpyinfo->root_window);
+  else
+    resources = XRRGetScreenResources (dpy, dpyinfo->root_window);
 #else
   resources = XRRGetScreenResources (dpy, dpyinfo->root_window);
 #endif
@@ -4275,8 +4287,9 @@ x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo)
   n_monitors = resources->noutput;
   monitors = xzalloc (n_monitors * sizeof *monitors);
 
-#ifdef HAVE_XRRGETOUTPUTPRIMARY
-  pxid = XRRGetOutputPrimary (dpy, dpyinfo->root_window);
+#if RANDR13_LIBRARY
+  if (randr13_avail)
+    pxid = XRRGetOutputPrimary (dpy, dpyinfo->root_window);
 #endif
 
   for (i = 0; i < n_monitors; ++i)
@@ -4359,9 +4372,11 @@ x_get_monitor_attributes (struct x_display_info *dpyinfo)
   xrr_ok = XRRQueryExtension (dpy, &xrr_event_base, &xrr_error_base);
   if (xrr_ok)
     {
-      int xrr_major, xrr_minor;
-      XRRQueryVersion (dpy, &xrr_major, &xrr_minor);
-      xrr_ok = (xrr_major == 1 && xrr_minor >= 2) || xrr_major > 1;
+      XRRQueryVersion (dpy, &dpyinfo->xrandr_major_version,
+                      &dpyinfo->xrandr_minor_version);
+      xrr_ok = ((dpyinfo->xrandr_major_version == 1
+                && dpyinfo->xrandr_minor_version >= 2)
+               || dpyinfo->xrandr_major_version > 1);
     }
 
   if (xrr_ok)
@@ -4758,7 +4773,7 @@ DEFUN ("x-set-mouse-absolute-pixel-position", Fx_set_mouse_absolute_pixel_positi
        Sx_set_mouse_absolute_pixel_position, 2, 2, 0,
        doc: /* Move mouse pointer to absolute pixel position (X, Y).
 The coordinates X and Y are interpreted in pixels relative to a position
-(0, 0) of the selected frame's display.  */)
+\(0, 0) of the selected frame's display.  */)
   (Lisp_Object x, Lisp_Object y)
   {
   struct frame *f = SELECTED_FRAME ();
@@ -4934,7 +4949,7 @@ DISPLAY is the name of the display to connect to.
 Optional second arg XRM-STRING is a string of resources in xrdb format.
 If the optional third arg MUST-SUCCEED is non-nil,
 terminate Emacs if we can't open the connection.
-(In the Nextstep version, the last two arguments are currently ignored.)  */)
+\(In the Nextstep version, the last two arguments are currently ignored.)  */)
   (Lisp_Object display, Lisp_Object xrm_string, Lisp_Object must_succeed)
 {
   char *xrm_option;
@@ -5581,6 +5596,8 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
                       "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
   x_default_parameter (f, parms, Qcursor_type, Qbox,
                       "cursorType", "CursorType", RES_TYPE_SYMBOL);
+  x_default_parameter (f, parms, Qalpha, Qnil,
+                      "alpha", "Alpha", RES_TYPE_NUMBER);
 
   /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
      Change will not be effected unless different from the current
@@ -5680,6 +5697,7 @@ compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, Lisp_Object
   int win_x, win_y;
   Window root, child;
   unsigned pmask;
+  int min_x, min_y, max_x, max_y = -1;
 
   /* User-specified position?  */
   left = Fcdr (Fassq (Qleft, parms));
@@ -5692,45 +5710,81 @@ compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, Lisp_Object
   if ((!INTEGERP (left) && !INTEGERP (right))
       || (!INTEGERP (top) && !INTEGERP (bottom)))
     {
+      Lisp_Object frame, attributes, monitor, geometry;
+
       block_input ();
       XQueryPointer (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window,
                     &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
       unblock_input ();
+
+      XSETFRAME(frame, f);
+      attributes = Fx_display_monitor_attributes_list (frame);
+
+      /* Try to determine the monitor where the mouse pointer is and
+         its geometry.  See bug#22549.  */
+      while (CONSP (attributes))
+       {
+          monitor = XCAR (attributes);
+          geometry = Fassq (Qgeometry, monitor);
+          if (CONSP (geometry))
+            {
+              min_x = XINT (Fnth (make_number (1), geometry));
+              min_y = XINT (Fnth (make_number (2), geometry));
+              max_x = min_x + XINT (Fnth (make_number (3), geometry));
+              max_y = min_y + XINT (Fnth (make_number (4), geometry));
+              if (min_x <= *root_x && *root_x < max_x
+                  && min_y <= *root_y && *root_y < max_y)
+                {
+                  break;
+                }
+              max_y = -1;
+            }
+
+          attributes = XCDR (attributes);
+       }
+    }
+
+  /* It was not possible to determine the monitor's geometry, so we
+     assign some sane defaults here: */
+  if ( max_y < 0 )
+    {
+      min_x = 0;
+      min_y = 0;
+      max_x = x_display_pixel_width (FRAME_DISPLAY_INFO (f));
+      max_y = x_display_pixel_height (FRAME_DISPLAY_INFO (f));
     }
 
   if (INTEGERP (top))
     *root_y = XINT (top);
   else if (INTEGERP (bottom))
     *root_y = XINT (bottom) - height;
-  else if (*root_y + XINT (dy) <= 0)
-    *root_y = 0; /* Can happen for negative dy */
-  else if (*root_y + XINT (dy) + height
-          <= x_display_pixel_height (FRAME_DISPLAY_INFO (f)))
+  else if (*root_y + XINT (dy) <= min_y)
+    *root_y = min_y; /* Can happen for negative dy */
+  else if (*root_y + XINT (dy) + height <= max_y)
     /* It fits below the pointer */
     *root_y += XINT (dy);
-  else if (height + XINT (dy) <= *root_y)
+  else if (height + XINT (dy) + min_y <= *root_y)
     /* It fits above the pointer.  */
     *root_y -= height + XINT (dy);
   else
     /* Put it on the top.  */
-    *root_y = 0;
+    *root_y = min_y;
 
   if (INTEGERP (left))
     *root_x = XINT (left);
   else if (INTEGERP (right))
-    *root_y = XINT (right) - width;
-  else if (*root_x + XINT (dx) <= 0)
+    *root_x = XINT (right) - width;
+  else if (*root_x + XINT (dx) <= min_x)
     *root_x = 0; /* Can happen for negative dx */
-  else if (*root_x + XINT (dx) + width
-          <= x_display_pixel_width (FRAME_DISPLAY_INFO (f)))
+  else if (*root_x + XINT (dx) + width <= max_x)
     /* It fits to the right of the pointer.  */
     *root_x += XINT (dx);
-  else if (width + XINT (dx) <= *root_x)
+  else if (width + XINT (dx) + min_x <= *root_x)
     /* It fits to the left of the pointer.  */
     *root_x -= width + XINT (dx);
   else
-    /* Put it left-justified on the screen--it ought to fit that way.  */
-    *root_x = 0;
+    /* Put it left justified on the screen -- it ought to fit that way.  */
+    *root_x = min_x;
 }
 
 
@@ -6081,16 +6135,19 @@ Value is t if tooltip was open, nil otherwise.  */)
         items is unmapped.  Redisplay the menu manually...  */
       {
         Widget w;
-       struct frame *f = SELECTED_FRAME ();
-       w = f->output_data.x->menubar_widget;
+        struct frame *f = SELECTED_FRAME ();
+        if (FRAME_X_P (f) && FRAME_LIVE_P (f))
+          {
+          w = f->output_data.x->menubar_widget;
 
-       if (!DoesSaveUnders (FRAME_DISPLAY_INFO (f)->screen)
-           && w != NULL)
-         {
-           block_input ();
-           xlwmenu_redisplay (w);
-           unblock_input ();
-         }
+          if (!DoesSaveUnders (FRAME_DISPLAY_INFO (f)->screen)
+              && w != NULL)
+            {
+              block_input ();
+              xlwmenu_redisplay (w);
+              unblock_input ();
+            }
+        }
       }
 #endif /* USE_LUCID */
     }
@@ -6561,31 +6618,27 @@ present and mapped to the usual X keysyms.  */)
 DEFUN ("x-export-frames", Fx_export_frames, Sx_export_frames, 0, 2, 0,
        doc: /* Return image data of FRAMES in TYPE format.
 FRAMES should be nil (the selected frame), a frame, or a list of
-frames (each of which corresponds to one page).  Optional arg TYPE
-should be either `pdf' (default), `png', `postscript', or `svg'.
-Supported types are determined by the compile-time configuration of
-cairo.  */)
+frames (each of which corresponds to one page).  Each frame should be
+visible.  Optional arg TYPE should be either `pdf' (default), `png',
+`postscript', or `svg'.  Supported types are determined by the
+compile-time configuration of cairo.  */)
      (Lisp_Object frames, Lisp_Object type)
 {
-  Lisp_Object result, rest, tmp;
+  Lisp_Object rest, tmp;
   cairo_surface_type_t surface_type;
 
-  if (NILP (frames))
-    frames = selected_frame;
   if (!CONSP (frames))
     frames = list1 (frames);
 
   tmp = Qnil;
   for (rest = frames; CONSP (rest); rest = XCDR (rest))
     {
-      struct frame *f = XFRAME (XCAR (rest));
-
-      if (! FRAME_LIVE_P (f) || ! FRAME_X_P (f) || ! FRAME_LIVE_P (f))
-        error ("Invalid frame");
-
+      struct frame *f = decode_window_system_frame (XCAR (rest));
       Lisp_Object frame;
 
       XSETFRAME (frame, f);
+      if (!FRAME_VISIBLE_P (f))
+       error ("Frames to be exported must be visible.");
       tmp = Fcons (frame, tmp);
     }
   frames = Fnreverse (tmp);
@@ -6621,9 +6674,7 @@ cairo.  */)
 #endif
     error ("Unsupported export type");
 
-  result = x_cr_export_frames (frames, surface_type);
-
-  return result;
+  return x_cr_export_frames (frames, surface_type);
 }
 
 #ifdef USE_GTK
@@ -6651,8 +6702,12 @@ The return value is an alist containing the following keys:
        on, in points.
 
 The paper width can be obtained as the sum of width, left-margin, and
-right-margin values.  Likewise, the paper height is the sum of height,
-top-margin, and bottom-margin values.  */)
+right-margin values if the page orientation is `portrait' or
+`reverse-portrait'.  Otherwise, it is the sum of width, top-margin,
+and bottom-margin values.  Likewise, the paper height is the sum of
+height, top-margin, and bottom-margin values if the page orientation
+is `portrait' or `reverse-portrait'.  Otherwise, it is the sum of
+height, left-margin, and right-margin values.  */)
      (void)
 {
   Lisp_Object result;
@@ -6672,29 +6727,29 @@ visible.  */)
      (Lisp_Object frames)
 {
   Lisp_Object rest, tmp;
+  int count;
 
-  if (NILP (frames))
-    frames = selected_frame;
   if (!CONSP (frames))
     frames = list1 (frames);
 
   tmp = Qnil;
   for (rest = frames; CONSP (rest); rest = XCDR (rest))
     {
-      struct frame *f = XFRAME (XCAR (rest));
-      if (! FRAME_LIVE_P (f) || ! FRAME_X_P (f) || ! FRAME_LIVE_P (f))
-        error ("Invalid frame");
+      struct frame *f = decode_window_system_frame (XCAR (rest));
       Lisp_Object frame;
 
       XSETFRAME (frame, f);
-      if (!EQ (Fframe_visible_p (frame), Qt))
+      if (!FRAME_VISIBLE_P (f))
        error ("Frames to be printed must be visible.");
       tmp = Fcons (frame, tmp);
     }
   frames = Fnreverse (tmp);
 
   /* Make sure the current matrices are up-to-date.  */
-  Fredisplay (Qt);
+  count = SPECPDL_INDEX ();
+  specbind (Qredisplay_dont_pause, Qt);
+  redisplay_preserve_echo_area (32);
+  unbind_to (count, Qnil);
 
   block_input ();
   xg_print_frames_dialog (frames);