FLTK logo

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

FLTK matrix user chat room
(using Element browser app)   FLTK gitter user chat room   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" Oct 12, 2020  
 
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 ]
 
     
Previous Message ]Next Message ]
 
 

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