summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorManolo Gouy <Manolo>2016-01-10 19:08:16 +0000
committerManolo Gouy <Manolo>2016-01-10 19:08:16 +0000
commiteeb65bef23b2d269ea38474c04a55ffca5c6e63e (patch)
treee00061d0a9dfd7b28e031b1f976ae31c852fac39 /src
parentacc50806538da470ba18a2f7b76ea65a64cb5f5c (diff)
1) Replicate in branch-1.3-porting all recent changes of branch-1.3
2) Advance branch-1.3-porting with new function Fl_X::capture_titlebar_and_borders() that contains all the platform-specific code of all operations related to drawing window borders and title bars. What is platform-specific and what is not is therefore much clearer, to ease porting. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11002 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src')
-rw-r--r--src/Fl_Copy_Surface.cxx14
-rw-r--r--src/Fl_Image_Surface.cxx49
-rw-r--r--src/Fl_Paged_Device.cxx41
-rw-r--r--src/Fl_cocoa.mm179
-rw-r--r--src/Fl_win32.cxx129
-rw-r--r--src/Fl_x.cxx83
6 files changed, 268 insertions, 227 deletions
diff --git a/src/Fl_Copy_Surface.cxx b/src/Fl_Copy_Surface.cxx
index 1f0b654c5..a0b942b67 100644
--- a/src/Fl_Copy_Surface.cxx
+++ b/src/Fl_Copy_Surface.cxx
@@ -89,7 +89,7 @@ Fl_Copy_Surface::Fl_Copy_Surface(int w, int h) : Fl_Surface_Device(NULL)
int vdots = GetDeviceCaps(hdc, VERTRES);
ReleaseDC(NULL, hdc);
float factorw = (100. * hmm) / hdots;
- float factorh = (100. * vmm) / vdots + 0.5;
+ float factorh = (100. * vmm) / vdots;
RECT rect; rect.left = 0; rect.top = 0; rect.right = w * factorw; rect.bottom = h * factorh;
gc = CreateEnhMetaFile (NULL, NULL, &rect, NULL);
@@ -217,20 +217,10 @@ void Fl_Copy_Surface::prepare_copy_pdf_and_tiff(int w, int h)
#endif // __APPLE__
-#if !defined(__APPLE__)
-/** Copies a window and its borders and title bar to the clipboard. */
void Fl_Copy_Surface::draw_decorated_window(Fl_Window* win, int delta_x, int delta_y)
{
-#if defined(WIN32)
- helper->draw_decorated_window(win, delta_x, delta_y, this);
-#elif defined(__APPLE__)
-#elif defined(FL_PORTING)
-# pragma message "FL_PORTING: do you want to draw a window border around a printout"
-#else
- helper->draw_decorated_window(win, delta_x, delta_y, this);
-#endif
+ helper->draw_decorated_window(win, delta_x, delta_y);
}
-#endif
#if defined(WIN32)
#elif defined(__APPLE__)
diff --git a/src/Fl_Image_Surface.cxx b/src/Fl_Image_Surface.cxx
index b73561fe4..79f5c28d3 100644
--- a/src/Fl_Image_Surface.cxx
+++ b/src/Fl_Image_Surface.cxx
@@ -34,31 +34,27 @@ const char *Fl_Image_Surface::class_id = "Fl_Image_Surface";
Fl_Image_Surface::Fl_Image_Surface(int w, int h) : Fl_Surface_Device(NULL) {
width = w;
height = h;
-#if defined(__APPLE__)
-#elif defined(WIN32)
-#elif defined(FL_PORTING)
-# pragma message "FL_PORTING: implement Fl_Image_Surface"
-#else
- gc = 0;
- if (!fl_gc) { // allows use of this class before any window is shown
- fl_open_display();
- gc = XCreateGC(fl_display, RootWindow(fl_display, fl_screen), 0, 0);
- fl_gc = gc;
- }
-#endif
- offscreen = fl_create_offscreen(w, h);
#ifdef __APPLE__
+ offscreen = Fl_Quartz_Graphics_Driver::create_offscreen_with_alpha(w, h);
helper = new Fl_Quartz_Flipped_Surface_(width, height);
driver(helper->driver());
CGContextSaveGState(offscreen);
CGContextTranslateCTM(offscreen, 0, height);
CGContextScaleCTM(offscreen, 1.0f, -1.0f);
#elif defined(WIN32)
+ offscreen = fl_create_offscreen(w, h);
helper = new Fl_GDI_Surface_();
driver(helper->driver());
#elif defined(FL_PORTING)
# pragma message "FL_PORTING: implement Fl_Image_Surface"
#else
+ gc = 0;
+ if (!fl_gc) { // allows use of this class before any window is shown
+ fl_open_display();
+ gc = XCreateGC(fl_display, RootWindow(fl_display, fl_screen), 0, 0);
+ fl_gc = gc;
+ }
+ offscreen = fl_create_offscreen(w, h);
helper = new Fl_Xlib_Surface_();
driver(helper->driver());
#endif
@@ -67,14 +63,18 @@ Fl_Image_Surface::Fl_Image_Surface(int w, int h) : Fl_Surface_Device(NULL) {
/** The destructor.
*/
Fl_Image_Surface::~Fl_Image_Surface() {
- fl_delete_offscreen(offscreen);
#ifdef __APPLE__
+ void *data = CGBitmapContextGetData((CGContextRef)offscreen);
+ free(data);
+ CGContextRelease((CGContextRef)offscreen);
delete (Fl_Quartz_Flipped_Surface_*)helper;
#elif defined(WIN32)
+ fl_delete_offscreen(offscreen);
delete (Fl_GDI_Surface_*)helper;
#elif defined(FL_PORTING)
# pragma message "FL_PORTING: implement Fl_Image_Surface"
#else
+ fl_delete_offscreen(offscreen);
if (gc) { XFreeGC(fl_display, gc); fl_gc = 0; }
delete (Fl_Xlib_Surface_*)helper;
#endif
@@ -86,9 +86,13 @@ Fl_Image_Surface::~Fl_Image_Surface() {
Fl_RGB_Image* Fl_Image_Surface::image()
{
unsigned char *data;
+ int depth = 3, ld = 0;
#ifdef __APPLE__
CGContextFlush(offscreen);
- data = fl_read_image(NULL, 0, 0, width, height, 0);
+ ld = CGBitmapContextGetBytesPerRow(offscreen);
+ data = (uchar*)malloc(ld * height);
+ memcpy(data, (uchar *)CGBitmapContextGetData(offscreen), ld * height);
+ depth = 4;
fl_gc = 0;
#elif defined(WIN32)
fl_pop_clip();
@@ -106,7 +110,7 @@ Fl_RGB_Image* Fl_Image_Surface::image()
fl_window = pre_window;
previous->set_current();
#endif
- Fl_RGB_Image *image = new Fl_RGB_Image(data, width, height);
+ Fl_RGB_Image *image = new Fl_RGB_Image(data, width, height, depth, ld);
image->alloc_array = 1;
return image;
}
@@ -168,7 +172,18 @@ void Fl_Quartz_Flipped_Surface_::untranslate() {
const char *Fl_Quartz_Flipped_Surface_::class_id = "Fl_Quartz_Flipped_Surface_";
-#endif // __APPLE__
+#endif
+
+/** Draws a window and its borders and title bar to the image drawing surface.
+ \param win an FLTK window to draw in the image
+ \param delta_x and \param delta_y give
+ the position in the image of the top-left corner of the window's title bar
+*/
+void Fl_Image_Surface::draw_decorated_window(Fl_Window* win, int delta_x, int delta_y)
+{
+ helper->draw_decorated_window(win, delta_x, delta_y);
+}
+
//
// End of "$Id$".
diff --git a/src/Fl_Paged_Device.cxx b/src/Fl_Paged_Device.cxx
index f3b5f21fe..eae08ef62 100644
--- a/src/Fl_Paged_Device.cxx
+++ b/src/Fl_Paged_Device.cxx
@@ -60,9 +60,7 @@ void Fl_Paged_Device::print_widget(Fl_Widget* widget, int delta_x, int delta_y)
fl_push_clip(0, 0, widget->w(), widget->h() );
#ifdef __APPLE__ // for Mac OS X 10.6 and above, make window with rounded bottom corners
if ( fl_mac_os_version >= 100600 && driver()->class_name() == Fl_Quartz_Graphics_Driver::class_id ) {
- CGContextRestoreGState(fl_gc);
Fl_X::clip_to_rounded_corners(fl_gc, widget->w(), widget->h());
- CGContextSaveGState(fl_gc);
}
#endif
}
@@ -296,6 +294,45 @@ const Fl_Paged_Device::page_format Fl_Paged_Device::page_formats[NO_PAGE_FORMATS
{ 297, 684, "Env10"} // envelope
};
+void Fl_Paged_Device::draw_decorated_window(Fl_Window *win, int x_offset, int y_offset)
+{
+ Fl_RGB_Image *top, *left, *bottom, *right;
+#if defined(FL_PORTING)
+# pragma message "FL_PORTING: implement Fl_X::capture_titlebar_and_borders"
+#endif
+ Fl_X::i(win)->capture_titlebar_and_borders(top, left, bottom, right);
+ int wsides = left ? left->w() : 0;
+ int toph = top ? top->h() : 0;
+ if (top) {
+#ifdef __APPLE__
+ top->draw(x_offset, y_offset); // draw with transparency
+#else
+ fl_draw_image(top->array, x_offset, y_offset, top->w(), top->h(), top->d());
+#endif // __APPLE__
+ delete top;
+ }
+ if (left) {
+ fl_draw_image(left->array, x_offset, y_offset + toph, left->w(), left->h(), left->d());
+ delete left;
+ }
+ if (right) {
+ fl_draw_image(right->array, x_offset + win->w() + wsides, y_offset + toph, right->w(), right->h(), right->d());
+ delete right;
+ }
+ if (bottom) {
+ fl_draw_image(bottom->array, x_offset, y_offset + toph + win->h(), bottom->w(), bottom->h(), bottom->d());
+ delete bottom;
+ }
+ this->print_widget(win, x_offset + wsides, y_offset + toph);
+}
+
+#if !defined(__APPLE__) // Mac OS version in Fl_Cocoa.mm
+void Fl_Paged_Device::print_window(Fl_Window *win, int x_offset, int y_offset)
+{
+ draw_decorated_window(win, x_offset, y_offset);
+}
+#endif
+
//
// End of "$Id$".
//
diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm
index f605df0f4..45dd10fc0 100644
--- a/src/Fl_cocoa.mm
+++ b/src/Fl_cocoa.mm
@@ -3851,45 +3851,6 @@ int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) {
}
@end
-
-void Fl_Copy_Surface::draw_decorated_window(Fl_Window* win, int delta_x, int delta_y)
-{
- int bx, by, bt;
- get_window_frame_sizes(bx, by, bt);
- draw(win, 0, bt); // draw the window content
- if (win->border()) {
- // draw the window title bar
- CGContextSaveGState(gc);
- CGContextTranslateCTM(gc, 0, bt);
- CGContextScaleCTM(gc, 1, -1);
- Fl_X::clip_to_rounded_corners(gc, win->w(), bt);
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
- CALayer *layer = fl_mac_os_version >= 101000 ?
- [[[fl_xid(win) standardWindowButton:NSWindowCloseButton] superview] layer] : nil; // 10.5
- if (layer) {
- CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB();
- // for unknown reason, rendering the layer to the Fl_Copy_Surface pdf graphics context does not work;
- // we use an auxiliary bitmap context
- CGContextRef auxgc = CGBitmapContextCreate(NULL, win->w(), bt, 8, 0, cspace, kCGImageAlphaPremultipliedLast);
- CGColorSpaceRelease(cspace);
- CGContextClearRect(auxgc, CGRectMake(0, 0, win->w(), bt));
- CGContextTranslateCTM(auxgc, 0, bt);
- CGContextScaleCTM(auxgc, 1, -1);
- [layer renderInContext:auxgc]; // 10.5
- fl_draw_image((uchar*)CGBitmapContextGetData(auxgc), 0, 0, win->w(), bt, 4, CGBitmapContextGetBytesPerRow(auxgc));
- CGContextRelease(auxgc);
- } else
-#endif
- {
- CGImageRef img = Fl_X::CGImage_from_window_rect(win, 0, -bt, win->w(), bt);
- CGContextDrawImage(gc, CGRectMake(0, 0, win->w(), bt), img);
- CFRelease(img);
- }
- CGContextRestoreGState(gc);
- }
-}
-
-
static void createAppleMenu(void)
{
static BOOL donethat = NO;
@@ -4423,46 +4384,98 @@ void Fl_X::clip_to_rounded_corners(CGContextRef gc, int w, int h) {
CGContextClip(gc);
}
+static CALayer *get_titlebar_layer(Fl_Window *win)
+{
+ // 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(win) standardWindowButton:NSWindowCloseButton] superview] layer] : nil; // 10.5
+#else
+ return nil;
+#endif
+}
+
+
+static void 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);
+ Fl_X::clip_to_rounded_corners(gc, w, h);
+ CGContextSetRGBFillColor(gc, .79, .79, .79, 1.); // equiv. to FL_DARK1
+ CGContextFillRect(gc, CGRectMake(0, 0, w, h));
+ [layer renderInContext:gc]; // 10.5
+ CGContextRestoreGState(gc);
+#endif
+}
+
+
+/* Returns images of the capture of the window title-bar.
+ On the Mac OS platform, left, bottom and right are returned NULL; top is returned with depth 4.
+ */
+void Fl_X::capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right)
+{
+ left = bottom = right = NULL;
+ int htop = w->decorated_h() - w->h();
+ CALayer *layer = get_titlebar_layer(w);
+ CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB();
+ uchar *rgba = new uchar[4 * w->w() * htop];
+ CGContextRef auxgc = CGBitmapContextCreate(rgba, w->w(), htop, 8, 4 * w->w(), cspace, kCGImageAlphaPremultipliedLast);
+ CGColorSpaceRelease(cspace);
+ CGRect rect = CGRectMake(0, 0, w->w(), htop);
+ if (layer) {
+ draw_layer_to_context(layer, auxgc, w->w(), htop);
+ } else {
+ CGImageRef img = Fl_X::CGImage_from_window_rect(w, 0, -htop, w->w(), htop);
+ CGContextSaveGState(auxgc);
+ Fl_X::clip_to_rounded_corners(auxgc, w->w(), htop);
+ CGContextDrawImage(auxgc, rect, img);
+ CGContextRestoreGState(auxgc);
+ CFRelease(img);
+ }
+ top = new Fl_RGB_Image(rgba, w->w(), htop, 4);
+ top->alloc_array = 1;
+ CGContextRelease(auxgc);
+}
+
+
void Fl_Paged_Device::print_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 bx, by, bt, bpp;
+ int bx, by, bt;
get_window_frame_sizes(bx, by, bt);
BOOL to_quartz = (this->driver()->class_name() == Fl_Quartz_Graphics_Driver::class_id);
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
-// a compilation warning appears with SDK 10.5, so we require SDK 10.6 instead
- if (fl_mac_os_version >= 101000) {
- CALayer *layer = [[[fl_xid(win) standardWindowButton:NSWindowCloseButton] superview] layer]; // 10.5
- if (layer) { // if program is linked with 10.10, title bar uses a layer
- if (to_quartz) { // to Quartz printer
- CGContextSaveGState(fl_gc);
- CGContextTranslateCTM(fl_gc, x_offset - 0.5, y_offset + bt - 0.5);
- CGContextScaleCTM(fl_gc, 1, -1);
- Fl_X::clip_to_rounded_corners(fl_gc, win->w(), bt);
- [layer renderInContext:fl_gc]; // 10.5 // print all title bar
- CGContextRestoreGState(fl_gc);
- }
- else { // to PostScript
- CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB ();
- CGContextRef gc = CGBitmapContextCreate(NULL, win->w(), bt, 8, 0, cspace, kCGImageAlphaPremultipliedLast);
- CGColorSpaceRelease(cspace);
- CGContextClearRect(gc, CGRectMake(0, 0, win->w(), bt));
- Fl_X::clip_to_rounded_corners(gc, win->w(), bt);
- [layer renderInContext:gc]; // 10.5 // draw all title bar to bitmap
- Fl_RGB_Image *image = new Fl_RGB_Image((const uchar*)CGBitmapContextGetData(gc), win->w(), bt, 4,
- CGBitmapContextGetBytesPerRow(gc)); // 10.2
- image->draw(x_offset, y_offset); // draw title bar to PostScript
- delete image;
- CGContextRelease(gc);
- }
- this->print_widget(win, x_offset, y_offset + bt);
- return;
+ CALayer *layer = get_titlebar_layer(win);
+ if (layer) { // if title bar uses a layer
+ if (to_quartz) { // to Quartz printer
+ CGContextSaveGState(fl_gc);
+ CGContextTranslateCTM(fl_gc, 0, bt);
+ CGContextScaleCTM(fl_gc, 1, -1);
+ draw_layer_to_context(layer, fl_gc, win->w(), bt);
+ CGContextRestoreGState(fl_gc);
+ }
+ else {
+ CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB ();
+ CGContextRef gc = CGBitmapContextCreate(NULL, 2*win->w(), 2*bt, 8, 0, cspace, kCGImageAlphaPremultipliedLast);
+ CGColorSpaceRelease(cspace);
+ CGContextScaleCTM(gc, 2, 2);
+ draw_layer_to_context(layer, gc, win->w(), bt);
+ Fl_RGB_Image *image = new Fl_RGB_Image((const uchar*)CGBitmapContextGetData(gc), 2*win->w(), 2*bt, 4,
+ CGBitmapContextGetBytesPerRow(gc)); // 10.2
+ int ori_x, ori_y;
+ origin(&ori_x, &ori_y);
+ scale(0.5);
+ origin(2*ori_x, 2*ori_y);
+ image->draw(2*x_offset, 2*y_offset); // draw title bar as double resolution image
+ scale(1);
+ origin(ori_x, ori_y);
+ delete image;
+ CGContextRelease(gc);
}
+ this->print_widget(win, x_offset, y_offset + bt);
+ return;
}
-#endif
Fl_Display_Device::display_device()->set_current(); // send win to front and make it current
const char *title = win->label();
win->label(""); // temporarily set a void window title
@@ -4470,27 +4483,12 @@ void Fl_Paged_Device::print_window(Fl_Window *win, int x_offset, int y_offset)
fl_gc = NULL;
Fl::check();
// capture the window title bar with no title
- CGImageRef img = NULL;
- unsigned char *bitmap = NULL;
- if (to_quartz)
- img = Fl_X::CGImage_from_window_rect(win, 0, -bt, win->w(), bt);
- else
- bitmap = Fl_X::bitmap_from_window_rect(win, 0, -bt, win->w(), bt, &bpp);
+ Fl_RGB_Image *top, *left, *bottom, *right;
+ Fl_X::i(win)->capture_titlebar_and_borders(top, left, bottom, right);
win->label(title); // put back the window title
this->set_current(); // back to the Fl_Paged_Device
- if (img && to_quartz) { // print the title bar
- CGRect rect = CGRectMake(x_offset, y_offset, win->w(), bt);
- Fl_X::q_begin_image(rect, 0, 0, win->w(), bt);
- CGContextDrawImage(fl_gc, rect, img);
- Fl_X::q_end_image();
- CFRelease(img);
- }
- else if(!to_quartz) {
- Fl_RGB_Image *rgb = new Fl_RGB_Image(bitmap, win->w(), bt, bpp);
- rgb->draw(x_offset, y_offset);
- delete rgb;
- delete[] bitmap;
- }
+ top->draw(x_offset, y_offset); // print the title bar
+ delete top;
if (title) { // print the window title
const int skip = 65; // approx width of the zone of the 3 window control buttons
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
@@ -4498,8 +4496,8 @@ void Fl_Paged_Device::print_window(Fl_Window *win, int x_offset, int y_offset)
// the exact font is LucidaGrande 13 pts (and HelveticaNeueDeskInterface-Regular with 10.10)
NSGraphicsContext *current = [NSGraphicsContext currentContext];
[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:fl_gc flipped:YES]];//10.4
- NSDictionary *attr = [NSDictionary dictionaryWithObject:[NSFont titleBarFontOfSize:0]
- forKey:NSFontAttributeName];
+ NSDictionary *attr = [NSDictionary dictionaryWithObject:[NSFont titleBarFontOfSize:0]
+ forKey:NSFontAttributeName];
NSString *title_s = [fl_xid(win) title];
NSSize size = [title_s sizeWithAttributes:attr];
int x = x_offset + win->w()/2 - size.width/2;
@@ -4525,7 +4523,6 @@ void Fl_Paged_Device::print_window(Fl_Window *win, int x_offset, int y_offset)
this->print_widget(win, x_offset, y_offset + bt); // print the window inner part
}
-
/* Returns the address of a Carbon function after dynamically loading the Carbon library if needed.
Supports old Mac OS X versions that may use a couple of Carbon calls:
GetKeys used by OS X 10.3 or before (in Fl::get_key())
diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx
index 2ae1e6145..ea4a43fac 100644
--- a/src/Fl_win32.cxx
+++ b/src/Fl_win32.cxx
@@ -1546,7 +1546,7 @@ static int fake_X_wm_style(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, in
W = r.right - r.left;
H = r.bottom - r.top;
bx = w->x() - r.left;
- by = r.bottom - w->y() - w->h(); // height of the bootm frame
+ by = r.bottom - w->y() - w->h(); // height of the bottom frame
bt = w->y() - r.top - by; // height of top caption bar
xoff = bx;
yoff = by + bt;
@@ -2697,81 +2697,90 @@ FL_EXPORT Window fl_xid_(const Fl_Window *w) {
return temp ? temp->xid : 0;
}
+static RECT border_width_title_bar_height(Fl_Window *win, int &bx, int &by, int &bt)
+{
+ RECT r = {0,0,0,0};
+ bx = by = bt = 0;
+ if (win->shown() && !win->parent() && win->border() && win->visible()) {
+ static HMODULE dwmapi_dll = LoadLibrary("dwmapi.dll");
+ typedef HRESULT (WINAPI* DwmGetWindowAttribute_type)(HWND hwnd, DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute);
+ static DwmGetWindowAttribute_type DwmGetWindowAttribute = dwmapi_dll ?
+ (DwmGetWindowAttribute_type)GetProcAddress(dwmapi_dll, "DwmGetWindowAttribute") : NULL;
+ int need_r = 1;
+ if (DwmGetWindowAttribute) {
+ const DWORD DWMWA_EXTENDED_FRAME_BOUNDS = 9;
+ if ( DwmGetWindowAttribute(fl_xid(win), DWMWA_EXTENDED_FRAME_BOUNDS, &r, sizeof(RECT)) == S_OK ) {
+ need_r = 0;
+ }
+ }
+ if (need_r) {
+ GetWindowRect(fl_xid(win), &r);
+ }
+ bx = (r.right - r.left - win->w())/2;
+ by = bx;
+ bt = r.bottom - r.top - win->h() - 2*by;
+ }
+ return r;
+}
+
int Fl_Window::decorated_w()
{
- if (!shown() || parent() || !border() || !visible()) return w();
- int X, Y, bt, bx, by;
- Fl_X::fake_X_wm(this, X, Y, bt, bx, by);
+ int bt, bx, by;
+ border_width_title_bar_height(this, bx, by, bt);
return w() + 2 * bx;
}
int Fl_Window::decorated_h()
{
- if (!shown() || parent() || !border() || !visible()) return h();
- int X, Y, bt, bx, by;
- Fl_X::fake_X_wm(this, X, Y, bt, bx, by);
+ int bt, bx, by;
+ border_width_title_bar_height(this, bx, by, bt);
return h() + bt + 2 * by;
}
-void Fl_Paged_Device::print_window(Fl_Window *win, int x_offset, int y_offset)
-{
- if (!win->shown() || win->parent() || !win->border() || !win->visible())
- print_widget(win, x_offset, y_offset);
- else
- draw_decorated_window(win, x_offset, y_offset, this);
-}
-
-void Fl_Paged_Device::draw_decorated_window(Fl_Window *win, int x_offset, int y_offset, Fl_Surface_Device *toset)
+/* Returns images of the captures of the window title-bar, and the left, bottom and right window borders.
+ On the WIN32 platform, this function exploits a feature of fl_read_image() which, when called
+ with NULL first argument and when fl_gc is set to the screen device context, captures the window decoration.
+ */
+void Fl_X::capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right)
{
- static HMODULE dwmapi_dll = LoadLibrary("dwmapi.dll");
- typedef HRESULT (WINAPI* DwmGetWindowAttribute_type)(HWND hwnd, DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute);
- static DwmGetWindowAttribute_type DwmGetWindowAttribute = 0;
- static const DWORD DWMWA_EXTENDED_FRAME_BOUNDS = 9;
- int bt, bx, by; // compute the window border sizes
- RECT r;
- int need_r = 1;
- if (dwmapi_dll) {
- if (!DwmGetWindowAttribute) DwmGetWindowAttribute = (DwmGetWindowAttribute_type)GetProcAddress(dwmapi_dll, "DwmGetWindowAttribute");
- if (DwmGetWindowAttribute) {
- if ( DwmGetWindowAttribute(fl_xid(win), DWMWA_EXTENDED_FRAME_BOUNDS, &r, sizeof(RECT)) == S_OK ) {
- need_r = 0;
- }
- }
- }
- if (need_r) {
- GetWindowRect(fl_xid(win), &r);
- }
- bx = (r.right - r.left - win->w())/2;
- by = bx;
- bt = r.bottom - r.top - win->h() - 2*by;
- int ww = win->w() + 2 * bx;
- int wh = win->h() + bt + 2 * by;
- Fl_Display_Device::display_device()->set_current(); // make window current
- win->show();
- Fl::check();
- win->make_current();
+ top = left = bottom = right = NULL;
+ if (!w->shown() || w->parent() || !w->border() || !w->visible()) return;
+ int wsides, hbottom, bt;
+ RECT r = border_width_title_bar_height(w, wsides, hbottom, bt);
+ int htop = bt + hbottom;
HDC save_gc = fl_gc;
+ Window save_win = fl_window;
+ Fl_Surface_Device *previous = Fl_Surface_Device::surface();
+ Fl_Display_Device::display_device()->set_current();
+ w->show();
+ Fl::check();
+ w->make_current();
fl_gc = GetDC(NULL); // get the screen device context
+ int ww = w->w() + 2 * wsides;
// capture the 4 window sides from screen
- Window save_win = fl_window;
fl_window = NULL; // force use of read_win_rectangle() by fl_read_image()
- uchar *top_image = fl_read_image(NULL, r.left, r.top, ww, bt + by);
- uchar *left_image = bx ? fl_read_image(NULL, r.left, r.top, bx, wh) : NULL;
- uchar *right_image = bx ? fl_read_image(NULL, r.right - bx, r.top, bx, wh) : NULL;
- uchar *bottom_image = by ? fl_read_image(NULL, r.left, r.bottom-by, ww, by) : NULL;
+ uchar *rgb;
+ if (htop) {
+ rgb = fl_read_image(NULL, r.left, r.top, ww, htop);
+ top = new Fl_RGB_Image(rgb, ww, htop, 3);
+ top->alloc_array = 1;
+ }
+ if (wsides) {
+ rgb = fl_read_image(NULL, r.left, r.top + htop, wsides, w->h());
+ left = new Fl_RGB_Image(rgb, wsides, w->h(), 3);
+ left->alloc_array = 1;
+ rgb = fl_read_image(NULL, r.right - wsides, r.top + htop, wsides, w->h());
+ right = new Fl_RGB_Image(rgb, wsides, w->h(), 3);
+ right->alloc_array = 1;
+ rgb = fl_read_image(NULL, r.left, r.bottom-hbottom, ww, hbottom);
+ bottom = new Fl_RGB_Image(rgb, ww, hbottom, 3);
+ bottom->alloc_array = 1;
+ }
+ ReleaseDC(NULL, fl_gc);
fl_window = save_win;
- ReleaseDC(NULL, fl_gc); fl_gc = save_gc;
- toset->set_current();
- // print the 4 window sides
- fl_draw_image(top_image, x_offset, y_offset, ww, bt + by, 3); delete[] top_image;
- if (left_image) { fl_draw_image(left_image, x_offset, y_offset, bx, wh, 3); delete left_image; }
- if (right_image) { fl_draw_image(right_image, x_offset + win->w() + bx, y_offset, bx, wh, 3); delete right_image; }
- if (bottom_image) { fl_draw_image(bottom_image, x_offset, y_offset + win->h() + bt + by, ww, by, 3); delete bottom_image; }
- // print the window inner part
- this->print_widget(win, x_offset + bx, y_offset + bt + by);
- fl_gc = GetDC(fl_xid(win));
- ReleaseDC(fl_xid(win), fl_gc);
-}
+ fl_gc = save_gc;
+ previous->Fl_Surface_Device::set_current();
+}
#ifdef USE_PRINT_BUTTON
// to test the Fl_Printer class creating a "Print front window" button in a separate window
diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx
index f860f9b71..c8a7620eb 100644
--- a/src/Fl_x.cxx
+++ b/src/Fl_x.cxx
@@ -3021,59 +3021,52 @@ int Fl_Window::decorated_w()
return w;
}
-void Fl_Paged_Device::print_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;
- }
- draw_decorated_window(win, x_offset, y_offset, this);
-}
-
-void Fl_Paged_Device::draw_decorated_window(Fl_Window *win, int x_offset, int y_offset, Fl_Surface_Device *toset)
+/* Returns images of the captures of the window title-bar, and the left, bottom and right window borders
+ (or NULL if a particular border is absent).
+ Returned images can be deleted after use. Their depth and size may be platform-dependent.
+ The top and bottom images extend from left of the left border to right of the right border.
+
+ On the X11 platform, this function exploits a feature of fl_read_image() which, when called
+ with negative 4th argument, captures the window decoration.
+ */
+void Fl_X::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 (w->decorated_h() == w->h()) return;
+ Window from = fl_window;
+ Fl_Surface_Device *previous = Fl_Surface_Device::surface();
Fl_Display_Device::display_device()->set_current();
- win->show();
+ w->show();
Fl::check();
- win->make_current();
- Window root, parent, *children, child_win, from;
+ w->make_current();
+ Window root, parent, *children, child_win;
unsigned n = 0;
- int bx, bt, do_it;
- from = fl_window;
- do_it = (XQueryTree(fl_display, fl_window, &root, &parent, &children, &n) != 0 &&
- XTranslateCoordinates(fl_display, fl_window, parent, 0, 0, &bx, &bt, &child_win) == True);
+ int do_it;
+ int wsides, htop;
+ do_it = (XQueryTree(fl_display, fl_window, &root, &parent, &children, &n) != 0 &&
+ XTranslateCoordinates(fl_display, fl_window, parent, 0, 0, &wsides, &htop, &child_win) == True);
if (n) XFree(children);
- // hack to bypass STR #2648: when compiz is used, root and parent are the same window
- // and I don't know where to find the window decoration
- if (do_it && root == parent) do_it = 0;
- if (!do_it) {
- this->set_current();
- this->print_widget(win, x_offset, y_offset);
- return;
- }
+ int hbottom = wsides;
fl_window = parent;
- uchar *top_image = 0, *left_image = 0, *right_image = 0, *bottom_image = 0;
- 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);
+ uchar *rgb;
+ if (htop) {
+ rgb = fl_read_image(NULL, 0, 0, - (w->w() + 2 * wsides), htop);
+ top = new Fl_RGB_Image(rgb, w->w() + 2 * wsides, htop, 3);
+ top->alloc_array = 1;
+ }
+ if (wsides) {
+ rgb = fl_read_image(NULL, 0, htop, -wsides, w->h());
+ left = new Fl_RGB_Image(rgb, wsides, w->h(), 3);
+ left->alloc_array = 1;
+ rgb = fl_read_image(NULL, w->w() + wsides, htop, -wsides, w->h());
+ right = new Fl_RGB_Image(rgb, wsides, w->h(), 3);
+ right->alloc_array = 1;
+ rgb = fl_read_image(NULL, 0, htop + w->h(), -(w->w() + 2*wsides), hbottom);
+ bottom = new Fl_RGB_Image(rgb, w->w() + 2*wsides, hbottom, 3);
+ bottom->alloc_array = 1;
}
fl_window = from;
- toset->set_current();
- if (top_image) {
- 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 );
+ previous->Fl_Surface_Device::set_current();
}
#ifdef USE_PRINT_BUTTON