summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
authorManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2019-05-27 13:36:29 +0200
committerManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2019-05-27 13:36:29 +0200
commit7c4239915f818ff26309ed6a638871ea284a82e9 (patch)
treed842df48425e00e7b0d3a621363f1ba03376937d /src/drivers
parent2cbc743c6ad32c09c4dca68ab36a0f24307df0bf (diff)
Fix Fl_X11_Window_Driver::capture_titlebar_and_borders() for scaled, partially visible windows
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/X11/Fl_X11_Screen_Driver.cxx30
-rw-r--r--src/drivers/X11/Fl_X11_Window_Driver.cxx12
2 files changed, 23 insertions, 19 deletions
diff --git a/src/drivers/X11/Fl_X11_Screen_Driver.cxx b/src/drivers/X11/Fl_X11_Screen_Driver.cxx
index d71ef7486..43482bb1a 100644
--- a/src/drivers/X11/Fl_X11_Screen_Driver.cxx
+++ b/src/drivers/X11/Fl_X11_Screen_Driver.cxx
@@ -772,20 +772,20 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int
int allow_outside = w < 0; // negative w allows negative X or Y, that is, window frame
if (w < 0) w = - w;
+ float s = allow_outside ? Fl::screen_driver()->scale(Fl_Window::current()->screen_num()) : Fl_Surface_Device::surface()->driver()->scale();
+ int ws = w * s, hs = h * s, Xs = X*s, Ys = Y*s;
+
# ifdef __sgi
if (XReadDisplayQueryExtension(fl_display, &i, &i)) {
- image = XReadDisplay(fl_display, fl_window, X, Y, w, h, 0, NULL);
+ image = XReadDisplay(fl_display, fl_window, Xs, Ys, ws, hs, 0, NULL);
} else
# else
image = 0;
# endif // __sgi
- float s = Fl_Surface_Device::surface()->driver()->scale();
- int ws = w * s, hs = h * s;
-
if (!image) {
// fetch absolute coordinates
- int dx, dy, dxs, dys, sx, sy, sw, sh;
+ int dx, dy, sx, sy, sw, sh;
Window child_win;
Fl_Window *win;
@@ -793,31 +793,31 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int
else win = fl_find(fl_window);
if (win) {
XTranslateCoordinates(fl_display, fl_window,
- RootWindow(fl_display, fl_screen), X*s, Y*s, &dxs, &dys, &child_win);
- dx = dxs/s; dy = dys/s;
+ RootWindow(fl_display, fl_screen), Xs, Ys, &dx, &dy, &child_win);
// screen dimensions
Fl::screen_xywh(sx, sy, sw, sh, Fl_Window_Driver::driver(win)->screen_num());
+ sx *= s; sy *= s; sw *= s; sh *= s;
}
if (win && !allow_outside && int(s) != s) {
ws = (w+1)*s-1;
hs = (h+1)*s-1;
- if (int(X*s) + ws >= win->w()*s) ws = win->w()*s - int(X*s) -1;
- if (int(Y*s) + hs >= win->h()*s) hs = win->h()*s - int(Y*s) -1;
+ if (Xs + ws >= int(win->w()*s)) ws = win->w()*s - Xs -1;
+ if (Ys + hs >= int(win->h()*s)) hs = win->h()*s - Ys -1;
}
if (ws < 1) ws = 1;
if (hs < 1) hs = 1;
- if (!win || (dx >= sx && dy >= sy && dxs + ws <= (sx+sw)*s && dys + hs <= (sy+sh)*s) ) {
+ if (!win || (dx >= sx && dy >= sy && dx + ws <= sx+sw && dy + hs <= sy+sh) ) {
// the image is fully contained, we can use the traditional method
// however, if the window is obscured etc. the function will still fail. Make sure we
// catch the error and continue, otherwise an exception will be thrown.
XErrorHandler old_handler = XSetErrorHandler(xgetimageerrhandler);
- image = XGetImage(fl_display, fl_window, int(X*s), int(Y*s), ws, hs, AllPlanes, ZPixmap);
+ image = XGetImage(fl_display, fl_window, Xs, Ys, ws, hs, AllPlanes, ZPixmap);
XSetErrorHandler(old_handler);
} else {
// image is crossing borders, determine visible region
int nw, nh, noffx, noffy;
- noffx = fl_subimage_offsets(sx, sw, dx, w, nw);
- noffy = fl_subimage_offsets(sy, sh, dy, h, nh);
+ noffx = fl_subimage_offsets(sx, sw, dx, ws, nw);
+ noffy = fl_subimage_offsets(sy, sh, dy, hs, nh);
if (nw <= 0 || nh <= 0) return 0;
// allocate the image
@@ -831,8 +831,8 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int
}
XErrorHandler old_handler = XSetErrorHandler(xgetimageerrhandler);
- XImage *subimg = XGetSubImage(fl_display, fl_window, (X + noffx)*s, (Y + noffy)*s,
- nw*s, nh*s, AllPlanes, ZPixmap, image, noffx*s, noffy*s);
+ XImage *subimg = XGetSubImage(fl_display, fl_window, Xs + noffx, Ys + noffy,
+ nw, nh, AllPlanes, ZPixmap, image, noffx, noffy);
XSetErrorHandler(old_handler);
if (!subimg) {
XDestroyImage(image);
diff --git a/src/drivers/X11/Fl_X11_Window_Driver.cxx b/src/drivers/X11/Fl_X11_Window_Driver.cxx
index 34313ce26..e2ed5d073 100644
--- a/src/drivers/X11/Fl_X11_Window_Driver.cxx
+++ b/src/drivers/X11/Fl_X11_Window_Driver.cxx
@@ -391,14 +391,17 @@ void Fl_X11_Window_Driver::free_icons() {
The top and bottom images extend from left of the left border to right of the right border.
This function exploits a feature of Fl_X11_Screen_Driver::read_win_rectangle() which,
- when called with negative 4th argument, captures the window decoration.
+ when called with negative 3rd argument, captures the window decoration.
+ Other requirements to capture the window decoration:
+ - fl_window is the parent window of the top window
+ - Fl_Window::current() is the top window
*/
void Fl_X11_Window_Driver::capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right)
{
top = left = bottom = right = NULL;
if (pWindow->decorated_h() == h()) return;
Window from = fl_window;
- Fl_Surface_Device::push_current( Fl_Display_Device::display_device() );
+ Fl_Window *oldcurrent = Fl_Window::current();
Window root, parent, *children, child_win, xid = fl_xid(pWindow);
unsigned n = 0;
int do_it;
@@ -411,9 +414,10 @@ void Fl_X11_Window_Driver::capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_R
float s = Fl::screen_driver()->scale(screen_num());
htop /= s; wsides /= s;
fl_window = parent;
+ current(pWindow);
if (htop) {
top = Fl::screen_driver()->read_win_rectangle(0, 0, - (w() + 2 * wsides), htop);
- top->scale(w() + 2 * wsides, htop, 0, 1);
+ if (top) top->scale(w() + 2 * wsides, htop, 0, 1);
}
if (wsides) {
left = Fl::screen_driver()->read_win_rectangle(0, htop, -wsides, h());
@@ -428,7 +432,7 @@ void Fl_X11_Window_Driver::capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_R
if (bottom) {
bottom->scale(w() + 2*wsides, wsides, 0, 1);
} }
- Fl_Surface_Device::pop_current();
+ current(oldcurrent);
fl_window = from;
}