]> git.eshelyaron.com Git - emacs.git/commitdiff
Rewrite and add frame geometry related functions.
authorMartin Rudalics <rudalics@gmx.at>
Tue, 18 Aug 2015 14:45:27 +0000 (16:45 +0200)
committerMartin Rudalics <rudalics@gmx.at>
Tue, 18 Aug 2015 14:45:27 +0000 (16:45 +0200)
* src/frame.c (Fframe_position): New function.
(Fset_frame_position): Rename parameters and rewrite doc-string.
(syms_of_frame): Remove Qframe_position, Qframe_outer_size,
Qtitle_height and Qframe_inner_size.  Add Qouter_edges,
Qouter_position, Qouter_size, Qnative_edges, Qinner_edges,
Qtitle_bar_size.
* src/nsfns.m (frame_geometry): New function.
(Fx_frame_geometry): Call frame_geometry.
(Fx_frame_edges): New function.
* src/w32fns.c (C_CHILDREN_TITLEBAR, TITLEBAR_INFO)
(GetTitleBarInfo_Proc): Define these so we can use the
GetTitleBarInfo API.
(Fw32_frame_menu_bar_size, Fw32_frame_rect): Remove.
(Fx_frame_geometry): Rewrite.
(Fx_frame_edges, Fx_mouse_absolute_pixel_position)
(Fx_set_mouse_absolute_pixel_position): New functions.
* src/xfns.c (frame_geometry): New function.
(Fx_frame_geometry): Call frame_geometry.
(Fx_frame_edges, Fx_mouse_absolute_pixel_position)
(Fx_set_mouse_absolute_pixel_position): New functions.

src/frame.c
src/nsfns.m
src/w32fns.c
src/xfns.c

index 9e695982d2b641c2dd71430a726a6ff2464a1ce1..204404893810aab1763b4ea8685bfe262c574e06 100644 (file)
@@ -2977,24 +2977,40 @@ font height.  */)
   return Qnil;
 }
 
+DEFUN ("frame-position", Fframe_position,
+       Sframe_position, 0, 1, 0,
+       doc: /* Return top left corner of FRAME in pixels.
+FRAME must be a live frame and defaults to the selected one.  The return
+value is a cons (x, y) of the coordinates of the top left corner of
+FRAME's outer frame, in pixels relative to an origin (0, 0) of FRAME's
+display.  */)
+     (Lisp_Object frame)
+{
+  register struct frame *f = decode_live_frame (frame);
+
+  return Fcons (make_number (f->left_pos), make_number (f->top_pos));
+}
+
 DEFUN ("set-frame-position", Fset_frame_position,
        Sset_frame_position, 3, 3, 0,
-       doc: /* Sets position of FRAME in pixels to XOFFSET by YOFFSET.
-If FRAME is nil, the selected frame is used.  XOFFSET and YOFFSET are
-actually the position of the upper left corner of the frame.  Negative
-values for XOFFSET or YOFFSET are interpreted relative to the rightmost
-or bottommost possible position (that stays within the screen).  */)
-  (Lisp_Object frame, Lisp_Object xoffset, Lisp_Object yoffset)
+       doc: /* Set position of FRAME to (X, Y).
+FRAME must be a live frame and defaults to the selected one.  X and Y,
+if positive, specify the coordinate of the left and top edge of FRAME's
+outer frame in pixels relative to an origin (0, 0) of FRAME's display.
+If any of X or Y is negative, it specifies the coordinates of the right
+or bottom edge of the outer frame of FRAME relative to the right or
+bottom edge of FRAME's display.  */)
+  (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
 {
   register struct frame *f = decode_live_frame (frame);
 
-  CHECK_TYPE_RANGED_INTEGER (int, xoffset);
-  CHECK_TYPE_RANGED_INTEGER (int, yoffset);
+  CHECK_TYPE_RANGED_INTEGER (int, x);
+  CHECK_TYPE_RANGED_INTEGER (int, y);
 
   /* I think this should be done with a hook.  */
 #ifdef HAVE_WINDOW_SYSTEM
   if (FRAME_WINDOW_P (f))
-    x_set_offset (f, XINT (xoffset), XINT (yoffset), 1);
+    x_set_offset (f, XINT (x), XINT (y), 1);
 #endif
 
   return Qt;
@@ -4890,15 +4906,17 @@ syms_of_frame (void)
   DEFSYM (Qframes, "frames");
   DEFSYM (Qsource, "source");
 
-  DEFSYM (Qframe_position, "frame-position");
-  DEFSYM (Qframe_outer_size, "frame-outer-size");
+  DEFSYM (Qouter_edges, "outer-edges");
+  DEFSYM (Qouter_position, "outer-position");
+  DEFSYM (Qouter_size, "outer-size");
+  DEFSYM (Qnative_edges, "native-edges");
+  DEFSYM (Qinner_edges, "inner-edges");
   DEFSYM (Qexternal_border_size, "external-border-size");
-  DEFSYM (Qtitle_height, "title-height");
+  DEFSYM (Qtitle_bar_size, "title-bar-size");
   DEFSYM (Qmenu_bar_external, "menu-bar-external");
   DEFSYM (Qmenu_bar_size, "menu-bar-size");
   DEFSYM (Qtool_bar_external, "tool-bar-external");
   DEFSYM (Qtool_bar_size, "tool-bar-size");
-  DEFSYM (Qframe_inner_size, "frame-inner-size");
   /* The following are used for frame_size_history.  */
   DEFSYM (Qadjust_frame_size_1, "adjust-frame-size-1");
   DEFSYM (Qadjust_frame_size_2, "adjust-frame-size-2");
@@ -5263,6 +5281,7 @@ in a more readable form.  */);
   defsubr (&Sset_frame_height);
   defsubr (&Sset_frame_width);
   defsubr (&Sset_frame_size);
+  defsubr (&Sframe_position);
   defsubr (&Sset_frame_position);
   defsubr (&Sframe_pointer_visible_p);
 
index 0fc867c1ebb2156353ada5ee5c5a7e68737a40cc..e94536045929c5ca3379531d44635b55c740d003 100644 (file)
@@ -2836,91 +2836,142 @@ Value is t if tooltip was open, nil otherwise.  */)
   return Qt;
 }
 
