Author: manolo
Date: 2011-09-29 09:04:24 -0700 (Thu, 29 Sep 2011)
New Revision: 9084
Log:
Fix STR#2695 & 2697: correct computation of work areas with multiple screens.

This introduces 3 new functions
static void Fl::screen_work_area(X,Y,W,H)
static void Fl::screen_work_area(X,Y,W,H,mx,my)
static void Fl::screen_work_area(X,Y,W,H,screen_no)
that compute screen work areas and are used by FLTK to position menu windows.

The Fl::x(),y(),w(),h() functions are made consistent across platforms: they 
return
the origin/size of the work area of the main screen (as far as possible, see 
below).

On the Mac OS platform, all screen functions reflect changes in screen number 
and 
positions without requiring the application to restart.

On the X11 platform, I did not find an API to compute the main screen work area
in all conditions. What's used does compute the correct work area when there's
a single screen, but not when there are several, because it returns an area that
encompasses all screens. The implemented workaround is that Fl::x(),y(),w(),h() 
and Fl::screen_work_area(X,Y,W,H,0) return the exact work area when there's 
a single screen, and return the full screen area when there are several.


Modified:
   branches/branch-1.3/FL/Fl.H
   branches/branch-1.3/FL/mac.H
   branches/branch-1.3/src/Fl_Menu.cxx
   branches/branch-1.3/src/Fl_cocoa.mm
   branches/branch-1.3/src/Fl_x.cxx
   branches/branch-1.3/src/screen_xywh.cxx

Modified: branches/branch-1.3/FL/Fl.H
===================================================================
--- branches/branch-1.3/FL/Fl.H 2011-09-28 20:44:35 UTC (rev 9083)
+++ branches/branch-1.3/FL/Fl.H 2011-09-29 16:04:24 UTC (rev 9084)
@@ -757,13 +757,13 @@
        fl global screen functions declared in <FL/Fl.H>
      @{ */
   // screen size:
-  /** Returns the origin of the current screen work area, where 0 indicates 
the left side of the screen. */
+  /** Returns the leftmost x coordinate of the main screen work area. */
   static int x(); // platform dependent
-  /** Returns the origin of the current screen work area, where 0 indicates 
the top edge of the screen. */
+  /** Returns the topmost y coordinate of the main screen work area. */
   static int y(); // platform dependent
-  /** Returns the width of the screen work area in pixels. */
+  /** Returns the width in pixels of the main screen work area. */
   static int w(); // platform dependent
-  /** Returns the height of the screen work area in pixels. */
+  /** Returns the height in pixels of the main screen work area. */
   static int h(); // platform dependent
 
   // multi-head support:
@@ -780,6 +780,16 @@
   static void screen_xywh(int &X, int &Y, int &W, int &H, int n); 
   static void screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my, int 
mw, int mh);
   static void screen_dpi(float &h, float &v, int n=0);
+  static void screen_work_area(int &X, int &Y, int &W, int &H, int mx, int my);
+  static void screen_work_area(int &X, int &Y, int &W, int &H, int n);
+  /** 
+   Gets the bounding box of the work area of the screen that contains the 
mouse pointer.
+   \param[out]  X,Y,W,H the work area bounding box
+   \see void screen_work_area(int &x, int &y, int &w, int &h, int mx, int my) 
+   */
+  static void screen_work_area(int &X, int &Y, int &W, int &H) {
+    screen_work_area(X, Y, W, H, e_x_root, e_y_root);
+  }
 
   /**   @} */
 

Modified: branches/branch-1.3/FL/mac.H
===================================================================
--- branches/branch-1.3/FL/mac.H        2011-09-28 20:44:35 UTC (rev 9083)
+++ branches/branch-1.3/FL/mac.H        2011-09-29 16:04:24 UTC (rev 9084)
@@ -125,6 +125,8 @@
   static CGContextRef nwse_cursor_image(void);
   static CGContextRef none_cursor_image(void);
   static void *get_carbon_function(const char *name);
+  static void screen_work_area(int &X, int &Y, int &W, int &H, int n); // 
compute work area of a given screen
+  static void mac_screen_init(void); // recompute screen number and dimensions
 private:
   static void relink(Fl_Window*, Fl_Window*);
   bool subwindow;

