#define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
-#ifdef GLYPH_DEBUG
static ptrdiff_t image_cache_refcount;
+#ifdef GLYPH_DEBUG
static int dpyinfo_refcount;
#endif
int *x_pixels_diff,
int *y_pixels_diff,
int *xptr,
- int *yptr)
+ int *yptr,
+ int *outer_border)
{
int win_x, win_y, outer_x IF_LINT (= 0), outer_y IF_LINT (= 0);
int real_x = 0, real_y = 0;
x_catch_errors (dpy);
+ if (x_pixels_diff) *x_pixels_diff = 0;
+ if (y_pixels_diff) *y_pixels_diff = 0;
+ if (left_offset_x) *left_offset_x = 0;
+ if (top_offset_y) *top_offset_y = 0;
+ if (right_offset_x) *right_offset_x = 0;
+ if (bottom_offset_y) *bottom_offset_y = 0;
+ if (xptr) *xptr = 0;
+ if (yptr) *yptr = 0;
+ if (outer_border) *outer_border = 0;
+
if (win == dpyinfo->root_window)
win = FRAME_OUTER_WINDOW (f);
XGetGeometry (FRAME_X_DISPLAY (f), win,
&rootw, &real_x, &real_y, &ow, &oh, &ign, &ign);
+ if (outer_border)
+ {
+ XWindowAttributes atts;
+ XGetWindowAttributes (FRAME_X_DISPLAY (f), win, &atts);
+ *outer_border = atts.border_width;
+ }
+
/* Translate real coordinates to coordinates relative to our
window. For our window, the upper left corner is 0, 0.
Since the upper left corner of the WM window is outside
if (y_pixels_diff) *y_pixels_diff = -win_y;
if (left_offset_x) *left_offset_x = -outer_x;
- if (top_offset_y) *top_offset_y = -outer_x;
+ if (top_offset_y) *top_offset_y = -outer_y;
if (xptr) *xptr = real_x;
if (yptr) *yptr = real_y;
void
x_real_positions (struct frame *f, int *xptr, int *yptr)
{
- x_real_pos_and_offsets (f, NULL, NULL, NULL, NULL, NULL, NULL, xptr, yptr);
+ x_real_pos_and_offsets (f, NULL, NULL, NULL, NULL, NULL, NULL, xptr, yptr,
+ NULL);
}
{
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);
y = FRAME_TOP_MARGIN_HEIGHT (f);
block_input ();
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- 0, y, width, height);
+ x_clear_area (f, 0, y, width, height);
unblock_input ();
}
height = nlines * FRAME_LINE_HEIGHT (f) - y;
block_input ();
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- 0, y, width, height);
+ x_clear_area (f, 0, y, width, height);
unblock_input ();
}
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);
specbind (Qx_resource_name, name);
}
+#ifdef USE_CAIRO
+ register_font_driver (&ftcrfont_driver, f);
+#else
#ifdef HAVE_FREETYPE
#ifdef HAVE_XFT
register_font_driver (&xftfont_driver, f);
#endif /* not HAVE_XFT */
#endif /* HAVE_FREETYPE */
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;
+
+ 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
-FRAME must be a live frame and defaults to the selected one.
+ /* 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)));
+}
-The return value is an association list containing the following
-elements (all size values are in pixels).
+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;
- XWindowAttributes atts;
+ return frame_geometry (frame, Qnil);
+}
- block_input ();
+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));
+}
- XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &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;
- x_real_pos_and_offsets (f, &left_off, &right_off, &top_off, &bottom_off,
- NULL, NULL, NULL, NULL);
+ 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 = FRAME_PIXEL_WIDTH (f) + 2 * border + right_off + left_off;
- outer_height = FRAME_PIXEL_HEIGHT (f) + 2 * border + top_off + bottom_off;
+ 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;
}
/************************************************************************
if (class == -1
|| !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
dpyinfo->n_planes, class, &vinfo))
- fatal ("Invalid visual specification `%s'", SDATA (value));
+ fatal ("Invalid visual specification '%s'",
+ SSDATA (ENCODE_SYSTEM (value)));
dpyinfo->visual = vinfo.visual;
}
specbind (Qx_resource_name, name);
}
+#ifdef USE_CAIRO
+ register_font_driver (&ftcrfont_driver, f);
+#else
register_font_driver (&xfont_driver, f);
#ifdef HAVE_FREETYPE
#ifdef HAVE_XFT
register_font_driver (&ftxfont_driver, f);
#endif /* not HAVE_XFT */
#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. */)
}
+\f
+/***********************************************************************
+ Printing
+ ***********************************************************************/
+
+#ifdef USE_CAIRO
+DEFUN ("x-export-frames", Fx_export_frames, Sx_export_frames, 0, 2, 0,
+ doc: /* XXX Experimental. Return image data of FRAMES in TYPE format.
+FRAMES should be nil (the selected frame), a frame, or a list of
+frames (each of which corresponds to one page). Optional arg TYPE
+should be either `pdf' (default), `png', `ps', or `svg'. Supported
+types are determined by the compile-time configuration of cairo. */)
+ (Lisp_Object frames, Lisp_Object type)
+{
+ Lisp_Object result, rest, tmp;
+ cairo_surface_type_t surface_type;
+
+ if (NILP (frames))
+ frames = selected_frame;
+ if (!CONSP (frames))
+ frames = list1 (frames);
+
+ tmp = Qnil;
+ for (rest = frames; CONSP (rest); rest = XCDR (rest))
+ {
+ struct frame *f = XFRAME (XCAR (rest));
+
+ if (! FRAME_LIVE_P (f) || ! FRAME_X_P (f) || ! FRAME_LIVE_P (f))
+ error ("Invalid frame");
+
+ Lisp_Object frame;
+
+ XSETFRAME (frame, f);
+ tmp = Fcons (frame, tmp);
+ }
+ frames = Fnreverse (tmp);
+
+#ifdef CAIRO_HAS_PDF_SURFACE
+ if (NILP (type) || EQ (type, intern ("pdf"))) /* XXX: Qpdf */
+ surface_type = CAIRO_SURFACE_TYPE_PDF;
+ else
+#endif
+#ifdef CAIRO_HAS_PNG_FUNCTIONS
+ if (EQ (type, intern ("png")))
+ {
+ if (!NILP (XCDR (frames)))
+ error ("PNG export cannot handle multiple frames.");
+ surface_type = CAIRO_SURFACE_TYPE_IMAGE;
+ }
+ else
+#endif
+#ifdef CAIRO_HAS_PS_SURFACE
+ if (EQ (type, intern ("ps")))
+ surface_type = CAIRO_SURFACE_TYPE_PS;
+ else
+#endif
+#ifdef CAIRO_HAS_SVG_SURFACE
+ if (EQ (type, intern ("svg")))
+ {
+ /* For now, we stick to SVG 1.1. */
+ if (!NILP (XCDR (frames)))
+ error ("SVG export cannot handle multiple frames.");
+ surface_type = CAIRO_SURFACE_TYPE_SVG;
+ }
+ else
+#endif
+ error ("Unsupported export type");
+
+ result = x_cr_export_frames (frames, surface_type);
+
+ return result;
+}
+
+#ifdef USE_GTK
+DEFUN ("x-page-setup-dialog", Fx_page_setup_dialog, Sx_page_setup_dialog, 0, 0, 0,
+ doc: /* Pop up a page setup dialog.
+The current page setup can be obtained using `x-get-page-setup'. */)
+ (void)
+{
+ block_input ();
+ xg_page_setup_dialog ();
+ unblock_input ();
+
+ return Qnil;
+}
+
+DEFUN ("x-get-page-setup", Fx_get_page_setup, Sx_get_page_setup, 0, 0, 0,
+ doc: /* Return the value of the current page setup.
+The return value is an alist containing the following keys:
+
+ orientation: page orientation (symbol `portrait', `landscape',
+ `reverse-portrait', or `reverse-landscape').
+ width, height: page width/height in points not including margins.
+ left-margin, right-margin, top-margin, bottom-margin: print margins,
+ which is the parts of the page that the printer cannot print
+ on, in points.
+
+The paper width can be obtained as the sum of width, left-margin, and
+right-margin values. Likewise, the paper height is the sum of height,
+top-margin, and bottom-margin values. */)
+ (void)
+{
+ Lisp_Object result;
+
+ block_input ();
+ result = xg_get_page_setup ();
+ unblock_input ();
+
+ return result;
+}
+
+DEFUN ("x-print-frames-dialog", Fx_print_frames_dialog, Sx_print_frames_dialog, 0, 1, "",
+ doc: /* Pop up a print dialog to print the current contents of FRAMES.
+FRAMES should be nil (the selected frame), a frame, or a list of
+frames (each of which corresponds to one page). Each frame should be
+visible. */)
+ (Lisp_Object frames)
+{
+ Lisp_Object rest, tmp;
+
+ if (NILP (frames))
+ frames = selected_frame;
+ if (!CONSP (frames))
+ frames = list1 (frames);
+
+ tmp = Qnil;
+ for (rest = frames; CONSP (rest); rest = XCDR (rest))
+ {
+ struct frame *f = XFRAME (XCAR (rest));
+ if (! FRAME_LIVE_P (f) || ! FRAME_X_P (f) || ! FRAME_LIVE_P (f))
+ error ("Invalid frame");
+ Lisp_Object frame;
+
+ XSETFRAME (frame, f);
+ if (!EQ (Fframe_visible_p (frame), Qt))
+ error ("Frames to be printed must be visible.");
+ tmp = Fcons (frame, tmp);
+ }
+ frames = Fnreverse (tmp);
+
+ /* Make sure the current matrices are up-to-date. */
+ Fredisplay (Qt);
+
+ block_input ();
+ xg_print_frames_dialog (frames);
+ unblock_input ();
+
+ return Qnil;
+}
+#endif /* USE_GTK */
+#endif /* USE_CAIRO */
+
\f
/***********************************************************************
Initialization
DEFSYM (Qfont_param, "font-parameter");
DEFSYM (Qmono, "mono");
+#ifdef USE_CAIRO
+ DEFSYM (Qorientation, "orientation");
+ DEFSYM (Qtop_margin, "top-margin");
+ DEFSYM (Qbottom_margin, "bottom-margin");
+ DEFSYM (Qportrait, "portrait");
+ DEFSYM (Qlandscape, "landscape");
+ DEFSYM (Qreverse_portrait, "reverse-portrait");
+ DEFSYM (Qreverse_landscape, "reverse-landscape");
+#endif
+
Fput (Qundefined_color, Qerror_conditions,
listn (CONSTYPE_PURE, 2, Qundefined_color, Qerror));
Fput (Qundefined_color, Qerror_message,
}
#endif /* USE_GTK */
+#ifdef USE_CAIRO
+ Fprovide (intern_c_string ("cairo"), Qnil);
+
+ DEFVAR_LISP ("cairo-version-string", Vcairo_version_string,
+ doc: /* Version info for cairo. */);
+ {
+ char cairo_version[sizeof ".." + 3 * INT_STRLEN_BOUND (int)];
+ int len = sprintf (cairo_version, "%d.%d.%d",
+ CAIRO_VERSION_MAJOR, CAIRO_VERSION_MINOR,
+ CAIRO_VERSION_MICRO);
+ Vcairo_version_string = make_pure_string (cairo_version, len, len, false);
+ }
+#endif
+
/* X window properties. */
defsubr (&Sx_change_window_property);
defsubr (&Sx_delete_window_property);
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);
#if defined (USE_GTK) && defined (HAVE_FREETYPE)
defsubr (&Sx_select_font);
#endif
+
+#ifdef USE_CAIRO
+ defsubr (&Sx_export_frames);
+#ifdef USE_GTK
+ defsubr (&Sx_page_setup_dialog);
+ defsubr (&Sx_get_page_setup);
+ defsubr (&Sx_print_frames_dialog);
+#endif
+#endif
}