diff options
| author | Albrecht Schlosser <albrechts.fltk@online.de> | 2021-11-14 15:17:03 +0100 |
|---|---|---|
| committer | Albrecht Schlosser <albrechts.fltk@online.de> | 2021-11-19 18:50:53 +0100 |
| commit | 1ce3a84e9fe74297aa764fc12536af544378d265 (patch) | |
| tree | 61a17c239aca387a978debd3fd3c733c383f902c | |
| parent | 0b8eabd184ac71b778c9fab3c6161b65b616f1f5 (diff) | |
Refactor and improve "Print front window" dialog
src/print_button.cxx: "Print front window" implementation (new file)
This is compiled and activated if USE_PRINT_BUTTON is defined.
The feature can be fine controlled by environment variable
'FLTK_PRINT_BUTTON' (see docs in source file).
| -rw-r--r-- | src/CMakeLists.txt | 9 | ||||
| -rw-r--r-- | src/Fl_Window_Driver.H | 3 | ||||
| -rw-r--r-- | src/Fl_win32.cxx | 89 | ||||
| -rw-r--r-- | src/Fl_x.cxx | 78 | ||||
| -rw-r--r-- | src/Makefile | 7 | ||||
| -rw-r--r-- | src/print_button.cxx | 192 |
6 files changed, 208 insertions, 170 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0efbfede4..8b64485a6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -133,6 +133,8 @@ set (CPPFILES fl_diamond_box.cxx fl_draw.cxx fl_draw_pixmap.cxx + fl_encoding_latin1.cxx + fl_encoding_mac_roman.cxx fl_engraved_label.cxx fl_file_dir.cxx fl_font.cxx @@ -153,13 +155,12 @@ set (CPPFILES fl_shadow_box.cxx fl_shortcut.cxx fl_show_colormap.cxx + fl_string.cxx fl_symbols.cxx + fl_utf8.cxx fl_vertex.cxx + print_button.cxx screen_xywh.cxx - fl_utf8.cxx - fl_string.cxx - fl_encoding_latin1.cxx - fl_encoding_mac_roman.cxx ) # find all header files in source directory <FL/...> diff --git a/src/Fl_Window_Driver.H b/src/Fl_Window_Driver.H index 6d740892c..aa1a62b9a 100644 --- a/src/Fl_Window_Driver.H +++ b/src/Fl_Window_Driver.H @@ -38,6 +38,9 @@ class Fl_X; class Fl_Image; class Fl_RGB_Image; +// not directly window driver related, but ... +int fl_create_print_window(); // used internally on some platforms + /** \brief A base class for platform specific window handling code. diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx index 3ca0744cc..9abbb5d58 100644 --- a/src/Fl_win32.cxx +++ b/src/Fl_win32.cxx @@ -1,7 +1,7 @@ // // Windows-specific code for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2018 by Bill Spitzak and others. +// Copyright 1998-2021 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 @@ -105,7 +105,6 @@ extern void fl_cleanup_pens(void); #define round(A) int((A) + 0.5) #endif // _MSC_VER <= 1600 -// // USE_ASYNC_SELECT - define it if you have WSAAsyncSelect()... // USE_ASYNC_SELECT is OBSOLETED in 1.3 for the following reasons: /* @@ -568,8 +567,8 @@ void Fl_WinAPI_Screen_Driver::open_display_platform() { } } OleInitialize(0L); - get_imm_module(); + fl_create_print_window(); } @@ -594,7 +593,7 @@ void Fl_WinAPI_Screen_Driver::desktop_scale_factor() { dpi[ns][0] = float(dpiX); dpi[ns][1] = float(dpiY); scale(ns, dpiX / 96.f); - //fprintf(LOG, "desktop_scale_factor ns=%d factor=%.2f dpi=%.1f\n", ns, scale(ns), dpi[ns][0]); + // fprintf(LOG, "desktop_scale_factor ns=%d factor=%.2f dpi=%.1f\n", ns, scale(ns), dpi[ns][0]); } } @@ -2631,10 +2630,6 @@ void Fl_WinAPI_Window_Driver::show() { BringWindowToTop(i->xid); // ShowWindow(i->xid,fl_capture?SW_SHOWNOACTIVATE:SW_RESTORE); } -#ifdef USE_PRINT_BUTTON - void preparePrintFront(void); - preparePrintFront(); -#endif } // the current context @@ -2807,82 +2802,4 @@ void Fl_WinAPI_Window_Driver::capture_titlebar_and_borders(Fl_RGB_Image *&top, F Fl_Surface_Device::pop_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 -#include <FL/Fl_Printer.H> -#include <FL/Fl_Button.H> -void printFront(Fl_Widget *o, void *data) { - Fl_Printer printer; - o->window()->hide(); - Fl_Window *win = Fl::first_window(); - if (!win) - return; - int w, h; - if (printer.begin_job(1)) { - o->window()->show(); - return; - } - if (printer.begin_page()) { - o->window()->show(); - return; - } - printer.printable_rect(&w, &h); - int wh, ww; - wh = win->decorated_h(); - ww = win->decorated_w(); - // scale the printer device so that the window fits on the page - float scale = 1; - if (ww > w || wh > h) { - scale = (float)w / ww; - if ((float)h / wh < scale) - scale = (float)h / wh; - printer.scale(scale, scale); - } -// #define ROTATE 20.0 -#ifdef ROTATE - printer.scale(scale * 0.8, scale * 0.8); - printer.printable_rect(&w, &h); - printer.origin(w / 2, h / 2); - printer.rotate(ROTATE); - printer.print_widget(win, -win->w() / 2, -win->h() / 2); - // printer.print_window_part(win, 0, 0, win->w(), win->h(), -win->w() / 2, -win->h() / 2); -#else - printer.print_window(win); -#endif - printer.end_page(); - printer.end_job(); - 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, 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(); -} -#endif // USE_PRINT_BUTTON - #endif // defined(_WIN32) and !defined(FL_DOXYGEN) diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx index 0a81f5a66..4d30cc2e3 100644 --- a/src/Fl_x.cxx +++ b/src/Fl_x.cxx @@ -716,6 +716,7 @@ void Fl_X11_Screen_Driver::open_display_platform() { // the unique GC used by all X windows GC gc = XCreateGC(fl_display, RootWindow(fl_display, fl_screen), 0, 0); Fl_Graphics_Driver::default_driver().gc(gc); + fl_create_print_window(); } @@ -3216,81 +3217,4 @@ void Fl_X11_Window_Driver::show() { } } - -//#define USE_PRINT_BUTTON 1 -#ifdef USE_PRINT_BUTTON - -// to test the Fl_Printer class creating a "Print front window" button in a separate window -#include <FL/Fl_Printer.H> -#include <FL/Fl_Button.H> - -void printFront(Fl_Widget *o, void *data) -{ - Fl_Printer printer; - o->window()->hide(); - Fl_Window *win = Fl::first_window(); - if(!win) return; - int w, h; - if( printer.begin_job(1) ) { o->window()->show(); return; } - if( printer.begin_page() ) { o->window()->show(); return; } - printer.printable_rect(&w,&h); - // scale the printer device so that the window fits on the page - float scale = 1; - int ww = win->decorated_w(); - int wh = win->decorated_h(); - if (ww > w || wh > h) { - scale = (float)w/ww; - if ((float)h/wh < scale) scale = (float)h/wh; - printer.scale(scale, scale); - printer.printable_rect(&w, &h); - } - -// #define ROTATE 20.0 -#ifdef ROTATE - printer.scale(scale * 0.8, scale * 0.8); - printer.printable_rect(&w, &h); - printer.origin(w/2, h/2 ); - printer.rotate(ROTATE); - printer.print_window( win, - win->w()/2, - win->h()/2); - //printer.print_window_part( win, 0,0, win->w(), win->h(), - win->w()/2, - win->h()/2 ); -#else - printer.origin(w/2, h/2 ); - printer.print_window(win, -ww/2, -wh/2); - //printer.print_window_part( win, 0,0, win->w(), win->h(), -ww/2, -wh/2 ); -#endif - - printer.end_page(); - printer.end_job(); - 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()); - Fl_Surface_Device::push_current(surf); - surf->draw_decorated_window(win); // draw the window content - Fl_Surface_Device::pop_current(); - delete surf; // put the window on the clipboard - o->window()->show(); -} - -static int prepare_print_button() { - static Fl_Window w(0,0,140,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(); - return 0; -} - -static int unused = prepare_print_button(); - -#endif // USE_PRINT_BUTTON - #endif // !defined(FL_DOXYGEN) diff --git a/src/Makefile b/src/Makefile index 0b7b89a92..e38040332 100644 --- a/src/Makefile +++ b/src/Makefile @@ -157,11 +157,12 @@ CPPFILES = \ fl_shadow_box.cxx \ fl_shortcut.cxx \ fl_show_colormap.cxx \ + fl_string.cxx \ fl_symbols.cxx \ - fl_vertex.cxx \ - screen_xywh.cxx \ fl_utf8.cxx \ - fl_string.cxx + fl_vertex.cxx \ + print_button.cxx \ + screen_xywh.cxx OBJCPPFILES = \ Fl_cocoa.mm \ diff --git a/src/print_button.cxx b/src/print_button.cxx new file mode 100644 index 000000000..35c7d1063 --- /dev/null +++ b/src/print_button.cxx @@ -0,0 +1,192 @@ +// +// "Print Window" functions for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2021 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 +// file is missing or damaged, see the license at: +// +// https://www.fltk.org/COPYING.php +// +// Please see the following page on how to report bugs and issues: +// +// https://www.fltk.org/bugs.php +// + +// Notes: This function must be activated by defining the preprocessor macro +// USE_PRINT_BUTTON on the commandline. +// +// Although this function is compiled on all platforms it is only used by +// platform specific code of fl_open_display() on Linux (X11) and Windows. +// macOS uses the "Print front window" menu in the application menu. +// +// The environment variable FLTK_PRINT_BUTTON can be defined to control the +// creation of the sometimes annoying print button feature at runtime if it +// has been compiled in (see above): +// +// - FLTK_PRINT_BUTTON undefined: like 1 below (default) +// +// - FLTK_PRINT_BUTTON = 0 : print front window disabled for this program +// - FLTK_PRINT_BUTTON = 1 : window shown at startup +// - FLTK_PRINT_BUTTON = 2 : window not shown, shortcut available to show +// - FLTK_PRINT_BUTTON = 3 : window shown at startup, shortcut available +// +// If options 2 or 3 are used the shortcut can be used to show the window +// if it was not shown (2) or accidentally closed (3). +// +// Currently the shortcut can't be configured and is always ALT+SHIFT+'s'. +// Todo: make the shortcut configurable. + +#ifdef USE_PRINT_BUTTON + +#include <FL/Fl_Printer.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_Check_Button.H> +#include <FL/Fl_Copy_Surface.H> +#include <FL/Fl_Image_Surface.H> +#include <FL/Fl_RGB_Image.H> +#include <FL/fl_draw.H> +#include <FL/fl_ask.H> + +#include <stdlib.h> +#include <stdio.h> + +// define the optional rotation of print output in degrees to test it +// #define ROTATE 20.0 + +// Global variables to simplify and clarify the code: + +static Fl_Window *print_window = 0; // "print front window" dialog window +static Fl_Check_Button *deco_button = 0; // window decoration button + +// The button callback does the job for both printing and copying to the +// clipboard. The callback is called with 'mode' == (int)(data). +// 1: print window +// 2: copy window to clipboard +// else: see 2. + +static void output_cb(Fl_Widget *o, void *data) { + + print_window->hide(); + Fl_Window *win = Fl::first_window(); + + // if no (other) window exists we return silently w/o showing the + // print window again (which ends the program) + + if (!win) return; + + int mode = fl_int(data); + int deco = deco_button->value(); + int ww = deco ? win->decorated_w() : win->w(); + int wh = deco ? win->decorated_h() : win->h(); + + if (mode == 1) { // print window + + Fl_Printer printer; + int w, h; + if (printer.begin_job(1)) { // fail or cancel + print_window->show(); + return; + } + if (printer.begin_page()) { // fail or cancel + print_window->show(); + return; + } + printer.printable_rect(&w, &h); + // scale the printer device so that the window fits on the page + float scale = 1; + if (ww > w || wh > h) { + scale = (float)w / ww; + if ((float)h / wh < scale) + scale = (float)h / wh; + printer.scale(scale, scale); + printer.printable_rect(&w, &h); + } +#ifdef ROTATE + printer.scale(scale * 0.8, scale * 0.8); + printer.printable_rect(&w, &h); + printer.origin(w / 2, h / 2); + printer.rotate(ROTATE); + printer.print_widget(win, -win->w() / 2, -win->h() / 2); +#else + printer.origin(w / 2, h / 2); + printer.print_window(win, -ww / 2, -wh / 2); +#endif + printer.end_page(); + printer.end_job(); + + } else { // copy window to clipboard + + Fl_Copy_Surface *surf = new Fl_Copy_Surface(ww, wh); + if (deco) + surf->draw_decorated_window(win); // draw the window content + else + surf->draw(win); // draw the window content + delete surf; // put the window on the clipboard + + } // print | copy + + print_window->show(); +} + +// Global event handler for screenshot (ctrl/alt/command + s) +// This pops up the "Print front window" dialog if it had been closed + +static int shortcut_handler(int event) { // global shortcut handler + + // required key and keyboard states for shortcut + // (should be configurable) + + const int key = 's'; // global shortcut key + const int state = FL_ALT | FL_SHIFT; // | FL_CTRL | FL_COMMAND; + + if (print_window && + (event == FL_SHORTCUT || event == FL_KEYBOARD) && + ((Fl::event_state() & state) == state) && + (Fl::event_key() == key)) { + print_window->show(); + return 1; + } + return 0; +} + +// create and initialize the "Print/copy front window" dialog window + +int fl_create_print_window() { + static int first = 1; + if (!first) + return 0; + first = 0; + int val = 1; + const char *print_button = fl_getenv("FLTK_PRINT_BUTTON"); + if (print_button) + val = atoi(print_button); + if (val) { + // prevent becoming a subwindow + Fl_Group *cg = Fl_Group::current(); + Fl_Group::current(0); + print_window = new Fl_Window( 0, 0, 200, 110, "FLTK screenshot"); + Fl_Button *bp = new Fl_Button(10, 10, 180, 30, "Print front window"); + Fl_Button *bc = new Fl_Button(10, 40, 180, 30, "Copy front window"); + deco_button = new Fl_Check_Button(10, 70, 180, 30, "Window decoration"); + bp->callback(output_cb, (void *)1); + bc->callback(output_cb, (void *)2); + print_window->end(); + if (val & 1) + print_window->show(); + // reset saved current group + Fl_Group::current(cg); + if (val & 2) + Fl::add_handler(shortcut_handler); + } + return 1; +} + +#else // USE_PRINT_BUTTON not defined + +int fl_create_print_window() { + return 0; +} + +#endif // USE_PRINT_BUTTON |
