summaryrefslogtreecommitdiff
path: root/src/Fl_win32.cxx
diff options
context:
space:
mode:
authorAaron M. Ucko <ucko@debian.org>2017-01-12 21:40:18 -0500
committerAaron M. Ucko <ucko@debian.org>2017-01-12 21:40:18 -0500
commit10b16ce2223d6869b94dfb68aff76e62971842ee (patch)
tree5479fe884c9d817aaafaf6618cc104ae12f89d9f /src/Fl_win32.cxx
parenta3d0ced57399c9fd8075377b7310d545f968e524 (diff)
New upstream version 1.3.4
Diffstat (limited to 'src/Fl_win32.cxx')
-rw-r--r--src/Fl_win32.cxx302
1 files changed, 209 insertions, 93 deletions
diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx
index 23f1422..e0127cb 100644
--- a/src/Fl_win32.cxx
+++ b/src/Fl_win32.cxx
@@ -1,9 +1,9 @@
//
-// "$Id: Fl_win32.cxx 10387 2014-10-20 15:14:12Z ossman $"
+// "$Id: Fl_win32.cxx 12028 2016-10-14 16:35:44Z AlbrechtS $"
//
// WIN32-specific code for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2012 by Bill Spitzak and others.
+// Copyright 1998-2016 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -48,7 +48,7 @@
// that makes fltk use easier as only fltk libs are now requested
// This idea could be extended to fltk libs themselves,
// implementer should then care about DLL linkage flags ...
-# if (_MSC_VER>=1310)
+# if defined(_MSC_VER) && (_MSC_VER>=1310)
# pragma comment (lib, "comctl32.lib")
# endif
#endif
@@ -87,10 +87,6 @@ static void fl_clipboard_notify_target(HWND wnd);
static void fl_clipboard_notify_untarget(HWND wnd);
// Internal variables
-static Fl_GDI_Graphics_Driver fl_gdi_driver;
-static Fl_Display_Device fl_gdi_display(&fl_gdi_driver);
-Fl_Display_Device *Fl_Display_Device::_display = &fl_gdi_display; // the platform display
-
static HWND clipboard_wnd = 0;
static HWND next_clipboard_wnd = 0;
@@ -350,6 +346,16 @@ extern int fl_send_system_handlers(void *e);
MSG fl_msg;
+// A local helper function to flush any pending callback requests
+// from the awake ring-buffer
+static void process_awake_handler_requests(void) {
+ Fl_Awake_Handler func;
+ void *data;
+ while (Fl::get_awake_handler_(func, data) == 0) {
+ func(data);
+ }
+}
+
// This is never called with time_to_wait < 0.0.
// It *should* return negative on error, 0 if nothing happens before
// timeout, and >0 if any callbacks were done. This version only
@@ -423,15 +429,37 @@ int fl_wait(double time_to_wait) {
if (fl_msg.message == fl_wake_msg) {
// Used for awaking wait() from another thread
thread_message_ = (void*)fl_msg.wParam;
- Fl_Awake_Handler func;
- void *data;
- while (Fl::get_awake_handler_(func, data)==0)
- func(data);
+ process_awake_handler_requests();
}
TranslateMessage(&fl_msg);
DispatchMessageW(&fl_msg);
}
+
+ // The following conditional test:
+ // (Fl::awake_ring_head_ != Fl::awake_ring_tail_)
+ // is a workaround / fix for STR #3143. This works, but a better solution
+ // would be to understand why the PostThreadMessage() messages are not
+ // seen by the main window if it is being dragged/ resized at the time.
+ // If a worker thread posts an awake callback to the ring buffer
+ // whilst the main window is unresponsive (if a drag or resize operation
+ // is in progress) we may miss the PostThreadMessage(). So here, we check if
+ // there is anything pending in the awake ring buffer and if so process
+ // it. This is not strictly thread safe (for speed it compares the head
+ // and tail indices without first locking the ring buffer) but is intended
+ // only as a fall-back recovery mechanism if the awake processing stalls.
+ // If the test erroneously returns true (may happen if we test the indices
+ // whilst they are being modified) we will call process_awake_handler_requests()
+ // unnecessarily, but this has no harmful consequences so is safe to do.
+ // Note also that if we miss the PostThreadMessage(), then thread_message_
+ // will not be updated, so this is not a perfect solution, but it does
+ // recover and process any pending awake callbacks.
+ // Normally the ring buffer head and tail indices will match and this
+ // comparison will do nothing. Addresses STR #3143
+ if (Fl::awake_ring_head_ != Fl::awake_ring_tail_) {
+ process_awake_handler_requests();
+ }
+
Fl::flush();
// This should return 0 if only timer events were handled:
@@ -574,9 +602,9 @@ public:
char *o;
int lencount;
// Predict size of \r\n conversion buffer
- for ( i=in, lencount = inlen; lencount--; ) {
- if ( *i == '\r' && *(i+1) == '\n' ) // leave \r\n untranslated
- { i+=2; outlen+=2; }
+ for (i = in, lencount = inlen; lencount > 0; lencount--) {
+ if ( *i == '\r' && *(i+1) == '\n' && lencount >= 2 ) // leave \r\n untranslated
+ { i+=2; outlen+=2; lencount--; }
else if ( *i == '\n' ) // \n by itself? leave room to insert \r
{ i++; outlen+=2; }
else
@@ -585,9 +613,9 @@ public:
// Alloc conversion buffer + NULL
out = new char[outlen+1];
// Handle \n -> \r\n conversion
- for ( i=in, o=out, lencount = inlen; lencount--; ) {
- if ( *i == '\r' && *(i+1) == '\n' ) // leave \r\n untranslated
- { *o++ = *i++; *o++ = *i++; }
+ for (i = in, o=out, lencount = inlen; lencount > 0; lencount--) {
+ if ( *i == '\r' && *(i+1) == '\n' && lencount >= 2 ) // leave \r\n untranslated
+ { *o++ = *i++; *o++ = *i++; lencount--; }
else if ( *i == '\n' ) // \n by itself? insert \r
{ *o++ = '\r'; *o++ = *i++; }
else
@@ -636,6 +664,8 @@ void fl_update_clipboard(void) {
// call this when you create a selection:
void Fl::copy(const char *stuff, int len, int clipboard, const char *type) {
if (!stuff || len<0) return;
+ if (clipboard >= 2)
+ clipboard = 1; // Only on X11 do multiple clipboards make sense.
// Convert \n -> \r\n (for old apps like Notepad, DOS)
Lf2CrlfConvert buf(stuff, len);
@@ -705,7 +735,7 @@ void Fl::paste(Fl_Widget &receiver, int clipboard, const char *type) {
}
else if (strcmp(type, Fl::clipboard_image) == 0) { // we want an image from clipboard
uchar *rgb = NULL;
- int width, height, depth;
+ int width = 0, height = 0, depth = 0;
if ( (h = GetClipboardData(CF_DIB)) ) { // if there's a DIB in clipboard
LPBITMAPINFO lpBI = (LPBITMAPINFO)GlobalLock(h) ;
width = lpBI->bmiHeader.biWidth; // bitmap width & height
@@ -754,12 +784,12 @@ void Fl::paste(Fl_Widget &receiver, int clipboard, const char *type) {
HDC hdc = GetDC(NULL); // get unit correspondance between .01 mm and screen pixels
int hmm = GetDeviceCaps(hdc, HORZSIZE);
int hdots = GetDeviceCaps(hdc, HORZRES);
- int vmm = GetDeviceCaps(hdc, VERTSIZE);
- int vdots = GetDeviceCaps(hdc, VERTRES);
+ int dhr = GetDeviceCaps(hdc, DESKTOPHORZRES); // true number of pixels on display
ReleaseDC(NULL, hdc);
- float factorw = (100. * hmm) / hdots;
- float factorh = (100. * vmm) / vdots + 0.5;
- width /= factorw; height /= factorh; // convert to screen pixel unit
+ // Global display scaling factor: 1, 1.25, 1.5, 1.75, etc...
+ float scaling = dhr/float(hdots);
+ float factor = (100.f * hmm) / hdots;
+ width = (int)(width*scaling/factor); height = (int)(height*scaling/factor); // convert to screen pixel unit
RECT rect = {0, 0, width, height};
Fl_Offscreen off = fl_create_offscreen(width, height);
fl_begin_offscreen(off);
@@ -1124,6 +1154,7 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
R = CreateRectRgn(0,0,0,0);
int r = GetUpdateRgn(hWnd,R,0);
if (r==NULLREGION && !redraw_whole_window) {
+ XDestroyRegion(R);
break;
}
@@ -1482,42 +1513,46 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
// 1 | fix | yes
// 2 | size | yes
-int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by) {
- int W, H, xoff, yoff, dx, dy;
+static int fake_X_wm_style(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by, DWORD style, DWORD styleEx,
+ int w_maxw, int w_minw, int w_maxh, int w_minh, uchar w_size_range_set) {
+ int W = 0, H = 0, xoff = 0, yoff = 0, dx = 0, dy = 0;
int ret = bx = by = bt = 0;
int fallback = 1;
if (!w->parent()) {
- HWND hwnd = fl_xid(w);
- if (hwnd) {
+ if (fl_xid(w) || style) {
// The block below calculates the window borders by requesting the
// required decorated window rectangle for a desired client rectangle.
// If any part of the function above fails, we will drop to a
// fallback to get the best guess which is always available.
- HWND hwnd = fl_xid(w);
- // request the style flags of this window, as WIN32 sees them
- LONG style = GetWindowLong(hwnd, GWL_STYLE);
- LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
+
+ if (!style) {
+ HWND hwnd = fl_xid(w);
+ // request the style flags of this window, as WIN32 sees them
+ style = GetWindowLong(hwnd, GWL_STYLE);
+ styleEx = GetWindowLong(hwnd, GWL_EXSTYLE);
+ }
+
RECT r;
r.left = w->x();
r.top = w->y();
r.right = w->x()+w->w();
r.bottom = w->y()+w->h();
// get the decoration rectangle for the desired client rectangle
- BOOL ok = AdjustWindowRectEx(&r, style, FALSE, exstyle);
+ BOOL ok = AdjustWindowRectEx(&r, style, FALSE, styleEx);
if (ok) {
X = r.left;
Y = r.top;
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;
dx = W - w->w();
dy = H - w->h();
- if (w->size_range_set && (w->maxw != w->minw || w->maxh != w->minh))
+ if (w_size_range_set && (w_maxw != w_minw || w_maxh != w_minh))
ret = 2;
else
ret = 1;
@@ -1528,7 +1563,7 @@ int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by)
// This is the original (pre 1.1.7) routine to calculate window border sizes.
if (fallback) {
if (w->border() && !w->parent()) {
- if (w->size_range_set && (w->maxw != w->minw || w->maxh != w->minh)) {
+ if (w_size_range_set && (w_maxw != w_minw || w_maxh != w_minh)) {
ret = 2;
bx = GetSystemMetrics(SM_CXSIZEFRAME);
by = GetSystemMetrics(SM_CYSIZEFRAME);
@@ -1557,7 +1592,7 @@ int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by)
//Proceed to positioning the window fully inside the screen, if possible
//Find screen that contains most of the window
//FIXME: this ought to be the "work area" instead of the entire screen !
- int scr_x, scr_y, scr_w, scr_h;
+ int scr_x = 0, scr_y = 0, scr_w = 0, scr_h = 0;
Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h, X, Y, W, H);
//Make border's lower right corner visible
if (scr_x+scr_w < X+W) X = scr_x+scr_w - W;
@@ -1582,6 +1617,10 @@ int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by)
return ret;
}
+int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by) {
+ return fake_X_wm_style(w, X, Y, bt, bx, by, 0, 0, w->maxw, w->minw, w->maxh, w->minh, w->size_range_set);
+}
+
////////////////////////////////////////////////////////////////
void Fl_Window::resize(int X,int Y,int W,int H) {
@@ -1789,7 +1828,7 @@ Fl_X* Fl_X::make(Fl_Window* w) {
wcw.lpfnWndProc = (WNDPROC)WndProc;
wcw.cbClsExtra = wcw.cbWndExtra = 0;
wcw.hInstance = fl_display;
- if (!w->icon())
+ if (!w->icon() && !w->icon_->count)
w->icon((void *)LoadIcon(NULL, IDI_APPLICATION));
wcw.hIcon = wcw.hIconSm = (HICON)w->icon();
wcw.hCursor = LoadCursor(NULL, IDC_ARROW);
@@ -1832,8 +1871,14 @@ Fl_X* Fl_X::make(Fl_Window* w) {
}
}
styleEx |= WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT;
- int xwm = xp , ywm = yp , bt, bx, by;
- switch (fake_X_wm(w, xwm, ywm, bt, bx, by)) {
+
+ int wintype = 0;
+ if (w->border() && !w->parent()) {
+ if (w->size_range_set && (w->maxw != w->minw || w->maxh != w->minh)) wintype = 2;
+ else wintype = 1;
+ }
+
+ switch (wintype) {
// No border (used for menus)
case 0:
style |= WS_POPUP;
@@ -1854,6 +1899,9 @@ Fl_X* Fl_X::make(Fl_Window* w) {
style |= WS_MINIMIZEBOX;
break;
}
+
+ int xwm = xp , ywm = yp , bt, bx, by;
+ fake_X_wm_style(w, xwm, ywm, bt, bx, by, style, styleEx, w->maxw, w->minw, w->maxh, w->minh, w->size_range_set);
if (by+bt) {
wp += 2*bx;
hp += 2*by+bt;
@@ -2177,8 +2225,10 @@ static HICON image_to_icon(const Fl_RGB_Image *image, bool is_icon,
return NULL;
const uchar *i = (const uchar*)*image->data();
- for (int y = 0;y < image->h();y++) {
- for (int x = 0;x < image->w();x++) {
+ const int extra_data = image->ld() ? (image->ld()-image->w()*image->d()) : 0;
+
+ for (int y = 0; y < image->h(); y++) {
+ for (int x = 0; x < image->w(); x++) {
switch (image->d()) {
case 1:
*bits = (0xff<<24) | (i[0]<<16) | (i[0]<<8) | i[0];
@@ -2196,7 +2246,7 @@ static HICON image_to_icon(const Fl_RGB_Image *image, bool is_icon,
i += image->d();
bits++;
}
- i += image->ld();
+ i += extra_data;
}
// A mask bitmap is still needed even though it isn't used
@@ -2219,9 +2269,6 @@ static HICON image_to_icon(const Fl_RGB_Image *image, bool is_icon,
DeleteObject(bitmap);
DeleteObject(mask);
- if (icon == NULL)
- return NULL;
-
return icon;
}
@@ -2494,8 +2541,8 @@ void Fl_Window::show() {
//ShowWindow(i->xid,fl_capture?SW_SHOWNOACTIVATE:SW_RESTORE);
}
#ifdef USE_PRINT_BUTTON
-void preparePrintFront(void);
-preparePrintFront();
+ void preparePrintFront(void);
+ preparePrintFront();
#endif
}
@@ -2649,60 +2696,113 @@ 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, float *pscaling=0)
+{
+ RECT r = {0,0,0,0};
+ bx = by = bt = 0;
+ float scaling = 1;
+ 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;
+ // Compute the global display scaling factor: 1, 1.25, 1.5, 1.75, etc...
+ // This factor can be set in Windows 10 by
+ // "Change the size of text, apps and other items" in display settings.
+ HDC hdc = GetDC(NULL);
+ int hr = GetDeviceCaps(hdc, HORZRES); // pixels visible to the app
+#ifndef DESKTOPHORZRES
+#define DESKTOPHORZRES 118
+#endif
+ int dhr = GetDeviceCaps(hdc, DESKTOPHORZRES); // true number of pixels on display
+ ReleaseDC(NULL, hdc);
+ scaling = dhr/float(hr); // display scaling factor
+ scaling = int(scaling * 100 + 0.5)/100.; // round to 2 digits after decimal point
+ }
+ }
+ if (need_r) {
+ GetWindowRect(fl_xid(win), &r);
+ }
+ bx = (r.right - r.left - int(win->w() * scaling))/2;
+ if (bx < 1) bx = 1;
+ by = bx;
+ bt = r.bottom - r.top - int(win->h() * scaling) - 2 * by;
+ }
+ if (pscaling) *pscaling = scaling;
+ 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);
- return h() + bt + 2 * by;
+ int bt, bx, by;
+ float scaling;
+ border_width_title_bar_height(this, bx, by, bt, &scaling);
+ return h() + bt/scaling + 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()) {
- 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)
+{
+ int bt, bx, by; // border width and title bar height of window
+ float scaling;
+ RECT r = border_width_title_bar_height(win, bx, by, bt, &scaling);
+ if (bt) {
+ Fl_Display_Device::display_device()->set_current(); // make window current
+ win->show();
+ Fl::check();
+ win->make_current();
+ HDC save_gc = fl_gc;
+ fl_gc = GetDC(NULL); // get the screen device context
+ int ww = win->w() + 2 * bx;
+ int wh = win->h() + bt + 2 * by;
+ // 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, r.right - r.left + 1, 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;
+ fl_window = save_win;
+ ReleaseDC(NULL, fl_gc); fl_gc = save_gc;
+ toset->set_current();
+ // draw the 4 window sides
+ //fl_draw_image(top_image, x_offset, y_offset, ww, bt + by, 3);
+ Fl_RGB_Image *top_r = new Fl_RGB_Image(top_image, r.right - r.left + 1, bt + by, 3);
+ top_r->alloc_array = 1;
+ if (scaling > 1) {
+ Fl_RGB_Scaling current = Fl_Image::RGB_scaling();
+ Fl_Image::RGB_scaling(FL_RGB_SCALING_BILINEAR);
+ Fl_RGB_Image *tmp_img = (Fl_RGB_Image*)top_r->copy(ww, (bt + by)/scaling);
+ Fl_Image::RGB_scaling(current);
+ delete top_r;
+ top_r = tmp_img;
+ }
+ top_r->draw(x_offset, y_offset);
+ delete top_r;
+
+ 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; }
}
- 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();
- HDC save_gc = fl_gc;
- fl_gc = GetDC(NULL); // get the screen device context
- // capture the 4 window sides from screen
- RECT r; GetWindowRect(fl_window, &r);
- uchar *top_image = fl_read_image(NULL, r.left, r.top, ww, bt + by);
- uchar *left_image = fl_read_image(NULL, r.left, r.top, bx, wh);
- uchar *right_image = fl_read_image(NULL, r.right - bx, r.top, bx, wh);
- uchar *bottom_image = fl_read_image(NULL, r.left, r.bottom-by, ww, by);
- ReleaseDC(NULL, fl_gc); fl_gc = save_gc;
- 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);
- fl_gc = GetDC(fl_xid(win));
- ReleaseDC(fl_xid(win), fl_gc);
-}
+ // draw the window inner part
+ this->print_widget(win, x_offset + bx, y_offset + (bt + by)/scaling);
+}
#ifdef USE_PRINT_BUTTON
// to test the Fl_Printer class creating a "Print front window" button in a separate window
@@ -2745,14 +2845,30 @@ void printFront(Fl_Widget *o, void *data)
o->window()->show();
}
+#include <FL/Fl_Copy_Surface.H>
+void copyFront(Fl_Widget *o, void *data)
+{
+ o->window()->hide();
+ Fl_Window *win = Fl::first_window();
+ if (!win) return;
+ Fl_Copy_Surface *surf = new Fl_Copy_Surface(win->decorated_w(), win->decorated_h());
+ surf->set_current();
+ surf->draw_decorated_window(win); // draw the window content
+ delete surf; // put the window on the clipboard
+ Fl_Display_Device::display_device()->set_current();
+ o->window()->show();
+}
+
void preparePrintFront(void)
{
static BOOL first=TRUE;
if(!first) return;
first=FALSE;
- static Fl_Window w(0,0,120,30);
- static Fl_Button b(0,0,w.w(),w.h(), "Print front window");
- b.callback(printFront);
+ static Fl_Window w(0,0,120,60);
+ static Fl_Button bp(0,0,w.w(),30, "Print front window");
+ bp.callback(printFront);
+ static Fl_Button bc(0,30,w.w(),30, "Copy front window");
+ bc.callback(copyFront);
w.end();
w.show();
}
@@ -2761,5 +2877,5 @@ void preparePrintFront(void)
#endif // FL_DOXYGEN
//
-// End of "$Id: Fl_win32.cxx 10387 2014-10-20 15:14:12Z ossman $".
+// End of "$Id: Fl_win32.cxx 12028 2016-10-14 16:35:44Z AlbrechtS $".
//