Omit some unnecessary casts.
[bpt/emacs.git] / src / xfns.c
index 315d509..4f728ad 100644 (file)
@@ -59,6 +59,13 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "xsettings.h"
 
+#ifdef HAVE_XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif
+#ifdef HAVE_XINERAMA
+#include <X11/extensions/Xinerama.h>
+#endif
+
 #ifdef USE_GTK
 #include "gtkutil.h"
 #endif
@@ -123,10 +130,6 @@ extern LWLIB_ID widget_id_tick;
 
 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
 
-/* Nonzero if using X.  */
-
-int x_in_use;
-
 static Lisp_Object Qsuppress_icon;
 static Lisp_Object Qundefined_color;
 static Lisp_Object Qcompound_text, Qcancel_timer;
@@ -139,38 +142,6 @@ static int dpyinfo_refcount;
 
 static struct x_display_info *x_display_info_for_name (Lisp_Object);
 
-\f
-/* Error if we are not connected to X.  */
-
-void
-check_x (void)
-{
-  if (! x_in_use)
-    error ("X windows are not in use or not initialized");
-}
-
-/* Nonzero if we can use mouse menus.
-   You should not call this unless HAVE_MENUS is defined.  */
-
-int
-have_menus_p (void)
-{
-  return x_in_use;
-}
-
-/* Extract a frame as a FRAME_PTR, defaulting to the selected frame
-   and checking validity for X.  */
-
-FRAME_PTR
-check_x_frame (Lisp_Object frame)
-{
-  struct frame *f = decode_live_frame (frame);
-
-  if (! FRAME_X_P (f))
-    error ("Non-X frame used");
-  return f;
-}
-
 /* Let the user specify an X display with a Lisp object.
    OBJECT may be nil, a frame or a terminal object.
    nil stands for the selected frame--or, if that is not an X frame,
@@ -197,7 +168,7 @@ check_x_display_info (Lisp_Object object)
       struct terminal *t = get_terminal (object, 1);
 
       if (t->type != output_x_window)
-        error ("Terminal %"pI"d is not an X display", XINT (object));
+        error ("Terminal %d is not an X display", t->id);
 
       dpyinfo = t->display_info.x;
     }
@@ -205,7 +176,7 @@ check_x_display_info (Lisp_Object object)
     dpyinfo = x_display_info_for_name (object);
   else
     {
-      FRAME_PTR f = check_x_frame (object);
+      struct frame *f = decode_window_system_frame (object);
       dpyinfo = FRAME_X_DISPLAY_INFO (f);
     }
 
@@ -398,7 +369,7 @@ x_top_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
    not Emacs's own window.  */
 
 void