-DEFUN ("x-frame-geometry", Fx_frame_geometry, Sx_frame_geometry, 0, 1, 0,
-       doc: /* Return geometric attributes of frame FRAME.
+/* Return geometric attributes of FRAME.  According to the value of
+   ATTRIBUTES return the outer edges of FRAME (Qouter_edges), the inner
+   edges of FRAME, the root window edges of frame (Qroot_edges).  Any
+   other value means to return the geometry as returned by
+   Fx_frame_geometry.  */
+static Lisp_Object
+frame_geometry (Lisp_Object frame, Lisp_Object attribute)
+{
+  struct frame *f = decode_live_frame (frame);
+  Lisp_Object fullscreen_symbol = Fframe_parameter (frame, Qfullscreen);
+  bool fullscreen = (EQ (fullscreen_symbol, Qfullboth)
+                    || EQ (fullscreen_symbol, Qfullscreen));
+  int border = fullscreen ? 0 : f->border_width;
+  int title_height = fullscreen ? 0 : FRAME_NS_TITLEBAR_HEIGHT (f);
+  int native_width = FRAME_PIXEL_WIDTH (f);
+  int native_height = FRAME_PIXEL_HEIGHT (f);
+  int outer_width = native_width + 2 * border;
+  int outer_height = native_height + 2 * border + title_height;
+  int native_left = f->left_pos + border;
+  int native_top = f->top_pos + border + title_height;
+  int native_right = f->left_pos + outer_width - border;
+  int native_bottom = f->top_pos + outer_height - border;
+  int internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
+  int tool_bar_height = FRAME_TOOLBAR_HEIGHT (f);
+  int tool_bar_width = (tool_bar_height
+                       ? outer_width - 2 * internal_border_width
+                       : 0);
+
+  /* Construct list.  */
+  if (EQ (attribute, Qouter_edges))
+    return list4 (make_number (f->left_pos), make_number (f->top_pos),
+                 make_number (f->left_pos + outer_width),
+                 make_number (f->top_pos + outer_height));
+  else if (EQ (attribute, Qnative_edges))
+    return list4 (make_number (native_left), make_number (native_top),
+                 make_number (native_right), make_number (native_bottom));
+  else if (EQ (attribute, Qinner_edges))
+    return list4 (make_number (native_left + internal_border_width),
+                 make_number (native_top
+                              + tool_bar_height
+                              + internal_border_width),
+                 make_number (native_right - internal_border_width),
+                 make_number (native_bottom - internal_border_width));
+  else
+    return
+      listn (CONSTYPE_HEAP, 10,
+            Fcons (Qouter_position,
+                   Fcons (make_number (f->left_pos),
+                          make_number (f->top_pos))),
+            Fcons (Qouter_size,
+                   Fcons (make_number (outer_width),
+                          make_number (outer_height))),
+            Fcons (Qexternal_border_size,
+                   (fullscreen
+                    ? Fcons (make_number (0), make_number (0))
+                    : Fcons (make_number (border), make_number (border)))),
+            Fcons (Qtitle_bar_size,
+                   Fcons (make_number (0), make_number (title_height))),
+            Fcons (Qmenu_bar_external, Qnil),
+            Fcons (Qmenu_bar_size, Fcons (make_number (0), make_number (0))),
+            Fcons (Qtool_bar_external,
+                   FRAME_EXTERNAL_TOOL_BAR (f) ? Qt : Qnil),
+            Fcons (Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)),
+            Fcons (Qtool_bar_size,
+                   Fcons (make_number (tool_bar_width),
+                          make_number (tool_bar_height))),
+            Fcons (Qinternal_border_width,
+                   make_number (internal_border_width)));
+}
 
-FRAME must be a live frame and defaults to the selected one.
+DEFUN ("x-frame-geometry", Fx_frame_geometry, Sx_frame_geometry, 0, 1, 0,
+       doc: /* Return geometric attributes of FRAME.
+FRAME must be a live frame and defaults to the selected one.  The return
+value is an association list of the attributes listed below.  All height
+and width values are in pixels.
 
-The return value is an association list containing the following
-elements (all size values are in pixels).
+`outer-position' is a cons of the outer left and top edges of FRAME
+  relative to the origin - the position (0, 0) - of FRAME's display.
 
-- `frame-outer-size' is a cons of the outer width and height of FRAME.
-  The outer size include the title bar and the external borders as well
-  as any menu and/or tool bar of frame.
+`outer-size' is a cons of the outer width and height of FRAME.  The
+  outer size includes the title bar and the external borders as well as
+  any menu and/or tool bar of frame.
 
-- `border' is a cons of the horizontal and vertical width of FRAME's
-  external borders.
+`external-border-size' is a cons of the horizontal and vertical width of
+  FRAME's external borders as supplied by the window manager.
 
-- `title-bar-height' is the height of the title bar of FRAME.
+`title-bar-size' is a cons of the width and height of the title bar of
+  FRAME as supplied by the window manager.  If both of them are zero,
+  FRAME has no title bar.  If only the width is zero, Emacs was not
+  able to retrieve the width information.
 
-- `menu-bar-external' if t means the menu bar is external (not
+`menu-bar-external', if non-nil, means the menu bar is external (never
   included in the inner edges of FRAME).
 
-`menu-bar-size' is a cons of the width and height of the menu bar of
+`menu-bar-size' is a cons of the width and height of the menu bar of
   FRAME.
 
-- `tool-bar-external' if t means the tool bar is external (not
+`tool-bar-external', if non-nil, means the tool bar is external (never
   included in the inner edges of FRAME).
 
-- `tool-bar-side' tells tells on which side the tool bar on FRAME is and
-  can be one of `left', `top', `right' or `bottom'.
+`tool-bar-position' tells on which side the tool bar on FRAME is and can
+  be one of `left', `top', `right' or `bottom'.  If this is nil, FRAME
+  has no tool bar.
 
-`tool-bar-size' is a cons of the width and height of the tool bar of
+`tool-bar-size' is a cons of the width and height of the tool bar of
   FRAME.
 
-- `frame-inner-size' is a cons of the inner width and height of FRAME.
-  This excludes FRAME's title bar and external border as well as any
-  external menu and/or tool bar.  */)
+`internal-border-width' is the width of the internal border of
+  FRAME.  */)
   (Lisp_Object frame)
 {
-  struct frame *f = decode_live_frame (frame);
-  int inner_width = FRAME_PIXEL_WIDTH (f);
-  int inner_height = FRAME_PIXEL_HEIGHT (f);
-  Lisp_Object fullscreen = Fframe_parameter (frame, Qfullscreen);
-  int border, title, outer_width, outer_height;
-  int tool_bar_height, tool_bar_width;
-  // Always 0 on NS.
-  int menu_bar_height = 0;
-  int menu_bar_width = 0;
-
-  if (FRAME_INITIAL_P (f) || !FRAME_NS_P (f))
-    return Qnil;
+  return frame_geometry (frame, Qnil);
+}
+
+DEFUN ("x-frame-edges", Fx_frame_edges, Sx_frame_edges, 0, 2, 0,
+       doc: /* Return edge coordinates of FRAME.
+FRAME must be a live frame and defaults to the selected one.  The return
+value is a list of the form (LEFT, TOP, RIGHT, BOTTOM).  All values are
+in pixels relative to the origin - the position (0, 0) - of FRAME's
+display.
 
-  border = f->border_width;
-  title = FRAME_NS_TITLEBAR_HEIGHT (f);
-  outer_width = FRAME_PIXEL_WIDTH (f) + 2 * border;
-  outer_height = FRAME_PIXEL_HEIGHT (f) + 2 * border;
-  tool_bar_height = FRAME_TOOLBAR_HEIGHT (f);
-  tool_bar_width = tool_bar_height > 0
-    ? outer_width - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)
-    : 0;
-
-  return
-    listn (CONSTYPE_HEAP, 10,
-          Fcons (Qframe_position,
-                 Fcons (make_number (f->left_pos), make_number (f->top_pos))),
-          Fcons (Qframe_outer_size,
-                 Fcons (make_number (outer_width), make_number (outer_height))),
-          Fcons (Qexternal_border_size,
-                 ((EQ (fullscreen, Qfullboth) || EQ (fullscreen, Qfullscreen))
-                  ? Fcons (make_number (0), make_number (0))
-                  : Fcons (make_number (border), make_number (border)))),
-           Fcons (Qtitle_height,
-                 ((EQ (fullscreen, Qfullboth) || EQ (fullscreen, Qfullscreen))
-                  ? make_number (0)
-                  : make_number (title))),
-          Fcons (Qmenu_bar_external, FRAME_EXTERNAL_MENU_BAR (f) ? Qt : Qnil),
-          Fcons (Qmenu_bar_size,
-                 Fcons (make_number (menu_bar_width),
-                        make_number (menu_bar_height))),
-          Fcons (Qtool_bar_external, FRAME_EXTERNAL_TOOL_BAR (f) ? Qt : Qnil),
-          Fcons (Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)),
-          Fcons (Qtool_bar_size,
-                 Fcons (make_number (tool_bar_width),
-                        make_number (tool_bar_height))),
-          Fcons (Qframe_inner_size,
-                 Fcons (make_number (inner_width),
-                        make_number (inner_height))));
+If optional argument TYPE is the symbol `outer-edges', return the outer
+edges of FRAME.  The outer edges comprise the decorations of the window
+manager (like the title bar or external borders) as well as any external
+menu or tool bar of FRAME.  If optional argument TYPE is the symbol
+`native-edges' or nil, return the native edges of FRAME.  The native
+edges exclude the decorations of the window manager and any external
+menu or tool bar of FRAME.  If TYPE is the symbol `inner-edges', return
+the inner edges of FRAME.  These edges exclude title bar, any borders,
+menu bar or tool bar of FRAME.  */)
+  (Lisp_Object frame, Lisp_Object type)
+{
+  return frame_geometry (frame, ((EQ (type, Qouter_edges)
+                                 || EQ (type, Qinner_edges))
+                                ? type
+                                : Qnative_edges));
 }
 
 /* ==========================================================================
@@ -3106,6 +3157,7 @@ be used as the image of the icon representing the frame.  */);
   defsubr (&Sx_display_pixel_height);
   defsubr (&Sns_display_monitor_attributes_list);
   defsubr (&Sx_frame_geometry);
