[master] 0d8385a - Simpler macOS implementation of capture of window titlebars.

GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Apps      FLTK Library      Forums      Links     Login 
 All Forums  |  Back to fltk.commit  ]
 
Previous Message ]Next Message ]

[master] 0d8385a - Simpler macOS implementation of capture of window titlebars. "ManoloFLTK" 12:17 Oct 12 top right image
 
commit 0d8385a652441440d8fa2db15bd40d4d5cf4e734
Author:     ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
AuthorDate: Mon Oct 12 21:05:27 2020 +0200
Commit:     ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
CommitDate: Mon Oct 12 21:05:38 2020 +0200

    Simpler macOS implementation of capture of window titlebars.

 FL/Fl_Copy_Surface.H                               |  1 -
 FL/Fl_Printer.H                                    |  1 -
 src/Fl_Copy_Surface.cxx                            |  4 --
 src/Fl_Printer.cxx                                 |  6 --
 src/Fl_cocoa.mm                                    | 55 ++++++--------
 src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm       | 83 ----------------------
 src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H         |  3 +-
 src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx       | 31 +-------
 src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.H |  1 -
 .../Quartz/Fl_Quartz_Copy_Surface_Driver.cxx       | 15 ----
 10 files changed, 26 insertions(+), 174 deletions(-)

diff --git FL/Fl_Copy_Surface.H FL/Fl_Copy_Surface.H
index 03faa14..cf62e1f 100644
--- FL/Fl_Copy_Surface.H
+++ FL/Fl_Copy_Surface.H
@@ -64,7 +64,6 @@ public:
   void origin(int *x, int *y);
   void origin(int x, int y);
   int printable_rect(int *w, int *h);
-  virtual void draw_decorated_window(Fl_Window *win, int x_offset = 0, int y_offset = 0);
 };
 
 
diff --git FL/Fl_Printer.H FL/Fl_Printer.H
index 320ec12..784fcb8 100644
--- FL/Fl_Printer.H
+++ FL/Fl_Printer.H
@@ -103,7 +103,6 @@ public:
   void untranslate(void);
   int end_page (void);
   void end_job (void);
-  void draw_decorated_window(Fl_Window *win, int x_offset = 0, int y_offset = 0);
   void set_current(void);
   virtual bool is_current();
 
diff --git src/Fl_Copy_Surface.cxx src/Fl_Copy_Surface.cxx
index 5ef4ea4..b40a72c 100644
--- src/Fl_Copy_Surface.cxx
+++ src/Fl_Copy_Surface.cxx
@@ -61,10 +61,6 @@ int Fl_Copy_Surface::printable_rect(int *w, int *h)  {
   return 1;
 }
 
