From c29a51df2de7eb800edf8e2235ee6c34bd1c9562 Mon Sep 17 00:00:00 2001 From: Martin Rudalics Date: Tue, 18 Aug 2015 16:45:27 +0200 Subject: [PATCH] Rewrite and add frame geometry related functions. * 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 | 45 +++++-- src/nsfns.m | 186 +++++++++++++++++---------- src/w32fns.c | 348 +++++++++++++++++++++++++++++++-------------------- src/xfns.c | 325 +++++++++++++++++++++++++++++++++-------------- 4 files changed, 594 insertions(+), 310 deletions(-) diff --git a/src/frame.c b/src/frame.c index 9e695982d2b..20440489381 100644 --- a/src/frame.c +++ b/src/frame.c @@ -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); diff --git a/src/nsfns.m b/src/nsfns.m index 0fc867c1ebb..e9453604592 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -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); diff --git a/src/w32fns.c b/src/w32fns.c index 2cb99c90057..8f0bde70875 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -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"); diff --git a/src/xfns.c b/src/xfns.c index 8137ceacb88..18fb343efd6 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -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); -- 2.39.2