Author: manolo
Date: 2011-09-30 09:19:31 -0700 (Fri, 30 Sep 2011)
New Revision: 9103
Log:
Backport of changes to 1.3 until Sep 30, 2011.

Modified:
   branches/branch-3.0/include/fltk3/enumerations.h
   branches/branch-3.0/include/fltk3/osx.h
   branches/branch-3.0/include/fltk3/run.h
   branches/branch-3.0/src/fltk3/Menu.cxx
   branches/branch-3.0/src/fltk3/cocoa.mm
   branches/branch-3.0/src/fltk3/rect.cxx
   branches/branch-3.0/src/fltk3/run.cxx
   branches/branch-3.0/src/fltk3/screen_xywh.cxx
   branches/branch-3.0/src/fltk3/win32.cxx
   branches/branch-3.0/src/fltk3/x11.cxx

Modified: branches/branch-3.0/include/fltk3/enumerations.h
===================================================================
--- branches/branch-3.0/include/fltk3/enumerations.h    2011-09-30 14:46:08 UTC 
(rev 9102)
+++ branches/branch-3.0/include/fltk3/enumerations.h    2011-09-30 16:19:31 UTC 
(rev 9103)
@@ -294,7 +294,11 @@
      If the widget returns 1, it will receive the data in the immediately 
      following fltk3::PASTE event.
      */
-    DND_RELEASE        = 23
+    DND_RELEASE        = 23,
+    /** The screen configuration (number, positions) was changed.
+     Use fltk3::add_handler() to be notified of this event.
+     */
+    SCREEN_CONFIGURATION_CHANGED = 24
   };
   
   

Modified: branches/branch-3.0/include/fltk3/osx.h
===================================================================
--- branches/branch-3.0/include/fltk3/osx.h     2011-09-30 14:46:08 UTC (rev 
9102)
+++ branches/branch-3.0/include/fltk3/osx.h     2011-09-30 16:19:31 UTC (rev 
9103)
@@ -139,6 +139,7 @@
   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
 private:
   static void relink(fltk3::Window*, fltk3::Window*);
   bool subwindow;

Modified: branches/branch-3.0/include/fltk3/run.h
===================================================================
--- branches/branch-3.0/include/fltk3/run.h     2011-09-30 14:46:08 UTC (rev 
9102)
+++ branches/branch-3.0/include/fltk3/run.h     2011-09-30 16:19:31 UTC (rev 
9103)
@@ -137,6 +137,7 @@
   extern fltk3::Window* modal_;
   extern fltk3::Window* grab_;
   extern int compose_state;
+  void call_screen_init(); // recompute screen number and dimensions
 #endif
   /**
    If true then flush() will do something.
@@ -761,14 +762,14 @@
    fl global screen functions declared in <fltk3/run.h>
    @{ */
   // screen size:
-  /** Returns the origin of the current screen work area, where 0 indicates 
the left side of the screen. */
-  int x(); // platform dependent
-  /** Returns the origin of the current screen work area, where 0 indicates 
the top edge of the screen. */
-  int y(); // platform dependent
-  /** Returns the width of the screen work area in pixels. */
-  int w(); // platform dependent
-  /** Returns the height of the screen work area in pixels. */
-  int h(); // platform dependent
+  /** Returns the leftmost x coordinate of the main screen work area. */
+  int x(); 
+  /** Returns the topmost y coordinate of the main screen work area. */
+  int y(); 
+  /** Returns the width in pixels of the main screen work area. */
+  int w();
+  /** Returns the height in pixels of the main screen work area. */
+  int h();
   
   // multi-head support:
   int screen_count();
@@ -784,6 +785,16 @@
   inline void screen_xywh(int &X, int &Y, int &W, int &H) {
     screen_xywh(X, Y, W, H, e_x_root, e_y_root);
   }
+  void screen_work_area(int &X, int &Y, int &W, int &H, int mx, int my);
+  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) 
+   */
+  inline 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-3.0/src/fltk3/Menu.cxx
===================================================================
--- branches/branch-3.0/src/fltk3/Menu.cxx      2011-09-30 14:46:08 UTC (rev 
9102)
+++ branches/branch-3.0/src/fltk3/Menu.cxx      2011-09-30 16:19:31 UTC (rev 
9103)
@@ -285,7 +285,7 @@
   int scr_x, scr_y, scr_w, scr_h;
   int tx = X, ty = Y;
 
-  fltk3::screen_xywh(scr_x, scr_y, scr_w, scr_h);
+  fltk3::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();
@@ -420,7 +420,7 @@
   int scr_x, scr_y, scr_w, scr_h;
   int Y = y()+fltk3::box_dx(box())+2+n*itemheight;
 