-void Fl_Copy_Surface::draw_decorated_window(Fl_Window *win, int x_offset, int y_offset) {
-  if (platform_surface) platform_surface->draw_decorated_window(win, x_offset, y_offset);
-}
-
 /**
  \cond DriverDev
  \addtogroup DriverDeveloper
diff --git src/Fl_Printer.cxx src/Fl_Printer.cxx
index 4c88607..8c587af 100644
--- src/Fl_Printer.cxx
+++ src/Fl_Printer.cxx
@@ -39,7 +39,6 @@ void Fl_Printer::translate(int x, int y) {}
 void Fl_Printer::untranslate(void) {}
 int Fl_Printer::end_page (void) {return 1;}
 void Fl_Printer::end_job (void) {}
-void Fl_Printer::draw_decorated_window(Fl_Window* win, int delta_x, int delta_y) {}
 void Fl_Printer::set_current(void) {}
 bool Fl_Printer::is_current(void) {return false;}
 Fl_Printer::~Fl_Printer(void) {}
@@ -199,11 +198,6 @@ void Fl_Printer::end_job (void)
   printer->end_job();
 }
 
-void Fl_Printer::draw_decorated_window(Fl_Window* win, int delta_x, int delta_y)
-{
-  printer->draw_decorated_window(win, delta_x, delta_y);
-}
-
 void Fl_Printer::set_current(void)
 {
   printer->set_current();
diff --git src/Fl_cocoa.mm src/Fl_cocoa.mm
index f70cc62..def25c8 100644
--- src/Fl_cocoa.mm
+++ src/Fl_cocoa.mm
@@ -4362,44 +4362,35 @@ int Fl_Cocoa_Window_Driver::decorated_h()
   return h() + bt/s;
 }
 
-CALayer *Fl_Cocoa_Window_Driver::get_titlebar_layer()
+void Fl_Cocoa_Window_Driver::draw_titlebar_to_context(CGContextRef gc, int w, int h)
 {
-  // a compilation warning appears with SDK 10.5, so we require SDK 10.6 instead
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
-  return fl_mac_os_version >= 101000 ? [[[fl_xid(pWindow) standardWindowButton:NSWindowCloseButton] superview] layer] : nil; // 10.5
-#else
-  return nil;
-#endif
-}
-
-void Fl_Cocoa_Window_Driver::draw_layer_to_context(CALayer *layer, CGContextRef gc, int w, int h)
-{
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
-  CGContextSaveGState(gc);
-  clip_to_rounded_corners(gc, w, h);
-  if (fl_mac_os_version < 101500) { // exact OS threshold might be lower
-    CGContextSetRGBFillColor(gc, .79, .79, .79, 1.); // equiv. to FL_DARK1
-    CGContextFillRect(gc, CGRectMake(0, 0, w, h));
-  }
-  CGContextSetShouldAntialias(gc, true);
-  if (fl_mac_os_version >= 101500) {
-    FLWindow *flwin = fl_xid(pWindow);
-    [flwin makeMainWindow];
-    [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:nil inMode:NSDefaultRunLoopMode dequeue:NO];
-    NSInteger win_id = [flwin windowNumber];
+  FLWindow *nswin = fl_xid(pWindow);
+  [nswin makeMainWindow];
+  [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:nil inMode:NSDefaultRunLoopMode dequeue:NO];  
+  CGImageRef img;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+  if (fl_mac_os_version >= 100600) { // verified OK from 10.6
+    NSInteger win_id = [nswin windowNumber];
     CFArrayRef array = CFArrayCreate(NULL, (const void**)&win_id, 1, NULL);
-    NSRect rr = [flwin frame];
-    rr.origin.y += rr.size.height - h;
-    rr.size.height = h;
+    CGRect rr = NSRectToCGRect([nswin frame]);
     rr.origin.y = CGDisplayBounds(CGMainDisplayID()).size.height - (rr.origin.y + rr.size.height);
-    CGImageRef img = CGWindowListCreateImageFromArray(rr, array, kCGWindowImageBoundsIgnoreFraming); // 10.5
+    rr.size.height = h;
+    img = CGWindowListCreateImageFromArray(rr, array, kCGWindowImageBoundsIgnoreFraming); // 10.5
     CFRelease(array);
-    CGContextDrawImage(gc, CGRectMake(0, 0, w, h), img);
-    CGImageRelease(img);
   } else
-    [layer renderInContext:gc]; // 10.5
-  CGContextRestoreGState(gc);
 #endif
+  {
+    Fl_Graphics_Driver::default_driver().scale(1);
+    img = CGImage_from_window_rect(0, -h, w, h, false);
+    Fl_Graphics_Driver::default_driver().scale(Fl::screen_driver()->scale(screen_num()));
+  }
+  if (img) {
+    CGContextSaveGState(gc);
+    clip_to_rounded_corners(gc, w, h);
+    CGContextDrawImage(gc, CGRectMake(0, 0, w, h), img);
+    CGImageRelease(img);
+    CGContextRestoreGState(gc);
+  }
 }
 
 void Fl_Cocoa_Window_Driver::gl_start(NSOpenGLContext *ctxt) {
diff --git src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm
index 9cf95a2..1f7511c 100644
--- src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm
+++ src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm
@@ -68,7 +68,6 @@ private:
   void untranslate(void);
   int end_page (void);
   void end_job (void);
-  void draw_decorated_window(Fl_Window *win, int x_offset, int y_offset);
   ~Fl_Cocoa_Printer_Driver(void);
 };
 
@@ -388,85 +387,3 @@ void Fl_Cocoa_Printer_Driver::origin(int *x, int *y)
 {
   Fl_Paged_Device::origin(x, y);
 }
-
-void Fl_Cocoa_Printer_Driver::draw_decorated_window(Fl_Window *win, int x_offset, int y_offset)
-{
-  if (!win->shown() || win->parent() || !win->border() || !win->visible()) {
-    this->print_widget(win, x_offset, y_offset);
-    return;
-  }
-  int bt, hleft, hright, hbottom;
-  Fl_Cocoa_Window_Driver::driver(win)->decoration_sizes(&bt, &hleft,  &hright, &hbottom);
-  float s = Fl::screen_scale(win->screen_num());
-  if (s < 1) y_offset += bt*(1/s-1);
-  CALayer *layer = Fl_Cocoa_Window_Driver::driver(win)->get_titlebar_layer();
-  if (layer) { // if title bar uses a layer
-    CGContextRef gc = (CGContextRef)driver()->gc();
-    CGContextSaveGState(gc);
-    CGContextTranslateCTM(gc, x_offset - 0.5, y_offset + bt - 0.5);
-    CGContextScaleCTM(gc, 1/s, -1/s);
-    Fl_Cocoa_Window_Driver::driver(win)->draw_layer_to_context(layer, gc, win->w() * s, bt);
-    CGContextRestoreGState(gc);
-    bool clip_corners = fl_mac_os_version >= 100600 && !win->parent();
-    if (clip_corners) {
-      CGContextRef gc = (CGContextRef)driver()->gc();
-      CGContextSaveGState(gc);
-      CGContextTranslateCTM(gc, x_offset, y_offset + bt );
-      Fl_Cocoa_Window_Driver::clip_to_rounded_corners(gc, win->w(), win->h());
-      CGContextTranslateCTM(gc, -x_offset, -y_offset - bt);
-    }
-    this->print_widget(win, x_offset, y_offset + bt);
-    if (clip_corners) {
-      CGContextRestoreGState((CGContextRef)driver()->gc());
-    }
-    return;
-  }
-  Fl_Display_Device::display_device()->set_current(); // send win to front and make it current
-  NSString *title = [(NSWindow*)fl_xid(win) title];
-  [title retain];
-  [(NSWindow*)fl_xid(win) setTitle:@""]; // temporarily set a void window title
-  win->show();
-  Fl::check();
-  // capture the window title bar with no title
-  Fl_RGB_Image *top, *left, *bottom, *right;
-  Fl_Window_Driver::driver(win)->capture_titlebar_and_borders(top, left, bottom, right);
-  [(NSWindow*)fl_xid(win) setTitle:title]; // put back the window title
-  this->set_current(); // back to the Fl_Paged_Device
-  top->scale(win->w(), bt/s, 0, 1);
-  top->draw(x_offset, y_offset + bt - bt/s); // print the title bar
-  delete top;
-  if (win->label()) { // print the window title
-    const int skip = 65; // approx width of the zone of the 3 window control buttons
-    float fs = [NSFont systemFontSize]/s;
-    int text_y = y_offset+bt*(1-1/(2*s))+fs/3;
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
-    if ( fl_mac_os_version >= 100400 ) { // use Cocoa string drawing with exact title bar font
-      // the exact font is LucidaGrande 13 pts (and HelveticaNeueDeskInterface-Regular with 10.10)
-      NSGraphicsContext *current = [NSGraphicsContext currentContext];
-      [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:driver()->gc() flipped:YES]];//10.4
-      NSDictionary *attr = [NSDictionary dictionaryWithObject:[NSFont titleBarFontOfSize:fs]
-                                                       forKey:NSFontAttributeName];
-      NSSize size = [title sizeWithAttributes:attr];
-      int x = x_offset + win->w()/2 - size.width/2;
-      if (x < x_offset+skip) x = x_offset+skip;
-      NSRect r = NSMakeRect(x, text_y , win->w() - skip, bt);
-      [[NSGraphicsContext currentContext] setShouldAntialias:YES];
-      [title drawWithRect:r options:(NSStringDrawingOptions)0 attributes:attr]; // 10.4
-      [[NSGraphicsContext currentContext] setShouldAntialias:NO];
-      [NSGraphicsContext setCurrentContext:current];
-    }
-    else
-#endif
-    {
-      fl_font(FL_HELVETICA, fs);
-      fl_color(FL_BLACK);
-      int x = x_offset + win->w()/2 - fl_width(win->label())/2;
-      if (x < x_offset+skip) x = x_offset+skip;
-      fl_push_clip(x_offset, y_offset + bt - bt/s, win->w(), bt/s);
-      fl_draw(win->label(), x, text_y);
-      fl_pop_clip();
-    }
-  }
-  [title release];
-  this->print_widget(win, x_offset, y_offset + bt); // print the window inner part
-}
diff --git src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H
index 2b48549..970d788 100644
--- src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H
+++ src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H
@@ -139,8 +139,7 @@ public:
   // next 4 are in Fl_cocoa.mm because they use Objective-c
   virtual void capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right);
   virtual void wait_for_expose();
-  CALayer *get_titlebar_layer();
-  void draw_layer_to_context(CALayer *layer, CGContextRef gc, int w, int h);
+  void draw_titlebar_to_context(CGContextRef gc, int w, int h);
   virtual int scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, void (*draw_area)(void*, int,int,int,int), void* data);
 
   // these functions are OpenGL-related and use objective-c
diff --git src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx
index cec8e0b..ed2772b 100644
--- src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx
+++ src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx
@@ -316,44 +316,17 @@ void Fl_Cocoa_Window_Driver::capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl
   int htop, hleft, hright, hbottom;
   Fl_Cocoa_Window_Driver::decoration_sizes(&htop, &hleft,  &hright, &hbottom);
   if (htop == 0) return; // when window is fullscreen
-  CALayer *layer = get_titlebar_layer();
   CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB();
   float s = Fl::screen_driver()->scale(screen_num());
   int scaled_w = int(w() * s);
-  const int factor = (layer && mapped_to_retina() ? 4 : 2); // resolution level for the titlebar (2 == retina's)
+  const int factor = (mapped_to_retina() ? 2 : 1);
   int data_w = factor * scaled_w, data_h = factor * htop;
   uchar *rgba = new uchar[4 * data_w * data_h];
   CGContextRef auxgc = CGBitmapContextCreate(rgba, data_w, data_h, 8, 4 * data_w, cspace, kCGImageAlphaPremultipliedLast);
   CGColorSpaceRelease(cspace);
   CGContextClearRect(auxgc, CGRectMake(0,0,data_w,data_h));
   CGContextScaleCTM(auxgc, factor, factor);
-  if (layer) {
-    draw_layer_to_context(layer, auxgc, scaled_w, htop);
-    if (fl_mac_os_version >= 101300 && fl_mac_os_version < 101500) {
-      // drawn layer is left transparent and alpha-premultiplied: demultiply it and set it opaque.
-      uchar *p = rgba;
-      uchar *last = rgba + data_w * data_h * 4;
-      while (p < last) {
-        uchar q = *(p+3);
-        if (q && q != 0xff) {
-          float m = 255./q;
-          *p++ *= m;
-          *p++ *= m;
-          *p++ *= m;
-          *p++ = 0xff;
-        } else p += 4;
-      }
-    }
-  } else {
-    Fl_Graphics_Driver::default_driver().scale(1);
-    CGImageRef img = CGImage_from_window_rect(0, -htop, scaled_w, htop, false);
-    Fl_Graphics_Driver::default_driver().scale(s);
-    CGContextSaveGState(auxgc);
-    clip_to_rounded_corners(auxgc, scaled_w, htop);
-    CGContextDrawImage(auxgc, CGRectMake(0, 0, scaled_w, htop), img);
-    CGContextRestoreGState(auxgc);
-    CFRelease(img);
-  }
+  draw_titlebar_to_context(auxgc, scaled_w, htop);
   top = new Fl_RGB_Image(rgba, data_w, data_h, 4);
   top->alloc_array = 1;
   top->scale(w(),htop, s <1 ? 0 : 1, 1);
diff --git src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.H src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.H
index e97304f..6aab639 100644
--- src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.H
+++ src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.H
@@ -33,7 +33,6 @@ protected:
   void set_current();
   void translate(int x, int y);
   void untranslate();
-  virtual void draw_decorated_window(Fl_Window *win, int x_offset, int y_offset);
 };
 
 #endif /* Fl_Quartz_Copy_Surface_Driver_H */