+  defsubr (&Sx_frame_edges);
   defsubr (&Sx_display_mm_width);
   defsubr (&Sx_display_mm_height);
   defsubr (&Sx_display_screens);
index 2cb99c9005786e7a021e62be4a6e6964ea2cb68b..8f0bde7087567bc2501d9d58d212630a4cc6734e 100644 (file)
@@ -138,6 +138,14 @@ struct MONITOR_INFO
     DWORD   dwFlags;
 };
 
+#define C_CHILDREN_TITLEBAR 5
+struct TITLEBAR_INFO
+{
+  DWORD cbSize;
+  RECT  rcTitleBar;
+  DWORD rgstate[C_CHILDREN_TITLEBAR+1];
+};
+
 #ifndef CCHDEVICENAME
 #define CCHDEVICENAME 32
 #endif
@@ -172,6 +180,8 @@ typedef BOOL CALLBACK (* MonitorEnum_Proc)
   (IN HMONITOR monitor, IN HDC hdc, IN RECT *rcMonitor, IN LPARAM dwData);
 typedef BOOL (WINAPI * EnumDisplayMonitors_Proc)
   (IN HDC hdc, IN RECT *rcClip, IN MonitorEnum_Proc fnEnum, IN LPARAM dwData);
+typedef BOOL (WINAPI * GetTitleBarInfo_Proc)
+  (IN HWND hwnd, OUT struct TITLEBAR_INFO* info);
 
 TrackMouseEvent_Proc track_mouse_event_fn = NULL;
 ImmGetCompositionString_Proc get_composition_string_fn = NULL;
@@ -182,6 +192,7 @@ MonitorFromPoint_Proc monitor_from_point_fn = NULL;
 GetMonitorInfo_Proc get_monitor_info_fn = NULL;
 MonitorFromWindow_Proc monitor_from_window_fn = NULL;
 EnumDisplayMonitors_Proc enum_display_monitors_fn = NULL;
+GetTitleBarInfo_Proc get_title_bar_info_fn = NULL;
 
 #ifdef NTGUI_UNICODE
 #define unicode_append_menu AppendMenuW
@@ -7986,183 +7997,247 @@ This is a direct interface to the Windows API FindWindow function.  */)
   return Qt;
 }
 
