Implement display-monitor-attributes-list for NS.

* lisp/frame.el (display-monitor-attributes-list): Add NS case.
(ns-display-monitor-attributes-list): Declare.

* src/nsfns.m: Include IOGraphicsLib.h if Cocoa.
(Qgeometry, Qworkarea, Qmm_size, Qframes, Qsource): Declare.
(MonitorInfo): New struct.
(free_monitors, ns_screen_name, ns_make_monitor_attribute_list)
(Fns_display_monitor_attributes_list): New functions.
(display-usable-bounds): Remove.
(syms_of_nsfns): DEFSYM Qgeometry, Qworkarea, Qmm_size, Qframes and
Qsource.
This commit is contained in:
Jan Djärv 2013-05-09 17:17:38 +02:00
parent 7583e2a0e2
commit 4465bfb465
5 changed files with 244 additions and 24 deletions

View file

@ -4247,6 +4247,9 @@ case "$opsys" in
## each); under Cocoa 31 commands are required.
if test "$HAVE_NS" = "yes"; then
libs_nsgui="-framework AppKit"
if test "$NS_IMPL_COCOA" = "yes"; then
libs_nsgui="$libs_nsgui -framework IOKit"
fi
headerpad_extra=6C8
else
libs_nsgui=

View file

@ -1,3 +1,8 @@
2013-05-09 Jan Djärv <jan.h.d@swipnet.se>
* frame.el (display-monitor-attributes-list): Add NS case.
(ns-display-monitor-attributes-list): Declare.
2013-05-09 Ulrich Mueller <ulm@gentoo.org>
* descr-text.el (describe-char): Fix %d/%x typo. (Bug#14360)

View file

@ -1495,6 +1495,8 @@ The value is one of the symbols `static-gray', `gray-scale',
(declare-function x-display-monitor-attributes-list "xfns.c"
(&optional terminal))
(declare-function ns-display-monitor-attributes-list "nsfns.c"
(&optional terminal))
(defun display-monitor-attributes-list (&optional display)
"Return a list of physical monitor attributes on DISPLAY.
@ -1528,6 +1530,8 @@ monitors."
(cond
((eq frame-type 'x)
(x-display-monitor-attributes-list display))
((eq frame-type 'ns)
(ns-display-monitor-attributes-list display))
(t
(let ((geometry (list 0 0 (display-pixel-width display)
(display-pixel-height display))))

View file

@ -1,3 +1,14 @@
2013-05-09 Jan Djärv <jan.h.d@swipnet.se>
* nsfns.m: Include IOGraphicsLib.h if Cocoa.
(Qgeometry, Qworkarea, Qmm_size, Qframes, Qsource): Declare.
(MonitorInfo): New struct.
(free_monitors, ns_screen_name, ns_make_monitor_attribute_list)
(Fns_display_monitor_attributes_list): New functions.
(display-usable-bounds): Remove.
(syms_of_nsfns): DEFSYM Qgeometry, Qworkarea, Qmm_size, Qframes and
Qsource.
2013-05-09 Paul Eggert <eggert@cs.ucla.edu>
* xterm.h (GTK_PREREQ): Remove, replacing with GTK_CHECK_VERSION.

View file

@ -44,6 +44,10 @@ Updated by Christian Limpach (chris@nice.ch)
#include "fontset.h"
#include "font.h"
#ifdef NS_IMPL_COCOA
#include <IOKit/graphics/IOGraphicsLib.h>
#endif
#if 0
int fns_trace_num = 1;
#define NSTRACE(x) fprintf (stderr, "%s:%d: [%d] " #x "\n", \
@ -101,6 +105,8 @@ Updated by Christian Limpach (chris@nice.ch)
static ptrdiff_t image_cache_refcount;
#endif
static Lisp_Object Qgeometry, Qworkarea, Qmm_size, Qframes, Qsource;
/* ==========================================================================
Internal utility functions
@ -2321,35 +2327,221 @@ and GNUstep implementations ("distributor-specific release
return make_number ((int) [ns_get_screen (display) frame].size.height);
}
struct MonitorInfo {
XRectangle geom, work;
int mm_width, mm_height;
char *name;
};
DEFUN ("display-usable-bounds", Fns_display_usable_bounds,
Sns_display_usable_bounds, 0, 1, 0,
doc: /* Return the bounds of the usable part of the screen.
The return value is a list of integers (LEFT TOP WIDTH HEIGHT), which
are the boundaries of the usable part of the screen, excluding areas
reserved for the Mac menu, dock, and so forth.
The screen queried corresponds to DISPLAY, which should be either a
frame, a display name (a string), or terminal ID. If omitted or nil,
that stands for the selected frame's display. */)
(Lisp_Object display)
static void
free_monitors (struct MonitorInfo *monitors, int n_monitors)
{
NSScreen *screen;
NSRect vScreen;
int i;
for (i = 0; i < n_monitors; ++i)
xfree (monitors[i].name);
xfree (monitors);
}
check_ns_display_info (display);
screen = ns_get_screen (display);
if (!screen)
#ifdef NS_IMPL_COCOA
/* Returns the name for the screen that DICT came from, or NULL.
Caller must free return value.
*/
char *
ns_screen_name (CGDirectDisplayID did)
{
char *name = NULL;
NSDictionary *info = (NSDictionary *)
IODisplayCreateInfoDictionary (CGDisplayIOServicePort (did),
kIODisplayOnlyPreferredName);
NSDictionary *names
= [info objectForKey:
[NSString stringWithUTF8String:kDisplayProductName]];
if ([names count] > 0) {
NSString *n = [names objectForKey: [[names allKeys] objectAtIndex:0]];
if (n != nil)
name = xstrdup ([n UTF8String]);
}
[info release];
return name;
}
#endif
static Lisp_Object
ns_make_monitor_attribute_list (struct MonitorInfo *monitors,
int n_monitors,
int primary_monitor,
const char *source)
{
Lisp_Object monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
Lisp_Object frame, rest, attributes_list = Qnil;
Lisp_Object primary_monitor_attributes = Qnil;
NSArray *screens = [NSScreen screens];
int i;
FOR_EACH_FRAME (rest, frame)
{
struct frame *f = XFRAME (frame);
if (FRAME_NS_P (f))
{
NSView *view = FRAME_NS_VIEW (f);
NSScreen *screen = [[view window] screen];
NSUInteger k;
i = -1;
for (k = 0; i == -1 && k < [screens count]; ++k)
{
if ([screens objectAtIndex: k] == screen)
i = (int)k;
}
if (i > -1)
ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
}
}
for (i = 0; i < n_monitors; ++i)
{
Lisp_Object geometry, workarea, attributes = Qnil;
struct MonitorInfo *mi = &monitors[i];
if (mi->geom.width == 0) continue;
workarea = list4i (mi->work.x, mi->work.y,
mi->work.width, mi->work.height);
geometry = list4i (mi->geom.x, mi->geom.y,
mi->geom.width, mi->geom.height);
attributes = Fcons (Fcons (Qsource,
make_string (source, strlen (source))),
attributes);
attributes = Fcons (Fcons (Qframes, AREF (monitor_frames, i)),
attributes);
attributes = Fcons (Fcons (Qmm_size,
list2i (mi->mm_width, mi->mm_height)),
attributes);
attributes = Fcons (Fcons (Qworkarea, workarea), attributes);
attributes = Fcons (Fcons (Qgeometry, geometry), attributes);
if (mi->name)
attributes = Fcons (Fcons (Qname, make_string (mi->name,
strlen (mi->name))),
attributes);
if (i == primary_monitor)
primary_monitor_attributes = attributes;
else
attributes_list = Fcons (attributes, attributes_list);
}
if (!NILP (primary_monitor_attributes))
attributes_list = Fcons (primary_monitor_attributes, attributes_list);
return attributes_list;
}
DEFUN ("ns-display-monitor-attributes-list",
Fns_display_monitor_attributes_list,
Sns_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, \"NS\" is always the source."
Internal use only, use `display-monitor-attributes-list' instead. */)
(Lisp_Object terminal)
{
struct terminal *term = get_terminal (terminal, 1);
NSArray *screens;
NSUInteger i, n_monitors;
struct MonitorInfo *monitors;
Lisp_Object attributes_list = Qnil;
CGFloat primary_display_height = 0;
if (term->type != output_ns)
return Qnil;
vScreen = [screen visibleFrame];
screens = [NSScreen screens];
n_monitors = [screens count];
if (n_monitors == 0)
return Qnil;
/* NS coordinate system is upside-down.
Transform to screen-specific coordinates. */
return list4i (vScreen.origin.x,
[screen frame].size.height
- vScreen.size.height - vScreen.origin.y,
vScreen.size.width, vScreen.size.height);
monitors = (struct MonitorInfo *) xzalloc (n_monitors * sizeof (*monitors));
for (i = 0; i < [screens count]; ++i)
{
NSScreen *s = [screens objectAtIndex:i];
struct MonitorInfo *m = &monitors[i];
NSRect fr = [s frame];
NSRect vfr = [s visibleFrame];
NSDictionary *dict = [s deviceDescription];
NSValue *resval = [dict valueForKey:NSDeviceResolution];
short y, vy;
#ifdef NS_IMPL_COCOA
NSNumber *nid = [dict objectForKey:@"NSScreenNumber"];
CGDirectDisplayID did = [nid unsignedIntValue];
#endif
if (i == 0)
{
primary_display_height = fr.size.height;
y = (short) fr.origin.y;
vy = (short) vfr.origin.y;
}
else
{
// Flip y coordinate as NS has y starting from the bottom.
y = (short) (primary_display_height - fr.size.height - fr.origin.y);
vy = (short) (primary_display_height -
vfr.size.height - vfr.origin.y);
}
m->geom.x = (short) fr.origin.x;
m->geom.y = y;
m->geom.width = (unsigned short) fr.size.width;
m->geom.height = (unsigned short) fr.size.height;
m->work.x = (short) vfr.origin.x;
// y is flipped on NS, so vy - y are pixels missing at the bottom,
// and fr.size.height - vfr.size.height are pixels missing in total.
// Pixels missing at top are
// fr.size.height - vfr.size.height - vy + y.
// work.y is then pixels missing at top + y.
m->work.y = (short) (fr.size.height - vfr.size.height) - vy + y + y;
m->work.width = (unsigned short) vfr.size.width;
m->work.height = (unsigned short) vfr.size.height;
#ifdef NS_IMPL_COCOA
m->name = ns_screen_name (did);
{
CGSize mms = CGDisplayScreenSize (did);
m->mm_width = (int) mms.width;
m->mm_height = (int) mms.height;
}
#else
// Assume 92 dpi as x-display-mm-height/x-display-mm-width does.
m->mm_width = (int) (25.4 * fr.size.width / 92.0);
m->mm_height = (int) (25.4 * fr.size.height / 92.0);
#endif
}
// Primary monitor is always first for NS.
attributes_list = ns_make_monitor_attribute_list (monitors, n_monitors,
0, "NS");
free_monitors (monitors, n_monitors);
return attributes_list;
}
@ -2729,6 +2921,11 @@ - (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename
void
syms_of_nsfns (void)
{
DEFSYM (Qgeometry, "geometry");
DEFSYM (Qworkarea, "workarea");
DEFSYM (Qmm_size, "mm-size");
DEFSYM (Qframes, "frames");
DEFSYM (Qsource, "source");
Qfontsize = intern_c_string ("fontsize");
staticpro (&Qfontsize);
@ -2774,7 +2971,7 @@ - (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename
defsubr (&Sx_server_version);
defsubr (&Sx_display_pixel_width);
defsubr (&Sx_display_pixel_height);
defsubr (&Sns_display_usable_bounds);
defsubr (&Sns_display_monitor_attributes_list);
defsubr (&Sx_display_mm_width);
defsubr (&Sx_display_mm_height);
defsubr (&Sx_display_screens);