-x_real_positions (FRAME_PTR f, int *xptr, int *yptr)
+x_real_positions (struct frame *f, int *xptr, int *yptr)
 {
   int win_x, win_y, outer_x IF_LINT (= 0), outer_y IF_LINT (= 0);
   int real_x = 0, real_y = 0;
@@ -594,7 +565,7 @@ x_defined_color (struct frame *f, const char *color_name,
    Signal an error if color can't be allocated.  */
 
 static int
-x_decode_color (FRAME_PTR f, Lisp_Object color_name, int mono_color)
+x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color)
 {
   XColor cdef;
 
@@ -655,7 +626,7 @@ x_set_tool_bar_position (struct frame *f,
    may be any format that GdkPixbuf knows about, i.e. not just bitmaps.  */
 
 int
-xg_set_icon (FRAME_PTR f, Lisp_Object file)
+xg_set_icon (struct frame *f, Lisp_Object file)
 {
   int result = 0;
   Lisp_Object found;
@@ -689,7 +660,7 @@ xg_set_icon (FRAME_PTR f, Lisp_Object file)
 }
 
 int
-xg_set_icon_from_xpm_data (FRAME_PTR f, const char **data)
+xg_set_icon_from_xpm_data (struct frame *f, const char **data)
 {
   GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (data);
 
@@ -971,7 +942,7 @@ static void
 x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 {
   unsigned long fore_pixel, pixel;
-  int fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
+  bool fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
   struct x_output *x = f->output_data.x;
 
   if (!NILP (Vx_cursor_fore_pixel))
@@ -1079,7 +1050,7 @@ x_set_border_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 
 
 static void
-x_set_cursor_type (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
+x_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 {
   set_frame_cursor_types (f, arg);
 
@@ -1478,7 +1449,7 @@ x_encode_text (Lisp_Object string, Lisp_Object coding_system, int selectionp,
    icon name to NAME.  */
 
 static void
-x_set_name_internal (FRAME_PTR f, Lisp_Object name)
+x_set_name_internal (struct frame *f, Lisp_Object name)
 {
   if (FRAME_X_WINDOW (f))
     {
@@ -1637,7 +1608,7 @@ x_set_name (struct frame *f, Lisp_Object name, int explicit)
    specified a name for the frame; the name will override any set by the
    redisplay code.  */
 static void
-x_explicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
+x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 {
   x_set_name (f, arg, 1);
 }
@@ -1646,7 +1617,7 @@ x_explicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
    name; names set this way will never override names set by the user's
    lisp code.  */
 void
-x_implicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
+x_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 {
   x_set_name (f, arg, 0);
 }
@@ -1744,7 +1715,7 @@ x_default_scroll_bar_color_parameter (struct frame *f,
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
     }
 
-  x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
+  x_set_frame_parameters (f, list1 (Fcons (prop, tem)));
   return tem;
 }
 
@@ -1759,7 +1730,7 @@ x_default_scroll_bar_color_parameter (struct frame *f,
    for example, but Xt doesn't).  */
 
 static void
-hack_wm_protocols (FRAME_PTR f, Widget widget)
+hack_wm_protocols (struct frame *f, Widget widget)
 {
   Display *dpy = XtDisplay (widget);
   Window w = XtWindow (widget);
@@ -2095,7 +2066,7 @@ void
 xic_free_xfontset (struct frame *f)
 {
   Lisp_Object rest, frame;
-  int shared_p = 0;
+  bool shared_p = 0;
 
   if (!FRAME_XIC_FONTSET (f))
     return;
@@ -2117,9 +2088,6 @@ xic_free_xfontset (struct frame *f)
     /* The fontset is not used anymore.  It is safe to free it.  */
     XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
 
-  if (FRAME_XIC_BASE_FONTNAME (f))
-    xfree (FRAME_XIC_BASE_FONTNAME (f));
-  FRAME_XIC_BASE_FONTNAME (f) = NULL;
   FRAME_XIC_FONTSET (f) = NULL;
 }
 
@@ -2345,12 +2313,7 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only)
      for the window manager, so GC relocation won't bother it.
 
      Elsewhere we specify the window name for the window manager.  */
-
-  {
-    char *str = SSDATA (Vx_resource_name);
-    f->namebuf = xmalloc (strlen (str) + 1);
-    strcpy (f->namebuf, str);
-  }
+  f->namebuf = xstrdup (SSDATA (Vx_resource_name));
 
   ac = 0;
   XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
@@ -2368,12 +2331,8 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only)
   /* maybe_set_screen_title_format (shell_widget); */
 
   pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
-                                 (widget_value *) NULL,
-                                 shell_widget, False,
-                                 (lw_callback) NULL,
-                                 (lw_callback) NULL,
-                                 (lw_callback) NULL,
-                                 (lw_callback) NULL);
+                                 NULL, shell_widget, False,
+                                 NULL, NULL, NULL, NULL);
 
   ac = 0;
   XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
@@ -2520,8 +2479,7 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only)
      */
   XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
                   FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
-                  XA_ATOM, 32, PropModeAppend,
-                  (unsigned char*) NULL, 0);
+                  XA_ATOM, 32, PropModeAppend, NULL, 0);
 
   /* Make all the standard events reach the Emacs frame.  */
   attributes.event_mask = STANDARD_EVENT_SET;
@@ -2570,7 +2528,7 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only)
 #else /* not USE_X_TOOLKIT */
 #ifdef USE_GTK
 static void
-x_window (FRAME_PTR f)
+x_window (struct frame *f)
 {
   if (! xg_create_frame_widgets (f))
     error ("Unable to create window");
@@ -2820,10 +2778,6 @@ x_make_gc (struct frame *f)
                  | GCFillStyle | GCLineWidth),
                 &gc_values);
 
-  /* Reliefs.  */
-  f->output_data.x->white_relief.gc = 0;
-  f->output_data.x->black_relief.gc = 0;
-
   /* Create the gray border tile used when the pointer is not in
      the frame.  Since this depends on the frame's pixel values,
      this must be done on a per-frame basis.  */
@@ -2912,11 +2866,16 @@ unwind_create_frame (Lisp_Object frame)
   return Qnil;
 }
 
-static Lisp_Object
+static void
+do_unwind_create_frame (Lisp_Object frame)
+{
+  unwind_create_frame (frame);
+}
+
+static void
 unwind_create_frame_1 (Lisp_Object val)
 {
   inhibit_lisp_code = val;
-  return Qnil;
 }
 
 static void
@@ -2977,7 +2936,7 @@ x_default_font_parameter (struct frame *f, Lisp_Object parms)
     {
       /* Remember the explicit font parameter, so we can re-apply it after
         we've applied the `default' face settings.  */
-      x_set_frame_parameters (f, Fcons (Fcons (Qfont_param, font_param), Qnil));
+      x_set_frame_parameters (f, list1 (Fcons (Qfont_param, font_param)));
     }
 
   /* This call will make X resources override any system font setting.  */
@@ -2992,7 +2951,7 @@ If FRAME is omitted or nil, use the selected frame.
 Signal error if FRAME is not an X frame.  */)
   (Lisp_Object frame)
 {
-  struct frame *f = check_x_frame (frame);
+  struct frame *f = decode_window_system_frame (frame);
 
   block_input ();
   x_wm_set_size_hint (f, 0, 0);
@@ -3119,7 +3078,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
   FRAME_X_DISPLAY_INFO (f) = dpyinfo;
 
   /* With FRAME_X_DISPLAY_INFO set up, this unwind-protect is safe.  */
-  record_unwind_protect (unwind_create_frame, frame);
+  record_unwind_protect (do_unwind_create_frame, frame);
 
   /* These colors will be set anyway later, but it's important
      to get the color reference counts right, so initialize them!  */
@@ -3182,9 +3141,6 @@ This function is an internal primitive--use `make-frame' instead.  */)
       specbind (Qx_resource_name, name);
     }
 
-  f->resx = dpyinfo->resx;
-  f->resy = dpyinfo->resy;
-
 #ifdef HAVE_FREETYPE
 #ifdef HAVE_XFT
   register_font_driver (&xftfont_driver, f);
@@ -3486,7 +3442,7 @@ DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
 FRAME nil means use the selected frame.  */)
   (Lisp_Object frame)
 {
-  struct frame *f = check_x_frame (frame);
+  struct frame *f = decode_window_system_frame (frame);
   Display *dpy = FRAME_X_DISPLAY (f);
 
   block_input ();
@@ -3519,7 +3475,7 @@ DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
   (Lisp_Object color, Lisp_Object frame)
 {
   XColor foo;
-  FRAME_PTR f = check_x_frame (frame);
+  struct frame *f = decode_window_system_frame (frame);
 
   CHECK_STRING (color);
 
@@ -3534,14 +3490,12 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
   (Lisp_Object color, Lisp_Object frame)
 {
   XColor foo;
-  FRAME_PTR f = check_x_frame (frame);
+  struct frame *f = decode_window_system_frame (frame);
 
   CHECK_STRING (color);
 
   if (x_defined_color (f, SSDATA (color), &foo, 0))
-    return list3 (make_number (foo.red),
-                 make_number (foo.green),
-                 make_number (foo.blue));
+    return list3i (foo.red, foo.green, foo.blue);
   else
     return Qnil;
 }
@@ -3602,7 +3556,11 @@ DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
        doc: /* Return the width in pixels of the X display TERMINAL.
 The optional argument TERMINAL specifies which display to ask about.
 TERMINAL should be a terminal object, a frame or a display name (a string).
-If omitted or nil, that stands for the selected frame's display.  */)
+If omitted or nil, that stands for the selected frame's display.
+
+On \"multi-monitor\" setups this refers to the pixel width for all
+physical monitors associated with TERMINAL.  To get information for
+each physical monitor, use `display-monitor-attributes-list'.  */)
   (Lisp_Object terminal)
 {
   struct x_display_info *dpyinfo = check_x_display_info (terminal);
@@ -3615,7 +3573,11 @@ DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
        doc: /* Return the height in pixels of the X display TERMINAL.
 The optional argument TERMINAL specifies which display to ask about.
 TERMINAL should be a terminal object, a frame or a display name (a string).
-If omitted or nil, that stands for the selected frame's display.  */)
+If omitted or nil, that stands for the selected frame's display.
+
+On \"multi-monitor\" setups this refers to the pixel height for all
+physical monitors associated with TERMINAL.  To get information for
+each physical monitor, use `display-monitor-attributes-list'.  */)
   (Lisp_Object terminal)
 {
   struct x_display_info *dpyinfo = check_x_display_info (terminal);
@@ -3703,9 +3665,8 @@ If omitted or nil, that stands for the selected frame's display.  */)
   struct x_display_info *dpyinfo = check_x_display_info (terminal);
   Display *dpy = dpyinfo->display;
 
-  return Fcons (make_number (ProtocolVersion (dpy)),
-               Fcons (make_number (ProtocolRevision (dpy)),
-                      Fcons (make_number (VendorRelease (dpy)), Qnil)));
+  return list3i (ProtocolVersion (dpy), ProtocolRevision (dpy),
+                VendorRelease (dpy));
 }
 
 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
@@ -3724,7 +3685,11 @@ DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1,
        doc: /* Return the height in millimeters of the X display TERMINAL.
 The optional argument TERMINAL specifies which display to ask about.
 TERMINAL should be a terminal object, a frame or a display name (a string).
-If omitted or nil, that stands for the selected frame's display.  */)
+If omitted or nil, that stands for the selected frame's display.
+
+On \"multi-monitor\" setups this refers to the height in millimeters for
+all physical monitors associated with TERMINAL.  To get information
+for each physical monitor, use `display-monitor-attributes-list'.  */)
   (Lisp_Object terminal)
 {
   struct x_display_info *dpyinfo = check_x_display_info (terminal);
@@ -3736,7 +3701,11 @@ DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
        doc: /* Return the width in millimeters of the X display TERMINAL.
 The optional argument TERMINAL specifies which display to ask about.
 TERMINAL should be a terminal object, a frame or a display name (a string).
-If omitted or nil, that stands for the selected frame's display.  */)
+If omitted or nil, that stands for the selected frame's display.
+
+On \"multi-monitor\" setups this refers to the width in millimeters for
+all physical monitors associated with TERMINAL.  To get information
+for each physical monitor, use `display-monitor-attributes-list'.  */)
   (Lisp_Object terminal)
 {
   struct x_display_info *dpyinfo = check_x_display_info (terminal);
@@ -3772,7 +3741,6 @@ If omitted or nil, that stands for the selected frame's display.  */)
 
     default:
       error ("Strange value for BackingStore parameter of screen");
-      result = Qnil;
     }
 
   return result;
@@ -3814,7 +3782,6 @@ If omitted or nil, that stands for the selected frame's display.  */)
       break;
     default:
       error ("Display has an unknown visual class");
-      result = Qnil;
     }
 
   return result;
@@ -3835,17 +3802,510 @@ If omitted or nil, that stands for the selected frame's display.  */)
   else
     return Qnil;
 }
-\f
-int
-x_pixel_width (register struct frame *f)
+
+/* Store the geometry of the workarea on display DPYINFO into *RECT.
+   Return false if and only if the workarea information cannot be
+   obtained via the _NET_WORKAREA root window property.  */
+
+#if ! GTK_CHECK_VERSION (3, 4, 0)
+static bool
+x_get_net_workarea (struct x_display_info *dpyinfo, XRectangle *rect)
 {
-  return FRAME_PIXEL_WIDTH (f);
+  Display *dpy = dpyinfo->display;
+  long offset, max_len;
+  Atom target_type, actual_type;
+  unsigned long actual_size, bytes_remaining;
+  int rc, actual_format;
+  unsigned char *tmp_data = NULL;
+  bool result = false;
+
+  x_catch_errors (dpy);
+  offset = 0;
+  max_len = 1;
+  target_type = XA_CARDINAL;
+  rc = XGetWindowProperty (dpy, dpyinfo->root_window,
+                          dpyinfo->Xatom_net_current_desktop,
+                          offset, max_len, False, target_type,
+                          &actual_type, &actual_format, &actual_size,
+                          &bytes_remaining, &tmp_data);
+  if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy)
+      && actual_format == 32 && actual_size == max_len)
+    {
+      long current_desktop = ((long *) tmp_data)[0];
+
+      XFree (tmp_data);
+      tmp_data = NULL;
+
+      offset = 4 * current_desktop;
+      max_len = 4;
+      rc = XGetWindowProperty (dpy, dpyinfo->root_window,
+                              dpyinfo->Xatom_net_workarea,
+                              offset, max_len, False, target_type,
+                              &actual_type, &actual_format, &actual_size,
+                              &bytes_remaining, &tmp_data);
+      if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy)
+         && actual_format == 32 && actual_size == max_len)
+       {
+         long *values = (long *) tmp_data;
+
+         rect->x = values[0];
+         rect->y = values[1];
+         rect->width = values[2];
+         rect->height = values[3];
+
+         XFree (tmp_data);
+         tmp_data = NULL;
+
+         result = true;
+       }
+    }
+  if (tmp_data)
+    XFree (tmp_data);
+  x_uncatch_errors ();
+
+  return result;
 }
+#endif
 
-int
-x_pixel_height (register struct frame *f)
+#ifndef USE_GTK
+
+/* Return monitor number where F is "most" or closest to.  */
+static int
+x_get_monitor_for_frame (struct frame *f,
+                         struct MonitorInfo *monitors,
+                         int n_monitors)
+{
+  XRectangle frect;
+  int area = 0, dist = -1;
+  int best_area = -1, best_dist = -1;
+  int i;
+
+  if (n_monitors == 1) return 0;
+  frect.x = f->left_pos;
+  frect.y = f->top_pos;
+  frect.width = FRAME_PIXEL_WIDTH (f);
+  frect.height = FRAME_PIXEL_HEIGHT (f);
+
+  for (i = 0; i < n_monitors; ++i)
+    {
+      struct MonitorInfo *mi = &monitors[i];
+      XRectangle res;
+      int a = 0;
+
+      if (mi->geom.width == 0) continue;
+
+      if (x_intersect_rectangles (&mi->geom, &frect, &res))
+        {
+          a = res.width * res.height;
+          if (a > area)
+           {
+             area = a;
+             best_area = i;
+           }
+        }
+
+      if (a == 0 && area == 0)
+        {
+          int dx, dy, d;
+          if (frect.x + frect.width < mi->geom.x)
+            dx = mi->geom.x - frect.x + frect.width;
+          else if (frect.x > mi->geom.x + mi->geom.width)
+            dx = frect.x - mi->geom.x + mi->geom.width;
+          else
+            dx = 0;
+          if (frect.y + frect.height < mi->geom.y)
+            dy = mi->geom.y - frect.y + frect.height;
+          else if (frect.y > mi->geom.y + mi->geom.height)
+            dy = frect.y - mi->geom.y + mi->geom.height;
+          else
+            dy = 0;
+
+          d = dx*dx + dy*dy;
+          if (dist == -1 || dist > d)
+            {
+              dist = d;
+              best_dist = i;
+            }
+        }
+    }
+
+  return best_area != -1 ? best_area : (best_dist != -1 ? best_dist : 0);
+}
+
+static Lisp_Object
+x_make_monitor_attribute_list (struct MonitorInfo *monitors,
+                               int n_monitors,
+                               int primary_monitor,
+                               struct x_display_info *dpyinfo,
+                               const char *source)
 {
-  return FRAME_PIXEL_HEIGHT (f);
+  Lisp_Object monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
+  Lisp_Object frame, rest;
+
+  FOR_EACH_FRAME (rest, frame)
+    {
+      struct frame *f = XFRAME (frame);
+
+      if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo
+         && !EQ (frame, tip_frame))
+       {
+         int i = x_get_monitor_for_frame (f, monitors, n_monitors);
+         ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
+       }
+    }
+
+  return make_monitor_attribute_list (monitors, n_monitors, primary_monitor,
+                                      monitor_frames, source);
+}
+
+static Lisp_Object
+x_get_monitor_attributes_fallback (struct x_display_info *dpyinfo)
+{
+  struct MonitorInfo monitor;
+  XRectangle workarea_r;
+
+  /* Fallback: treat (possibly) multiple physical monitors as if they
+     formed a single monitor as a whole.  This should provide a
+     consistent result at least on single monitor environments.  */
+  monitor.geom.x = monitor.geom.y = 0;
+  monitor.geom.width = x_display_pixel_width (dpyinfo);
+  monitor.geom.height = x_display_pixel_height (dpyinfo);
+  monitor.mm_width = WidthMMOfScreen (dpyinfo->screen);
+  monitor.mm_height = HeightMMOfScreen (dpyinfo->screen);
+  monitor.name = xstrdup ("combined screen");
+
+  if (x_get_net_workarea (dpyinfo, &workarea_r))
+    monitor.work = workarea_r;
+  else
+    monitor.work = monitor.geom;
+  return x_make_monitor_attribute_list (&monitor, 1, 0, dpyinfo, "fallback");
+}
+
+
+#ifdef HAVE_XINERAMA
+static Lisp_Object
+x_get_monitor_attributes_xinerama (struct x_display_info *dpyinfo)
+{
+  int n_monitors, i;
+  Lisp_Object attributes_list = Qnil;
+  Display *dpy = dpyinfo->display;
+  XineramaScreenInfo *info = XineramaQueryScreens (dpy, &n_monitors);
+  struct MonitorInfo *monitors;
+  double mm_width_per_pixel, mm_height_per_pixel;
+
+  if (! info || n_monitors == 0)
+    {
+      if (info)
+       XFree (info);
+      return attributes_list;
+    }
+
+  mm_width_per_pixel = ((double) WidthMMOfScreen (dpyinfo->screen)
+                       / x_display_pixel_width (dpyinfo));
+  mm_height_per_pixel = ((double) HeightMMOfScreen (dpyinfo->screen)
+                        / x_display_pixel_height (dpyinfo));
+  monitors = xzalloc (n_monitors * sizeof *monitors);
+  for (i = 0; i < n_monitors; ++i)
+    {
+      struct MonitorInfo *mi = &monitors[i];
+      XRectangle workarea_r;
+
+      mi->geom.x = info[i].x_org;
+      mi->geom.y = info[i].y_org;
+      mi->geom.width = info[i].width;
+      mi->geom.height = info[i].height;
+      mi->mm_width = mi->geom.width * mm_width_per_pixel + 0.5;
+      mi->mm_height = mi->geom.height * mm_height_per_pixel + 0.5;
+      mi->name = 0;
+
+      /* Xinerama usually have primary monitor first, just use that.  */
+      if (i == 0 && x_get_net_workarea (dpyinfo, &workarea_r))
+       {
+         mi->work = workarea_r;
+         if (! x_intersect_rectangles (&mi->geom, &mi->work, &mi->work))
+           mi->work = mi->geom;
+       }
+      else
+       mi->work = mi->geom;
+    }
+  XFree (info);
+
+  attributes_list = x_make_monitor_attribute_list (monitors,
+                                                   n_monitors,
+                                                   0,
+                                                   dpyinfo,
+                                                   "Xinerama");
+  free_monitors (monitors, n_monitors);
+  return attributes_list;
+}
+#endif /* HAVE_XINERAMA */
+
+
+#ifdef HAVE_XRANDR
+static Lisp_Object
+x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo)
+{
+  Lisp_Object attributes_list = Qnil;
+  XRRScreenResources *resources;
+  Display *dpy = dpyinfo->display;
+  int i, n_monitors, primary = -1;
+  RROutput pxid = None;
+  struct MonitorInfo *monitors;
+
+#ifdef HAVE_XRRGETSCREENRESOURCESCURRENT
+  resources = XRRGetScreenResourcesCurrent (dpy, dpyinfo->root_window);
+#else
+  resources = XRRGetScreenResources (dpy, dpyinfo->root_window);
+#endif
+  if (! resources || resources->noutput == 0)
+    {
+      if (resources)
+       XRRFreeScreenResources (resources);
+      return Qnil;
+    }
+  n_monitors = resources->noutput;
+  monitors = xzalloc (n_monitors * sizeof *monitors);
+
+#ifdef HAVE_XRRGETOUTPUTPRIMARY
+  pxid = XRRGetOutputPrimary (dpy, dpyinfo->root_window);
+#endif
+
+  for (i = 0; i < n_monitors; ++i)
+    {
+      XRROutputInfo *info = XRRGetOutputInfo (dpy, resources,
+                                              resources->outputs[i]);
+      Connection conn = info ? info->connection : RR_Disconnected;
+      RRCrtc id = info ? info->crtc : None;
+
+      if (strcmp (info->name, "default") == 0)
+        {
+          /* Non XRandr 1.2 driver, does not give useful data.  */
+         XRRFreeOutputInfo (info);
+         XRRFreeScreenResources (resources);
+          free_monitors (monitors, n_monitors);
+          return Qnil;
+        }
+
+      if (conn != RR_Disconnected && id != None)
+        {
+          XRRCrtcInfo *crtc = XRRGetCrtcInfo (dpy, resources, id);
+          struct MonitorInfo *mi = &monitors[i];
+          XRectangle workarea_r;
+
+          if (! crtc)
+           {
+             XRRFreeOutputInfo (info);
+             continue;
+           }
+
+          mi->geom.x = crtc->x;
+          mi->geom.y = crtc->y;
+          mi->geom.width = crtc->width;
+          mi->geom.height = crtc->height;
+          mi->mm_width = info->mm_width;
+          mi->mm_height = info->mm_height;
+          mi->name = xstrdup (info->name);
+
+          if (pxid != None && pxid == resources->outputs[i])
+            primary = i;
+          else if (primary == -1 && strcmp (info->name, "LVDS") == 0)
+            primary = i;
+
+          if (i == primary && x_get_net_workarea (dpyinfo, &workarea_r))
+            {
+              mi->work= workarea_r;
+              if (! x_intersect_rectangles (&mi->geom, &mi->work, &mi->work))
+                mi->work = mi->geom;
+            }
+          else
+            mi->work = mi->geom;
+
+          XRRFreeCrtcInfo (crtc);
+        }
+      XRRFreeOutputInfo (info);
+    }
+  XRRFreeScreenResources (resources);
+
+  attributes_list = x_make_monitor_attribute_list (monitors,
+                                                   n_monitors,
+                                                   primary,
+                                                   dpyinfo,
+                                                   "XRandr");
+  free_monitors (monitors, n_monitors);
+  return attributes_list;
+}
+#endif /* HAVE_XRANDR */
+
+static Lisp_Object
+x_get_monitor_attributes (struct x_display_info *dpyinfo)
+{
+  Lisp_Object attributes_list = Qnil;
+  Display *dpy = dpyinfo->display;
+
+#ifdef HAVE_XRANDR
+  int xrr_event_base, xrr_error_base;
+  bool xrr_ok = false;
+  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;
+    }
+
+  if (xrr_ok)
+    attributes_list = x_get_monitor_attributes_xrandr (dpyinfo);
+#endif /* HAVE_XRANDR */
+
+#ifdef HAVE_XINERAMA
+  if (NILP (attributes_list))
+    {
+      int xin_event_base, xin_error_base;
+      bool xin_ok = false;
+      xin_ok = XineramaQueryExtension (dpy, &xin_event_base, &xin_error_base);
+      if (xin_ok && XineramaIsActive (dpy))
+        attributes_list = x_get_monitor_attributes_xinerama (dpyinfo);
+    }
+#endif /* HAVE_XINERAMA */
+
+  if (NILP (attributes_list))
+    attributes_list = x_get_monitor_attributes_fallback (dpyinfo);
+
+  return attributes_list;
+}
+
+#endif /* !USE_GTK */
+
+DEFUN ("x-display-monitor-attributes-list", Fx_display_monitor_attributes_list,
+       Sx_display_monitor_attributes_list,
+       0, 1, 0,
+       doc: /* Return a list of physical monitor attributes on the X display TERMINAL.
+
+The optional argument TERMINAL specifies which display to ask about.
+TERMINAL should be a terminal object, a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.
+
+In addition to the standard attribute keys listed in
+`display-monitor-attributes-list', the following keys are contained in
+the attributes:
+
+ source -- String describing the source from which multi-monitor
+          information is obtained, one of \"Gdk\", \"XRandr\",
+          \"Xinerama\", or \"fallback\"
+
+Internal use only, use `display-monitor-attributes-list' instead.  */)
+  (Lisp_Object terminal)
+{
+  struct x_display_info *dpyinfo = check_x_display_info (terminal);
+  Lisp_Object attributes_list = Qnil;
+
+#ifdef USE_GTK
+  double mm_width_per_pixel, mm_height_per_pixel;
+  GdkDisplay *gdpy;
+  GdkScreen *gscreen;
+  gint primary_monitor = 0, n_monitors, i;
+  Lisp_Object monitor_frames, rest, frame;
+  static const char *source = "Gdk";
+  struct MonitorInfo *monitors;
+
+  block_input ();
+  mm_width_per_pixel = ((double) WidthMMOfScreen (dpyinfo->screen)
+                       / x_display_pixel_width (dpyinfo));
+  mm_height_per_pixel = ((double) HeightMMOfScreen (dpyinfo->screen)
+                        / x_display_pixel_height (dpyinfo));
+  gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
+  gscreen = gdk_display_get_default_screen (gdpy);
+#if GTK_CHECK_VERSION (2, 20, 0)
+  primary_monitor = gdk_screen_get_primary_monitor (gscreen);
+#endif
+  n_monitors = gdk_screen_get_n_monitors (gscreen);
+  monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
+  monitors = xzalloc (n_monitors * sizeof *monitors);
+
+  FOR_EACH_FRAME (rest, frame)
+    {
+      struct frame *f = XFRAME (frame);
+
+      if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo
+         && !EQ (frame, tip_frame))
+       {
+         GdkWindow *gwin = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
+
+         i = gdk_screen_get_monitor_at_window (gscreen, gwin);
+         ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
+       }
+    }
+
+  for (i = 0; i < n_monitors; ++i)
+    {
+      gint width_mm = -1, height_mm = -1;
+      GdkRectangle rec, work;
+      struct MonitorInfo *mi = &monitors[i];
+
+      gdk_screen_get_monitor_geometry (gscreen, i, &rec);
+
+#if GTK_CHECK_VERSION (2, 14, 0)
+      width_mm = gdk_screen_get_monitor_width_mm (gscreen, i);
+      height_mm = gdk_screen_get_monitor_height_mm (gscreen, i);
+#endif
+      if (width_mm < 0)
+       width_mm = rec.width * mm_width_per_pixel + 0.5;
+      if (height_mm < 0)
+       height_mm = rec.height * mm_height_per_pixel + 0.5;
+
+#if GTK_CHECK_VERSION (3, 4, 0)
+      gdk_screen_get_monitor_workarea (gscreen, i, &work);
+#else
+      /* Emulate the behavior of GTK+ 3.4.  */
+      {
+       XRectangle workarea_r;
+
+       if (i == primary_monitor && x_get_net_workarea (dpyinfo, &workarea_r))
+         {
+           work.x = workarea_r.x;
+           work.y = workarea_r.y;
+           work.width = workarea_r.width;
+           work.height = workarea_r.height;
+           if (! gdk_rectangle_intersect (&rec, &work, &work))
+              work = rec;
+          }
+        else
+          work = rec;
+      }
+#endif
+
+
+      mi->geom.x = rec.x;
+      mi->geom.y = rec.y;
+      mi->geom.width = rec.width;
+      mi->geom.height = rec.height;
+      mi->work.x = work.x;
+      mi->work.y = work.y;
+      mi->work.width = work.width;
+      mi->work.height = work.height;
+      mi->mm_width = width_mm;
+      mi->mm_height = height_mm;
+
+#if GTK_CHECK_VERSION (2, 14, 0)
+      mi->name = gdk_screen_get_monitor_plug_name (gscreen, i);
+#endif
+    }
+
+  attributes_list = make_monitor_attribute_list (monitors,
+                                                 n_monitors,
+                                                 primary_monitor,
+                                                 monitor_frames,
+                                                 source);
+  unblock_input ();
+#else  /* not USE_GTK */
+
+  block_input ();
+  attributes_list = x_get_monitor_attributes (dpyinfo);
+  unblock_input ();
+
+#endif /* not USE_GTK */
+
+  return attributes_list;
 }
 
 /************************************************************************
@@ -3998,13 +4458,11 @@ x_display_info_for_name (Lisp_Object name)
 
   validate_x_resource_name ();
 
-  dpyinfo = x_term_init (name, (char *)0,
-                        SSDATA (Vx_resource_name));
+  dpyinfo = x_term_init (name, 0, SSDATA (Vx_resource_name));
 
   if (dpyinfo == 0)
     error ("Cannot connect to X server %s", SDATA (name));
 
-  x_in_use = 1;
   XSETFASTINT (Vwindow_system_version, 11);
 
   return dpyinfo;
@@ -4033,10 +4491,7 @@ terminate Emacs if we can't open the connection.
     error ("Not using X Windows"); /* That doesn't stop us anymore. */
 #endif
 
-  if (! NILP (xrm_string))
-    xrm_option = SSDATA (xrm_string);
-  else
-    xrm_option = (char *) 0;
+  xrm_option = NILP (xrm_string) ? 0 : SSDATA (xrm_string);
 
   validate_x_resource_name ();
 
@@ -4058,8 +4513,6 @@ An insecure way to solve the problem may be to use `xhost'.\n",
        error ("Cannot connect to X server %s", SDATA (display));
     }
 