-DEFUN ("w32-frame-menu-bar-size", Fw32_frame_menu_bar_size, Sw32_frame_menu_bar_size, 0, 1, 0,
-       doc: /* Return sizes of menu bar on frame FRAME.
-The return value is a list of four elements: The current width and
-height of FRAME's menu bar in pixels, the height of one menu bar line in
-a wrapped menu bar in pixels, and the height of a single line menu bar
-in pixels.
-
-If FRAME is omitted or nil, the selected frame is used.  */)
-  (Lisp_Object frame)
-{
-  struct frame *f = decode_any_frame (frame);
-  MENUBARINFO menu_bar;
-  int width, height, single_height, wrapped_height;
-
-  if (FRAME_INITIAL_P (f) || !FRAME_W32_P (f))
-    return Qnil;
-
-  block_input ();
-
-  single_height = GetSystemMetrics (SM_CYMENU);
-  wrapped_height = GetSystemMetrics (SM_CYMENUSIZE);
-  menu_bar.cbSize = sizeof (menu_bar);
-  menu_bar.rcBar.right = menu_bar.rcBar.left = 0;
-  menu_bar.rcBar.top = menu_bar.rcBar.bottom = 0;
-  GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &menu_bar);
-  width = menu_bar.rcBar.right - menu_bar.rcBar.left;
-  height = menu_bar.rcBar.bottom - menu_bar.rcBar.top;
-
-  unblock_input ();
-
-  return list4 (make_number (width), make_number (height),
-               make_number (wrapped_height), make_number (single_height));
-}
-
-DEFUN ("w32-frame-rect", Fw32_frame_rect, Sw32_frame_rect, 0, 2, 0,
-       doc: /* Return boundary rectangle of FRAME in screen coordinates.
-FRAME must be a live frame and defaults to the selected one.
-
-The boundary rectangle is a list of four elements, specifying the left,
-top, right and bottom screen coordinates of FRAME including menu and
-title bar and decorations.  Optional argument CLIENT non-nil means to
-return the boundaries of the client rectangle which excludes menu and
-title bar and decorations.  */)
-  (Lisp_Object frame, Lisp_Object client)
-{
-  struct frame *f = decode_live_frame (frame);
-  RECT rect;
-
-  if (FRAME_INITIAL_P (f) || !FRAME_W32_P (f))
-    return Qnil;
-
-  block_input ();
-
-  if (!NILP (client))
-    GetClientRect (FRAME_W32_WINDOW (f), &rect);
-  else
-    GetWindowRect (FRAME_W32_WINDOW (f), &rect);
-
-  unblock_input ();
-
-  return list4 (make_number (rect.left), make_number (rect.top),
-               make_number (rect.right), make_number (rect.bottom));
-}
-
 DEFUN ("x-frame-geometry", Fx_frame_geometry, Sx_frame_geometry, 0, 1, 0,
-       doc: /* Return geometric attributes of frame FRAME.
-FRAME must be a live frame and defaults to the selected one.
+       doc: /* Return geometric attributes of FRAME.
+FRAME must be a live frame and defaults to the selected one.  The return
+value is an association list of the attributes listed below.  All height
+and width values are in pixels.
 
-The return value is an association list containing the following
-elements (all size values are in pixels).
+`outer-position' is a cons of the outer left and top edges of FRAME
+  relative to the origin - the position (0, 0) - of FRAME's display.
 
-- `frame-outer-size' is a cons of the outer width and height of FRAME.
-  The outer size includes the title bar and the external borders as well
-  as any menu and/or tool bar of frame.
+`outer-size' is a cons of the outer width and height of FRAME.  The
+  outer size includes the title bar and the external borders as well as
+  any menu and/or tool bar of frame.
 
-- `border' is a cons of the horizontal and vertical width of FRAME's
-  external borders.
+`external-border-size' is a cons of the horizontal and vertical width of
+  FRAME's external borders as supplied by the window manager.
 
-- `title-bar-height' is the height of the title bar of FRAME.
+`title-bar-size' is a cons of the width and height of the title bar of
+  FRAME as supplied by the window manager.  If both of them are zero,
+  FRAME has no title bar.  If only the width is zero, Emacs was not
+  able to retrieve the width information.
 
-- `menu-bar-external' if t means the menu bar is by default external
-  (not included in the inner size of FRAME).
+`menu-bar-external', if non-nil, means the menu bar is external (never
+  included in the inner edges of FRAME).
 
-`menu-bar-size' is a cons of the width and height of the menu bar of
+`menu-bar-size' is a cons of the width and height of the menu bar of
   FRAME.
 
-- `tool-bar-external' if t means the tool bar is by default external
-  (not included in the inner size of FRAME).
+`tool-bar-external', if non-nil, means the tool bar is external (never
+  included in the inner edges of FRAME).
 
-- `tool-bar-side' tells tells on which side the tool bar on FRAME is by
-  default and can be one of `left', `top', `right' or `bottom'.
+`tool-bar-position' tells on which side the tool bar on FRAME is and can
+  be one of `left', `top', `right' or `bottom'.  If this is nil, FRAME
+  has no tool bar.
 
-`tool-bar-size' is a cons of the width and height of the tool bar of
+`tool-bar-size' is a cons of the width and height of the tool bar of
   FRAME.
 
-- `frame-inner-size' is a cons of the inner width and height of FRAME.
-  This excludes FRAME's title bar and external border as well as any
-  external menu and/or tool bar.  */)
+`internal-border-width' is the width of the internal border of
+  FRAME.  */)
   (Lisp_Object frame)
 {
   struct frame *f = decode_live_frame (frame);
-  Lisp_Object geometry = Qnil;
-  RECT frame_outer_edges, frame_inner_edges;
+
   MENUBARINFO menu_bar;
-  int  border_width, border_height, title_height;
-  int single_bar_height, wrapped_bar_height, menu_bar_height;
-  Lisp_Object fullscreen = Fframe_parameter (frame, Qfullscreen);
+  WINDOWINFO window;
+  int left, top, right, bottom;
+  unsigned int external_border_width, external_border_height;
+  int title_bar_width = 0, title_bar_height = 0;
+  int single_menu_bar_height, wrapped_menu_bar_height, menu_bar_height;
+  int tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
+  int internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
+  bool fullboth = EQ (get_frame_param (f, Qfullscreen), Qfullboth);
 
   if (FRAME_INITIAL_P (f) || !FRAME_W32_P (f))
     return Qnil;
 
   block_input ();
-
-  /* Outer frame rectangle, including outer borders and title bar. */
-  GetWindowRect (FRAME_W32_WINDOW (f), &frame_outer_edges);
-  /* Inner frame rectangle, excluding borders and title bar.  */
-  GetClientRect (FRAME_W32_WINDOW (f), &frame_inner_edges);
-  /* Outer border.  */
-  border_width = GetSystemMetrics (SM_CXFRAME);
-  border_height = GetSystemMetrics (SM_CYFRAME);
+  /* Outer rectangle and borders.  */
+  window.cbSize = sizeof (window);
+  GetWindowInfo (FRAME_W32_WINDOW (f), &window);
+  external_border_width = window.cxWindowBorders;
+  external_border_height = window.cyWindowBorders;
   /* Title bar.  */
-  title_height = GetSystemMetrics (SM_CYCAPTION);
+  if ((window.dwStyle & WS_CAPTION) == WS_CAPTION)
+    {
+      if (get_title_bar_info_fn)
+       {
+         struct TITLEBAR_INFO title_bar;
+
+         title_bar.cbSize = sizeof (title_bar);
+         title_bar.rcTitleBar.left = title_bar.rcTitleBar.right = 0;
+         title_bar.rcTitleBar.top = title_bar.rcTitleBar.bottom = 0;
+         get_title_bar_info_fn (FRAME_W32_WINDOW (f), &title_bar);
+          title_bar_width
+           = title_bar.rcTitleBar.right - title_bar.rcTitleBar.left;
+         title_bar_height
+           = title_bar.rcTitleBar.bottom - title_bar.rcTitleBar.top;
+       }
+      else
+       title_bar_height = GetSystemMetrics (SM_CYCAPTION);
+    }
   /* Menu bar.  */
   menu_bar.cbSize = sizeof (menu_bar);
   menu_bar.rcBar.right = menu_bar.rcBar.left = 0;
   menu_bar.rcBar.top = menu_bar.rcBar.bottom = 0;
   GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &menu_bar);
-  single_bar_height = GetSystemMetrics (SM_CYMENU);
-  wrapped_bar_height = GetSystemMetrics (SM_CYMENUSIZE);
+  single_menu_bar_height = GetSystemMetrics (SM_CYMENU);
+  wrapped_menu_bar_height = GetSystemMetrics (SM_CYMENUSIZE);
   unblock_input ();
 
+  left = window.rcWindow.left;
+  top = window.rcWindow.top;
+  right = window.rcWindow.right;
+  bottom = window.rcWindow.bottom;
+
+  /* Menu bar.  */
   menu_bar_height = menu_bar.rcBar.bottom - menu_bar.rcBar.top;
   /* Fix menu bar height reported by GetMenuBarInfo.  */
-  if (menu_bar_height > single_bar_height)
+  if (menu_bar_height > single_menu_bar_height)
     /* A wrapped menu bar.  */
-    menu_bar_height += single_bar_height - wrapped_bar_height;
+    menu_bar_height += single_menu_bar_height - wrapped_menu_bar_height;
   else if (menu_bar_height > 0)
     /* A single line menu bar.  */
-    menu_bar_height = single_bar_height;
-
-  return
-    listn (CONSTYPE_HEAP, 10,
-          Fcons (Qframe_position,
-                 Fcons (make_number (frame_outer_edges.left),
-                        make_number (frame_outer_edges.top))),
-          Fcons (Qframe_outer_size,
-                 Fcons (make_number
-                        (frame_outer_edges.right - frame_outer_edges.left),
-                        make_number
-                        (frame_outer_edges.bottom - frame_outer_edges.top))),
+    menu_bar_height = single_menu_bar_height;
+
+  return listn (CONSTYPE_HEAP, 10,
+               Fcons (Qouter_position,
+                      Fcons (make_number (left), make_number (top))),
+               Fcons (Qouter_size,
+                      Fcons (make_number (right - left),
+                             make_number (bottom - top))),
           Fcons (Qexternal_border_size,
-                 ((EQ (fullscreen, Qfullboth) || EQ (fullscreen, Qfullscreen))
-                  ? Fcons (make_number (0), make_number (0))
-                  : Fcons (make_number (border_width),
-                           make_number (border_height)))),
-          Fcons (Qtitle_height,
-                 ((EQ (fullscreen, Qfullboth) || EQ (fullscreen, Qfullscreen))
-                  ? make_number (0)
-                  : make_number (title_height))),
+                      Fcons (make_number (external_border_width),
+                             make_number (external_border_height))),
+               Fcons (Qtitle_bar_size,
+                      Fcons (make_number (title_bar_width),
+                             make_number (title_bar_height))),
           Fcons (Qmenu_bar_external, Qt),
           Fcons (Qmenu_bar_size,
                  Fcons (make_number
                         (menu_bar.rcBar.right - menu_bar.rcBar.left),
                         make_number (menu_bar_height))),
           Fcons (Qtool_bar_external, Qnil),
-          Fcons (Qtool_bar_position, Qtop),
+               Fcons (Qtool_bar_position, tool_bar_height ? Qtop : Qnil),
           Fcons (Qtool_bar_size,
-                 Fcons (make_number (FRAME_TOOL_BAR_LINES (f)
-                                     ? (FRAME_PIXEL_WIDTH (f)
-                                        - 2 * FRAME_INTERNAL_BORDER_WIDTH (f))
+                      Fcons (make_number
+                             (tool_bar_height
+                              ? right - left - 2 * internal_border_width
                                      : 0),
-                        make_number (FRAME_TOOL_BAR_HEIGHT (f)))),
-          Fcons (Qframe_inner_size,
-                 Fcons (make_number
-                        (frame_inner_edges.right - frame_inner_edges.left),
-                        make_number
-                        (frame_inner_edges.bottom - frame_inner_edges.top))));
+                             make_number (tool_bar_height))),
+               Fcons (Qinternal_border_width,
+                      make_number (internal_border_width)));
+}
+
+DEFUN ("x-frame-edges", Fx_frame_edges, Sx_frame_edges, 0, 2, 0,
+       doc: /* Return edge coordinates of FRAME.
+FRAME must be a live frame and defaults to the selected one.  The return
+value is a list of the form (LEFT, TOP, RIGHT, BOTTOM).  All values are
+in pixels relative to the origin - the position (0, 0) - of FRAME's
+display.
+
+If optional argument TYPE is the symbol `outer-edges', return the outer
+edges of FRAME.  The outer edges comprise the decorations of the window
+manager (like the title bar or external borders) as well as any external
+menu or tool bar of FRAME.  If optional argument TYPE is the symbol
+`native-edges' or nil, return the native edges of FRAME.  The native
+edges exclude the decorations of the window manager and any external
+menu or tool bar of FRAME.  If TYPE is the symbol `inner-edges', return
+the inner edges of FRAME.  These edges exclude title bar, any borders,
+menu bar or tool bar of FRAME.  */)
+  (Lisp_Object frame, Lisp_Object type)
+{
+  struct frame *f = decode_live_frame (frame);
+
+  if (FRAME_INITIAL_P (f) || !FRAME_W32_P (f))
+    return Qnil;
+
+  if (EQ (type, Qouter_edges))
+    {
+      RECT rectangle;
+
+      block_input ();
+      /* Outer frame rectangle, including outer borders and title bar. */
+      GetWindowRect (FRAME_W32_WINDOW (f), &rectangle);
+      unblock_input ();
+
+      return list4 (make_number (rectangle.left),
+                   make_number (rectangle.top),
+                   make_number (rectangle.right),
+                   make_number (rectangle.bottom));
+    }
+  else
+    {
+      RECT rectangle;
+      POINT pt;
+      int left, top, right, bottom;
+
+      block_input ();
+      /* Inner frame rectangle, excluding borders and title bar.  */
+      GetClientRect (FRAME_W32_WINDOW (f), &rectangle);
+      /* Get top-left corner of native rectangle in screen
+        coordinates.  */
+      pt.x = 0;
+      pt.y = 0;
+      ClientToScreen (FRAME_W32_WINDOW (f), &pt);
+      unblock_input ();
+
+      left = pt.x;
+      top = pt.y;
+      right = left + rectangle.right;
+      bottom = top + rectangle.bottom;
+
+      if (EQ (type, Qinner_edges))
+       {
+         int internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
+
+         return list4 (make_number (left + internal_border_width),
+                       make_number (top
+                                    + FRAME_TOOL_BAR_HEIGHT (f)
+                                    + internal_border_width),
+                       make_number (right - internal_border_width),
+                       make_number (bottom - internal_border_width));
+       }
+      else
+       return list4 (make_number (left), make_number (top),
+                     make_number (right), make_number (bottom));
+    }
+}
+
+DEFUN ("x-mouse-absolute-pixel-position", Fx_mouse_absolute_pixel_position,
+       Sx_mouse_absolute_pixel_position, 0, 0, 0,
+       doc: /* Return absolute position of mouse cursor in pixels.
+The position is returned as a cons cell (X . Y) of the coordinates of
+the mouse cursor position in pixels relative to a position (0, 0) of the
+selected frame's display.  */)
+  (void)
+{
+  POINT pt;
+
+  block_input ();
+  GetCursorPos (&pt);
+  unblock_input ();
+
+  return Fcons (make_number (pt.x), make_number (pt.y));
+}
+
+DEFUN ("x-set-mouse-absolute-pixel-position", Fx_set_mouse_absolute_pixel_position,
+       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.  */)
+  (Lisp_Object x, Lisp_Object y)
+{
+  CHECK_TYPE_RANGED_INTEGER (int, x);
+  CHECK_TYPE_RANGED_INTEGER (int, y);
+
+  block_input ();
+  SetCursorPos (XINT (x), XINT (y));
+  unblock_input ();
+
+  return Qnil;
 }
 
 DEFUN ("w32-battery-status", Fw32_battery_status, Sw32_battery_status, 0, 0, 0,
@@ -9189,6 +9264,9 @@ This variable has effect only on NT family of systems, not on Windows 9X.  */);
   defsubr (&Sx_close_connection);
   defsubr (&Sx_display_list);
   defsubr (&Sx_frame_geometry);
