#include "xsettings.h"
+#ifdef HAVE_XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif
+#ifdef HAVE_XINERAMA
+#include <X11/extensions/Xinerama.h>
+#endif
+
#ifdef USE_GTK
#include "gtkutil.h"
#endif
#define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
-/* Nonzero if using X. */
-
-int x_in_use;
-
static Lisp_Object Qsuppress_icon;
static Lisp_Object Qundefined_color;
static Lisp_Object Qcompound_text, Qcancel_timer;
static struct x_display_info *x_display_info_for_name (Lisp_Object);
-\f
-/* Error if we are not connected to X. */
-
-void
-check_x (void)
-{
- if (! x_in_use)
- error ("X windows are not in use or not initialized");
-}
-
-/* Nonzero if we can use mouse menus.
- You should not call this unless HAVE_MENUS is defined. */
-
-int
-have_menus_p (void)
-{
- return x_in_use;
-}
-
-/* Extract a frame as a FRAME_PTR, defaulting to the selected frame
- and checking validity for X. */
-
-FRAME_PTR
-check_x_frame (Lisp_Object frame)
-{
- struct frame *f = decode_live_frame (frame);
-
- if (! FRAME_X_P (f))
- error ("Non-X frame used");
- return f;
-}
-
/* Let the user specify an X display with a Lisp object.
OBJECT may be nil, a frame or a terminal object.
nil stands for the selected frame--or, if that is not an X frame,
struct terminal *t = get_terminal (object, 1);
if (t->type != output_x_window)
- error ("Terminal %"pI"d is not an X display", XINT (object));
+ error ("Terminal %d is not an X display", t->id);
dpyinfo = t->display_info.x;
}
dpyinfo = x_display_info_for_name (object);
else
{
- FRAME_PTR f = check_x_frame (object);
+ struct frame *f = decode_window_system_frame (object);
dpyinfo = FRAME_X_DISPLAY_INFO (f);
}
not Emacs's own window. */
void
-x_real_positions (FRAME_PTR f, int *xptr, int *yptr)
+x_real_positions (struct frame *f, int *xptr, int *yptr)
{
int win_x, win_y, outer_x IF_LINT (= 0), outer_y IF_LINT (= 0);
int real_x = 0, real_y = 0;
Signal an error if color can't be allocated. */
static int
-x_decode_color (FRAME_PTR f, Lisp_Object color_name, int mono_color)
+x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color)
{
XColor cdef;
may be any format that GdkPixbuf knows about, i.e. not just bitmaps. */
int
-xg_set_icon (FRAME_PTR f, Lisp_Object file)
+xg_set_icon (struct frame *f, Lisp_Object file)
{
int result = 0;
Lisp_Object found;
}
int
-xg_set_icon_from_xpm_data (FRAME_PTR f, const char **data)
+xg_set_icon_from_xpm_data (struct frame *f, const char **data)
{
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (data);
x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
unsigned long fore_pixel, pixel;
- int fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
+ bool fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
struct x_output *x = f->output_data.x;
if (!NILP (Vx_cursor_fore_pixel))
static void
-x_set_cursor_type (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
+x_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
set_frame_cursor_types (f, arg);
icon name to NAME. */
static void
-x_set_name_internal (FRAME_PTR f, Lisp_Object name)
+x_set_name_internal (struct frame *f, Lisp_Object name)
{
if (FRAME_X_WINDOW (f))
{
specified a name for the frame; the name will override any set by the
redisplay code. */
static void
-x_explicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
+x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
x_set_name (f, arg, 1);
}
name; names set this way will never override names set by the user's
lisp code. */
void
-x_implicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
+x_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
x_set_name (f, arg, 0);
}
#endif /* not USE_TOOLKIT_SCROLL_BARS */
}
- x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
+ x_set_frame_parameters (f, list1 (Fcons (prop, tem)));
return tem;
}
for example, but Xt doesn't). */
static void
-hack_wm_protocols (FRAME_PTR f, Widget widget)
+hack_wm_protocols (struct frame *f, Widget widget)
{
Display *dpy = XtDisplay (widget);
Window w = XtWindow (widget);
xic_free_xfontset (struct frame *f)
{
Lisp_Object rest, frame;
- int shared_p = 0;
+ bool shared_p = 0;
if (!FRAME_XIC_FONTSET (f))
return;
/* The fontset is not used anymore. It is safe to free it. */
XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
- if (FRAME_XIC_BASE_FONTNAME (f))
- xfree (FRAME_XIC_BASE_FONTNAME (f));
- FRAME_XIC_BASE_FONTNAME (f) = NULL;
FRAME_XIC_FONTSET (f) = NULL;
}
for the window manager, so GC relocation won't bother it.
Elsewhere we specify the window name for the window manager. */
-
- {
- char *str = SSDATA (Vx_resource_name);
- f->namebuf = xmalloc (strlen (str) + 1);
- strcpy (f->namebuf, str);
- }
+ f->namebuf = xstrdup (SSDATA (Vx_resource_name));
ac = 0;
XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
/* maybe_set_screen_title_format (shell_widget); */
pane_widget = lw_create_widget ("main", "pane", widget_id_tick++,
- (widget_value *) NULL,
- shell_widget, False,
- (lw_callback) NULL,
- (lw_callback) NULL,
- (lw_callback) NULL,
- (lw_callback) NULL);
+ NULL, shell_widget, False,
+ NULL, NULL, NULL, NULL);
ac = 0;
XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
*/
XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
- XA_ATOM, 32, PropModeAppend,
- (unsigned char*) NULL, 0);
+ XA_ATOM, 32, PropModeAppend, NULL, 0);
/* Make all the standard events reach the Emacs frame. */
attributes.event_mask = STANDARD_EVENT_SET;
#else /* not USE_X_TOOLKIT */
#ifdef USE_GTK
static void
-x_window (FRAME_PTR f)
+x_window (struct frame *f)
{
if (! xg_create_frame_widgets (f))
error ("Unable to create window");
| GCFillStyle | GCLineWidth),
&gc_values);
- /* Reliefs. */
- f->output_data.x->white_relief.gc = 0;
- f->output_data.x->black_relief.gc = 0;
-
/* Create the gray border tile used when the pointer is not in
the frame. Since this depends on the frame's pixel values,
this must be done on a per-frame basis. */
return Qnil;
}
-static Lisp_Object
+static void
+do_unwind_create_frame (Lisp_Object frame)
+{
+ unwind_create_frame (frame);
+}
+
+static void
unwind_create_frame_1 (Lisp_Object val)
{
inhibit_lisp_code = val;
- return Qnil;
}
static void
{
/* Remember the explicit font parameter, so we can re-apply it after
we've applied the `default' face settings. */
- x_set_frame_parameters (f, Fcons (Fcons (Qfont_param, font_param), Qnil));
+ x_set_frame_parameters (f, list1 (Fcons (Qfont_param, font_param)));
}
/* This call will make X resources override any system font setting. */
Signal error if FRAME is not an X frame. */)
(Lisp_Object frame)
{
- struct frame *f = check_x_frame (frame);
+ struct frame *f = decode_window_system_frame (frame);
block_input ();
x_wm_set_size_hint (f, 0, 0);
FRAME_X_DISPLAY_INFO (f) = dpyinfo;
/* With FRAME_X_DISPLAY_INFO set up, this unwind-protect is safe. */
- record_unwind_protect (unwind_create_frame, frame);
+ record_unwind_protect (do_unwind_create_frame, frame);
/* These colors will be set anyway later, but it's important
to get the color reference counts right, so initialize them! */
specbind (Qx_resource_name, name);
}
- f->resx = dpyinfo->resx;
- f->resy = dpyinfo->resy;
-
#ifdef HAVE_FREETYPE
#ifdef HAVE_XFT
register_font_driver (&xftfont_driver, f);
FRAME nil means use the selected frame. */)
(Lisp_Object frame)
{
- struct frame *f = check_x_frame (frame);
+ struct frame *f = decode_window_system_frame (frame);
Display *dpy = FRAME_X_DISPLAY (f);
block_input ();
(Lisp_Object color, Lisp_Object frame)
{
XColor foo;
- FRAME_PTR f = check_x_frame (frame);
+ struct frame *f = decode_window_system_frame (frame);
CHECK_STRING (color);
(Lisp_Object color, Lisp_Object frame)
{
XColor foo;
- FRAME_PTR f = check_x_frame (frame);
+ struct frame *f = decode_window_system_frame (frame);
CHECK_STRING (color);
if (x_defined_color (f, SSDATA (color), &foo, 0))
- return list3 (make_number (foo.red),
- make_number (foo.green),
- make_number (foo.blue));
+ return list3i (foo.red, foo.green, foo.blue);
else
return Qnil;
}
doc: /* Return the width in pixels of the X display TERMINAL.
The optional argument TERMINAL specifies which display to ask about.
TERMINAL should be a terminal object, a frame or a display name (a string).
-If omitted or nil, that stands for the selected frame's display. */)
+If omitted or nil, that stands for the selected frame's display.
+
+On \"multi-monitor\" setups this refers to the pixel width for all
+physical monitors associated with TERMINAL. To get information for
+each physical monitor, use `display-monitor-attributes-list'. */)
(Lisp_Object terminal)
{
struct x_display_info *dpyinfo = check_x_display_info (terminal);
doc: /* Return the height in pixels of the X display TERMINAL.
The optional argument TERMINAL specifies which display to ask about.
TERMINAL should be a terminal object, a frame or a display name (a string).
-If omitted or nil, that stands for the selected frame's display. */)
+If omitted or nil, that stands for the selected frame's display.
+
+On \"multi-monitor\" setups this refers to the pixel height for all
+physical monitors associated with TERMINAL. To get information for
+each physical monitor, use `display-monitor-attributes-list'. */)
(Lisp_Object terminal)
{
struct x_display_info *dpyinfo = check_x_display_info (terminal);
struct x_display_info *dpyinfo = check_x_display_info (terminal);
Display *dpy = dpyinfo->display;
- return Fcons (make_number (ProtocolVersion (dpy)),
- Fcons (make_number (ProtocolRevision (dpy)),
- Fcons (make_number (VendorRelease (dpy)), Qnil)));
+ return list3i (ProtocolVersion (dpy), ProtocolRevision (dpy),
+ VendorRelease (dpy));
}
DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
doc: /* Return the height in millimeters of the X display TERMINAL.
The optional argument TERMINAL specifies which display to ask about.
TERMINAL should be a terminal object, a frame or a display name (a string).
-If omitted or nil, that stands for the selected frame's display. */)
+If omitted or nil, that stands for the selected frame's display.
+
+On \"multi-monitor\" setups this refers to the height in millimeters for
+all physical monitors associated with TERMINAL. To get information
+for each physical monitor, use `display-monitor-attributes-list'. */)
(Lisp_Object terminal)
{
struct x_display_info *dpyinfo = check_x_display_info (terminal);
doc: /* Return the width in millimeters of the X display TERMINAL.
The optional argument TERMINAL specifies which display to ask about.
TERMINAL should be a terminal object, a frame or a display name (a string).
-If omitted or nil, that stands for the selected frame's display. */)
+If omitted or nil, that stands for the selected frame's display.
+
+On \"multi-monitor\" setups this refers to the width in millimeters for
+all physical monitors associated with TERMINAL. To get information
+for each physical monitor, use `display-monitor-attributes-list'. */)
(Lisp_Object terminal)
{
struct x_display_info *dpyinfo = check_x_display_info (terminal);
default:
error ("Strange value for BackingStore parameter of screen");
- result = Qnil;
}
return result;
break;
default:
error ("Display has an unknown visual class");
- result = Qnil;
}
return result;
else
return Qnil;
}
-\f
-int
-x_pixel_width (register struct frame *f)
+
+/* Store the geometry of the workarea on display DPYINFO into *RECT.
+ Return false if and only if the workarea information cannot be
+ obtained via the _NET_WORKAREA root window property. */
+
+#if ! GTK_CHECK_VERSION (3, 4, 0)
+static bool
+x_get_net_workarea (struct x_display_info *dpyinfo, XRectangle *rect)
{
- return FRAME_PIXEL_WIDTH (f);
+ Display *dpy = dpyinfo->display;
+ long offset, max_len;
+ Atom target_type, actual_type;
+ unsigned long actual_size, bytes_remaining;
+ int rc, actual_format;
+ unsigned char *tmp_data = NULL;
+ bool result = false;
+
+ x_catch_errors (dpy);
+ offset = 0;
+ max_len = 1;
+ target_type = XA_CARDINAL;
+ rc = XGetWindowProperty (dpy, dpyinfo->root_window,
+ dpyinfo->Xatom_net_current_desktop,
+ offset, max_len, False, target_type,
+ &actual_type, &actual_format, &actual_size,
+ &bytes_remaining, &tmp_data);
+ if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy)
+ && actual_format == 32 && actual_size == max_len)
+ {
+ long current_desktop = ((long *) tmp_data)[0];
+
+ XFree (tmp_data);
+ tmp_data = NULL;
+
+ offset = 4 * current_desktop;
+ max_len = 4;
+ rc = XGetWindowProperty (dpy, dpyinfo->root_window,
+ dpyinfo->Xatom_net_workarea,
+ offset, max_len, False, target_type,
+ &actual_type, &actual_format, &actual_size,
+ &bytes_remaining, &tmp_data);
+ if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy)
+ && actual_format == 32 && actual_size == max_len)
+ {
+ long *values = (long *) tmp_data;
+
+ rect->x = values[0];
+ rect->y = values[1];
+ rect->width = values[2];
+ rect->height = values[3];
+
+ XFree (tmp_data);
+ tmp_data = NULL;
+
+ result = true;
+ }
+ }
+ if (tmp_data)
+ XFree (tmp_data);
+ x_uncatch_errors ();
+
+ return result;
}
+#endif
-int
-x_pixel_height (register struct frame *f)
+#ifndef USE_GTK
+
+/* Return monitor number where F is "most" or closest to. */
+static int
+x_get_monitor_for_frame (struct frame *f,
+ struct MonitorInfo *monitors,
+ int n_monitors)
+{
+ XRectangle frect;
+ int area = 0, dist = -1;
+ int best_area = -1, best_dist = -1;
+ int i;
+
+ if (n_monitors == 1) return 0;
+ frect.x = f->left_pos;
+ frect.y = f->top_pos;
+ frect.width = FRAME_PIXEL_WIDTH (f);
+ frect.height = FRAME_PIXEL_HEIGHT (f);
+
+ for (i = 0; i < n_monitors; ++i)
+ {
+ struct MonitorInfo *mi = &monitors[i];
+ XRectangle res;
+ int a = 0;
+
+ if (mi->geom.width == 0) continue;
+
+ if (x_intersect_rectangles (&mi->geom, &frect, &res))
+ {
+ a = res.width * res.height;
+ if (a > area)
+ {
+ area = a;
+ best_area = i;
+ }
+ }
+
+ if (a == 0 && area == 0)
+ {
+ int dx, dy, d;
+ if (frect.x + frect.width < mi->geom.x)
+ dx = mi->geom.x - frect.x + frect.width;
+ else if (frect.x > mi->geom.x + mi->geom.width)
+ dx = frect.x - mi->geom.x + mi->geom.width;
+ else
+ dx = 0;
+ if (frect.y + frect.height < mi->geom.y)
+ dy = mi->geom.y - frect.y + frect.height;
+ else if (frect.y > mi->geom.y + mi->geom.height)
+ dy = frect.y - mi->geom.y + mi->geom.height;
+ else
+ dy = 0;
+
+ d = dx*dx + dy*dy;
+ if (dist == -1 || dist > d)
+ {
+ dist = d;
+ best_dist = i;
+ }
+ }
+ }
+
+ return best_area != -1 ? best_area : (best_dist != -1 ? best_dist : 0);
+}
+
+static Lisp_Object
+x_make_monitor_attribute_list (struct MonitorInfo *monitors,
+ int n_monitors,
+ int primary_monitor,
+ struct x_display_info *dpyinfo,
+ const char *source)
{
- return FRAME_PIXEL_HEIGHT (f);
+ Lisp_Object monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
+ Lisp_Object frame, rest;
+
+ FOR_EACH_FRAME (rest, frame)
+ {
+ struct frame *f = XFRAME (frame);
+
+ if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo
+ && !EQ (frame, tip_frame))
+ {
+ int i = x_get_monitor_for_frame (f, monitors, n_monitors);
+ ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
+ }
+ }
+
+ return make_monitor_attribute_list (monitors, n_monitors, primary_monitor,
+ monitor_frames, source);
+}
+
+static Lisp_Object
+x_get_monitor_attributes_fallback (struct x_display_info *dpyinfo)
+{
+ struct MonitorInfo monitor;
+ XRectangle workarea_r;
+
+ /* Fallback: treat (possibly) multiple physical monitors as if they
+ formed a single monitor as a whole. This should provide a
+ consistent result at least on single monitor environments. */
+ monitor.geom.x = monitor.geom.y = 0;
+ monitor.geom.width = x_display_pixel_width (dpyinfo);
+ monitor.geom.height = x_display_pixel_height (dpyinfo);
+ monitor.mm_width = WidthMMOfScreen (dpyinfo->screen);
+ monitor.mm_height = HeightMMOfScreen (dpyinfo->screen);
+ monitor.name = xstrdup ("combined screen");
+
+ if (x_get_net_workarea (dpyinfo, &workarea_r))
+ monitor.work = workarea_r;
+ else
+ monitor.work = monitor.geom;
+ return x_make_monitor_attribute_list (&monitor, 1, 0, dpyinfo, "fallback");
+}
+
+
+#ifdef HAVE_XINERAMA
+static Lisp_Object
+x_get_monitor_attributes_xinerama (struct x_display_info *dpyinfo)
+{
+ int n_monitors, i;
+ Lisp_Object attributes_list = Qnil;
+ Display *dpy = dpyinfo->display;
+ XineramaScreenInfo *info = XineramaQueryScreens (dpy, &n_monitors);
+ struct MonitorInfo *monitors;
+ double mm_width_per_pixel, mm_height_per_pixel;
+
+ if (! info || n_monitors == 0)
+ {
+ if (info)
+ XFree (info);
+ return attributes_list;
+ }
+
+ mm_width_per_pixel = ((double) WidthMMOfScreen (dpyinfo->screen)
+ / x_display_pixel_width (dpyinfo));
+ mm_height_per_pixel = ((double) HeightMMOfScreen (dpyinfo->screen)
+ / x_display_pixel_height (dpyinfo));
+ monitors = xzalloc (n_monitors * sizeof *monitors);
+ for (i = 0; i < n_monitors; ++i)
+ {
+ struct MonitorInfo *mi = &monitors[i];
+ XRectangle workarea_r;
+
+ mi->geom.x = info[i].x_org;
+ mi->geom.y = info[i].y_org;
+ mi->geom.width = info[i].width;
+ mi->geom.height = info[i].height;
+ mi->mm_width = mi->geom.width * mm_width_per_pixel + 0.5;
+ mi->mm_height = mi->geom.height * mm_height_per_pixel + 0.5;
+ mi->name = 0;
+
+ /* Xinerama usually have primary monitor first, just use that. */
+ if (i == 0 && x_get_net_workarea (dpyinfo, &workarea_r))
+ {
+ mi->work = workarea_r;
+ if (! x_intersect_rectangles (&mi->geom, &mi->work, &mi->work))
+ mi->work = mi->geom;
+ }
+ else
+ mi->work = mi->geom;
+ }
+ XFree (info);
+
+ attributes_list = x_make_monitor_attribute_list (monitors,
+ n_monitors,
+ 0,
+ dpyinfo,
+ "Xinerama");
+ free_monitors (monitors, n_monitors);
+ return attributes_list;
+}
+#endif /* HAVE_XINERAMA */
+
+
+#ifdef HAVE_XRANDR
+static Lisp_Object
+x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo)
+{
+ Lisp_Object attributes_list = Qnil;
+ XRRScreenResources *resources;
+ Display *dpy = dpyinfo->display;
+ int i, n_monitors, primary = -1;
+ RROutput pxid = None;
+ struct MonitorInfo *monitors;
+
+#ifdef HAVE_XRRGETSCREENRESOURCESCURRENT
+ resources = XRRGetScreenResourcesCurrent (dpy, dpyinfo->root_window);
+#else
+ resources = XRRGetScreenResources (dpy, dpyinfo->root_window);
+#endif
+ if (! resources || resources->noutput == 0)
+ {
+ if (resources)
+ XRRFreeScreenResources (resources);
+ return Qnil;
+ }
+ n_monitors = resources->noutput;
+ monitors = xzalloc (n_monitors * sizeof *monitors);
+
+#ifdef HAVE_XRRGETOUTPUTPRIMARY
+ pxid = XRRGetOutputPrimary (dpy, dpyinfo->root_window);
+#endif
+
+ for (i = 0; i < n_monitors; ++i)
+ {
+ XRROutputInfo *info = XRRGetOutputInfo (dpy, resources,
+ resources->outputs[i]);
+ Connection conn = info ? info->connection : RR_Disconnected;
+ RRCrtc id = info ? info->crtc : None;
+
+ if (strcmp (info->name, "default") == 0)
+ {
+ /* Non XRandr 1.2 driver, does not give useful data. */
+ XRRFreeOutputInfo (info);
+ XRRFreeScreenResources (resources);
+ free_monitors (monitors, n_monitors);
+ return Qnil;
+ }
+
+ if (conn != RR_Disconnected && id != None)
+ {
+ XRRCrtcInfo *crtc = XRRGetCrtcInfo (dpy, resources, id);
+ struct MonitorInfo *mi = &monitors[i];
+ XRectangle workarea_r;
+
+ if (! crtc)
+ {
+ XRRFreeOutputInfo (info);
+ continue;
+ }
+
+ mi->geom.x = crtc->x;
+ mi->geom.y = crtc->y;
+ mi->geom.width = crtc->width;
+ mi->geom.height = crtc->height;
+ mi->mm_width = info->mm_width;
+ mi->mm_height = info->mm_height;
+ mi->name = xstrdup (info->name);
+
+ if (pxid != None && pxid == resources->outputs[i])
+ primary = i;
+ else if (primary == -1 && strcmp (info->name, "LVDS") == 0)
+ primary = i;
+
+ if (i == primary && x_get_net_workarea (dpyinfo, &workarea_r))
+ {
+ mi->work= workarea_r;
+ if (! x_intersect_rectangles (&mi->geom, &mi->work, &mi->work))
+ mi->work = mi->geom;
+ }
+ else
+ mi->work = mi->geom;
+
+ XRRFreeCrtcInfo (crtc);
+ }
+ XRRFreeOutputInfo (info);
+ }
+ XRRFreeScreenResources (resources);
+
+ attributes_list = x_make_monitor_attribute_list (monitors,
+ n_monitors,
+ primary,
+ dpyinfo,
+ "XRandr");
+ free_monitors (monitors, n_monitors);
+ return attributes_list;
+}
+#endif /* HAVE_XRANDR */
+
+static Lisp_Object
+x_get_monitor_attributes (struct x_display_info *dpyinfo)
+{
+ Lisp_Object attributes_list = Qnil;
+ Display *dpy = dpyinfo->display;
+
+#ifdef HAVE_XRANDR
+ int xrr_event_base, xrr_error_base;
+ bool xrr_ok = false;
+ xrr_ok = XRRQueryExtension (dpy, &xrr_event_base, &xrr_error_base);
+ if (xrr_ok)
+ {
+ int xrr_major, xrr_minor;
+ XRRQueryVersion (dpy, &xrr_major, &xrr_minor);
+ xrr_ok = (xrr_major == 1 && xrr_minor >= 2) || xrr_major > 1;
+ }
+
+ if (xrr_ok)
+ attributes_list = x_get_monitor_attributes_xrandr (dpyinfo);
+#endif /* HAVE_XRANDR */
+
+#ifdef HAVE_XINERAMA
+ if (NILP (attributes_list))
+ {
+ int xin_event_base, xin_error_base;
+ bool xin_ok = false;
+ xin_ok = XineramaQueryExtension (dpy, &xin_event_base, &xin_error_base);
+ if (xin_ok && XineramaIsActive (dpy))
+ attributes_list = x_get_monitor_attributes_xinerama (dpyinfo);
+ }
+#endif /* HAVE_XINERAMA */
+
+ if (NILP (attributes_list))
+ attributes_list = x_get_monitor_attributes_fallback (dpyinfo);
+
+ return attributes_list;
+}
+
+#endif /* !USE_GTK */
+
+DEFUN ("x-display-monitor-attributes-list", Fx_display_monitor_attributes_list,
+ Sx_display_monitor_attributes_list,
+ 0, 1, 0,
+ doc: /* Return a list of physical monitor attributes on the X display TERMINAL.
+
+The optional argument TERMINAL specifies which display to ask about.
+TERMINAL should be a terminal object, a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.
+
+In addition to the standard attribute keys listed in
+`display-monitor-attributes-list', the following keys are contained in
+the attributes:
+
+ source -- String describing the source from which multi-monitor
+ information is obtained, one of \"Gdk\", \"XRandr\",
+ \"Xinerama\", or \"fallback\"
+
+Internal use only, use `display-monitor-attributes-list' instead. */)
+ (Lisp_Object terminal)
+{
+ struct x_display_info *dpyinfo = check_x_display_info (terminal);
+ Lisp_Object attributes_list = Qnil;
+
+#ifdef USE_GTK
+ double mm_width_per_pixel, mm_height_per_pixel;
+ GdkDisplay *gdpy;
+ GdkScreen *gscreen;
+ gint primary_monitor = 0, n_monitors, i;
+ Lisp_Object monitor_frames, rest, frame;
+ static const char *source = "Gdk";
+ struct MonitorInfo *monitors;
+
+ block_input ();
+ mm_width_per_pixel = ((double) WidthMMOfScreen (dpyinfo->screen)
+ / x_display_pixel_width (dpyinfo));
+ mm_height_per_pixel = ((double) HeightMMOfScreen (dpyinfo->screen)
+ / x_display_pixel_height (dpyinfo));
+ gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
+ gscreen = gdk_display_get_default_screen (gdpy);
+#if GTK_CHECK_VERSION (2, 20, 0)
+ primary_monitor = gdk_screen_get_primary_monitor (gscreen);
+#endif
+ n_monitors = gdk_screen_get_n_monitors (gscreen);
+ monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
+ monitors = xzalloc (n_monitors * sizeof *monitors);
+
+ FOR_EACH_FRAME (rest, frame)
+ {
+ struct frame *f = XFRAME (frame);
+
+ if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo
+ && !EQ (frame, tip_frame))
+ {
+ GdkWindow *gwin = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
+
+ i = gdk_screen_get_monitor_at_window (gscreen, gwin);
+ ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
+ }
+ }
+
+ for (i = 0; i < n_monitors; ++i)
+ {
+ gint width_mm = -1, height_mm = -1;
+ GdkRectangle rec, work;
+ struct MonitorInfo *mi = &monitors[i];
+
+ gdk_screen_get_monitor_geometry (gscreen, i, &rec);
+
+#if GTK_CHECK_VERSION (2, 14, 0)
+ width_mm = gdk_screen_get_monitor_width_mm (gscreen, i);
+ height_mm = gdk_screen_get_monitor_height_mm (gscreen, i);
+#endif
+ if (width_mm < 0)
+ width_mm = rec.width * mm_width_per_pixel + 0.5;
+ if (height_mm < 0)
+ height_mm = rec.height * mm_height_per_pixel + 0.5;
+
+#if GTK_CHECK_VERSION (3, 4, 0)
+ gdk_screen_get_monitor_workarea (gscreen, i, &work);
+#else
+ /* Emulate the behavior of GTK+ 3.4. */
+ {
+ XRectangle workarea_r;
+
+ if (i == primary_monitor && x_get_net_workarea (dpyinfo, &workarea_r))
+ {
+ work.x = workarea_r.x;
+ work.y = workarea_r.y;
+ work.width = workarea_r.width;
+ work.height = workarea_r.height;
+ if (! gdk_rectangle_intersect (&rec, &work, &work))
+ work = rec;
+ }
+ else
+ work = rec;
+ }
+#endif
+
+
+ mi->geom.x = rec.x;
+ mi->geom.y = rec.y;
+ mi->geom.width = rec.width;
+ mi->geom.height = rec.height;
+ mi->work.x = work.x;
+ mi->work.y = work.y;
+ mi->work.width = work.width;
+ mi->work.height = work.height;
+ mi->mm_width = width_mm;
+ mi->mm_height = height_mm;
+
+#if GTK_CHECK_VERSION (2, 14, 0)
+ mi->name = gdk_screen_get_monitor_plug_name (gscreen, i);
+#endif
+ }
+
+ attributes_list = make_monitor_attribute_list (monitors,
+ n_monitors,
+ primary_monitor,
+ monitor_frames,
+ source);
+ unblock_input ();
+#else /* not USE_GTK */
+
+ block_input ();
+ attributes_list = x_get_monitor_attributes (dpyinfo);
+ unblock_input ();
+
+#endif /* not USE_GTK */
+
+ return attributes_list;
}
/************************************************************************
validate_x_resource_name ();
- dpyinfo = x_term_init (name, (char *)0,
- SSDATA (Vx_resource_name));
+ dpyinfo = x_term_init (name, 0, SSDATA (Vx_resource_name));
if (dpyinfo == 0)
error ("Cannot connect to X server %s", SDATA (name));
- x_in_use = 1;
XSETFASTINT (Vwindow_system_version, 11);
return dpyinfo;
error ("Not using X Windows"); /* That doesn't stop us anymore. */
#endif
- if (! NILP (xrm_string))
- xrm_option = SSDATA (xrm_string);
- else
- xrm_option = (char *) 0;
+ xrm_option = NILP (xrm_string) ? 0 : SSDATA (xrm_string);
validate_x_resource_name ();
error ("Cannot connect to X server %s", SDATA (display));
}
- x_in_use = 1;
-
XSETFASTINT (Vwindow_system_version, 11);
return Qnil;
}
/* Wait for responses to all X commands issued so far for frame F. */
void
-x_sync (FRAME_PTR f)
+x_sync (struct frame *f)
{
block_input ();
XSync (FRAME_X_DISPLAY (f), False);
(Lisp_Object prop, Lisp_Object value, Lisp_Object frame,
Lisp_Object type, Lisp_Object format, Lisp_Object outer_p)
{
- struct frame *f = check_x_frame (frame);
+ struct frame *f = decode_window_system_frame (frame);
Atom prop_atom;
Atom target_type = XA_STRING;
int element_format = 8;
FRAME nil or omitted means use the selected frame. Value is PROP. */)
(Lisp_Object prop, Lisp_Object frame)
{
- struct frame *f = check_x_frame (frame);
+ struct frame *f = decode_window_system_frame (frame);
Atom prop_atom;
CHECK_STRING (prop);
(Lisp_Object prop, Lisp_Object frame, Lisp_Object type,
Lisp_Object source, Lisp_Object delete_p, Lisp_Object vector_ret_p)
{
- struct frame *f = check_x_frame (frame);
+ struct frame *f = decode_window_system_frame (frame);
Atom prop_atom;
int rc;
Lisp_Object prop_value = Qnil;
property and those are indeed in 32 bit quantities if format is
32. */
- if (32 < BITS_PER_LONG && actual_format == 32)
+ if (BITS_PER_LONG > 32 && actual_format == 32)
{
unsigned long i;
int *idata = (int *) tmp_data;
static Lisp_Object last_show_tip_args;
-static Lisp_Object
+static void
unwind_create_tip_frame (Lisp_Object frame)
{
Lisp_Object deleted;
tip_window = None;
tip_frame = Qnil;
}
-
- return deleted;
}
Lisp_Object buffer;
struct buffer *old_buffer;
- check_x ();
-
if (!dpyinfo->terminal->name)
error ("Terminal is not live, can't create new frames on it");
specbind (Qx_resource_name, name);
}
- f->resx = dpyinfo->resx;
- f->resy = dpyinfo->resy;
-
register_font_driver (&xfont_driver, f);
#ifdef HAVE_FREETYPE
#ifdef HAVE_XFT
/* Add `tooltip' frame parameter's default value. */
if (NILP (Fframe_parameter (frame, Qtooltip)))
- Fmodify_frame_parameters (frame, Fcons (Fcons (Qtooltip, Qt), Qnil));
+ Fmodify_frame_parameters (frame, list1 (Fcons (Qtooltip, Qt)));
/* FIXME - can this be done in a similar way to normal frames?
http://lists.gnu.org/archive/html/emacs-devel/2007-10/msg00641.html */
disptype = intern ("color");
if (NILP (Fframe_parameter (frame, Qdisplay_type)))
- Fmodify_frame_parameters (frame, Fcons (Fcons (Qdisplay_type, disptype),
- Qnil));
+ Fmodify_frame_parameters (frame, list1 (Fcons (Qdisplay_type, disptype)));
}
/* Set up faces after all frame parameters are known. This call
call2 (Qface_set_after_frame_default, frame, Qnil);
if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
- Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
- Qnil));
+ Fmodify_frame_parameters (frame, list1 (Fcons (Qbackground_color, bg)));
}
f->no_split = 1;
if (SCHARS (string) == 0)
string = make_unibyte_string (" ", 1);
- f = check_x_frame (frame);
+ f = decode_window_system_frame (frame);
if (NILP (timeout))
timeout = make_number (5);
else
/* Set up the frame's root window. */
w = XWINDOW (FRAME_ROOT_WINDOW (f));
- wset_left_col (w, make_number (0));
- wset_top_line (w, make_number (0));
+ w->left_col = 0;
+ w->top_line = 0;
if (CONSP (Vx_max_tooltip_size)
&& RANGED_INTEGERP (1, XCAR (Vx_max_tooltip_size), INT_MAX)
&& RANGED_INTEGERP (1, XCDR (Vx_max_tooltip_size), INT_MAX))
{
- wset_total_cols (w, XCAR (Vx_max_tooltip_size));
- wset_total_lines (w, XCDR (Vx_max_tooltip_size));
+ w->total_cols = XFASTINT (XCAR (Vx_max_tooltip_size));
+ w->total_lines = XFASTINT (XCDR (Vx_max_tooltip_size));
}
else
{
- wset_total_cols (w, make_number (80));
- wset_total_lines (w, make_number (40));
+ w->total_cols = 80;
+ w->total_lines = 40;
}
- FRAME_TOTAL_COLS (f) = XINT (w->total_cols);
+ FRAME_TOTAL_COLS (f) = w->total_cols;
adjust_glyphs (f);
w->pseudo_window_p = 1;
/* Display the tooltip text in a temporary buffer. */
old_buffer = current_buffer;
- set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
+ set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->contents));
bset_truncate_lines (current_buffer, Qnil);
clear_glyph_matrix (w->desired_matrix);
clear_glyph_matrix (w->current_matrix);
int row_width;
/* Stop at the first empty row at the end. */
- if (!row->enabled_p || !row->displays_text_p)
+ if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
break;
/* Let the row go over the full width of the frame. */
/* w->total_cols and FRAME_TOTAL_COLS want the width in columns,
not in pixels. */
width /= WINDOW_FRAME_COLUMN_WIDTH (w);
- wset_total_cols (w, make_number (width));
+ w->total_cols = width;
FRAME_TOTAL_COLS (f) = width;
adjust_glyphs (f);
clear_glyph_matrix (w->desired_matrix);
struct glyph *last;
int row_width;
- if (!row->enabled_p || !row->displays_text_p)
+ if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
break;
row->full_width_p = 1;
row_width = row->pixel_width;
#ifdef USE_GTK
if (use_dialog_box
&& use_file_dialog
- && have_menus_p ()
+ && window_system_available (SELECTED_FRAME ())
&& xg_uses_old_file_dialog ())
return Qt;
#endif
static void
file_dialog_cb (Widget widget, XtPointer client_data, XtPointer call_data)
{
- int *result = (int *) client_data;
- XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
+ int *result = client_data;
+ XmAnyCallbackStruct *cb = call_data;
*result = cb->reason;
}
static void
file_dialog_unmap_cb (Widget widget, XtPointer client_data, XtPointer call_data)
{
- int *result = (int *) client_data;
+ int *result = client_data;
*result = XmCR_CANCEL;
}
-static Lisp_Object
-clean_up_file_dialog (Lisp_Object arg)
+static void
+clean_up_file_dialog (void *arg)
{
- Widget dialog = XSAVE_POINTER (arg);
+ Widget dialog = arg;
/* Clean up. */
block_input ();
XtDestroyWidget (dialog);
x_menu_set_in_use (0);
unblock_input ();
-
- return Qnil;
}
This function is only defined on NS, MS Windows, and X Windows with the
Motif or Gtk toolkits. With the Motif toolkit, ONLY-DIR-P is ignored.
Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
- (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p)
+ (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename,
+ Lisp_Object mustmatch, Lisp_Object only_dir_p)
{
int result;
struct frame *f = SELECTED_FRAME ();
ptrdiff_t count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
- check_x ();
+ check_window_system (f);
GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
XmStringFree (default_xmstring);
}
- record_unwind_protect (clean_up_file_dialog, make_save_value (dialog, 0));
+ record_unwind_protect_ptr (clean_up_file_dialog, dialog);
/* Process events until the user presses Cancel or OK. */
x_menu_set_in_use (1);
#ifdef USE_GTK
-static Lisp_Object
-clean_up_dialog (Lisp_Object arg)
+static void
+clean_up_dialog (void)
{
x_menu_set_in_use (0);
-
- return Qnil;
}
DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
(Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p)
{
- FRAME_PTR f = SELECTED_FRAME ();
+ struct frame *f = SELECTED_FRAME ();
char *fn;
Lisp_Object file = Qnil;
Lisp_Object decoded_file;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
char *cdef_file;
- check_x ();
+ check_window_system (f);
GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
/* Prevent redisplay. */
specbind (Qinhibit_redisplay, Qt);
- record_unwind_protect (clean_up_dialog, Qnil);
+ record_unwind_protect_void (clean_up_dialog);
block_input ();
nil, it defaults to the selected frame. */)
(Lisp_Object frame, Lisp_Object ignored)
{
- FRAME_PTR f = check_x_frame (frame);
+ struct frame *f = decode_window_system_frame (frame);
Lisp_Object font;
Lisp_Object font_param;
char *default_name = NULL;
struct gcpro gcpro1, gcpro2;
ptrdiff_t count = SPECPDL_INDEX ();
- check_x ();
-
if (popup_activated ())
error ("Trying to use a menu from within a menu-entry");
/* Prevent redisplay. */
specbind (Qinhibit_redisplay, Qt);
- record_unwind_protect (clean_up_dialog, Qnil);
+ record_unwind_protect_void (clean_up_dialog);
block_input ();
Keyboard
***********************************************************************/
-#ifdef HAVE_XKBGETKEYBOARD
+#ifdef HAVE_XKB
#include <X11/XKBlib.h>
#include <X11/keysym.h>
#endif
present and mapped to the usual X keysyms. */)
(Lisp_Object frame)
{
-#ifdef HAVE_XKBGETKEYBOARD
+#ifndef HAVE_XKB
+ return Qlambda;
+#else
XkbDescPtr kb;
- struct frame *f = check_x_frame (frame);
+ struct frame *f = decode_window_system_frame (frame);
Display *dpy = FRAME_X_DISPLAY (f);
Lisp_Object have_keys;
int major, minor, op, event, error_code;
}
unblock_input ();
return have_keys;
-#else /* not HAVE_XKBGETKEYBOARD */
- return Qlambda;
-#endif /* not HAVE_XKBGETKEYBOARD */
+#endif
}
void
syms_of_xfns (void)
{
- /* This is zero if not using X windows. */
- x_in_use = 0;
-
/* The section below is built by the lisp expression at the top of the file,
just above where these variables are declared. */
/*&&& init symbols here &&&*/
defsubr (&Sx_display_visual_class);
defsubr (&Sx_display_backing_store);
defsubr (&Sx_display_save_under);
+ defsubr (&Sx_display_monitor_attributes_list);
defsubr (&Sx_wm_set_size_hint);
defsubr (&Sx_create_frame);
defsubr (&Sx_open_connection);
defsubr (&Sx_focus_frame);
defsubr (&Sx_backspace_delete_keys_p);
- /* Setting callback functions for fontset handler. */
- check_window_system_func = check_x;
-
defsubr (&Sx_show_tip);
defsubr (&Sx_hide_tip);
tip_timer = Qnil;