-  x_in_use = 1;
-
   XSETFASTINT (Vwindow_system_version, 11);
   return Qnil;
 }
@@ -4119,7 +4572,7 @@ If TERMINAL is omitted or nil, that stands for the selected frame's display.  */
 /* Wait for responses to all X commands issued so far for frame F.  */
 
 void
-x_sync (FRAME_PTR f)
+x_sync (struct frame *f)
 {
   block_input ();
   XSync (FRAME_X_DISPLAY (f), False);
@@ -4151,7 +4604,7 @@ FRAME.  Default is to change on the edit X window.  */)
   (Lisp_Object prop, Lisp_Object value, Lisp_Object frame,
    Lisp_Object type, Lisp_Object format, Lisp_Object outer_p)
 {
-  struct frame *f = check_x_frame (frame);
+  struct frame *f = decode_window_system_frame (frame);
   Atom prop_atom;
   Atom target_type = XA_STRING;
   int element_format = 8;
@@ -4229,7 +4682,7 @@ DEFUN ("x-delete-window-property", Fx_delete_window_property,
 FRAME nil or omitted means use the selected frame.  Value is PROP.  */)
   (Lisp_Object prop, Lisp_Object frame)
 {
-  struct frame *f = check_x_frame (frame);
+  struct frame *f = decode_window_system_frame (frame);
   Atom prop_atom;
 
   CHECK_STRING (prop);
@@ -4265,7 +4718,7 @@ no value of TYPE (always string in the MS Windows case).  */)
   (Lisp_Object prop, Lisp_Object frame, Lisp_Object type,
    Lisp_Object source, Lisp_Object delete_p, Lisp_Object vector_ret_p)
 {
-  struct frame *f = check_x_frame (frame);
+  struct frame *f = decode_window_system_frame (frame);
   Atom prop_atom;
   int rc;
   Lisp_Object prop_value = Qnil;
@@ -4330,7 +4783,7 @@ no value of TYPE (always string in the MS Windows case).  */)
              property and those are indeed in 32 bit quantities if format is
              32.  */
 
-          if (32 < BITS_PER_LONG && actual_format == 32)
+          if (BITS_PER_LONG > 32 && actual_format == 32)
             {
               unsigned long i;
               int  *idata = (int *) tmp_data;
@@ -4493,7 +4946,7 @@ Window tip_window;
 static Lisp_Object last_show_tip_args;
 
 
-static Lisp_Object
+static void
 unwind_create_tip_frame (Lisp_Object frame)
 {
   Lisp_Object deleted;
@@ -4504,8 +4957,6 @@ unwind_create_tip_frame (Lisp_Object frame)
       tip_window = None;
       tip_frame = Qnil;
     }
-
-  return deleted;
 }
 
 
@@ -4533,8 +4984,6 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
   Lisp_Object buffer;
   struct buffer *old_buffer;
 
-  check_x ();
-
   if (!dpyinfo->terminal->name)
     error ("Terminal is not live, can't create new frames on it");
 
@@ -4636,9 +5085,6 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
       specbind (Qx_resource_name, name);
     }
 