Modified: branches/branch-1.3/src/Fl_Menu.cxx
===================================================================
--- branches/branch-1.3/src/Fl_Menu.cxx 2011-09-28 20:44:35 UTC (rev 9083)
+++ branches/branch-1.3/src/Fl_Menu.cxx 2011-09-29 16:04:24 UTC (rev 9084)
@@ -276,13 +276,7 @@
   int scr_x, scr_y, scr_w, scr_h;
   int tx = X, ty = Y;
 
-  Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h);
-#ifdef __APPLE__
-  scr_x = Fl::x();
-  scr_w = Fl::w();
-#endif
-  scr_y = Fl::y();
-  scr_h = Fl::h();
+  Fl::screen_work_area(scr_x, scr_y, scr_w, scr_h);
   if (!right_edge || right_edge > scr_x+scr_w) right_edge = scr_x+scr_w;
 
   end();
@@ -417,8 +411,8 @@
   int scr_y, scr_h;
   int Y = y()+Fl::box_dx(box())+2+n*itemheight;
 
-  scr_y = Fl::y();
-  scr_h = Fl::h();
+  int xx, ww;
+  Fl::screen_work_area(xx, scr_y, ww, scr_h);
   if (Y <= scr_y) Y = scr_y-Y+10;
   else {
     Y = Y+itemheight-scr_h-scr_y;

Modified: branches/branch-1.3/src/Fl_cocoa.mm
===================================================================
--- branches/branch-1.3/src/Fl_cocoa.mm 2011-09-28 20:44:35 UTC (rev 9083)
+++ branches/branch-1.3/src/Fl_cocoa.mm 2011-09-29 16:04:24 UTC (rev 9084)
@@ -109,6 +109,7 @@
 // forward declarations of variables in this file
 static int got_events = 0;
 static Fl_Window* resize_from_system;
+static int main_screen_height; // height of menubar-containing screen used to 
convert between Cocoa and FLTK global screen coordinates
 
 #if CONSOLIDATE_MOTION
 static Fl_Window* send_motion;
@@ -675,6 +676,7 @@
   return retval;
 }
 
+
 // updates Fl::e_x, Fl::e_y, Fl::e_x_root, and Fl::e_y_root
 static void update_e_xy_and_e_xy_root(NSWindow *nsw)
 {
@@ -684,7 +686,7 @@
   Fl::e_y = int([[nsw contentView] frame].size.height - pt.y);
   pt = [NSEvent mouseLocation];
   Fl::e_x_root = int(pt.x);
-  Fl::e_y_root = int([[nsw screen] frame].size.height - pt.y);
+  Fl::e_y_root = int(main_screen_height - pt.y);
 }
 
 /*
@@ -902,16 +904,6 @@
 }
 
 
-/*
- * initialize the Mac toolboxes, dock status, and set the default menubar
- */
-
-extern "C" {
-  extern OSErr CPSEnableForegroundOperation(ProcessSerialNumber *psn, UInt32 
_arg2,
-                                            UInt32 _arg3, UInt32 _arg4, UInt32 
_arg5);
-}
-
-
 @interface FLDelegate : NSObject 
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
 <NSWindowDelegate, NSApplicationDelegate>
@@ -929,6 +921,7 @@
 - (void)anywindowwillclosenotif:(NSNotification *)notif;
 - 
(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender;
 - (void)applicationDidBecomeActive:(NSNotification *)notify;
+- (void)applicationDidChangeScreenParameters:(NSNotification *)aNotification;
 - (void)applicationWillResignActive:(NSNotification *)notify;
 - (void)applicationWillHide:(NSNotification *)notify;
 - (void)applicationWillUnhide:(NSNotification *)notify;
@@ -946,7 +939,7 @@
   pt.y = [[nsw contentView] frame].size.height;
   pt2 = [nsw convertBaseToScreen:pt];
   update_e_xy_and_e_xy_root(nsw);
-  window->position((int)pt2.x, (int)([[nsw screen] frame].size.height - 
pt2.y));
+  window->position((int)pt2.x, (int)(main_screen_height - pt2.y));
   if ([nsw containsGLsubwindow] ) {
     [nsw display];// redraw window after moving if it contains OpenGL 
subwindows
   }
@@ -965,7 +958,7 @@
   resize_from_system = window;
   update_e_xy_and_e_xy_root(nsw);
   window->resize((int)pt2.x, 
-                 (int)([[nsw screen] frame].size.height - pt2.y),
+                 (int)(main_screen_height - pt2.y),
                 (int)r.size.width,
                 (int)r.size.height);
   fl_unlock_function();
@@ -1092,6 +1085,21 @@
   }
   fl_unlock_function();
 }