diff --git src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.cxx src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.cxx
index 5f37355..4a913ab 100644
--- src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.cxx
+++ src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.cxx
@@ -87,19 +87,4 @@ void Fl_Quartz_Copy_Surface_Driver::untranslate() {
   CGContextRestoreGState(gc);
 }
 
-void Fl_Quartz_Copy_Surface_Driver::draw_decorated_window(Fl_Window *win, int x_offset, int y_offset) {
-  CALayer *layer = Fl_Cocoa_Window_Driver::driver(win)->get_titlebar_layer();
-  if (!layer) {
-    return Fl_Widget_Surface::draw_decorated_window(win, x_offset, y_offset);
-  }
-  CGContextSaveGState(gc);
-  int bt = win->decorated_h() - win->h();
-  CGContextTranslateCTM(gc, x_offset - 0.5, y_offset + bt - 0.5);
-  float s = Fl::screen_scale(win->screen_num());
-  CGContextScaleCTM(gc, 1/s, s >= 1 ? -1/s : -1);
-  Fl_Cocoa_Window_Driver::driver(win)->draw_layer_to_context(layer, gc, win->w() * s, bt*s);
-  CGContextRestoreGState(gc);
-  draw(win, x_offset, y_offset + bt); // print the window inner part
-}
-
 #endif // FL_CFG_GFX_QUARTZ
Direct Link to Message ]
 
bottom left image   bottom right image
Previous Message ]Next Message ]
 
 

Comments are owned by the poster. All other content is copyright 1998-2020 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.