-  f->resx = dpyinfo->resx;
-  f->resy = dpyinfo->resy;
-
   register_font_driver (&xfont_driver, f);
 #ifdef HAVE_FREETYPE
 #ifdef HAVE_XFT
@@ -4761,7 +5207,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
 
   /* Add `tooltip' frame parameter's default value. */
   if (NILP (Fframe_parameter (frame, Qtooltip)))
-    Fmodify_frame_parameters (frame, Fcons (Fcons (Qtooltip, Qt), Qnil));
+    Fmodify_frame_parameters (frame, list1 (Fcons (Qtooltip, Qt)));
 
   /* FIXME - can this be done in a similar way to normal frames?
      http://lists.gnu.org/archive/html/emacs-devel/2007-10/msg00641.html */
@@ -4779,8 +5225,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
       disptype = intern ("color");
 
     if (NILP (Fframe_parameter (frame, Qdisplay_type)))
-      Fmodify_frame_parameters (frame, Fcons (Fcons (Qdisplay_type, disptype),
-                                              Qnil));
+      Fmodify_frame_parameters (frame, list1 (Fcons (Qdisplay_type, disptype)));
   }
 
   /* Set up faces after all frame parameters are known.  This call
@@ -4799,8 +5244,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
     call2 (Qface_set_after_frame_default, frame, Qnil);
 
     if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
-      Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
-                                             Qnil));
+      Fmodify_frame_parameters (frame, list1 (Fcons (Qbackground_color, bg)));
   }
 
   f->no_split = 1;
@@ -4934,7 +5378,7 @@ Text larger than the specified size is clipped.  */)
   if (SCHARS (string) == 0)
     string = make_unibyte_string (" ", 1);
 