+- (void)applicationDidChangeScreenParameters:(NSNotification *)unused
+{ // react to changes in screen numbers and positions
+  main_screen_height = [[[NSScreen screens] objectAtIndex:0] 
frame].size.height;
+  Fl_X::mac_screen_init();
+  // FLTK windows have already been notified they were moved,
+  // but they had the old main_screen_height, so they must be notified again.
+  NSArray *windows = [NSApp windows];
+  int count = [windows count];
+  for (int i = 0; i < count; i++) {
+    NSWindow *win = [windows objectAtIndex:i];
+    if ([win isKindOfClass:[FLWindow class]]) {
+      [[NSNotificationCenter defaultCenter] 
postNotificationName:NSWindowDidMoveNotification object:win];
+      }
+    }
+}
 - (void)applicationWillResignActive:(NSNotification *)notify
 {
   fl_lock_function();
@@ -1213,7 +1221,10 @@
 }
 @end
 
-static FLDelegate *mydelegate;
+extern "C" {
+  OSErr CPSEnableForegroundOperation(ProcessSerialNumber *psn, UInt32 _arg2,
+                                    UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
+}
 
 void fl_open_display() {
   static char beenHereDoneThat = 0;
@@ -1224,8 +1235,7 @@
     if (need_new_nsapp) [NSApplication sharedApplication];
     NSAutoreleasePool *localPool;
     localPool = [[NSAutoreleasePool alloc] init]; // never released
-    mydelegate = [[FLDelegate alloc] init];
-    [NSApp setDelegate:mydelegate];
+    [NSApp setDelegate:[[FLDelegate alloc] init]];
     if (need_new_nsapp) [NSApp finishLaunching];
 
     // empty the event queue but keep system events for drag&drop of files at 
launch
@@ -1266,17 +1276,12 @@
         // both TransformProcessType and CPSEnableForegroundOperation, the 
following
         // conditional code compiled on 10.2 will still work on newer 
releases...
         OSErr err;
-#if __LP64__
-        err = TransformProcessType(&cur_psn, 
kProcessTransformToForegroundApplication);
-#else
-        
-#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3
         if (TransformProcessType != NULL) {
           err = TransformProcessType(&cur_psn, 
kProcessTransformToForegroundApplication);
         } else
-#endif // MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
+#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3
           err = CPSEnableForegroundOperation(&cur_psn, 0x03, 0x3C, 0x2C, 
0x1103);
-#endif // __LP64__
         if (err == noErr) {
           SetFrontProcess( &cur_psn );
         }
@@ -1285,10 +1290,11 @@
     if (![NSApp servicesMenu]) createAppleMenu();
     fl_system_menu = [NSApp mainMenu];
     
-    [[NSNotificationCenter defaultCenter] addObserver:mydelegate 
+    [[NSNotificationCenter defaultCenter] addObserver:[NSApp delegate] 
               selector:@selector(anywindowwillclosenotif:) 
                   name:NSWindowWillCloseNotification 
                 object:nil];
+    [[NSNotificationCenter defaultCenter] 
postNotificationName:NSApplicationDidChangeScreenParametersNotification 
object:NSApp];
   }
 }
 
@@ -1319,38 +1325,46 @@
 }
 
 /*
- * smallest x ccordinate in screen space
+ * smallest x coordinate in screen space of work area of menubar-containing 
display
  */
 int Fl::x() {
-  return int([[NSScreen mainScreen] visibleFrame].origin.x);
+  return int([[[NSScreen screens] objectAtIndex:0] visibleFrame].origin.x);
 }
 
 
 /*
- * smallest y coordinate in screen space
+ * smallest y coordinate in screen space of work area of menubar-containing 
display
  */
 int Fl::y() {
-  NSRect all = [[NSScreen mainScreen] frame];
-  NSRect visible = [[NSScreen mainScreen] visibleFrame];
-  return int(all.size.height - (visible.origin.y + visible.size.height));
+  NSRect visible = [[[NSScreen screens] objectAtIndex:0] visibleFrame];
+  return int(main_screen_height - (visible.origin.y + visible.size.height));
 }
 
 
 /*
- * screen width
+ * width of work area of menubar-containing display
  */
 int Fl::w() {
-  return int([[NSScreen mainScreen] visibleFrame].size.width);
+  return int([[[NSScreen screens] objectAtIndex:0] visibleFrame].size.width);
 }
 
 
 /*
- * screen height
+ * height of work area of menubar-containing display
  */
 int Fl::h() {
-  return int([[NSScreen mainScreen] visibleFrame].size.height);
+  return int([[[NSScreen screens] objectAtIndex:0] visibleFrame].size.height);
 }
 