-  fltk3::screen_xywh(scr_x, scr_y, scr_w, scr_h);
+  fltk3::screen_work_area(scr_x, scr_y, scr_w, scr_h);
   if (Y <= scr_y) Y = scr_y-Y+10;
   else {
     Y = Y+itemheight-scr_h-scr_y;

Modified: branches/branch-3.0/src/fltk3/cocoa.mm
===================================================================
--- branches/branch-3.0/src/fltk3/cocoa.mm      2011-09-30 14:46:08 UTC (rev 
9102)
+++ branches/branch-3.0/src/fltk3/cocoa.mm      2011-09-30 16:19:31 UTC (rev 
9103)
@@ -110,6 +110,7 @@
 // forward declarations of variables in this file
 static int got_events = 0;
 static fltk3::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 fltk3::Window* send_motion;
@@ -685,7 +686,7 @@
   fltk3::e_y = int([[nsw contentView] frame].size.height - pt.y);
   pt = [NSEvent mouseLocation];
   fltk3::e_x_root = int(pt.x);
-  fltk3::e_y_root = int([[nsw screen] frame].size.height - pt.y);
+  fltk3::e_y_root = int(main_screen_height - pt.y);
 }
 
 /*
@@ -904,16 +905,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>
@@ -931,6 +922,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;
@@ -948,7 +940,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
   }
@@ -967,7 +959,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();
@@ -1094,6 +1086,22 @@
   }
   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;
+  fltk3::call_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];
+    }
+  }
+  fltk3::handle(fltk3::SCREEN_CONFIGURATION_CHANGED, NULL);
+}
 - (void)applicationWillResignActive:(NSNotification *)notify
 {
   fl_lock_function();
@@ -1215,7 +1223,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;
@@ -1226,8 +1237,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
@@ -1268,17 +1278,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 );
         }
@@ -1287,10 +1292,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];
   }
 }
 
@@ -1321,38 +1327,46 @@
 }
 
 /*
- * smallest x ccordinate in screen space
+ * smallest x coordinate in screen space of work area of menubar-containing 
display
  */
 int fltk3::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 fltk3::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 fltk3::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 fltk3::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
@@ -1362,7 +1376,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);
 }
 
 
@@ -1440,7 +1454,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;
@@ -1451,8 +1465,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];
@@ -1461,8 +1476,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];
@@ -1471,8 +1487,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];
@@ -1481,8 +1498,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];
@@ -1492,11 +1510,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)
@@ -2031,7 +2049,7 @@
       hp += 2*by+bt;
     }
     if (!(w->flags() & fltk3::Window::FORCE_POSITION)) {
-      // use the Carbon functions below for default window positioning
+      // default window positioning on the main screen
       w->x(xyPos+fltk3::x());
       w->y(xyPos+fltk3::y());
       xyPos += 25;
@@ -2061,10 +2079,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 
@@ -2112,7 +2129,7 @@
     w->set_visible();
     if ( w->border() || (!w->modal() && !w->tooltip_window()) ) 
fltk3::handle(fltk3::FOCUS, w);
     fltk3::first_window(w);
-    [cw setDelegate:mydelegate];
+    [cw setDelegate:[NSApp delegate]];
     if (fl_show_iconic) { 
       fl_show_iconic = 0;
       [cw miniaturize:nil];
@@ -2125,8 +2142,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 = fltk3::e_number;
     w->handle(fltk3::e_number = fltk3::SHOW);
@@ -2242,14 +2258,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];
     }
   }
@@ -3355,7 +3371,7 @@
 
 // so a CGRect matches exactly what is denoted x,y,w,h for clipping purposes
 CGRect fl_cgrectmake_cocoa(int x, int y, int w, int h) {
-  return CGRectMake(x, y, w - 1, h - 1);
+  return CGRectMake(x, y, w > 0 ? w - 0.9 : 0, h > 0 ? h - 0.9 : 0);
 }
 
 Window fl_xid(const fltk3::Window* w)

Modified: branches/branch-3.0/src/fltk3/rect.cxx
===================================================================
--- branches/branch-3.0/src/fltk3/rect.cxx      2011-09-30 14:46:08 UTC (rev 
9102)
+++ branches/branch-3.0/src/fltk3/rect.cxx      2011-09-30 16:19:31 UTC (rev 
9103)
@@ -197,7 +197,7 @@
   rect.right = x + w; rect.bottom = y + h;
   FillRect(fl_gc, &rect, fl_brush());
 #elif defined(__APPLE_QUARTZ__)
-  CGRect rect = CGRectMake(x, y, w-1, h-1);
+  CGRect rect = CGRectMake(x, y, w-0.9, h-0.9);
   CGContextFillRect(fl_gc, rect);
 #else
 # error unsupported platform

Modified: branches/branch-3.0/src/fltk3/run.cxx
===================================================================
--- branches/branch-3.0/src/fltk3/run.cxx       2011-09-30 14:46:08 UTC (rev 
9102)
+++ branches/branch-3.0/src/fltk3/run.cxx       2011-09-30 16:19:31 UTC (rev 
9103)
@@ -789,6 +789,7 @@
   
   - fltk3::SHORTCUT events that are not recognized by any widget.
     This lets you provide global shortcut keys.