-  f = check_x_frame (frame);
+  f = decode_window_system_frame (frame);
   if (NILP (timeout))
     timeout = make_number (5);
   else
@@ -5032,29 +5476,29 @@ Text larger than the specified size is clipped.  */)
 
   /* Set up the frame's root window.  */
   w = XWINDOW (FRAME_ROOT_WINDOW (f));
-  wset_left_col (w, make_number (0));
-  wset_top_line (w, make_number (0));
+  w->left_col = 0;
+  w->top_line = 0;
 
   if (CONSP (Vx_max_tooltip_size)
       && RANGED_INTEGERP (1, XCAR (Vx_max_tooltip_size), INT_MAX)
       && RANGED_INTEGERP (1, XCDR (Vx_max_tooltip_size), INT_MAX))
     {
-      wset_total_cols (w, XCAR (Vx_max_tooltip_size));
-      wset_total_lines (w, XCDR (Vx_max_tooltip_size));
+      w->total_cols = XFASTINT (XCAR (Vx_max_tooltip_size));
+      w->total_lines = XFASTINT (XCDR (Vx_max_tooltip_size));
     }
   else
     {
-      wset_total_cols (w, make_number (80));
-      wset_total_lines (w, make_number (40));
+      w->total_cols = 80;
+      w->total_lines = 40;
     }
 
