summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--FL/Fl_Paged_Device.H8
-rw-r--r--FL/Fl_Window.H12
-rw-r--r--src/Fl_cocoa.mm89
-rw-r--r--src/Fl_win32.cxx65
-rw-r--r--src/Fl_x.cxx77
-rw-r--r--src/fl_read_image.cxx8
-rw-r--r--src/fl_read_image_win32.cxx23
7 files changed, 230 insertions, 52 deletions
diff --git a/FL/Fl_Paged_Device.H b/FL/Fl_Paged_Device.H
index bdc448925..5ef4a1137 100644
--- a/FL/Fl_Paged_Device.H
+++ b/FL/Fl_Paged_Device.H
@@ -132,6 +132,14 @@ public:
virtual void translate(int x, int y);
virtual void untranslate(void);
virtual void print_widget(Fl_Widget* widget, int delta_x = 0, int delta_y = 0);
+ /** Prints a window with its title bar and frame if any.
+
+ \p x_offset and \p y_offset are optional coordinates of where to position the window top left.
+ Equivalent to print_widget() if \p win is a subwindow or has no border.
+ Use Fl_Window::decorated_w() and Fl_Window::decorated_h() to get the size of the
+ printed window.
+ */
+ void print_window(Fl_Window *win, int x_offset = 0, int y_offset = 0);
virtual void print_window_part(Fl_Window *win, int x, int y, int w, int h, int delta_x = 0, int delta_y = 0);
virtual int end_page (void);
virtual void end_job (void);
diff --git a/FL/Fl_Window.H b/FL/Fl_Window.H
index 1390f173e..ab7f43e16 100644
--- a/FL/Fl_Window.H
+++ b/FL/Fl_Window.H
@@ -443,6 +443,18 @@ public:
void cursor(Fl_Cursor, Fl_Color=FL_BLACK, Fl_Color=FL_WHITE); // platform dependent
void default_cursor(Fl_Cursor, Fl_Color=FL_BLACK, Fl_Color=FL_WHITE);
static void default_callback(Fl_Window*, void* v);
+
+ /** Returns the window width including any frame added by the window manager.
+
+ Same as w() if applied to a subwindow.
+ */
+ int decorated_w();
+ /** Returns the window height including any window title bar and any frame
+ added by the window manager.
+
+ Same as h() if applied to a subwindow.
+ */
+ int decorated_h();
};
diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm
index eac031a28..0951e1c06 100644
--- a/src/Fl_cocoa.mm
+++ b/src/Fl_cocoa.mm
@@ -1417,12 +1417,20 @@ void fl_close_display() {
// Gets the border sizes and the titlebar size
static void get_window_frame_sizes(int &bx, int &by, int &bt) {
- if (NSApp == nil) fl_open_display();
- NSRect inside = { {20,20}, {100,100} };
- NSRect outside = [NSWindow frameRectForContentRect:inside styleMask:NSTitledWindowMask];
- bx = int(outside.origin.x - inside.origin.x);
- by = int(outside.origin.y - inside.origin.y);
- bt = int(outside.size.height - inside.size.height - by);
+ static bool first = true;
+ static int top, left, bottom;
+ if (first) {
+ first = false;
+ if (NSApp == nil) fl_open_display();
+ NSRect inside = { {20,20}, {100,100} };
+ NSRect outside = [NSWindow frameRectForContentRect:inside styleMask:NSTitledWindowMask];
+ left = int(outside.origin.x - inside.origin.x);
+ bottom = int(outside.origin.y - inside.origin.y);
+ top = int(outside.size.height - inside.size.height) - bottom;
+ }
+ bx = left;
+ by = bottom;
+ bt = top;
}
/*
@@ -2861,7 +2869,7 @@ int Fl_X::screen_init(XRectangle screens[], float dpi[])
{
Fl_Printer printer;
//Fl_PostScript_File_Device printer;
- int w, h, wh;
+ int w, h, ww, wh;
Fl_Window *win = Fl::first_window();
if(!win) return;
if( printer.start_job(1) ) return;
@@ -2869,13 +2877,9 @@ int Fl_X::screen_init(XRectangle screens[], float dpi[])
// scale the printer device so that the window fits on the page
float scale = 1;
printer.printable_rect(&w, &h);
- wh = win->h();
- int bx, by, bt = 0;
- if (win->border()) {
- get_window_frame_sizes(bx, by, bt);
- wh += bt;
- }
- if (win->w()>w || wh>h) {
+ ww = win->decorated_w();
+ wh = win->decorated_h();
+ if (ww>w || wh>h) {
scale = (float)w/win->w();
if ((float)h/wh < scale) scale = (float)h/wh;
printer.scale(scale);
@@ -2888,22 +2892,7 @@ int Fl_X::screen_init(XRectangle screens[], float dpi[])
printer.rotate(20.);
printer.print_widget( win, - win->w()/2, - win->h()/2 );
#else
- if (bt) { // print the window title bar
- //printer.print_window_part(win, 0, -bt, win->w(), bt, 0, 1);
- Fl_Display_Device::display_device()->set_current();
- win->show();
- fl_gc = NULL;
- Fl::check();
- win->make_current();
- CGImageRef img = Fl_X::CGImage_from_window_rect(win, 0, -bt, win->w(), bt);
- printer.set_current();
- CGRect rect = { { 0, 1 }, { win->w(), bt } };
- Fl_X::q_begin_image(rect, 0, 0, win->w(), bt);
- CGContextDrawImage(fl_gc, rect, img);
- Fl_X::q_end_image();
- CGImageRelease(img);
- }
- printer.print_widget(win, 0, bt);
+ printer.print_window(win);
#endif
printer.end_page();
printer.end_job();
@@ -3401,6 +3390,46 @@ Window fl_xid(const Fl_Window* w)
return Fl_X::i(w)->xid;
}
+int Fl_Window::decorated_w()
+{
+ if (this->parent() || !border()) return w();
+ int bx, by, bt;
+ get_window_frame_sizes(bx, by, bt);
+ return w() + 2 * bx;
+}
+
+int Fl_Window::decorated_h()
+{
+ if (this->parent() || !border()) return h();
+ int bx, by, bt;
+ get_window_frame_sizes(bx, by, bt);
+ return h() + bt + by;
+}
+
+void Fl_Paged_Device::print_window(Fl_Window *win, int x_offset, int y_offset)
+{
+ if (win->parent() || !win->border()) {
+ this->print_widget(win, x_offset, y_offset);
+ return;
+ }
+ int bx, by, bt;
+ get_window_frame_sizes(bx, by, bt);
+ Fl_Display_Device::display_device()->set_current(); // send win to front and make it current
+ win->show();
+ fl_gc = NULL;
+ Fl::check();
+ win->make_current();
+ // capture the window title bar from screen
+ CGImageRef img = Fl_X::CGImage_from_window_rect(win, 0, -bt, win->w(), bt);
+ this->set_current(); // back to the Fl_Paged_Device
+ CGRect rect = { { 0, 1 }, { win->w(), bt } }; // print the title bar
+ Fl_X::q_begin_image(rect, 0, 0, win->w(), bt);
+ CGContextDrawImage(fl_gc, rect, img);
+ Fl_X::q_end_image();
+ CGImageRelease(img);
+ this->print_widget(win, x_offset, y_offset + bt); // print the window inner part
+}
+
#include <dlfcn.h>
/* Returns the address of a Carbon function after dynamically loading the Carbon library if needed.
diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx
index 7ded352ef..20b9a2b00 100644
--- a/src/Fl_win32.cxx
+++ b/src/Fl_win32.cxx
@@ -38,6 +38,7 @@
#include <FL/fl_draw.H>
#include <FL/Enumerations.H>
#include <FL/Fl_Tooltip.H>
+#include <FL/Fl_Paged_Device.H>
#include "flstring.h"
#include "Fl_Font.H"
#include <stdio.h>
@@ -1945,6 +1946,56 @@ Window fl_xid_(const Fl_Window *w) {
return temp ? temp->xid : 0;
}
+int Fl_Window::decorated_w()
+{
+ if (parent() || !shown()) return w();
+ int X, Y, bt, bx, by;
+ Fl_X::fake_X_wm(this, X, Y, bt, bx, by);
+ return w() + 2 * bx;
+}
+
+int Fl_Window::decorated_h()
+{
+ if (this->parent() || !shown()) return h();
+ int X, Y, bt, bx, by;
+ Fl_X::fake_X_wm(this, X, Y, bt, bx, by);
+ return h() + bt + 2 * by;
+}
+
+void Fl_Paged_Device::print_window(Fl_Window *win, int x_offset, int y_offset)
+{
+ if (win->parent() || !win->border()) {
+ this->print_widget(win, x_offset, y_offset);
+ return;
+ }
+ int X, Y, bt, bx, by, ww, wh; // compute the window border sizes
+ Fl_X::fake_X_wm(win, X, Y, bt, bx, by);
+ ww = win->w() + 2 * bx;
+ wh = win->h() + bt + 2 * by;
+ Fl_Display_Device::display_device()->set_current(); // make window current
+ win->show();
+ Fl::check();
+ win->make_current();
+ // capture the 4 window sides from screen
+ // use negative 4th argument to allow negative 2nd or 3rd arguments
+ uchar *top_image = fl_read_image(NULL, -bx, - bt - by, -ww, bt + by);
+ uchar *left_image = fl_read_image(NULL, -bx, - bt - by, -bx, wh);
+ uchar *right_image = fl_read_image(NULL, win->w(), - bt - by, -bx, wh);
+ uchar *bottom_image = fl_read_image(NULL, -bx, win->h(), -ww, by);
+ this->set_current();
+ // print the 4 window sides
+ fl_draw_image(top_image, x_offset, y_offset, ww, bt + by, 3);
+ fl_draw_image(left_image, x_offset, y_offset, bx, wh, 3);
+ fl_draw_image(right_image, x_offset + win->w() + bx, y_offset, bx, wh, 3);
+ fl_draw_image(bottom_image, x_offset, y_offset + win->h() + bt + by, ww, by, 3);
+ delete[] top_image;
+ delete[] left_image;
+ delete[] right_image;
+ delete[] bottom_image;
+ // print the window inner part
+ this->print_widget(win, x_offset + bx, y_offset + bt + by);
+}
+
#ifdef USE_PRINT_BUTTON
// to test the Fl_Printer class creating a "Print front window" button in a separate window
// contains also preparePrintFront call above
@@ -1960,11 +2011,14 @@ void printFront(Fl_Widget *o, void *data)
if( printer.start_job(1) ) { o->window()->show(); return; }
if( printer.start_page() ) { o->window()->show(); return; }
printer.printable_rect(&w,&h);
+ int wh, ww;
+ wh = win->decorated_h();
+ ww = win->decorated_w();
// scale the printer device so that the window fits on the page
float scale = 1;
- if (win->w() > w || win->h() > h) {
- scale = (float)w/win->w();
- if ((float)h/win->h() < scale) scale = (float)h/win->h();
+ if (ww > w || wh > h) {
+ scale = (float)w/ww;
+ if ((float)h/wh < scale) scale = (float)h/wh;
printer.scale(scale, scale);
}
// #define ROTATE 20.0
@@ -1975,9 +2029,8 @@ void printFront(Fl_Widget *o, void *data)
printer.rotate(ROTATE);
printer.print_widget( win, - win->w()/2, - win->h()/2 );
//printer.print_window_part( win, 0,0, win->w(), win->h(), - win->w()/2, - win->h()/2 );
-#else
- printer.print_widget( win );
- //printer.print_window_part( win, 0,0, win->w(), win->h() );
+#else
+ printer.print_window(win);
#endif
printer.end_page();
printer.end_job();
diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx
index 282c10b60..45e4aa18f 100644
--- a/src/Fl_x.cxx
+++ b/src/Fl_x.cxx
@@ -42,6 +42,7 @@
# include <FL/fl_utf8.h>
# include <FL/Fl_Tooltip.H>
# include <FL/fl_draw.H>
+# include <FL/Fl_Paged_Device.H>
# include <stdio.h>
# include <stdlib.h>
# include "flstring.h"
@@ -1890,6 +1891,69 @@ Window fl_xid_(const Fl_Window* w)
return Fl_X::i(w)->xid;
}
+
+int Fl_Window::decorated_h()
+{
+ if (parent() || !shown()) return h();
+ Window root, parent, *children;
+ unsigned n;
+ XQueryTree(fl_display, i->xid, &root, &parent, &children, &n); if (n) XFree(children);
+ XWindowAttributes attributes;
+ XGetWindowAttributes(fl_display, parent, &attributes);
+ return attributes.height;
+}
+
+int Fl_Window::decorated_w()
+{
+ if (parent() || !shown()) return w();
+ Window root, parent, *children;
+ unsigned n;
+ XQueryTree(fl_display, i->xid, &root, &parent, &children, &n); if (n) XFree(children);
+ XWindowAttributes attributes;
+ XGetWindowAttributes(fl_display, parent, &attributes);
+ return attributes.width;
+}
+
+void Fl_Paged_Device::print_window(Fl_Window *win, int x_offset, int y_offset)
+{
+ if (win->parent() || !win->border()) {
+ this->print_widget(win, x_offset, y_offset);
+ return;
+ }
+ Fl_Display_Device::display_device()->set_current();
+ win->show();
+ Fl::check();
+ win->make_current();
+ Window root, parent, *children, child_win, from;
+ unsigned n;
+ int bx, bt;
+ from = fl_window;
+ XQueryTree(fl_display, fl_window, &root, &parent, &children, &n); if (n) XFree(children);
+ XTranslateCoordinates(fl_display, fl_window, parent, 0, 0, &bx, &bt, &child_win);
+ fl_window = parent;
+ uchar *top_image, *left_image, *right_image, *bottom_image;
+ top_image = fl_read_image(NULL, 0, 0, - (win->w() + 2 * bx), bt);
+ if (bx) {
+ left_image = fl_read_image(NULL, 0, bt, -bx, win->h() + bx);
+ right_image = fl_read_image(NULL, win->w() + bx, bt, -bx, win->h() + bx);
+ bottom_image = fl_read_image(NULL, 0, bt + win->h(), -(win->w() + 2*bx), bx);
+ }
+ fl_window = from;
+ this->set_current();
+ fl_draw_image(top_image, x_offset, y_offset, win->w() + 2 * bx, bt, 3);
+ delete[] top_image;
+ if (bx) {
+ if (left_image) fl_draw_image(left_image, x_offset, y_offset + bt, bx, win->h() + bx, 3);
+ if (right_image) fl_draw_image(right_image, x_offset + win->w() + bx, y_offset + bt, bx, win->h() + bx, 3);
+ if (bottom_image) fl_draw_image(bottom_image, x_offset, y_offset + bt + win->h(), win->w() + 2*bx, bx, 3);
+ if (left_image) delete[] left_image;
+ if (right_image) delete[] right_image;
+ if (bottom_image) delete[] bottom_image;
+ }
+ this->print_widget( win, x_offset + bx, y_offset + bt );
+}
+
+
#ifdef USE_PRINT_BUTTON
// to test the Fl_Printer class creating a "Print front window" button in a separate window
// contains also preparePrintFront call above
@@ -1907,9 +1971,11 @@ void printFront(Fl_Widget *o, void *data)
printer.printable_rect(&w,&h);
// scale the printer device so that the window fits on the page
float scale = 1;
- if (win->w() > w || win->h() > h) {
- scale = (float)w/win->w();
- if ((float)h/win->h() < scale) scale = (float)h/win->h();
+ int ww = win->decorated_w();
+ int wh = win->decorated_h();
+ if (ww > w || wh > h) {
+ scale = (float)w/ww;
+ if ((float)h/wh < scale) scale = (float)h/wh;
printer.scale(scale, scale);
}
@@ -1921,9 +1987,8 @@ void printFront(Fl_Widget *o, void *data)
printer.rotate(ROTATE);
printer.print_widget( win, - win->w()/2, - win->h()/2 );
//printer.print_window_part( win, 0,0, win->w(), win->h(), - win->w()/2, - win->h()/2 );
-#else
- printer.print_widget( win );
- //printer.print_window_part( win, 0,0,win->w(), win->h() );
+#else
+ printer.print_window(win);
#endif
printer.end_page();
diff --git a/src/fl_read_image.cxx b/src/fl_read_image.cxx
index 9475e2ec9..9597005e1 100644
--- a/src/fl_read_image.cxx
+++ b/src/fl_read_image.cxx
@@ -92,6 +92,7 @@ fl_read_image(uchar *p, // I - Pixel buffer or NULL to allocate
int X, // I - Left position
int Y, // I - Top position
int w, // I - Width of area to read
+ // negative allows capture of window title bar and frame
int h, // I - Height of area to read
int alpha) { // I - Alpha value for image (0 for none)
XImage *image; // Captured image
@@ -118,6 +119,8 @@ fl_read_image(uchar *p, // I - Pixel buffer or NULL to allocate
// ReadDisplay extension which does all of the really hard work for
// us...
//
+ int allow_outside = w < 0; // negative w allows negative X or Y, that is, window frame
+ if (w < 0) w = - w;
# ifdef __sgi
if (XReadDisplayQueryExtension(fl_display, &i, &i)) {
@@ -131,7 +134,10 @@ fl_read_image(uchar *p, // I - Pixel buffer or NULL to allocate
// fetch absolute coordinates
int dx, dy, sx, sy, sw, sh;
Window child_win;
- Fl_Window *win = fl_find(fl_window);
+
+ Fl_Window *win;
+ if (allow_outside) win = (Fl_Window*)1;
+ else win = fl_find(fl_window);
if (win) {
XTranslateCoordinates(fl_display, fl_window,
RootWindow(fl_display, fl_screen), X, Y, &dx, &dy, &child_win);
diff --git a/src/fl_read_image_win32.cxx b/src/fl_read_image_win32.cxx
index eb881d4a8..875b945a9 100644
--- a/src/fl_read_image_win32.cxx
+++ b/src/fl_read_image_win32.cxx
@@ -34,10 +34,13 @@ fl_read_image(uchar *p, // I - Pixel buffer or NULL to allocate
int X, // I - Left position
int Y, // I - Top position
int w, // I - Width of area to read
+ // negative w means negative X or Y are allowed
int h, // I - Height of area to read
int alpha) { // I - Alpha value for image (0 for none)
int d; // Depth of image
+ int allow_outside = w < 0; // negative w allows negative X or Y, that is, window border
+ if (w < 0) w = - w;
// Allocate the image data array as needed...
d = alpha ? 4 : 3;
@@ -58,15 +61,17 @@ fl_read_image(uchar *p, // I - Pixel buffer or NULL to allocate
int shift_x = 0; // X target shift if X modified
int shift_y = 0; // Y target shift if X modified
- if (X < 0) {
- shift_x = -X;
- w += X;
- X = 0;
- }
- if (Y < 0) {
- shift_y = -Y;
- h += Y;
- Y = 0;
+ if (!allow_outside) {
+ if (X < 0) {
+ shift_x = -X;
+ w += X;
+ X = 0;
+ }
+ if (Y < 0) {
+ shift_y = -Y;
+ h += Y;
+ Y = 0;
+ }
}
if (h < 1 || w < 1) return p; // nothing to copy