emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] /srv/bzr/emacs/trunk r112534: Implement display-monitor-at


From: Jan D.
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r112534: Implement display-monitor-attributes-list for NS.
Date: Thu, 09 May 2013 17:17:38 +0200
User-agent: Bazaar (2.6b2)

------------------------------------------------------------
revno: 112534
committer: Jan D. <address@hidden>
branch nick: trunk
timestamp: Thu 2013-05-09 17:17:38 +0200
message:
  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.
modified:
  configure.ac
  lisp/ChangeLog
  lisp/frame.el
  src/ChangeLog
  src/nsfns.m
=== modified file 'configure.ac'
--- a/configure.ac      2013-05-07 21:34:03 +0000
+++ b/configure.ac      2013-05-09 15:17:38 +0000
@@ -4247,6 +4247,9 @@
    ## 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=

=== modified file 'lisp/ChangeLog'
--- a/lisp/ChangeLog    2013-05-09 02:44:12 +0000
+++ b/lisp/ChangeLog    2013-05-09 15:17:38 +0000
@@ -1,3 +1,8 @@
+2013-05-09  Jan Djärv  <address@hidden>
+
+       * frame.el (display-monitor-attributes-list): Add NS case.
+       (ns-display-monitor-attributes-list): Declare.
+
 2013-05-09  Ulrich Mueller  <address@hidden>
 
        * descr-text.el (describe-char): Fix %d/%x typo.  (Bug#14360)

=== modified file 'lisp/frame.el'
--- a/lisp/frame.el     2013-05-07 01:12:22 +0000
+++ b/lisp/frame.el     2013-05-09 15:17:38 +0000
@@ -1495,6 +1495,8 @@
 
 (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 @@
     (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))))

=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2013-05-09 14:49:56 +0000
+++ b/src/ChangeLog     2013-05-09 15:17:38 +0000
@@ -1,3 +1,14 @@
+2013-05-09  Jan Djärv  <address@hidden>
+
+       * 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  <address@hidden>
 
        * xterm.h (GTK_PREREQ): Remove, replacing with GTK_CHECK_VERSION.

=== modified file 'src/nsfns.m'
--- a/src/nsfns.m       2013-05-05 05:03:08 +0000
+++ b/src/nsfns.m       2013-05-09 15:17:38 +0000
@@ -44,6 +44,10 @@
 #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 @@
 static ptrdiff_t image_cache_refcount;
 #endif
 
+static Lisp_Object Qgeometry, Qworkarea, Qmm_size, Qframes, Qsource;
+
 /* ==========================================================================
 
     Internal utility functions
@@ -2321,35 +2327,221 @@
   return make_number ((int) [ns_get_screen (display) frame].size.height);
 }
 
-
-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)
-{
-  NSScreen *screen;
-  NSRect vScreen;
-
-  check_ns_display_info (display);
-  screen = ns_get_screen (display);
-  if (!screen)
-    return Qnil;
-
-  vScreen = [screen visibleFrame];
-
-  /* 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);
+struct MonitorInfo {
+  XRectangle geom, work;
+  int mm_width, mm_height;
+  char *name;
+};
+
+static void
+free_monitors (struct MonitorInfo *monitors, int n_monitors)
+{
+  int i;
+  for (i = 0; i < n_monitors; ++i)
+    xfree (monitors[i].name);
+  xfree (monitors);
+}
+
+#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;
+
+  screens = [NSScreen screens];
+  n_monitors = [screens count];
+  if (n_monitors == 0)
+    return Qnil;
+
+  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 @@
 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 @@
   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);


reply via email to

[Prev in Thread] Current Thread [Next in Thread]