+  defsubr (&Sx_frame_edges);
+  defsubr (&Sx_mouse_absolute_pixel_position);
+  defsubr (&Sx_set_mouse_absolute_pixel_position);
   defsubr (&Sx_synchronize);
 
   /* W32 specific functions */
@@ -9204,8 +9282,6 @@ This variable has effect only on NT family of systems, not on Windows 9X.  */);
   defsubr (&Sw32_reconstruct_hot_key);
   defsubr (&Sw32_toggle_lock_key);
   defsubr (&Sw32_window_exists_p);
-  defsubr (&Sw32_frame_rect);
-  defsubr (&Sw32_frame_menu_bar_size);
   defsubr (&Sw32_battery_status);
   defsubr (&Sw32__menu_bar_in_use);
 
@@ -9470,6 +9546,8 @@ globals_of_w32fns (void)
     GetProcAddress (user32_lib, "MonitorFromWindow");
   enum_display_monitors_fn = (EnumDisplayMonitors_Proc)
     GetProcAddress (user32_lib, "EnumDisplayMonitors");
+  get_title_bar_info_fn = (GetTitleBarInfo_Proc)
+    GetProcAddress (user32_lib, "GetTitleBarInfo");
 
   {
     HMODULE imm32_lib = GetModuleHandle ("imm32.dll");
index 8137ceacb88973b267727b05a93ab9c06265cc2a..18fb343efd6e0bb8db81492fdcaafb2cc4c384e9 100644 (file)
@@ -4312,130 +4312,262 @@ Internal use only, use `display-monitor-attributes-list' instead.  */)
   return attributes_list;
 }
 
-DEFUN ("x-frame-geometry", Fx_frame_geometry, Sx_frame_geometry, 0, 1, 0,
-       doc: /* Return geometric attributes of frame FRAME.
+/* Return geometric attributes of FRAME.  According to the value of
+   ATTRIBUTES return the outer edges of FRAME (Qouter_edges), the native
+   edges of FRAME (Qnative_edges), or the inner edges of frame
+   (Qinner_edges).  Any other value means to return the geometry as
+   returned by Fx_frame_geometry.  */
+static Lisp_Object
+frame_geometry (Lisp_Object frame, Lisp_Object attribute)
+{
+  struct frame *f = decode_live_frame (frame);
+  /**   XWindowAttributes atts; **/
+  Window rootw;
+  unsigned int ign, native_width, native_height;
+  int xy_ign, xptr, yptr;
+  int left_off, right_off, top_off, bottom_off;
+  int outer_left, outer_top, outer_right, outer_bottom;
+  int native_left, native_top, native_right, native_bottom;
+  int inner_left, inner_top, inner_right, inner_bottom;
+  int internal_border_width;
+  bool menu_bar_external = false, tool_bar_external = false;
+  int menu_bar_height = 0, menu_bar_width = 0;
+  int tool_bar_height = 0, tool_bar_width = 0;
+
+  if (FRAME_INITIAL_P (f) || !FRAME_X_P (f))
+    return Qnil;
+
+  block_input ();
+  XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
+               &rootw, &xy_ign, &xy_ign, &native_width, &native_height,
+               &ign, &ign);
+  /**   XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &atts); **/
+  x_real_pos_and_offsets (f, &left_off, &right_off, &top_off, &bottom_off,
+                          NULL, NULL, &xptr, &yptr, NULL);
+  unblock_input ();
+
+  /**   native_width = atts.width; **/
+  /**   native_height = atts.height; **/
+
+  outer_left = xptr;
+  outer_top = yptr;
+  outer_right = outer_left + left_off + native_width + right_off;
+  outer_bottom = outer_top + top_off + native_height + bottom_off;
+
+  native_left = outer_left + left_off;
+  native_top = outer_top + top_off;
+  native_right = native_left + native_width;
+  native_bottom = native_top + native_height;
+
+  internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
+  inner_left = native_left + internal_border_width;
+  inner_top = native_top + internal_border_width;
+  inner_right = native_right - internal_border_width;
+  inner_bottom = native_bottom - internal_border_width;
+
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
+  menu_bar_external = true;
+  menu_bar_height = FRAME_MENUBAR_HEIGHT (f);
+  native_top += menu_bar_height;
+  inner_top += menu_bar_height;
+#else
+  menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
+  inner_top += menu_bar_height;
+#endif
+  menu_bar_width = menu_bar_height ? native_width : 0;
+
+#if defined (USE_GTK)
+  tool_bar_external = true;
+  if (EQ (FRAME_TOOL_BAR_POSITION (f), Qleft))
+    {
+      tool_bar_width = FRAME_TOOLBAR_WIDTH (f);
+      native_left += tool_bar_width;
+      inner_left += tool_bar_width;
+      tool_bar_height
+       = tool_bar_width ? native_height - menu_bar_height : 0;
+    }
+  else if (EQ (FRAME_TOOL_BAR_POSITION (f), Qtop))
+    {
+      tool_bar_height = FRAME_TOOLBAR_HEIGHT (f);
+      native_top += tool_bar_height;
+      inner_top += tool_bar_height;
+      tool_bar_width = tool_bar_height ? native_width : 0;
+    }
+  else if (EQ (FRAME_TOOL_BAR_POSITION (f), Qright))
+    {
+      tool_bar_width = FRAME_TOOLBAR_WIDTH (f);
+      native_right -= tool_bar_width;
+      inner_right -= tool_bar_width;
+      tool_bar_height
+       = tool_bar_width ? native_height - menu_bar_height : 0;
+    }
+  else
+    {
+      tool_bar_height = FRAME_TOOLBAR_HEIGHT (f);
+      native_bottom -= tool_bar_height;
+      inner_bottom -= tool_bar_height;
+      tool_bar_width = tool_bar_height ? native_width : 0;
+    }
+#else
+  tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
+  tool_bar_width = tool_bar_height ? native_width : 0;
+  inner_top += tool_bar_height;
+#endif
+
+  /* Construct list.  */
+  if (EQ (attribute, Qouter_edges))
+    return list4 (make_number (outer_left), make_number (outer_top),
+                 make_number (outer_right), make_number (outer_bottom));
+  else if (EQ (attribute, Qnative_edges))
+    return list4 (make_number (native_left), make_number (native_top),
+                 make_number (native_right), make_number (native_bottom));
+  else if (EQ (attribute, Qinner_edges))
+    return list4 (make_number (inner_left), make_number (inner_top),
+                 make_number (inner_right), make_number (inner_bottom));
+  else
+    return
+      listn (CONSTYPE_HEAP, 10,
+            Fcons (Qouter_position,
+                   Fcons (make_number (outer_left),
+                          make_number (outer_top))),
+            Fcons (Qouter_size,
+                   Fcons (make_number (outer_right - outer_left),
+                          make_number (outer_bottom - outer_top))),
+            /* Approximate.  */
+            Fcons (Qexternal_border_size,
+                   Fcons (make_number (right_off),
+                          make_number (bottom_off))),
+            /* Approximate.  */
+            Fcons (Qtitle_bar_size,
+                   Fcons (make_number (0),
+                          make_number (top_off - bottom_off))),
+            Fcons (Qmenu_bar_external, menu_bar_external ? Qt : Qnil),
+            Fcons (Qmenu_bar_size,
+                   Fcons (make_number (menu_bar_width),
+                          make_number (menu_bar_height))),
+            Fcons (Qtool_bar_external, tool_bar_external ? Qt : Qnil),
+            Fcons (Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)),
+            Fcons (Qtool_bar_size,
+                   Fcons (make_number (tool_bar_width),
+                          make_number (tool_bar_height))),
+            Fcons (Qinternal_border_width,
+                   make_number (internal_border_width)));
+}
 
-FRAME must be a live frame and defaults to the selected one.
+DEFUN ("x-frame-geometry", Fx_frame_geometry, Sx_frame_geometry, 0, 1, 0,
+       doc: /* Return geometric attributes of FRAME.
+FRAME must be a live frame and defaults to the selected one.  The return
+value is an association list of the attributes listed below.  All height
+and width values are in pixels.
 
-The return value is an association list containing the following
-elements (all size values are in pixels).
+`outer-position' is a cons of the outer left and top edges of FRAME
+  relative to the origin - the position (0, 0) - of FRAME's display.
 
-- `frame-outer-size' is a cons of the outer width and height of FRAME.
-  The outer size include the title bar and the external borders as well
-  as any menu and/or tool bar of frame.
+`outer-size' is a cons of the outer width and height of FRAME.  The
+  outer size includes the title bar and the external borders as well as
+  any menu and/or tool bar of frame.
 
-- `border' is a cons of the horizontal and vertical width of FRAME's
-  external borders.
+`external-border-size' is a cons of the horizontal and vertical width of
+  FRAME's external borders as supplied by the window manager.
 
-- `title-bar-height' is the height of the title bar of FRAME.
+`title-bar-size' is a cons of the width and height of the title bar of
+  FRAME as supplied by the window manager.  If both of them are zero,
+  FRAME has no title bar.  If only the width is zero, Emacs was not
+  able to retrieve the width information.
 
-- `menu-bar-external' if t means the menu bar is external (not
+`menu-bar-external', if non-nil, means the menu bar is external (never
   included in the inner edges of FRAME).
 