+// computes the work area of the nth screen (screen #0 has the menubar)
+void Fl_X::screen_work_area(int &X, int &Y, int &W, int &H, int n)
+{
+    NSRect r = [[[NSScreen screens] objectAtIndex:n] visibleFrame];
+    X   = int(r.origin.x);
+    Y   = main_screen_height - int(r.origin.y + r.size.height);
+    W   = int(r.size.width);
+    H   = int(r.size.height);
+}
 
 /*
  * get the current mouse pointer world coordinates
@@ -1360,7 +1374,7 @@
   fl_open_display();
   NSPoint pt = [NSEvent mouseLocation];
   x = int(pt.x);
-  y = int([[NSScreen mainScreen] frame].size.height - pt.y);
+  y = int(main_screen_height - pt.y);
 }
 
 
@@ -1438,7 +1452,7 @@
   NSArray *a = [NSScreen screens]; int count = (int)[a count]; NSRect r; int i;
   for( i = 0; i < count; i++) {
     r = [[a objectAtIndex:i] frame];
-    cy = int(r.size.height - cy);
+    r.origin.y = main_screen_height - (r.origin.y + r.size.height); // use 
FLTK's multiscreen coordinates
     if (   cx >= r.origin.x && cx <= r.origin.x + r.size.width
         && cy >= r.origin.y && cy <= r.origin.y + r.size.height)
       break;
@@ -1449,8 +1463,9 @@
   if (!gd) {
     for( i = 0; i < count; i++) {
       r = [[a objectAtIndex:i] frame];
+      r.origin.y = main_screen_height - (r.origin.y + r.size.height); // use 
FLTK's multiscreen coordinates
       if (    X >= r.origin.x && X <= r.origin.x + r.size.width
-          && r.size.height - Y >= r.origin.y  && r.size.height - Y <= 
r.origin.y + r.size.height)
+          && Y >= r.origin.y  && Y <= r.origin.y + r.size.height)
         break;
     }
     if (i < count) gd = [a objectAtIndex:i];
@@ -1459,8 +1474,9 @@
   if (!gd) {
     for( i = 0; i < count; i++) {
       r = [[a objectAtIndex:i] frame];
+      r.origin.y = main_screen_height - (r.origin.y + r.size.height); // use 
FLTK's multiscreen coordinates
       if (    R >= r.origin.x && R <= r.origin.x + r.size.width
-          && r.size.height - Y >= r.origin.y  && r.size.height - Y <= 
r.origin.y + r.size.height)
+          && Y >= r.origin.y  && Y <= r.origin.y + r.size.height)
         break;
     }
     if (i < count) gd = [a objectAtIndex:i];
@@ -1469,8 +1485,9 @@
   if (!gd) {
     for( i = 0; i < count; i++) {
       r = [[a objectAtIndex:i] frame];
+      r.origin.y = main_screen_height - (r.origin.y + r.size.height); // use 
FLTK's multiscreen coordinates
       if (    X >= r.origin.x && X <= r.origin.x + r.size.width
-          && Y-H >= r.origin.y  && Y-H <= r.origin.y + r.size.height)
+          && Y+H >= r.origin.y  && Y+H <= r.origin.y + r.size.height)
         break;
     }
     if (i < count) gd = [a objectAtIndex:i];
@@ -1479,8 +1496,9 @@
   if (!gd) {
     for( i = 0; i < count; i++) {
       r = [[a objectAtIndex:i] frame];
+      r.origin.y = main_screen_height - (r.origin.y + r.size.height); // use 
FLTK's multiscreen coordinates
       if (    R >= r.origin.x && R <= r.origin.x + r.size.width
-          && Y-H >= r.origin.y  && Y-H <= r.origin.y + r.size.height)
+          && Y+H >= r.origin.y  && Y+H <= r.origin.y + r.size.height)
         break;
     }
     if (i < count) gd = [a objectAtIndex:i];
@@ -1490,11 +1508,11 @@
   if (!gd) gd = [a objectAtIndex:0];
   if (gd) {
     r = [gd visibleFrame];
-    int sh = int([gd frame].size.height);
+    r.origin.y = main_screen_height - (r.origin.y + r.size.height); // use 
FLTK's multiscreen coordinates
     if ( R > r.origin.x + r.size.width ) X -= int(R - (r.origin.x + 
r.size.width));
-    if ( B > sh - r.origin.y ) Y -= int(B - (sh - r.origin.y));
+    if ( B > r.size.height + r.origin.y ) Y -= int(B - (r.size.height + 
r.origin.y));
     if ( X < r.origin.x ) X = int(r.origin.x);
-    if ( Y < sh - (r.origin.y + r.size.height) ) Y = int(sh - (r.origin.y + 
r.size.height));
+    if ( Y < r.origin.y ) Y = int(r.origin.y);
   }
   
   // Return the client area's top left corner in (X,Y)
@@ -2024,7 +2042,7 @@
       hp += 2*by+bt;
     }
     if (!(w->flags() & Fl_Window::FORCE_POSITION)) {
-      // use the Carbon functions below for default window positioning
+      // default window positioning on the main screen
       w->x(xyPos+Fl::x());
       w->y(xyPos+Fl::y());
       xyPos += 25;
@@ -2054,10 +2072,9 @@
     x->xidNext = 0;
     x->gc = 0;
          
-    NSRect srect = [[NSScreen mainScreen] frame];
     NSRect crect;
     crect.origin.x = w->x(); 
-    crect.origin.y = srect.size.height - (w->y() + w->h());
+    crect.origin.y = main_screen_height - (w->y() + w->h());
     crect.size.width=w->w(); 
     crect.size.height=w->h();
     FLWindow *cw = [[FLWindow alloc] initWithFl_W:w 
@@ -2105,7 +2122,7 @@
     w->set_visible();
     if ( w->border() || (!w->modal() && !w->tooltip_window()) ) 
Fl::handle(FL_FOCUS, w);
     Fl::first_window(w);
-    [cw setDelegate:mydelegate];
+    [cw setDelegate:[NSApp delegate]];
     if (fl_show_iconic) { 
       fl_show_iconic = 0;
       [cw miniaturize:nil];
@@ -2118,8 +2135,7 @@
     w->h(int(crect.size.height));
     crect = [cw frame];
     w->x(int(crect.origin.x));
-    srect = [[cw screen] frame];
-    w->y(int(srect.size.height - (crect.origin.y + w->h())));
+    w->y(int(main_screen_height - (crect.origin.y + w->h())));
     
     int old_event = Fl::e_number;
     w->handle(Fl::e_number = FL_SHOW);
@@ -2235,14 +2251,14 @@
       else get_window_frame_sizes(bx, by, bt);
       NSRect dim;
       dim.origin.x = X;
-      dim.origin.y = [[(NSWindow*)i->xid screen] frame].size.height - (Y + H);
+      dim.origin.y = main_screen_height - (Y + H);
       dim.size.width = W;
       dim.size.height = H + bt;
       [(NSWindow*)i->xid setFrame:dim display:YES];
     } else {
       NSPoint pt; 
       pt.x = X; 
-      pt.y = [[(NSWindow*)i->xid screen] frame].size.height - (Y + h());
+      pt.y = main_screen_height - (Y + h());
       [(NSWindow*)i->xid setFrameOrigin:pt];
     }
   }

Modified: branches/branch-1.3/src/Fl_x.cxx
===================================================================
--- branches/branch-1.3/src/Fl_x.cxx    2011-09-28 20:44:35 UTC (rev 9083)
+++ branches/branch-1.3/src/Fl_x.cxx    2011-09-29 16:04:24 UTC (rev 9084)
@@ -655,16 +655,21 @@
   int format;
   unsigned *xywh;
 
-  if (XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen),
+  /* If there are several screens, the _NET_WORKAREA property 
+   does not give the work area of the main screen, but that of all screens 
together.
+   Therefore, we use this property only when there is a single screen,
+   and fall back to the main screen full area when there are several screens.
+   */
+  if (Fl::screen_count() > 1 || XGetWindowProperty(fl_display, 
RootWindow(fl_display, fl_screen),
                          _NET_WORKAREA, 0, 4 * sizeof(unsigned), False,
                          XA_CARDINAL, &actual, &format, &count, &remaining,
                          (unsigned char **)&xywh) || !xywh || !xywh[2] ||
                          !xywh[3])
   {
-    fl_workarea_xywh[0] = 0;
-    fl_workarea_xywh[1] = 0;
-    fl_workarea_xywh[2] = DisplayWidth(fl_display, fl_screen);
-    fl_workarea_xywh[3] = DisplayHeight(fl_display, fl_screen);
+    Fl::screen_xywh(fl_workarea_xywh[0], 
+                   fl_workarea_xywh[1], 
+                   fl_workarea_xywh[2], 
+                   fl_workarea_xywh[3], 0);
   }
   else
   {

Modified: branches/branch-1.3/src/screen_xywh.cxx
===================================================================
--- branches/branch-1.3/src/screen_xywh.cxx     2011-09-28 20:44:35 UTC (rev 
9083)
+++ branches/branch-1.3/src/screen_xywh.cxx     2011-09-29 16:04:24 UTC (rev 
9084)
@@ -47,6 +47,7 @@
 static fl_gmi_func fl_gmi = NULL; // used to get a proc pointer for 
GetMonitorInfoA
 
 static RECT screens[16];
+static RECT work_area[16];
 static float dpi[16][2];
 
 static BOOL CALLBACK screen_cb(HMONITOR mon, HDC, LPRECT r, LPARAM) {
@@ -60,8 +61,11 @@
   if (fl_gmi(mon, &mi)) {
     screens[num_screens] = mi.rcMonitor;
 // If we also want to record the work area, we would also store mi.rcWork at 
this point
-//  work_area[num_screens] = mi.rcWork;
-
+    work_area[num_screens] = mi.rcWork;
+/*fl_alert("screen %d %d,%d,%d,%d work %d,%d,%d,%d",num_screens,
+        
screens[num_screens].left,screens[num_screens].right,screens[num_screens].top,screens[num_screens].bottom,
+    
work_area[num_screens].left,work_area[num_screens].right,work_area[num_screens].top,work_area[num_screens].bottom);
+*/
     // find the pixel size
     if (mi.cbSize == sizeof(mi)) {
       HDC screen = CreateDC(mi.szDevice, NULL, NULL, NULL);
@@ -107,6 +111,7 @@
   screens[0].left      = 0;
   screens[0].right  = GetSystemMetrics(SM_CXSCREEN);
   screens[0].bottom = GetSystemMetrics(SM_CYSCREEN);
+  work_area[0] = screens[0];
 }
 #elif defined(__APPLE__)
 static XRectangle screens[16];
@@ -124,12 +129,23 @@
     screens[i].y      = int(r.origin.y);
     screens[i].width  = int(r.size.width);
     screens[i].height = int(r.size.height);
-    CGSize s = CGDisplayScreenSize(displays[i]);
-    dpi_h[i] = screens[i].width / (s.width/25.4);
-    dpi_v[i] = screens[i].height / (s.height/25.4);
+//fprintf(stderr,"screen %d 
%dx%dx%dx%d\n",i,screens[i].x,screens[i].y,screens[i].width,screens[i].height);
+    if (CGDisplayScreenSize != NULL) {
+      CGSize s = CGDisplayScreenSize(displays[i]); // from 10.3
+      dpi_h[i] = screens[i].width / (s.width/25.4);
+      dpi_v[i] = screens[i].height / (s.height/25.4);
+      }
+    else {
+      dpi_h[i] = dpi_v[i] = 75.;
+      }
   }
   num_screens = count;
 }
+
+void Fl_X::mac_screen_init() {
+  screen_init();
+  }
+
 #elif HAVE_XINERAMA
 #  include <X11/extensions/Xinerama.h>
 
@@ -183,19 +199,11 @@
   return num_screens ? num_screens : 1;
 }
 