-  FRAME_TOTAL_COLS (f) = XINT (w->total_cols);
+  FRAME_TOTAL_COLS (f) = w->total_cols;
   adjust_glyphs (f);
   w->pseudo_window_p = 1;
 
   /* Display the tooltip text in a temporary buffer.  */
   old_buffer = current_buffer;
-  set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
+  set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->contents));
   bset_truncate_lines (current_buffer, Qnil);
   clear_glyph_matrix (w->desired_matrix);
   clear_glyph_matrix (w->current_matrix);
@@ -5070,7 +5514,7 @@ Text larger than the specified size is clipped.  */)
       int row_width;
 
       /* Stop at the first empty row at the end.  */
-      if (!row->enabled_p || !row->displays_text_p)
+      if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
        break;
 
       /* Let the row go over the full width of the frame.  */
@@ -5115,7 +5559,7 @@ Text larger than the specified size is clipped.  */)
       /* w->total_cols and FRAME_TOTAL_COLS want the width in columns,
         not in pixels.  */
       width /= WINDOW_FRAME_COLUMN_WIDTH (w);
-      wset_total_cols (w, make_number (width));
+      w->total_cols = width;
       FRAME_TOTAL_COLS (f) = width;
       adjust_glyphs (f);
       clear_glyph_matrix (w->desired_matrix);
