#define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
-#ifdef GLYPH_DEBUG
static ptrdiff_t image_cache_refcount;
+#ifdef GLYPH_DEBUG
static int dpyinfo_refcount;
#endif
{
GdkPixbuf *pixbuf;
GError *err = NULL;
- char *filename = SSDATA (found);
+ char *filename = SSDATA (ENCODE_FILE (found));
block_input ();
pixbuf = gdk_pixbuf_new_from_file (filename, &err);
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
#endif
+ /* If the frame's image cache refcount is still the same as our
+ private shadow variable, it means we are unwinding a frame
+ for which we didn't yet call init_frame_faces, where the
+ refcount is incremented. Therefore, we increment it here, so
+ that free_frame_faces, called in x_free_frame_resources
+ below, will not mistakenly decrement the counter that was not
+ incremented yet to account for this new frame. */
+ if (FRAME_IMAGE_CACHE (f) != NULL
+ && FRAME_IMAGE_CACHE (f)->refcount == image_cache_refcount)
+ FRAME_IMAGE_CACHE (f)->refcount++;
+
x_free_frame_resources (f);
free_glyphs (f);
register_font_driver (&xfont_driver, f);
#endif /* not USE_CAIRO */
+ image_cache_refcount =
+ FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
+#ifdef GLYPH_DEBUG
+ dpyinfo_refcount = dpyinfo->reference_count;
+#endif /* GLYPH_DEBUG */
+
x_default_parameter (f, parms, Qfont_backend, Qnil,
"fontBackend", "FontBackend", RES_TYPE_STRING);
"scrollBarBackground",
"ScrollBarBackground", false);
-#ifdef GLYPH_DEBUG
- image_cache_refcount =
- FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
- dpyinfo_refcount = dpyinfo->reference_count;
-#endif /* GLYPH_DEBUG */
-
/* Init faces before x_default_parameter is called for the
scroll-bar-width parameter because otherwise we end up in
init_iterator with a null face cache, which should not happen. */
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;
-FRAME must be a live frame and defaults to the selected one.
+ native_left = outer_left + left_off;
+ native_top = outer_top + top_off;
+ native_right = native_left + native_width;
+ native_bottom = native_top + native_height;
-The return value is an association list containing the following
-elements (all size values are in pixels).
+ 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)));
+}
+
+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.
-- `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-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.
-- `border' is a cons of the horizontal and vertical width of FRAME's
- external borders.
+`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.
-- `title-bar-height' is the height of the title bar of FRAME.
+`external-border-size' is a cons of the horizontal and vertical width of
+ FRAME's external borders as supplied by the window manager.
-- `menu-bar-external' if t means the menu bar is external (not
+`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 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;
-
- int left_off, right_off, top_off, bottom_off, outer_border;
- XWindowAttributes atts;
-
- block_input ();
+ return frame_geometry (frame, Qnil);
+}
- XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &atts);
+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));
+}
- x_real_pos_and_offsets (f, &left_off, &right_off, &top_off, &bottom_off,
- NULL, NULL, NULL, NULL, &outer_border);
+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 ();
+ 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;
- 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))));
+ CHECK_TYPE_RANGED_INTEGER (int, x);
+ CHECK_TYPE_RANGED_INTEGER (int, y);
+
+ 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;
}
/************************************************************************
#endif /* HAVE_FREETYPE */
#endif /* not USE_CAIRO */
+ image_cache_refcount =
+ FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
+#ifdef GLYPH_DEBUG
+ dpyinfo_refcount = dpyinfo->reference_count;
+#endif /* GLYPH_DEBUG */
+
x_default_parameter (f, parms, Qfont_backend, Qnil,
"fontBackend", "FontBackend", RES_TYPE_STRING);
x_default_parameter (f, parms, Qborder_color, build_string ("black"),
"borderColor", "BorderColor", RES_TYPE_STRING);
-#ifdef GLYPH_DEBUG
- image_cache_refcount =
- FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
- dpyinfo_refcount = dpyinfo->reference_count;
-#endif /* GLYPH_DEBUG */
-
/* Init faces before x_default_parameter is called for the
scroll-bar-width parameter because otherwise we end up in
init_iterator with a null face cache, which should not happen. */
static void
compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, Lisp_Object dy, int width, int height, int *root_x, int *root_y)
{
- Lisp_Object left, top;
+ Lisp_Object left, top, right, bottom;
int win_x, win_y;
Window root, child;
unsigned pmask;
/* User-specified position? */
left = Fcdr (Fassq (Qleft, parms));
top = Fcdr (Fassq (Qtop, parms));
+ right = Fcdr (Fassq (Qright, parms));
+ bottom = Fcdr (Fassq (Qbottom, parms));
/* Move the tooltip window where the mouse pointer is. Resize and
show it. */
- if (!INTEGERP (left) || !INTEGERP (top))
+ if ((!INTEGERP (left) && !INTEGERP (right))
+ || (!INTEGERP (top) && !INTEGERP (bottom)))
{
block_input ();
XQueryPointer (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window,
if (INTEGERP (top))
*root_y = XINT (top);
+ else if (INTEGERP (bottom))
+ *root_y = XINT (bottom) - height;
else if (*root_y + XINT (dy) <= 0)
*root_y = 0; /* Can happen for negative dy */
else if (*root_y + XINT (dy) + height
if (INTEGERP (left))
*root_x = XINT (left);
+ else if (INTEGERP (right))
+ *root_y = XINT (right) - width;
else if (*root_x + XINT (dx) <= 0)
*root_x = 0; /* Can happen for negative dx */
else if (*root_x + XINT (dx) + width
Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
means use the default timeout of 5 seconds.
-If the list of frame parameters PARMS contains a `left' parameters,
-the tooltip is displayed at that x-position. Otherwise it is
-displayed at the mouse position, with offset DX added (default is 5 if
-DX isn't specified). Likewise for the y-position; if a `top' frame
-parameter is specified, it determines the y-position of the tooltip
-window, otherwise it is displayed at the mouse position, with offset
-DY added (default is -10).
+If the list of frame parameters PARMS contains a `left' parameter,
+display the tooltip at that x-position. If the list of frame parameters
+PARMS contains no `left' but a `right' parameter, display the tooltip
+right-adjusted at that x-position. Otherwise display it at the
+x-position of the mouse, with offset DX added (default is 5 if DX isn't
+specified).
+
+Likewise for the y-position: If a `top' frame parameter is specified, it
+determines the position of the upper edge of the tooltip window. If a
+`bottom' parameter but no `top' frame parameter is specified, it
+determines the position of the lower edge of the tooltip window.
+Otherwise display the tooltip window at the y-position of the mouse,
+with offset DY added (default is -10).
A tooltip's maximum size is specified by `x-max-tooltip-size'.
Text larger than the specified size is clipped. */)
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);