-/**
-  Gets the bounding box of a screen
-  that contains the specified screen position \p mx, \p my
-  \param[out]  X,Y,W,H the corresponding screen bounding box
-  \param[in] mx, my the absolute screen position
-*/
-void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my) {
+static int find_screen_with_point(int mx, int my) {
   int screen = 0;
-  int i;
-
   if (num_screens < 0) screen_init();
-
-  for (i = 0; i < num_screens; i ++) {
+  
+  for (int i = 0; i < num_screens; i ++) {
     int sx, sy, sw, sh;
     Fl::screen_xywh(sx, sy, sw, sh, i);
     if ((mx >= sx) && (mx < (sx+sw)) && (my >= sy) && (my < (sy+sh))) {
@@ -203,12 +211,62 @@
       break;
     }
   }
+  return screen;
+}
 
-  screen_xywh(X, Y, W, H, screen);
+/**
+  Gets the bounding box of a screen
+  that contains the specified screen position \p mx, \p my
+  \param[out]  X,Y,W,H the corresponding screen bounding box
+  \param[in] mx, my the absolute screen position
+*/
+void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my) {
+  screen_xywh(X, Y, W, H, find_screen_with_point(mx, my));
 }
 
+
 /**
+ Gets the bounding box of the work area of a screen
+ that contains the specified screen position \p mx, \p my
+ \param[out]  X,Y,W,H the work area bounding box
+ \param[in] mx, my the absolute screen position
+ */
+void Fl::screen_work_area(int &X, int &Y, int &W, int &H, int mx, int my) {
+  screen_work_area(X, Y, W, H, find_screen_with_point(mx, my));
+}
+
+/**
+ Gets the bounding box of the work area of the given screen.
+ \param[out]  X,Y,W,H the work area bounding box
+ \param[in] n the screen number (0 to Fl::screen_count() - 1)
+ \see void screen_xywh(int &x, int &y, int &w, int &h, int mx, int my)
+*/
+void Fl::screen_work_area(int &X, int &Y, int &W, int &H, int n) {
+  if (num_screens < 0) screen_init();
+  if (n < 0 || n >= num_screens) n = 0;
+#ifdef WIN32
+  X = work_area[n].left;
+  Y = work_area[n].top;
+  W = work_area[n].right - X;
+  H = work_area[n].bottom - Y;
+#elif defined(__APPLE__)
+  Fl_X::screen_work_area(X, Y, W, H, n);
+#else
+  if (n == 0) { // for the main screen, these return the work area
+    X = Fl::x();
+    Y = Fl::y();
+    W = Fl::w();
+    H = Fl::h();
+    }
+  else { // for other screens, work area is full screen,
+    screen_xywh(X, Y, W, H, n);
+    }
+#endif
+}
+
+/**
   Gets the screen bounding rect for the given screen.
+  Under MSWindows, Mac OS X, and the Gnome desktop, screen #0 contains the 
menubar/taskbar
   \param[out]  X,Y,W,H the corresponding screen bounding box
   \param[in] n the screen number (0 to Fl::screen_count() - 1)
   \see void screen_xywh(int &x, int &y, int &w, int &h, int mx, int my)
@@ -233,18 +291,10 @@
     H = GetSystemMetrics(SM_CYSCREEN);
   }
 #elif defined(__APPLE__)
-  if (num_screens > 0) {
     X = screens[n].x;
     Y = screens[n].y;
     W = screens[n].width;
     H = screens[n].height;
-  } else {
-    /* Fallback if something is broken... */
-    X = Fl::x();
-    Y = Fl::y();
-    W = Fl::w();
-    H = Fl::h();
-  }
 #else
 #if HAVE_XINERAMA
   if (num_screens > 0 && screens) {

_______________________________________________
fltk-commit mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-commit

Reply via email to