-`menu-bar-size' is a cons of the width and height of the menu bar of
+`menu-bar-size' is a cons of the width and height of the menu bar of
   FRAME.
 
-- `tool-bar-external' if t means the tool bar is external (not
+`tool-bar-external', if non-nil, means the tool bar is external (never
   included in the inner edges of FRAME).
 
-- `tool-bar-side' tells tells on which side the tool bar on FRAME is and
-  can be one of `left', `top', `right' or `bottom'.
+`tool-bar-position' tells on which side the tool bar on FRAME is and can
+  be one of `left', `top', `right' or `bottom'.  If this is nil, FRAME
+  has no tool bar.
 
-`tool-bar-size' is a cons of the width and height of the tool bar of
+`tool-bar-size' is a cons of the width and height of the tool bar of
   FRAME.
 
-- `frame-inner-size' is a cons of the inner width and height of FRAME.
-  This excludes FRAME's title bar and external border as well as any
-  external menu and/or tool bar.  */)
+`internal-border-width' is the width of the internal border of
+  FRAME.  */)
   (Lisp_Object frame)
 {
-  struct frame *f = decode_live_frame (frame);
-  int inner_width = FRAME_PIXEL_WIDTH (f);
-  int inner_height = FRAME_PIXEL_HEIGHT (f);
-  int outer_width, outer_height, border, title;
-  Lisp_Object fullscreen = Fframe_parameter (frame, Qfullscreen);
-  int menu_bar_height, menu_bar_width, tool_bar_height, tool_bar_width;
+  return frame_geometry (frame, Qnil);
+}
+
+DEFUN ("x-frame-edges", Fx_frame_edges, Sx_frame_edges, 0, 2, 0,
+       doc: /* Return edge coordinates of FRAME.
+FRAME must be a live frame and defaults to the selected one.  The return
+value is a list of the form (LEFT, TOP, RIGHT, BOTTOM).  All values are
+in pixels relative to the origin - the position (0, 0) - of FRAME's
+display.
+
+If optional argument TYPE is the symbol `outer-edges', return the outer
+edges of FRAME.  The outer edges comprise the decorations of the window
+manager (like the title bar or external borders) as well as any external
+menu or tool bar of FRAME.  If optional argument TYPE is the symbol
+`native-edges' or nil, return the native edges of FRAME.  The native
+edges exclude the decorations of the window manager and any external
+menu or tool bar of FRAME.  If TYPE is the symbol `inner-edges', return
+the inner edges of FRAME.  These edges exclude title bar, any borders,
+menu bar or tool bar of FRAME.  */)
+  (Lisp_Object frame, Lisp_Object type)
+{
+  return frame_geometry (frame, ((EQ (type, Qouter_edges)
+                                 || EQ (type, Qinner_edges))
+                                ? type
+                                : Qnative_edges));
+}
 
