Author: spitzak
Date: 2007-06-07 08:36:39 -0400 (Thu, 07 Jun 2007)
New Revision: 5887
Log:
Fix for STR 1692
OSX returns correct list for Monitors::list() and Monitors::all(), including
the work area.
Added new monitors test/demo program that is actually fairly nice
Fixed bugs with drawing scaled rectangles so that the demo program works.


Added:
   trunk/test/monitors.cxx
Modified:
   trunk/fltk/draw.h
   trunk/src/fillrect.cxx
   trunk/src/osx/run.cxx
   trunk/src/path.cxx
   trunk/test/Makefile

Modified: trunk/fltk/draw.h
===================================================================
--- trunk/fltk/draw.h   2007-06-06 20:30:41 UTC (rev 5886)
+++ trunk/fltk/draw.h   2007-06-07 12:36:39 UTC (rev 5887)
@@ -70,7 +70,7 @@
 FL_API void transform_distance(float& x, float& y);
 FL_API void transform(int& x, int& y);
 FL_API void transform(const Rectangle& from, Rectangle& to);
-FL_API void transform(int x, int y, int w, int h, Rectangle& to);
+FL_API void transform(int& x, int& y, int& w, int& h);
 //@}
 
 /// \name Clipping

Modified: trunk/src/fillrect.cxx
===================================================================
--- trunk/src/fillrect.cxx      2007-06-06 20:30:41 UTC (rev 5886)
+++ trunk/src/fillrect.cxx      2007-06-07 12:36:39 UTC (rev 5887)
@@ -33,12 +33,12 @@
 /*! Fill the rectangle with the current color. */
 void fltk::fillrect(int x, int y, int w, int h) {
   if (w <= 0 || h <= 0) return;
-  transform(x,y);
+  transform(x,y,w,h);
 #if USE_CAIRO
   cairo_rectangle(cc,x,y,w,h);
   cairo_fill(cc);
 #elif USE_X11
-  XFillRectangle(xdisplay, xwindow, gc, x, y, w, h);
+  if (w && h) XFillRectangle(xdisplay, xwindow, gc, x, y, w, h);
 #elif defined(_WIN32)
   RECT rect;
   rect.left = x; rect.top = y;  
@@ -61,12 +61,13 @@
 */
 void fltk::strokerect(int x, int y, int w, int h) {
   if (w <= 0 || h <= 0) return;
-  transform(x,y);
+  transform(x,y,w,h);
 #if USE_CAIRO
   cairo_rectangle(cc,x+.5,y+.5,w-1,h-1);
   cairo_stroke(cc);
 #elif USE_X11
-  XDrawRectangle(xdisplay, xwindow, gc, x, y, w-1, h-1);
+  if (w && h) XDrawRectangle(xdisplay, xwindow, gc, x, y, w-1, h-1);
+  else XDrawLine(xdisplay, xwindow, gc, x, y, x+w, y+h);
 #elif defined(_WIN32)
   setpen();
   POINT pts[4];

Modified: trunk/src/osx/run.cxx
===================================================================
--- trunk/src/osx/run.cxx       2007-06-06 20:30:41 UTC (rev 5886)
+++ trunk/src/osx/run.cxx       2007-06-07 12:36:39 UTC (rev 5887)
@@ -995,7 +995,10 @@
 
 ////////////////////////////////////////////////////////////////
 
-static bool reload_info = true;
+// this should be turned on by changes to monitor layout, nyi.
+// Apparently CGDisplayReconfigurationCallBack is what you need
+static bool reload_list = true; 
+static bool reload_all = true;
 
 /* Return a "monitor" that surrounds all the monitors.
     If you have a single monitor, this returns a monitor structure that
@@ -1005,42 +1008,62 @@
 //+++ verify port to FLTK2
 const Monitor& Monitor::all() {
   static Monitor monitor;
-  if (reload_info) {
-    reload_info = false;
-    BitMap r;
-    GetQDGlobalsScreenBits(&r);
-    monitor.set(r.bounds.left, r.bounds.top,
-                r.bounds.right - r.bounds.left,
-                r.bounds.bottom - r.bounds.top);
-    //++ there is a wonderful call in Carbon that will return exactly 
-    //++ this information...
-    monitor.work.set(r.bounds.left, r.bounds.top+22,
-                     r.bounds.right - r.bounds.left,
-                     r.bounds.bottom - r.bounds.top - 22);
-    //++ I don't know if this scale info is available...
-    monitor.depth_ = 32;
-    monitor.dpi_x_ = 100;
-    monitor.dpi_y_ = 100;
+  if (reload_list || reload_all) {
+    const Monitor* list;
+    int count = Monitor::list(&list);
+    reload_all = false;
+    monitor = list[0];
+    for (int i=1; i < count; i++) {
+      monitor.merge(list[i]);
+      monitor.work.merge(list[i].work);
+    }
   }
   return monitor;
 }
 
+static Monitor* monitors = 0;
+static int num_monitors = 0;
+
 /* Return an array of all Monitors.
     p is set to point to a static array of Monitor structures describing
     all monitors connected to the system. Subsequent calls will usually
     return the same array, but if a signal comes in indicating a change
     it will probably delete the old array and return a new one.
 */
-//+++ verify port to FLTK2
 int Monitor::list(const Monitor** p) {
-  *p = &all();
-  return 1;
+  if (reload_list) {
+    reload_list = false;
+    reload_all = true;
+    const unsigned int Max = 10;
+    CGDirectDisplayID list[Max];
+    CGDisplayCount count = 0;
+    /*CGDisplayErr err =*/ CGGetActiveDisplayList(Max, list, &count);
+    // maybe do something if count < 1?
+    num_monitors = count;
+    delete[] monitors;
+    monitors = new Monitor[count];
+    for (unsigned int d = 0; d < count; ++d) {
+      CGRect bounds = CGDisplayBounds(list[d]);
+      monitors[d].set(bounds.origin.x,
+                      bounds.origin.y,
+                      bounds.size.width,
+                      bounds.size.height);
+      GDHandle gdhandle; 
DMGetGDeviceByDisplayID((DisplayIDType)(list[d]),&gdhandle,false);
+      Rect work; GetAvailableWindowPositioningBounds(gdhandle, &work);
+      monitors[d].work.set(work.left, work.top, work.right-work.left, 
work.bottom-work.top);
+      monitors[d].depth_ = CGDisplayBitsPerPixel(list[d]);
+      CGSize size = CGDisplayScreenSize(list[d]); //display size in mm
+      monitors[d].dpi_x_ = bounds.size.width*25.4f/size.width;
+      monitors[d].dpi_y_ = bounds.size.height*25.4f/size.height;
+    }
+  }
+  *p = monitors;
+  return num_monitors;
 }
 
 /* Return a pointer to a Monitor structure describing the monitor
     that contains or is closest to the given x,y, position.
 */
-//+++ verify port to FLTK2
 const Monitor& Monitor::find(int x, int y) {
   const Monitor* monitors;
   int count = list(&monitors);

Modified: trunk/src/path.cxx
===================================================================
--- trunk/src/path.cxx  2007-06-06 20:30:41 UTC (rev 5886)
+++ trunk/src/path.cxx  2007-06-07 12:36:39 UTC (rev 5887)
@@ -305,12 +305,12 @@
 }
 
 /**
-Same as transform(Rectangle(X,Y,W,H),to). This may be faster as it
-avoids the rectangle construction.
+Same as transform(Rectangle(X,Y,W,H),to) but replaces XYWH with the transformed
+rectangle. This may be faster as it avoids the rectangle construction.
 */
-void fltk::transform(int X,int Y,int W,int H, Rectangle& to) {
+void fltk::transform(int& X,int& Y,int& W,int& H) {
   if (m.trivial) {
-    to.set(X+m.ix, Y+m.iy, W, H);
+    X += m.ix; Y += m.iy;
     return;
   }
   float x = X+W*.5f;
@@ -318,11 +318,10 @@
   transform(x,y);
   float d1x,d1y; d1x = float(W); d1y = 0; transform_distance(d1x, d1y);
   float d2x,d2y; d2x = 0; d2y = float(H); transform_distance(d2x, d2y);
-  float w = rintf(sqrtf(d1x*d1x+d2x*d2x));
-  x = floorf(x - (w+1)/2);
-  float h = rintf(sqrtf(d1y*d1y+d2y*d2y));
-  y = floorf(y - (h+1)/2);
-  to.set(int(x),int(y),int(w),int(h));
+  W = int(sqrtf(d1x*d1x+d2x*d2x)+.5f);
+  H = int(sqrtf(d1y*d1y+d2y*d2y)+.5f);
+  X = int(floorf(x - .5f*(W+1)));
+  Y = int(floorf(y - .5f*(H+1)));
 }
 
 ////////////////////////////////////////////////////////////////

Modified: trunk/test/Makefile
===================================================================
--- trunk/test/Makefile 2007-06-06 20:30:41 UTC (rev 5886)
+++ trunk/test/Makefile 2007-06-07 12:36:39 UTC (rev 5887)
@@ -82,6 +82,7 @@
        mandelbrot.cxx \
        menu.cxx \
        message.cxx \
+       monitors.cxx \
        navigation.cxx \
        output.cxx \
        overlay.cxx \
@@ -153,6 +154,7 @@
        mandelbrot$(EXEEXT) \
        menu$(EXEEXT) \
        message$(EXEEXT) \
+       monitors$(EXEEXT) \
        navigation$(EXEEXT) \
        output$(EXEEXT) \
        pack$(EXEEXT) \

Added: trunk/test/monitors.cxx
===================================================================
--- trunk/test/monitors.cxx                             (rev 0)
+++ trunk/test/monitors.cxx     2007-06-07 12:36:39 UTC (rev 5887)
@@ -0,0 +1,92 @@
+// Test of the fltk::Monitor calls
+
+#include <fltk/run.h>
+#include <fltk/Window.h>
+#include <fltk/Monitor.h>
+#include <fltk/draw.h>
+#include <stdio.h>
+
+using namespace fltk;
+
+void print_monitor(const Monitor& m, int i) {
+  if (i < 0) printf("all: ");
+  else printf("%d: ", i);
+  printf("area %d %d %d %d, work %d %d %d %d, depth %d, dpi %g %g\n",
+         m.x(), m.y(), m.w(), m.h(),
+         m.work.x(), m.work.y(), m.work.w(), m.work.h(),
+         m.depth(), m.dpi_x(), m.dpi_y());
+}
+
+class MonitorWindow : public Window {
+public:
+  MonitorWindow() : Window(500,500) {resizable(this);}
+
+  void draw_monitor(const Monitor& m, int i) {
+    setcolor(GRAY50);
+    strokerect(m.work);
+    setcolor(BLACK);
+    strokerect(m);
+    char b[256];
+    char* p = b;
+    if (i < 0) p += sprintf(p,"all: ");
+    else p += sprintf(p, "%d: ", i);
+    sprintf(p, "area %d %d %d %d\nwork %d %d %d %d\ndepth %d, dpi %g %g",
+            m.x(), m.y(), m.w(), m.h(),
+            m.work.x(), m.work.y(), m.work.w(), m.work.h(),
+            m.depth(), m.dpi_x(), m.dpi_y());
+    if (i < 0)
+      drawtext(b, Rectangle(m.x(),m.b(),m.w(),1000), 
ALIGN_TOP|ALIGN_RIGHT|ALIGN_WRAP);
+    else 
+      drawtext(b, m, ALIGN_CENTER|ALIGN_WRAP|ALIGN_CLIP);
+  }
+
+  void draw() {
+    draw_box();
+    setfont(textfont(), textsize());
+    const Monitor& all = Monitor::all();
+    push_matrix();
+    translate(w()/10,h()/10);
+    float s = w()*.8/all.w();
+    float s2 = h()*.8/all.h();
+    if (s2 < s) s = s2;
+    scale(s,s);
+    translate(-all.x(), -all.y());
+
+    setcolor(GRAY25);
+    Rectangle b; borders(&b);
+    fillrect(this->x()+b.x(), this->y()+b.y(), this->w()+b.w(), 
this->h()+b.h());
+    setcolor(GRAY50);
+    fillrect(*this);
+    setcolor(WHITE);
+    drawtext("this window", *this, ALIGN_CENTER|ALIGN_WRAP|ALIGN_CLIP);
+
+    draw_monitor(all, -1);
+
+    const Monitor* list;
+    int size = Monitor::list(&list);
+    for (int i=0; i<size; i++)
+      draw_monitor(list[i], i);
+
+    pop_matrix();
+  }
+
+  void layout() { // make it redraw when user moves window
+    redraw();
+    Window::layout();
+  }
+};
+
+int main(int argc, char** argv) {
+  MonitorWindow window;
+  window.show(argc,argv);
+
+  print_monitor(Monitor::all(),-1);
+
+  const Monitor* list;
+  int size = Monitor::list(&list);
+
+  for (int i=0; i<size; i++)
+    print_monitor(list[i],i);
+
+  return fltk::run();
+}

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

Reply via email to