@@ -5129,7 +5573,7 @@ Text larger than the specified size is clipped.  */)
          struct glyph *last;
          int row_width;
 
-         if (!row->enabled_p || !row->displays_text_p)
+         if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
            break;
          row->full_width_p = 1;
          row_width = row->pixel_width;
@@ -5257,7 +5701,7 @@ DEFUN ("x-uses-old-gtk-dialog", Fx_uses_old_gtk_dialog,
 #ifdef USE_GTK
   if (use_dialog_box
       && use_file_dialog
-      && have_menus_p ()
+      && window_system_available (SELECTED_FRAME ())
       && xg_uses_old_file_dialog ())
     return Qt;
 #endif
@@ -5271,8 +5715,8 @@ DEFUN ("x-uses-old-gtk-dialog", Fx_uses_old_gtk_dialog,
 static void
 file_dialog_cb (Widget widget, XtPointer client_data, XtPointer call_data)
 {
-  int *result = (int *) client_data;
-  XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
+  int *result = client_data;
+  XmAnyCallbackStruct *cb = call_data;
   *result = cb->reason;
 }
 
@@ -5285,15 +5729,14 @@ file_dialog_cb (Widget widget, XtPointer client_data, XtPointer call_data)
 static void
 file_dialog_unmap_cb (Widget widget, XtPointer client_data, XtPointer call_data)
 {
-  int *result = (int *) client_data;
+  int *result = client_data;
   *result = XmCR_CANCEL;
 }
 
-static Lisp_Object
-clean_up_file_dialog (Lisp_Object arg)
+static void
+clean_up_file_dialog (void *arg)
 {
-  struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
-  Widget dialog = (Widget) p->pointer;
+  Widget dialog = arg;
 
   /* Clean up.  */
   block_input ();
@@ -5301,8 +5744,6 @@ clean_up_file_dialog (Lisp_Object arg)
   XtDestroyWidget (dialog);
   x_menu_set_in_use (0);
   unblock_input ();
-
-  return Qnil;
 }
 
 
@@ -5315,7 +5756,8 @@ or directory must exist.
 This function is only defined on NS, MS Windows, and X Windows with the
 Motif or Gtk toolkits.  With the Motif toolkit, ONLY-DIR-P is ignored.
 Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.  */)
-  (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p)
+  (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename,
+   Lisp_Object mustmatch, Lisp_Object only_dir_p)
 {
   int result;
   struct frame *f = SELECTED_FRAME ();
@@ -5328,7 +5770,7 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.  */)
   ptrdiff_t count = SPECPDL_INDEX ();
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
 
-  check_x ();
+  check_window_system (f);
 
   GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
 
@@ -5417,7 +5859,7 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.  */)
       XmStringFree (default_xmstring);
     }
 
