mirror of https://github.com/fltk/fltk
Fix a case when fl_read_window() did not capture subwindows correctly.
The case was under macOS with a non-GL parent window mapped to a retina display containing a GL subwindow and if the app did not call Fl::use_high_res_GL(1).
This commit is contained in:
parent
5255640e7a
commit
33eb87940d
|
@ -136,16 +136,17 @@ public:
|
|||
// we no longer need the on-screen keyboard; it's up to the system to hide it
|
||||
virtual void release_keyboard() { }
|
||||
|
||||
// read raw image from a window or an offscreen buffer
|
||||
/* Member function read_win_rectangle() supports the public function
|
||||
fl_read_image() which captures pixel data either from
|
||||
the current window or from an offscreen buffer.
|
||||
|
||||
With fl_read_image() and for capture from a window, the returned pixel array
|
||||
also contains data from any embedded sub-window.
|
||||
/* Member function read_win_rectangle() supports public functions
|
||||
fl_read_image() and fl_capture_window_part() which capture pixel data from
|
||||
a window (or also from an offscreen buffer with fl_read_image).
|
||||
|
||||
In the case of read_win_rectangle() and for capture from a window, only data
|
||||
from the current window is collected.
|
||||
If 'may_capture_subwins' is true, an implementation may or may not capture
|
||||
also the content of subwindows embedded in 'win'. If subwindows were captured,
|
||||
*'did_capture_subwins' is returned set to true. If read_win_rectangle()
|
||||
is called with 'may_capture_subwins' set to true, 'did_capture_subwins' should
|
||||
be set before the call to the address of a boolean set to false.
|
||||
The implementation of this virtual function for the macOS platform has the
|
||||
capability of capturing subwindows when asked for.
|
||||
|
||||
A platform may also use its read_win_rectangle() implementation to capture
|
||||
window decorations (e.g., title bar). In that case, it is called by
|
||||
|
@ -153,7 +154,8 @@ public:
|
|||
|
||||
win is the window to capture from, or NULL to capture from the current offscreen
|
||||
*/
|
||||
virtual Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win) {return NULL;}
|
||||
virtual Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win,
|
||||
bool may_capture_subwins = false, bool *did_capture_subwins = NULL) {return NULL;}
|
||||
static void write_image_inside(Fl_RGB_Image *to, Fl_RGB_Image *from, int to_x, int to_y);
|
||||
static Fl_RGB_Image *traverse_to_gl_subwindows(Fl_Group *g, int x, int y, int w, int h,
|
||||
Fl_RGB_Image *full_img);
|
||||
|
|
|
@ -190,17 +190,18 @@ Image depths can differ between "to" and "from".
|
|||
Fl_RGB_Image *Fl_Screen_Driver::traverse_to_gl_subwindows(Fl_Group *g, int x, int y, int w, int h,
|
||||
Fl_RGB_Image *full_img)
|
||||
{
|
||||
bool captured_subwin = false;
|
||||
if ( g->as_gl_window() ) {
|
||||
Fl_Device_Plugin *plugin = Fl_Device_Plugin::opengl_plugin();
|
||||
if (!plugin) return full_img;
|
||||
full_img = plugin->rectangle_capture(g, x, y, w, h);
|
||||
}
|
||||
else if ( g->as_window() ) {
|
||||
full_img = Fl::screen_driver()->read_win_rectangle(x, y, w, h, g->as_window());
|
||||
full_img = Fl::screen_driver()->read_win_rectangle(x, y, w, h, g->as_window(), true, &captured_subwin);
|
||||
}
|
||||
if (!full_img) return NULL;
|
||||
float full_img_scale = (full_img && w > 0 ? float(full_img->data_w())/w : 1);
|
||||
int n = g->children();
|
||||
int n = (captured_subwin ? 0 : g->children());
|
||||
for (int i = 0; i < n; i++) {
|
||||
Fl_Widget *c = g->child(i);
|
||||
if ( !c->visible() || !c->as_group()) continue;
|
||||
|
|
|
@ -4255,13 +4255,13 @@ static NSBitmapImageRep* rect_to_NSBitmapImageRep(Fl_Window *win, int x, int y,
|
|||
#endif
|
||||
}
|
||||
}
|
||||
if (!bitmap) return nil;
|
||||
if (!capture_subwins || !bitmap) return bitmap;
|
||||
|
||||
// capture also subwindows
|
||||
NSArray *children = [fl_xid(win) childWindows]; // 10.2
|
||||
NSEnumerator *enumerator = [children objectEnumerator];
|
||||
id child;
|
||||
while (capture_subwins && ((child = [enumerator nextObject]) != nil)) {
|
||||
while ((child = [enumerator nextObject]) != nil) {
|
||||
if (![child isKindOfClass:[FLWindow class]]) continue;
|
||||
Fl_Window *sub = [(FLWindow*)child getFl_Window];
|
||||
CGRect rsub = CGRectMake(sub->x(), win->h() -(sub->y()+sub->h()), sub->w(), sub->h());
|
||||
|
@ -4272,7 +4272,9 @@ static NSBitmapImageRep* rect_to_NSBitmapImageRep(Fl_Window *win, int x, int y,
|
|||
win->h() - clip.origin.y - sub->y() - clip.size.height, clip.size.width, clip.size.height);
|
||||
if (childbitmap) {
|
||||
// if bitmap is high res and childbitmap is not, childbitmap must be rescaled
|
||||
if ([bitmap pixelsWide] > w && [childbitmap pixelsWide] == clip.size.width) childbitmap = scale_nsbitmapimagerep(childbitmap, 2);
|
||||
if (!win->as_gl_window() && Fl_Cocoa_Window_Driver::driver(win)->mapped_to_retina() && sub->as_gl_window() && !Fl::use_high_res_GL()) {
|
||||
childbitmap = scale_nsbitmapimagerep(childbitmap, 2);
|
||||
}
|
||||
write_bitmap_inside(bitmap, w*s, childbitmap,
|
||||
(clip.origin.x - x)*s, (win->h() - clip.origin.y - clip.size.height - y)*s );
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ public:
|
|||
virtual APP_SCALING_CAPABILITY rescalable() { return SYSTEMWIDE_APP_SCALING; }
|
||||
virtual float scale(int n) {return scale_;}
|
||||
virtual void scale(int n, float f) { scale_ = f;}
|
||||
virtual Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win);
|
||||
virtual Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win, bool may_capture_subwins, bool *did_capture_subwins);
|
||||
private:
|
||||
float scale_;
|
||||
};
|
||||
|
|
|
@ -339,7 +339,8 @@ void Fl_Cocoa_Screen_Driver::offscreen_size(Fl_Offscreen off, int &width, int &h
|
|||
height = CGBitmapContextGetHeight(off);
|
||||
}
|
||||
|
||||
Fl_RGB_Image *Fl_Cocoa_Screen_Driver::read_win_rectangle(int X, int Y, int w, int h, Fl_Window *window)
|
||||
Fl_RGB_Image *Fl_Cocoa_Screen_Driver::read_win_rectangle(int X, int Y, int w, int h, Fl_Window *window,
|
||||
bool may_capture_subwins, bool *did_capture_subwins)
|
||||
{
|
||||
int bpp, bpr, depth = 4;
|
||||
uchar *base, *p;
|
||||
|
@ -374,7 +375,8 @@ Fl_RGB_Image *Fl_Cocoa_Screen_Driver::read_win_rectangle(int X, int Y, int w, in
|
|||
bpr = 0;
|
||||
} else { // read from window
|
||||
Fl_Cocoa_Window_Driver *d = Fl_Cocoa_Window_Driver::driver(window);
|
||||
CGImageRef cgimg = d->CGImage_from_window_rect(X, Y, w, h, false);
|
||||
CGImageRef cgimg = d->CGImage_from_window_rect(X, Y, w, h, may_capture_subwins);
|
||||
if (did_capture_subwins) *did_capture_subwins = may_capture_subwins;
|
||||
if (!cgimg) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ public:
|
|||
virtual void remove_timeout(Fl_Timeout_Handler cb, void *argp);
|
||||
virtual int dnd(int unused);
|
||||
virtual int compose(int &del);
|
||||
virtual Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win);
|
||||
virtual Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win, bool may_capture_subwins, bool *did_capture_subwins);
|
||||
Fl_RGB_Image *read_win_rectangle_unscaled(int X, int Y, int w, int h, Fl_Window *win);
|
||||
virtual int get_mouse(int &x, int &y);
|
||||
virtual void enable_im();
|
||||
|
|
|
@ -488,7 +488,8 @@ Fl_WinAPI_Screen_Driver::read_win_rectangle(
|
|||
int Y, // I - Top position
|
||||
int w, // I - Width of area to read
|
||||
int h, // I - Height of area to read
|
||||
Fl_Window *win) // I - window to capture from or NULL to capture from current offscreen
|
||||
Fl_Window *win, // I - window to capture from or NULL to capture from current offscreen
|
||||
bool may_capture_subwins, bool *did_capture_subwins)
|
||||
{
|
||||
float s = Fl_Surface_Device::surface()->driver()->scale();
|
||||
int ws, hs;
|
||||
|
|
|
@ -95,7 +95,7 @@ public:
|
|||
virtual int compose(int &del);
|
||||
virtual void compose_reset();
|
||||
virtual int text_display_can_leak();
|
||||
virtual Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win);
|
||||
virtual Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win, bool may_capture_subwins, bool *did_capture_subwins);
|
||||
virtual int get_mouse(int &x, int &y);
|
||||
virtual void enable_im();
|
||||
virtual void disable_im();
|
||||
|
|
|
@ -745,7 +745,7 @@ extern "C" {
|
|||
}
|
||||
}
|
||||
|
||||
Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win)
|
||||
Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win, bool may_capture_subwins, bool *did_capture_subwins)
|
||||
{
|
||||
XImage *image; // Captured image
|
||||
int i, maxindex; // Looping vars
|
||||
|
|
Loading…
Reference in New Issue