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
This commit is contained in:
parent
acc5080653
commit
eeb65bef23
@ -70,6 +70,7 @@ public:
|
||||
void set_current();
|
||||
void draw(Fl_Widget*, int delta_x = 0, int delta_y = 0);
|
||||
Fl_RGB_Image *image();
|
||||
void draw_decorated_window(Fl_Window* win, int delta_x = 0, int delta_y = 0);
|
||||
};
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
@ -36,17 +36,9 @@
|
||||
or Fl_PostScript_File_Device instead.
|
||||
*/
|
||||
class FL_EXPORT Fl_Paged_Device : public Fl_Surface_Device {
|
||||
#ifdef __APPLE__
|
||||
// not needed
|
||||
#elif defined(WIN32)
|
||||
friend class Fl_Copy_Surface;
|
||||
void draw_decorated_window(Fl_Window *win, int x_offset, int y_offset, Fl_Surface_Device *toset);
|
||||
#elif defined(FL_PORTING)
|
||||
# pragma message "FL_PORTING: define member variables to support Fl_Copy_Surface in Fl_Paged_Device"
|
||||
#else // X11
|
||||
friend class Fl_Copy_Surface;
|
||||
void draw_decorated_window(Fl_Window *win, int x_offset, int y_offset, Fl_Surface_Device *toset);
|
||||
#endif
|
||||
friend class Fl_Image_Surface;
|
||||
void draw_decorated_window(Fl_Window *win, int x_offset, int y_offset);
|
||||
public:
|
||||
/**
|
||||
\brief Possible page formats.
|
||||
|
1
FL/mac.H
1
FL/mac.H
@ -199,6 +199,7 @@ public:
|
||||
void set_icons() {};
|
||||
int set_cursor(Fl_Cursor);
|
||||
int set_cursor(const Fl_RGB_Image*, int, int);
|
||||
void capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right);
|
||||
static CGImageRef CGImage_from_window_rect(Fl_Window *win, int x, int y, int w, int h);
|
||||
static unsigned char *bitmap_from_window_rect(Fl_Window *win, int x, int y, int w, int h, int *bytesPerPixel);
|
||||
static Fl_Region intersect_region_and_rect(Fl_Region current, int x,int y,int w, int h);
|
||||
|
@ -90,6 +90,7 @@ public:
|
||||
void set_icons();
|
||||
int set_cursor(Fl_Cursor);
|
||||
int set_cursor(const Fl_RGB_Image*, int, int);
|
||||
void capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right);
|
||||
static Fl_X* make(Fl_Window*);
|
||||
};
|
||||
extern FL_EXPORT UINT fl_wake_msg;
|
||||
|
1
FL/x.H
1
FL/x.H
@ -147,6 +147,7 @@ public:
|
||||
void set_icons();
|
||||
int set_cursor(Fl_Cursor);
|
||||
int set_cursor(const Fl_RGB_Image*, int, int);
|
||||
void capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right);
|
||||
static void make_xid(Fl_Window*,XVisualInfo* =fl_visual, Colormap=fl_colormap);
|
||||
static Fl_X* set_xid(Fl_Window*, Window);
|
||||
// kludges to get around protection:
|
||||
|
@ -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__)
|
||||
|
@ -34,8 +34,17 @@ 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__)
|
||||
#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
|
||||
@ -44,21 +53,8 @@ Fl_Image_Surface::Fl_Image_Surface(int w, int h) : Fl_Surface_Device(NULL) {
|
||||
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__
|
||||
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)
|
||||
helper = new Fl_GDI_Surface_();
|
||||
driver(helper->driver());
|
||||
#elif defined(FL_PORTING)
|
||||
# pragma message "FL_PORTING: implement Fl_Image_Surface"
|
||||
#else
|
||||
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$".
|
||||
|
@ -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$".
|
||||
//
|
||||
|
179
src/Fl_cocoa.mm
179
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())
|
||||
|
131
src/Fl_win32.cxx
131
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)
|
||||
/* 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
fl_gc = GetDC(NULL); // get the screen device context
|
||||
// capture the 4 window sides from screen
|
||||
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
|
||||
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
|
||||
|
83
src/Fl_x.cxx
83
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
|
||||
|
@ -551,15 +551,30 @@ const char *operation;
|
||||
|
||||
void copy(Fl_Widget *, void *data) {
|
||||
if (strcmp(operation, "Fl_Image_Surface") == 0) {
|
||||
Fl_Image_Surface *rgb_surf = new Fl_Image_Surface(target->w()+20, target->h()+10);
|
||||
Fl_Image_Surface *rgb_surf;
|
||||
int W, H, decorated;
|
||||
if (target->as_window() && !target->parent()) {
|
||||
W = target->as_window()->decorated_w();
|
||||
H = target->as_window()->decorated_h();
|
||||
decorated = 1;
|
||||
}
|
||||
else {
|
||||
W = target->w();
|
||||
H = target->h();
|
||||
decorated = 0;
|
||||
}
|
||||
rgb_surf = new Fl_Image_Surface(W, H);
|
||||
rgb_surf->set_current();
|
||||
fl_color(FL_BLUE);fl_rectf(0,0,1000,1000);
|
||||
rgb_surf->draw(target,10,5);
|
||||
if (decorated)
|
||||
rgb_surf->draw_decorated_window(target->as_window());
|
||||
else
|
||||
rgb_surf->draw(target);
|
||||
Fl_Image *img = rgb_surf->image();
|
||||
delete rgb_surf;
|
||||
Fl_Display_Device::display_device()->set_current();
|
||||
Fl_Window* g2 = new Fl_Window(img->w(), img->h());
|
||||
Fl_Box *b = new Fl_Box(FL_NO_BOX,0,0,img->w(), img->h(),0);
|
||||
Fl_Window* g2 = new Fl_Window(img->w()+10, img->h()+10);
|
||||
g2->color(FL_YELLOW);
|
||||
Fl_Box *b = new Fl_Box(FL_NO_BOX,5,5,img->w(), img->h(),0);
|
||||
b->image(img);
|
||||
g2->end();
|
||||
g2->show();
|
||||
@ -709,7 +724,7 @@ int main(int argc, char ** argv) {
|
||||
g1->end();
|
||||
|
||||
Fl_Group *g2 = new Fl_Group(w3->x(),w3->y(),w3->w(),w3->h());
|
||||
rb = new Fl_Radio_Round_Button(170,5,150,12, "Window");
|
||||
rb = new Fl_Radio_Round_Button(170,5,150,12, "Decorated Window");
|
||||
rb->set(); rb->callback(target_cb, w2); target = w2;
|
||||
rb = new Fl_Radio_Round_Button(170,22,150,12, "Sub-window"); rb->callback(target_cb, w3);
|
||||
rb = new Fl_Radio_Round_Button(170,39,150,12, "Group"); rb->callback(target_cb, group);
|
||||
|
Loading…
x
Reference in New Issue
Block a user