-  record_unwind_protect (clean_up_file_dialog, make_save_value (dialog, 0));
+  record_unwind_protect_ptr (clean_up_file_dialog, dialog);
 
   /* Process events until the user presses Cancel or OK.  */
   x_menu_set_in_use (1);
@@ -5471,12 +5913,10 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.  */)
 
 #ifdef USE_GTK
 
-static Lisp_Object
-clean_up_dialog (Lisp_Object arg)
+static void
+clean_up_dialog (void)
 {
   x_menu_set_in_use (0);
-
-  return Qnil;
 }
 
 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
@@ -5490,7 +5930,7 @@ Motif or Gtk toolkits.  With the Motif toolkit, ONLY-DIR-P is ignored.
 Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.  */)
   (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p)
 {
-  FRAME_PTR f = SELECTED_FRAME ();
+  struct frame *f = SELECTED_FRAME ();
   char *fn;
   Lisp_Object file = Qnil;
   Lisp_Object decoded_file;
@@ -5498,7 +5938,7 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.  */)
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
   char *cdef_file;
 
-  check_x ();
+  check_window_system (f);
 
   GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
 
@@ -5510,7 +5950,7 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.  */)
 
   /* Prevent redisplay.  */
   specbind (Qinhibit_redisplay, Qt);
-  record_unwind_protect (clean_up_dialog, Qnil);
+  record_unwind_protect_void (clean_up_dialog);
 
   block_input ();
 
@@ -5553,21 +5993,19 @@ FRAME is the frame on which to pop up the font chooser.  If omitted or
 nil, it defaults to the selected frame. */)
   (Lisp_Object frame, Lisp_Object ignored)
 {
-  FRAME_PTR f = check_x_frame (frame);
+  struct frame *f = decode_window_system_frame (frame);
   Lisp_Object font;
   Lisp_Object font_param;
   char *default_name = NULL;
   struct gcpro gcpro1, gcpro2;
   ptrdiff_t count = SPECPDL_INDEX ();
 
-  check_x ();
-
   if (popup_activated ())
     error ("Trying to use a menu from within a menu-entry");
 
   /* Prevent redisplay.  */
   specbind (Qinhibit_redisplay, Qt);
-  record_unwind_protect (clean_up_dialog, Qnil);
+  record_unwind_protect_void (clean_up_dialog);
 
   block_input ();
 
@@ -5603,7 +6041,7 @@ nil, it defaults to the selected frame. */)
                               Keyboard
  ***********************************************************************/
 
-#ifdef HAVE_XKBGETKEYBOARD
+#ifdef HAVE_XKB
 #include <X11/XKBlib.h>
 #include <X11/keysym.h>
 #endif
@@ -5617,9 +6055,11 @@ usual X keysyms.  Value is `lambda' if we cannot determine if both keys are
 present and mapped to the usual X keysyms.  */)
   (Lisp_Object frame)
 {
-#ifdef HAVE_XKBGETKEYBOARD
+#ifndef HAVE_XKB
+  return Qlambda;
+#else
   XkbDescPtr kb;
-  struct frame *f = check_x_frame (frame);
+  struct frame *f = decode_window_system_frame (frame);
   Display *dpy = FRAME_X_DISPLAY (f);
   Lisp_Object have_keys;
   int major, minor, op, event, error_code;
@@ -5695,9 +6135,7 @@ present and mapped to the usual X keysyms.  */)
     }
   unblock_input ();
   return have_keys;
-#else /* not HAVE_XKBGETKEYBOARD */
-  return Qlambda;
-#endif /* not HAVE_XKBGETKEYBOARD */
+#endif
 }
 
 
@@ -5749,9 +6187,6 @@ frame_parm_handler x_frame_parm_handlers[] =
 void
 syms_of_xfns (void)
 {
-  /* This is zero if not using X windows.  */
-  x_in_use = 0;
-
   /* The section below is built by the lisp expression at the top of the file,
      just above where these variables are declared.  */
   /*&&& init symbols here &&&*/
@@ -5922,6 +6357,7 @@ When using Gtk+ tooltips, the tooltip face is not used.  */);
   defsubr (&Sx_display_visual_class);
   defsubr (&Sx_display_backing_store);
   defsubr (&Sx_display_save_under);
+  defsubr (&Sx_display_monitor_attributes_list);
   defsubr (&Sx_wm_set_size_hint);
   defsubr (&Sx_create_frame);
   defsubr (&Sx_open_connection);
@@ -5931,9 +6367,6 @@ When using Gtk+ tooltips, the tooltip face is not used.  */);
   defsubr (&Sx_focus_frame);
   defsubr (&Sx_backspace_delete_keys_p);
 
-  /* Setting callback functions for fontset handler.  */
-  check_window_system_func = check_x;
-
   defsubr (&Sx_show_tip);
   defsubr (&Sx_hide_tip);
   tip_timer = Qnil;