Rewrite capture of window decorations using the window driver approach.

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11345 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Manolo Gouy 2016-03-11 07:07:42 +00:00
parent 914248bbf0
commit 2952c530b8
12 changed files with 92 additions and 92 deletions

View File

@ -580,8 +580,6 @@ public:
*/
int decorated_h();
// Captures the titlebar and borders of the window, if they exist.
void capture_titlebar_and_borders(Fl_Shared_Image*& top, Fl_Shared_Image*& left, Fl_Shared_Image*& bottom, Fl_Shared_Image*& right);
Fl_Window_Driver *driver() { return pWindowDriver; }
/**

View File

@ -30,7 +30,7 @@
class Fl_Window;
class Fl_X;
class Fl_Image;
class Fl_Shared_Image;
/**
\brief A base class for platform specific window handling code.
@ -63,6 +63,7 @@ public:
virtual const void *icon() const {return NULL;}
virtual void icon(const void * ic) {}
virtual void free_icons() {}
virtual void capture_titlebar_and_borders(Fl_Shared_Image*& top, Fl_Shared_Image*& left, Fl_Shared_Image*& bottom, Fl_Shared_Image*& right);
};

View File

@ -20,6 +20,7 @@
#include <FL/fl_draw.H>
#include <FL/Fl.H>
#include <FL/Fl_Shared_Image.H>
#include <FL/Fl_Window_Driver.H>
/** The constructor.
@ -193,7 +194,7 @@ int Fl_Widget_Surface::printable_rect(int *w, int *h) {return 1;}
void Fl_Widget_Surface::draw_decorated_window(Fl_Window *win, int x_offset, int y_offset)
{
Fl_Shared_Image *top, *left, *bottom, *right;
win->capture_titlebar_and_borders(top, left, bottom, right);
win->driver()->capture_titlebar_and_borders(top, left, bottom, right);
int wsides = left ? left->w() : 0;
int toph = top ? top->h() : 0;
if (top) {

View File

@ -433,15 +433,6 @@ void Fl_Window::wait_for_expose() {
}
}
#if defined(FL_PORTING)
# pragma message "FL_PORTING: implement Fl_Window::capture_titlebar_and_borders"
void Fl_Window::capture_titlebar_and_borders(Fl_Shared_Image*& top, Fl_Shared_Image*& left, Fl_Shared_Image*& bottom, Fl_Shared_Image*& right)
{
top = left = bottom = right = NULL;
}
#endif
#endif // ! __APPLE__ // PORTME: Fl_Window_Driver - platform window driver
//

View File

@ -156,8 +156,9 @@ void Fl_Window_Driver::shape_pixmap_(Fl_Image* pixmap) {
delete rgba;
}
void Fl_Window_Driver::capture_titlebar_and_borders(Fl_Shared_Image*& top, Fl_Shared_Image*& left, Fl_Shared_Image*& bottom, Fl_Shared_Image*& right) {
top = left = bottom = right = NULL;
}
//
// End of "$Id$".

View File

@ -41,8 +41,9 @@ extern "C" {
#include <FL/Fl_Tooltip.H>
#include <FL/Fl_Printer.H>
#include <FL/Fl_Shared_Image.H>
#include "drivers/Quartz/Fl_Quartz_Graphics_Driver.h"
#include "drivers/Cocoa/Fl_Cocoa_Screen_Driver.h"
#include "drivers/Quartz/Fl_Quartz_Graphics_Driver.H"
#include "drivers/Cocoa/Fl_Cocoa_Screen_Driver.H"
#include "drivers/Cocoa/Fl_Cocoa_Window_Driver.H"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@ -4338,30 +4339,30 @@ static void draw_layer_to_context(CALayer *layer, CGContextRef gc, int w, int h)
/* 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_Window::capture_titlebar_and_borders(Fl_Shared_Image*& top, Fl_Shared_Image*& left, Fl_Shared_Image*& bottom, Fl_Shared_Image*& right)
void Fl_Cocoa_Window_Driver::capture_titlebar_and_borders(Fl_Shared_Image*& top, Fl_Shared_Image*& left, Fl_Shared_Image*& bottom, Fl_Shared_Image*& right)
{
left = bottom = right = NULL;
int htop = decorated_h() - h();
CALayer *layer = get_titlebar_layer(this);
int htop = pWindow->decorated_h() - pWindow->h();
CALayer *layer = get_titlebar_layer(pWindow);
CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB();
uchar *rgba = new uchar[4 * w() * htop * 4];
CGContextRef auxgc = CGBitmapContextCreate(rgba, 2 * w(), 2 * htop, 8, 8 * w(), cspace, kCGImageAlphaPremultipliedLast);
uchar *rgba = new uchar[4 * pWindow->w() * htop * 4];
CGContextRef auxgc = CGBitmapContextCreate(rgba, 2 * pWindow->w(), 2 * htop, 8, 8 * pWindow->w(), cspace, kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(cspace);
CGContextScaleCTM(auxgc, 2, 2);
if (layer) {
draw_layer_to_context(layer, auxgc, w(), htop);
draw_layer_to_context(layer, auxgc, pWindow->w(), htop);
} else {
CGImageRef img = Fl_X::CGImage_from_window_rect(this, 0, -htop, w(), htop);
CGImageRef img = Fl_X::CGImage_from_window_rect(pWindow, 0, -htop, pWindow->w(), htop);
CGContextSaveGState(auxgc);
Fl_X::clip_to_rounded_corners(auxgc, w(), htop);
CGContextDrawImage(auxgc, CGRectMake(0, 0, w(), htop), img);
Fl_X::clip_to_rounded_corners(auxgc, pWindow->w(), htop);
CGContextDrawImage(auxgc, CGRectMake(0, 0, pWindow->w(), htop), img);
CGContextRestoreGState(auxgc);
CFRelease(img);
}
Fl_RGB_Image *top_rgb = new Fl_RGB_Image(rgba, 2 * w(), 2 * htop, 4);
Fl_RGB_Image *top_rgb = new Fl_RGB_Image(rgba, 2 * pWindow->w(), 2 * htop, 4);
top_rgb->alloc_array = 1;
top = Fl_Shared_Image::get(top_rgb);
top->scale(w(),htop);
top->scale(pWindow->w(),htop);
CGContextRelease(auxgc);
}
@ -4413,7 +4414,7 @@ void Fl_System_Printer::draw_decorated_window(Fl_Window *win, int x_offset, int
Fl::check();
// capture the window title bar with no title
Fl_Shared_Image *top, *left, *bottom, *right;
win->capture_titlebar_and_borders(top, left, bottom, right);
win->driver()->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
top->draw(x_offset, y_offset); // print the title bar

View File

@ -2556,22 +2556,22 @@ int Fl_Window::decorated_h()
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_Window::capture_titlebar_and_borders(Fl_Shared_Image*& top, Fl_Shared_Image*& left, Fl_Shared_Image*& bottom, Fl_Shared_Image*& right)
void Fl_WinAPI_Window_Driver::capture_titlebar_and_borders(Fl_Shared_Image*& top, Fl_Shared_Image*& left, Fl_Shared_Image*& bottom, Fl_Shared_Image*& right)
{
Fl_RGB_Image *r_top, *r_left, *r_bottom, *r_right;
top = left = bottom = right = NULL;
if (!shown() || parent() || !border() || !visible()) return;
if (!pWindow->shown() || pWindow->parent() || !pWindow->border() || !pWindow->visible()) return;
int wsides, hbottom, bt;
RECT r = border_width_title_bar_height(this, wsides, hbottom, bt);
RECT r = border_width_title_bar_height(pWindow, wsides, hbottom, bt);
int htop = bt + hbottom;
Fl_Surface_Device *previous = Fl_Surface_Device::surface();
Window save_win = fl_window;
Fl_Display_Device::display_device()->set_current();
show();
pWindow->show();
Fl::check();
void* save_gc = fl_graphics_driver->gc();
fl_graphics_driver->gc(GetDC(NULL));
int ww = w() + 2 * wsides;
int ww = pWindow->w() + 2 * wsides;
// capture the 4 window sides from screen
fl_window = NULL; // force use of read_win_rectangle() by fl_read_image()
uchar *rgb;
@ -2582,12 +2582,12 @@ void Fl_Window::capture_titlebar_and_borders(Fl_Shared_Image*& top, Fl_Shared_Im
top = Fl_Shared_Image::get(r_top);
}
if (wsides) {
rgb = fl_read_image(NULL, r.left, r.top + htop, wsides, h());
r_left = new Fl_RGB_Image(rgb, wsides, h(), 3);
rgb = fl_read_image(NULL, r.left, r.top + htop, wsides, pWindow->h());
r_left = new Fl_RGB_Image(rgb, wsides, pWindow->h(), 3);
r_left->alloc_array = 1;
left = Fl_Shared_Image::get(r_left);
rgb = fl_read_image(NULL, r.right - wsides, r.top + htop, wsides, h());
r_right = new Fl_RGB_Image(rgb, wsides, h(), 3);
rgb = fl_read_image(NULL, r.right - wsides, r.top + htop, wsides, pWindow->h());
r_right = new Fl_RGB_Image(rgb, wsides, pWindow->h(), 3);
r_right->alloc_array = 1;
right = Fl_Shared_Image::get(r_right);
rgb = fl_read_image(NULL, r.left, r.bottom-hbottom, ww, hbottom);

View File

@ -2983,60 +2983,6 @@ int Fl_Window::decorated_w()
return w;
}
/* 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_Window::capture_titlebar_and_borders(Fl_Shared_Image*& top, Fl_Shared_Image*& left, Fl_Shared_Image*& bottom, Fl_Shared_Image*& right)
{
Fl_RGB_Image *r_top, *r_left, *r_bottom, *r_right;
top = left = bottom = right = NULL;
if (decorated_h() == h()) return;
Window from = fl_window;
Fl_Surface_Device *previous = Fl_Surface_Device::surface();
Fl_Display_Device::display_device()->set_current();
show();
Fl::check();
make_current();
Window root, parent, *children, child_win;
unsigned n = 0;
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);
if (!do_it) wsides = htop = 0;
int hbottom = wsides;
fl_window = parent;
uchar *rgb;
if (htop) {
rgb = fl_read_image(NULL, 0, 0, - (w() + 2 * wsides), htop);
r_top = new Fl_RGB_Image(rgb, w() + 2 * wsides, htop, 3);
r_top->alloc_array = 1;
top = Fl_Shared_Image::get(r_top);
}
if (wsides) {
rgb = fl_read_image(NULL, 0, htop, -wsides, h());
r_left = new Fl_RGB_Image(rgb, wsides, h(), 3);
r_left->alloc_array = 1;
left = Fl_Shared_Image::get(r_left);
rgb = fl_read_image(NULL, w() + wsides, htop, -wsides, h());
r_right = new Fl_RGB_Image(rgb, wsides, h(), 3);
r_right->alloc_array = 1;
right = Fl_Shared_Image::get(r_right);
rgb = fl_read_image(NULL, 0, htop + h(), -(w() + 2*wsides), hbottom);
r_bottom = new Fl_RGB_Image(rgb, w() + 2*wsides, hbottom, 3);
r_bottom->alloc_array = 1;
bottom = Fl_Shared_Image::get(r_bottom);
}
fl_window = from;
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
// contains also preparePrintFront call above

View File

@ -63,6 +63,8 @@ public:
virtual void take_focus();
virtual void shape(const Fl_Image* img);
virtual void draw();
// that one is implemented in Fl_Cocoa.mm because it uses Objective-c
virtual void capture_titlebar_and_borders(Fl_Shared_Image*& top, Fl_Shared_Image*& left, Fl_Shared_Image*& bottom, Fl_Shared_Image*& right);
};

View File

@ -73,6 +73,8 @@ public:
virtual void icon(const void * ic);
virtual void free_icons();
void icons(HICON big_icon, HICON small_icon);
// this one is implemented in Fl_win32.cxx
virtual void capture_titlebar_and_borders(Fl_Shared_Image*& top, Fl_Shared_Image*& left, Fl_Shared_Image*& bottom, Fl_Shared_Image*& right);
};

View File

@ -73,6 +73,7 @@ public:
virtual const void *icon() const;
virtual void icon(const void * ic);
virtual void free_icons();
virtual void capture_titlebar_and_borders(Fl_Shared_Image*& top, Fl_Shared_Image*& left, Fl_Shared_Image*& bottom, Fl_Shared_Image*& right);
};

View File

@ -19,7 +19,9 @@
#include "../../config_lib.h"
#include "Fl_X11_Window_Driver.H"
#include <FL/Fl_Shared_Image.H>
#include <FL/fl_draw.H>
#include <FL/Fl.H>
#include <string.h>
#if HAVE_DLFCN_H
#include <dlfcn.h>
@ -275,6 +277,60 @@ void Fl_X11_Window_Driver::free_icons() {
}
/* 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_X11_Window_Driver::capture_titlebar_and_borders(Fl_Shared_Image*& top, Fl_Shared_Image*& left, Fl_Shared_Image*& bottom, Fl_Shared_Image*& right)
{
Fl_RGB_Image *r_top, *r_left, *r_bottom, *r_right;
top = left = bottom = right = NULL;
if (pWindow->decorated_h() == pWindow->h()) return;
Window from = fl_window;
Fl_Surface_Device *previous = Fl_Surface_Device::surface();
Fl_Display_Device::display_device()->set_current();
pWindow->show();
Fl::check();
pWindow->make_current();
Window root, parent, *children, child_win;
unsigned n = 0;
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);
if (!do_it) wsides = htop = 0;
int hbottom = wsides;
fl_window = parent;
uchar *rgb;
if (htop) {
rgb = fl_read_image(NULL, 0, 0, - (pWindow->w() + 2 * wsides), htop);
r_top = new Fl_RGB_Image(rgb, pWindow->w() + 2 * wsides, htop, 3);
r_top->alloc_array = 1;
top = Fl_Shared_Image::get(r_top);
}
if (wsides) {
rgb = fl_read_image(NULL, 0, htop, -wsides, pWindow->h());
r_left = new Fl_RGB_Image(rgb, wsides, pWindow->h(), 3);
r_left->alloc_array = 1;
left = Fl_Shared_Image::get(r_left);
rgb = fl_read_image(NULL, pWindow->w() + wsides, htop, -wsides, pWindow->h());
r_right = new Fl_RGB_Image(rgb, wsides, pWindow->h(), 3);
r_right->alloc_array = 1;
right = Fl_Shared_Image::get(r_right);
rgb = fl_read_image(NULL, 0, htop + pWindow->h(), -(pWindow->w() + 2*wsides), hbottom);
r_bottom = new Fl_RGB_Image(rgb, pWindow->w() + 2*wsides, hbottom, 3);
r_bottom->alloc_array = 1;
bottom = Fl_Shared_Image::get(r_bottom);
}
fl_window = from;
previous->Fl_Surface_Device::set_current();
}
//
// End of "$Id$".
//