#define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
-#ifdef GLYPH_DEBUG
static ptrdiff_t image_cache_refcount;
+#ifdef GLYPH_DEBUG
static int dpyinfo_refcount;
#endif
return dpyinfo;
}
-/* Store the screen positions of frame F into XPTR and YPTR.
+/* Return the screen positions and offsets of frame F.
+ Store the offsets between FRAME_OUTER_WINDOW and the containing
+ window manager window into LEFT_OFFSET_X, RIGHT_OFFSET_X,
+ TOP_OFFSET_Y and BOTTOM_OFFSET_Y.
+ Store the offsets between FRAME_X_WINDOW and the containing
+ window manager window into X_PIXELS_DIFF and Y_PIXELS_DIFF.
+ Store the screen positions of frame F into XPTR and YPTR.
These are the positions of the containing window manager window,
not Emacs's own window. */
-
void
-x_real_positions (struct frame *f, int *xptr, int *yptr)
+x_real_pos_and_offsets (struct frame *f,
+ int *left_offset_x,
+ int *right_offset_x,
+ int *top_offset_y,
+ int *bottom_offset_y,
+ int *x_pixels_diff,
+ int *y_pixels_diff,
+ int *xptr,
+ 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;
Display *dpy = FRAME_X_DISPLAY (f);
unsigned char *tmp_data = NULL;
Atom target_type = XA_CARDINAL;
+ unsigned int ow IF_LINT (= 0), oh IF_LINT (= 0);
block_input ();
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);
/* Get the real coordinates for the WM window upper left corner */
XGetGeometry (FRAME_X_DISPLAY (f), win,
- &rootw, &real_x, &real_y, &ign, &ign, &ign, &ign);
+ &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.
if (had_errors) return;
- f->x_pixels_diff = -win_x;
- f->y_pixels_diff = -win_y;
+ if (x_pixels_diff) *x_pixels_diff = -win_x;
+ 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_y;
- FRAME_X_OUTPUT (f)->x_pixels_outer_diff = -outer_x;
- FRAME_X_OUTPUT (f)->y_pixels_outer_diff = -outer_y;
+ if (xptr) *xptr = real_x;
+ if (yptr) *yptr = real_y;
- *xptr = real_x;
- *yptr = real_y;
+ if (right_offset_x || bottom_offset_y)
+ {
+ int xy_ign;
+ unsigned int ign, fw, fh;
+ Window rootw;
+
+ XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
+ &rootw, &xy_ign, &xy_ign, &fw, &fh, &ign, &ign);
+ if (right_offset_x) *right_offset_x = ow - fw + outer_x;
+ if (bottom_offset_y) *bottom_offset_y = oh - fh + outer_y;
+ }
}
+/* Store the screen positions of frame F into XPTR and YPTR.
+ These are the positions of the containing window manager window,
+ not Emacs's own window. */
+
+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,
+ NULL);
+}
+
+
/* Get the mouse position in frame relative coordinates. */
void
we don't care. */
(unsigned int *) &dummy);
- unblock_input ();
+ XTranslateCoordinates (FRAME_X_DISPLAY (f),
+
+ /* From-window, to-window. */
+ FRAME_DISPLAY_INFO (f)->root_window,
+ FRAME_X_WINDOW (f),
+
+ /* From-position, to-position. */
+ *x, *y, x, y,
- /* Translate root window coordinates to window coordinates. */
- *x -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
- *y -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
+ /* Child of win. */
+ &dummy_window);
+
+ unblock_input ();
}
/* Gamma-correct COLOR on frame F. */
{
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 ();
-FRAME must be a live frame and defaults to the selected one.
+ /** native_width = atts.width; **/
+ /** native_height = atts.height; **/
-The return value is an association list containing the following
-elements (all size values are in pixels).
+ 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-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.
+ native_left = outer_left + left_off;
+ native_top = outer_top + top_off;
+ native_right = native_left + native_width;
+ native_bottom = native_top + native_height;
-- `border' is a cons of the horizontal and vertical width of FRAME's
- external borders.
+ 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;
-- `title-bar-height' is the height of the title bar of FRAME.
+#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.
+
+`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.
-- `menu-bar-external' if `t' means the menu bar is external (not
+`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.
+
+`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-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;
+ return frame_geometry (frame, Qnil);
+}
- border = FRAME_OUTER_TO_INNER_DIFF_X (f);
- title = FRAME_X_OUTPUT (f)->y_pixels_outer_diff - border;
+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));
+}
- outer_width = FRAME_PIXEL_WIDTH (f) + 2 * border;
- outer_height = (FRAME_PIXEL_HEIGHT (f)
- + FRAME_OUTER_TO_INNER_DIFF_Y (f)
- + FRAME_OUTER_TO_INNER_DIFF_X (f));
+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 defined (USE_GTK)
+ 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 ();
+
+ return Fcons (make_number (x), make_number (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)
{
- 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));
- if (tool_bar_left_right)
- /* For some reason FRAME_OUTER_TO_INNER_DIFF_X does not count the
- width of a tool bar. */
- outer_width += FRAME_TOOLBAR_WIDTH (f);
- }
-#else
- tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
- tool_bar_width = ((tool_bar_height > 0)
- ? outer_width - 2 * FRAME_INTERNAL_BORDER_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);
+
+ block_input ();
+ XWarpPointer (FRAME_X_DISPLAY (f), None, DefaultRootWindow (FRAME_X_DISPLAY (f)),
+ 0, 0, 0, 0, XINT (x), XINT (y));
+ unblock_input ();
- menu_bar_width = ((menu_bar_height > 0)
- ? outer_width - 2 * border
- : 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))));
+ 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. */
Lisp_Object disptype;
if (FRAME_DISPLAY_INFO (f)->n_planes == 1)
- disptype = intern ("mono");
+ disptype = Qmono;
else if (FRAME_DISPLAY_INFO (f)->visual->class == GrayScale
|| FRAME_DISPLAY_INFO (f)->visual->class == StaticGray)
disptype = intern ("grayscale");
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. */)
GCPRO2 (font_param, font);
XSETFONT (font, FRAME_FONT (f));
- font_param = Ffont_get (font, intern (":name"));
+ font_param = Ffont_get (font, QCname);
if (STRINGP (font_param))
default_name = xlispstrdup (font_param);
else
}
+\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 (Qcompound_text, "compound-text");
DEFSYM (Qcancel_timer, "cancel-timer");
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));
}
#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
}