-  int left_off, right_off, top_off, bottom_off, outer_border;
-  XWindowAttributes atts;
+DEFUN ("x-mouse-absolute-pixel-position", Fx_mouse_absolute_pixel_position,
+       Sx_mouse_absolute_pixel_position, 0, 0, 0,
+       doc: /* Return absolute position of mouse cursor in pixels.
+The position is returned as a cons cell (X . Y) of the coordinates of
+the mouse cursor position in pixels relative to a position (0, 0) of the
+selected frame's display.  */)
+  (void)
+{
+  struct frame *f = SELECTED_FRAME ();
+  Window root, dummy_window;
+  int x, y, dummy;
 
   if (FRAME_INITIAL_P (f) || !FRAME_X_P (f))
     return Qnil;
 
   block_input ();
-
-  XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &atts);
-
-  x_real_pos_and_offsets (f, &left_off, &right_off, &top_off, &bottom_off,
-                          NULL, NULL, NULL, NULL, &outer_border);
-
-
+  XQueryPointer (FRAME_X_DISPLAY (f),
+                 DefaultRootWindow (FRAME_X_DISPLAY (f)),
+                 &root, &dummy_window, &x, &y, &dummy, &dummy,
+                 (unsigned int *) &dummy);
   unblock_input ();
 
-  border = atts.border_width;
-  title = top_off;
-
-  outer_width = atts.width + 2 * border + right_off + left_off
-    + 2 * outer_border;
-  outer_height = atts.height + 2 * border + top_off + bottom_off
-    + 2 * outer_border;
+  return Fcons (make_number (x), make_number (y));
+}
 