+ -  fltk3::SCREEN_CONFIGURATION_CHANGED events.
   - System events that FLTK does not recognize.  See fl_xevent.
   - \e Some other events when the widget FLTK selected returns
     zero from its handle() method.  Exactly which ones may change

Modified: branches/branch-3.0/src/fltk3/screen_xywh.cxx
===================================================================
--- branches/branch-3.0/src/fltk3/screen_xywh.cxx       2011-09-30 14:46:08 UTC 
(rev 9102)
+++ branches/branch-3.0/src/fltk3/screen_xywh.cxx       2011-09-30 16:19:31 UTC 
(rev 9103)
@@ -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,7 +61,7 @@
   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;
 
     // find the pixel size
     if (mi.cbSize == sizeof(mi)) {
@@ -107,6 +108,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 +126,18 @@
     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);
+    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;
 }
+
 #elif HAVE_XINERAMA
 #  include <X11/extensions/Xinerama.h>
 
@@ -173,6 +181,11 @@
 }
 #endif // WIN32
 
+#ifndef FL_DOXYGEN
+void fltk3::call_screen_init() {
+  screen_init();
+}
+#endif
 
 /**
   Gets the number of available screens.
@@ -183,19 +196,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 fltk3::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;
     fltk3::screen_xywh(sx, sy, sw, sh, i);
     if ((mx >= sx) && (mx < (sx+sw)) && (my >= sy) && (my < (sy+sh))) {
@@ -203,13 +208,61 @@
       break;
     }
   }
-  
-  screen_xywh(X, Y, W, H, screen);
+  return 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 fltk3::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 fltk3::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 fltk3::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) 
@@ -234,18 +287,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 = fltk3::x();
-    Y = fltk3::y();
-    W = fltk3::w();
-    H = fltk3::h();
-  }
 #else
 #if HAVE_XINERAMA
   if (num_screens > 0 && screens) {

Modified: branches/branch-3.0/src/fltk3/win32.cxx
===================================================================
--- branches/branch-3.0/src/fltk3/win32.cxx     2011-09-30 14:46:08 UTC (rev 
9102)
+++ branches/branch-3.0/src/fltk3/win32.cxx     2011-09-30 16:19:31 UTC (rev 
9103)
@@ -1214,7 +1214,11 @@
     // unclear on what is correct:
     if (fl_msg.message == WM_RENDERALLFORMATS) CloseClipboard();
     return 1;}
-
+  case WM_DISPLAYCHANGE: // occurs when screen configuration (number, 
position) changes
+    fltk3::call_screen_init();
+      fltk3::handle(fltk3::SCREEN_CONFIGURATION_CHANGED, NULL);
+    return 0;
+      
   default:
     if (fltk3::handle(0,0)) return 0;
     break;

Modified: branches/branch-3.0/src/fltk3/x11.cxx
===================================================================
--- branches/branch-3.0/src/fltk3/x11.cxx       2011-09-30 14:46:08 UTC (rev 
9102)
+++ branches/branch-3.0/src/fltk3/x11.cxx       2011-09-30 16:19:31 UTC (rev 
9103)
@@ -53,6 +53,10 @@
 #  include <X11/Xlocale.h>
 #  include <X11/Xlib.h>
 #  include <X11/keysym.h>
+#ifdef HAVE_XRANDR
+#include <X11/extensions/Xrandr.h>
+static int randrEventBase = -1;
+#endif
 
 static fltk3::XlibGraphicsDriver fl_xlib_driver;
 static fltk3::DisplayDevice fl_xlib_display(&fl_xlib_driver);
@@ -649,6 +653,12 @@
 #if !USE_COLORMAP
   fltk3::visual(fltk3::RGB);
 #endif
+#ifdef HAVE_XRANDR
+  int error_base;
+  if (XRRQueryExtension(d, &randrEventBase, &error_base))
+    XRRSelectInput(d, RootWindow(d, fl_screen), RRScreenChangeNotifyMask);
+  else randrEventBase = -1;
+#endif
 }
 
 void fl_close_display() {
@@ -667,16 +677,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 (fltk3::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);
+    fltk3::screen_xywh(fl_workarea_xywh[0], 
+                   fl_workarea_xywh[1], 
+                   fl_workarea_xywh[2], 
+                   fl_workarea_xywh[3], 0);
   }
   else
   {
@@ -928,6 +943,15 @@
   if ( XFilterEvent((XEvent *)&xevent, 0) )
       return(1);
 
+#ifdef HAVE_XRANDR  
+  if( randrEventBase >= 0 && xevent.type == randrEventBase + 
RRScreenChangeNotify) {
+    XRRUpdateConfiguration (&xevent);
+    fltk3::call_screen_init();
+    fl_init_workarea();
+    fltk3::handle(fltk3::SCREEN_CONFIGURATION_CHANGED, NULL);
+  }
+#endif
+  
   switch (xevent.type) {
 
   case KeymapNotify:

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

Reply via email to