-#if defined (USE_GTK)
+DEFUN ("x-set-mouse-absolute-pixel-position", Fx_set_mouse_absolute_pixel_position,
+       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.  */)
+  (Lisp_Object x, Lisp_Object y)
   {
-    bool tool_bar_left_right = (EQ (FRAME_TOOL_BAR_POSITION (f), Qleft)
-                               || EQ (FRAME_TOOL_BAR_POSITION (f), Qright));
-
-    tool_bar_width = (tool_bar_left_right
-                     ? FRAME_TOOLBAR_WIDTH (f)
-                     : FRAME_PIXEL_WIDTH (f));
-    tool_bar_height = (tool_bar_left_right
-                      ? FRAME_PIXEL_HEIGHT (f)
-                      : FRAME_TOOLBAR_HEIGHT (f));
-  }
-#else
-  tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
-  tool_bar_width = tool_bar_height > 0 ? FRAME_PIXEL_WIDTH (f) : 0;
-#endif
+  struct frame *f = SELECTED_FRAME ();
 
-#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
-  menu_bar_height = FRAME_MENUBAR_HEIGHT (f);
-#else
-  menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
-#endif
+  if (FRAME_INITIAL_P (f) || !FRAME_X_P (f))
+    return Qnil;
+
+  CHECK_TYPE_RANGED_INTEGER (int, x);
+  CHECK_TYPE_RANGED_INTEGER (int, y);
 
-  menu_bar_width = menu_bar_height > 0 ? FRAME_PIXEL_WIDTH (f) : 0;
-
-  if (!FRAME_EXTERNAL_MENU_BAR (f))
-    inner_height -= menu_bar_height;
-  if (!FRAME_EXTERNAL_TOOL_BAR (f))
-    inner_height -= tool_bar_height;
-
-  return
-    listn (CONSTYPE_HEAP, 10,
-          Fcons (Qframe_position,
-                 Fcons (make_number (f->left_pos), make_number (f->top_pos))),
-          Fcons (Qframe_outer_size,
-                 Fcons (make_number (outer_width), make_number (outer_height))),
-          Fcons (Qexternal_border_size,
-                 ((EQ (fullscreen, Qfullboth) || EQ (fullscreen, Qfullscreen))
-                  ? Fcons (make_number (0), make_number (0))
-                  : Fcons (make_number (border), make_number (border)))),
-          Fcons (Qtitle_height,
-                 ((EQ (fullscreen, Qfullboth) || EQ (fullscreen, Qfullscreen))
-                  ? make_number (0)
-                  : make_number (title))),
-          Fcons (Qmenu_bar_external, FRAME_EXTERNAL_MENU_BAR (f) ? Qt : Qnil),
-          Fcons (Qmenu_bar_size,
-                 Fcons (make_number (menu_bar_width),
-                        make_number (menu_bar_height))),
-          Fcons (Qtool_bar_external, FRAME_EXTERNAL_TOOL_BAR (f) ? Qt : Qnil),
-          Fcons (Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)),
-          Fcons (Qtool_bar_size,
-                 Fcons (make_number (tool_bar_width),
-                        make_number (tool_bar_height))),
-          Fcons (Qframe_inner_size,
-                 Fcons (make_number (inner_width),
-                        make_number (inner_height))));
+  block_input ();
+  XWarpPointer (FRAME_X_DISPLAY (f), None, DefaultRootWindow (FRAME_X_DISPLAY (f)),
+               0, 0, 0, 0, XINT (x), XINT (y));
+  unblock_input ();
+
+  return Qnil;
 }
 
 /************************************************************************
@@ -6639,6 +6771,9 @@ When using Gtk+ tooltips, the tooltip face is not used.  */);
   defsubr (&Sx_display_save_under);
   defsubr (&Sx_display_monitor_attributes_list);
   defsubr (&Sx_frame_geometry);
+  defsubr (&Sx_frame_edges);
+  defsubr (&Sx_mouse_absolute_pixel_position);
+  defsubr (&Sx_set_mouse_absolute_pixel_position);
   defsubr (&Sx_wm_set_size_hint);
   defsubr (&Sx_create_frame);
   defsubr (&Sx_open_connection);