From db214d1145e46d527a46d1fc2519548d2c4d23f1 Mon Sep 17 00:00:00 2001 From: maxim nikonov Date: Thu, 5 Feb 2026 15:21:34 +0500 Subject: wip: fork --- src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.H | 62 -- src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx | 472 --------- src/drivers/WinAPI/Fl_WinAPI_Pen_Driver.cxx | 518 ---------- src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx | 518 ---------- src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H | 104 -- src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx | 493 --------- src/drivers/WinAPI/Fl_WinAPI_System_Driver.H | 124 --- src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx | 1134 --------------------- src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H | 131 --- src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx | 731 ------------- src/drivers/WinAPI/fl_WinAPI_platform_init.cxx | 85 -- 11 files changed, 4372 deletions(-) delete mode 100644 src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.H delete mode 100644 src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx delete mode 100644 src/drivers/WinAPI/Fl_WinAPI_Pen_Driver.cxx delete mode 100644 src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx delete mode 100644 src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H delete mode 100644 src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx delete mode 100644 src/drivers/WinAPI/Fl_WinAPI_System_Driver.H delete mode 100644 src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx delete mode 100644 src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H delete mode 100644 src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx delete mode 100644 src/drivers/WinAPI/fl_WinAPI_platform_init.cxx (limited to 'src/drivers/WinAPI') diff --git a/src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.H deleted file mode 100644 index 2958fe6e5..000000000 --- a/src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.H +++ /dev/null @@ -1,62 +0,0 @@ -// -// Class Fl_WinAPI_Gl_Window_Driver for the Fast Light Tool Kit (FLTK). -// -// Copyright 2021-2023 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 -// - -#ifndef FL_WINAPI_GL_WINDOW_DRIVER_H -#define FL_WINAPI_GL_WINDOW_DRIVER_H - -#include -#if HAVE_GL -#include -#include "../../Fl_Gl_Window_Driver.H" -#include - -class Fl_WinAPI_Gl_Window_Driver : public Fl_Gl_Window_Driver { - friend Fl_Gl_Window_Driver* Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *); - Fl_WinAPI_Gl_Window_Driver(Fl_Gl_Window *win) : Fl_Gl_Window_Driver(win) {} - float pixels_per_unit() FL_OVERRIDE; - int mode_(int m, const int *a) FL_OVERRIDE; - void make_current_after() FL_OVERRIDE; - void swap_buffers() FL_OVERRIDE; - void swap_interval(int) FL_OVERRIDE; - int swap_interval() const FL_OVERRIDE; - void invalidate() FL_OVERRIDE {} - int flush_begin(char& valid_f) FL_OVERRIDE; - Fl_Gl_Choice *find(int m, const int *alistp) FL_OVERRIDE; - GLContext create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g) FL_OVERRIDE; - GLContext do_create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, - int layer); - void set_gl_context(Fl_Window* w, GLContext context) FL_OVERRIDE; - void delete_gl_context(GLContext) FL_OVERRIDE; - void make_overlay_current() FL_OVERRIDE; - void redraw_overlay() FL_OVERRIDE; - void* GetProcAddress(const char *procName) FL_OVERRIDE; - void draw_string_legacy(const char* str, int n) FL_OVERRIDE; - void gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize) FL_OVERRIDE; - void get_list(Fl_Font_Descriptor *fd, int r) FL_OVERRIDE; - int genlistsize() FL_OVERRIDE; - void switch_to_GL1() FL_OVERRIDE; - void switch_back() FL_OVERRIDE; -#if HAVE_GL_OVERLAY - void gl_hide_before(void *& overlay) FL_OVERRIDE; - int can_do_overlay() FL_OVERRIDE; - int overlay_color(Fl_Color i) FL_OVERRIDE; - void make_overlay(void*&overlay) FL_OVERRIDE; -#endif -}; - -#endif // HAVE_GL - -#endif // FL_WINAPI_GL_WINDOW_DRIVER_H diff --git a/src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx deleted file mode 100644 index 8e199b09c..000000000 --- a/src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx +++ /dev/null @@ -1,472 +0,0 @@ -// -// Class Fl_WinAPI_Gl_Window_Driver for the Fast Light Tool Kit (FLTK). -// -// Copyright 2021-2022 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 -// - -#include -#if HAVE_GL -#include -#include "../../Fl_Screen_Driver.H" -#include -#include "Fl_WinAPI_Gl_Window_Driver.H" -#include "../../Fl_Gl_Choice.H" -#include "Fl_WinAPI_Window_Driver.H" -#include "../GDI/Fl_Font.H" -extern void fl_save_dc(HWND, HDC); - -#ifndef GL_CURRENT_PROGRAM -# define GL_CURRENT_PROGRAM 0x8B8D // from glew.h -#endif - -// STR #3119: select pixel format with composition support -// ... and no more than 32 color bits (8 bits/color) -// Ref: PixelFormatDescriptor Object -// https://msdn.microsoft.com/en-us/library/cc231189.aspx -#if !defined(PFD_SUPPORT_COMPOSITION) -# define PFD_SUPPORT_COMPOSITION (0x8000) -#endif - -#define DEBUG_PFD (0) // 1 = PFD selection debug output, 0 = no debug output - - -// Describes crap needed to create a GLContext. -class Fl_WinAPI_Gl_Choice : public Fl_Gl_Choice { - friend class Fl_WinAPI_Gl_Window_Driver; -private: - int pixelformat; // the visual to use - PIXELFORMATDESCRIPTOR pfd; // some wgl calls need this thing -public: - Fl_WinAPI_Gl_Choice(int m, const int *alistp, Fl_Gl_Choice *n) : Fl_Gl_Choice(m, alistp, n) { - pixelformat = 0; - } -}; - - -Fl_Gl_Window_Driver *Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *w) -{ - return new Fl_WinAPI_Gl_Window_Driver(w); -} - - -Fl_Gl_Choice *Fl_WinAPI_Gl_Window_Driver::find(int m, const int *alistp) -{ - Fl_WinAPI_Gl_Choice *g = (Fl_WinAPI_Gl_Choice*)Fl_Gl_Window_Driver::find_begin(m, alistp); - if (g) return g; - - // Replacement for ChoosePixelFormat() that finds one with an overlay if possible: - HDC gc = (HDC)(fl_graphics_driver ? fl_graphics_driver->gc() : 0); - if (!gc) gc = fl_GetDC(0); - int pixelformat = 0; - PIXELFORMATDESCRIPTOR chosen_pfd; - for (int i = 1; ; i++) { - PIXELFORMATDESCRIPTOR pfd; - if (!DescribePixelFormat(gc, i, sizeof(pfd), &pfd)) break; - // continue if it does not satisfy our requirements: - if (~pfd.dwFlags & (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL)) continue; - if (pfd.iPixelType != ((m&FL_INDEX)?PFD_TYPE_COLORINDEX:PFD_TYPE_RGBA)) continue; - if ((m & FL_ALPHA) && !pfd.cAlphaBits) continue; - if ((m & FL_ACCUM) && !pfd.cAccumBits) continue; - if ((!(m & FL_DOUBLE)) != (!(pfd.dwFlags & PFD_DOUBLEBUFFER))) continue; - if ((!(m & FL_STEREO)) != (!(pfd.dwFlags & PFD_STEREO))) continue; - // Skipt his descriptor if we want a depth buffer, but this one has none - if ((m & FL_DEPTH) && !pfd.cDepthBits) continue; - // Skipt his descriptor if we want a 32 bit depth buffer, but this one has less or none - if ((m & FL_DEPTH32) && pfd.cDepthBits < 32) continue; - if ((m & FL_STENCIL) && !pfd.cStencilBits) continue; - -#if DEBUG_PFD - printf("pfd #%d supports composition: %s\n", i, (pfd.dwFlags & PFD_SUPPORT_COMPOSITION) ? "yes" : "no"); - printf(" ... & PFD_GENERIC_FORMAT: %s\n", (pfd.dwFlags & PFD_GENERIC_FORMAT) ? "generic" : "accelerated"); - printf(" ... Overlay Planes : %d\n", pfd.bReserved & 15); - printf(" ... Color & Depth : %d, %d\n", pfd.cColorBits, pfd.cDepthBits); - if (pixelformat) - printf(" current pixelformat : %d\n", pixelformat); - fflush(stdout); -#endif // DEBUG_PFD - - // see if better than the one we have already: - if (pixelformat) { - // offering non-generic rendering is better (read: hardware acceleration) - if (!(chosen_pfd.dwFlags & PFD_GENERIC_FORMAT) && - (pfd.dwFlags & PFD_GENERIC_FORMAT)) continue; - // offering overlay is better: - else if (!(chosen_pfd.bReserved & 15) && (pfd.bReserved & 15)) {} - // otherwise prefer a format that supports composition (STR #3119) - else if ((chosen_pfd.dwFlags & PFD_SUPPORT_COMPOSITION) && - !(pfd.dwFlags & PFD_SUPPORT_COMPOSITION)) continue; - // otherwise more bit planes is better, but no more than 32 (8 bits per channel): - else if (pfd.cColorBits > 32 || chosen_pfd.cColorBits > pfd.cColorBits) continue; - else if (chosen_pfd.cDepthBits > pfd.cDepthBits) continue; - } - pixelformat = i; - chosen_pfd = pfd; - } - -#if DEBUG_PFD - static int bb = 0; - if (!bb) { - bb = 1; - printf("PFD_SUPPORT_COMPOSITION = 0x%x\n", PFD_SUPPORT_COMPOSITION); - } - printf("Chosen pixel format is %d\n", pixelformat); - printf("Color bits = %d, Depth bits = %d\n", chosen_pfd.cColorBits, chosen_pfd.cDepthBits); - printf("Pixel format supports composition: %s\n", (chosen_pfd.dwFlags & PFD_SUPPORT_COMPOSITION) ? "yes" : "no"); - fflush(stdout); -#endif // DEBUG_PFD - - if (!pixelformat) return 0; - - g = new Fl_WinAPI_Gl_Choice(m, alistp, first); - first = g; - - g->pixelformat = pixelformat; - g->pfd = chosen_pfd; - - return g; -} - - -GLContext Fl_WinAPI_Gl_Window_Driver::do_create_gl_context(Fl_Window* window, - const Fl_Gl_Choice* g, int layer) -{ - Fl_X* i = Fl_X::flx(window); - HDC hdc = Fl_WinAPI_Window_Driver::driver(window)->private_dc; - if (!hdc) { - hdc = Fl_WinAPI_Window_Driver::driver(window)->private_dc = GetDCEx((HWND)i->xid, 0, DCX_CACHE); - fl_save_dc((HWND)i->xid, hdc); - SetPixelFormat(hdc, ((Fl_WinAPI_Gl_Choice*)g)->pixelformat, (PIXELFORMATDESCRIPTOR*)(&((Fl_WinAPI_Gl_Choice*)g)->pfd)); -# if USE_COLORMAP - if (fl_palette) SelectPalette(hdc, fl_palette, FALSE); -# endif - } - GLContext context = layer ? wglCreateLayerContext(hdc, layer) : wglCreateContext(hdc); - if (context) { - if (context_list && nContext) - wglShareLists((HGLRC)context_list[0], (HGLRC)context); - add_context(context); - } - return context; -} - - -GLContext Fl_WinAPI_Gl_Window_Driver::create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g) -{ - return do_create_gl_context(window, g, 0); -} - -void Fl_WinAPI_Gl_Window_Driver::set_gl_context(Fl_Window* w, GLContext context) { - GLContext current_context = wglGetCurrentContext(); - if (context != current_context || w != cached_window) { - cached_window = w; - wglMakeCurrent(Fl_WinAPI_Window_Driver::driver(w)->private_dc, (HGLRC)context); - } -} - -void Fl_WinAPI_Gl_Window_Driver::delete_gl_context(GLContext context) { - GLContext current_context = wglGetCurrentContext(); - if (current_context == context) { - cached_window = 0; - wglMakeCurrent(0, 0); - } - wglDeleteContext((HGLRC)context); - del_context(context); -} - - -void Fl_WinAPI_Gl_Window_Driver::make_overlay_current() { -#if HAVE_GL_OVERLAY - if (overlay() != this) { - set_gl_context(pWindow, (GLContext)overlay()); - // if (fl_overlay_depth) - // wglRealizeLayerPalette(Fl_X::flx(this)->private_dc, 1, TRUE); - } else -#endif - glDrawBuffer(GL_FRONT); -} - -void Fl_WinAPI_Gl_Window_Driver::redraw_overlay() { - pWindow->damage(FL_DAMAGE_OVERLAY); -} - -#if HAVE_GL_OVERLAY - -// Methods on Fl_Gl_Window_driver that create an overlay window. - -// Under win32 another GLX context is created to draw into the overlay -// and it is stored in the "overlay" pointer. - -// If overlay hardware is unavailable, the overlay is -// "faked" by drawing into the main layers. This is indicated by -// setting overlay == this. - -//static COLORREF *palette; -static int fl_overlay_depth = 0; - -void Fl_WinAPI_Gl_Window_Driver::gl_hide_before(void *& overlay) { - if (overlay && overlay != pWindow) { - delete_gl_context((GLContext)overlay); - overlay = 0; - } -} - -void Fl_WinAPI_Gl_Window_Driver::make_overlay(void*&overlay) { - if (overlay) return; - - GLContext context = do_create_gl_context(pWindow, g(), 1); - if (!context) {overlay = pWindow; return;} // fake the overlay - - HDC hdc = Fl_WinAPI_Window_Driver::driver(pWindow)->private_dc; - overlay = context; - LAYERPLANEDESCRIPTOR pfd; - wglDescribeLayerPlane(hdc, g()->pixelformat, 1, sizeof(pfd), &pfd); - if (!pfd.iPixelType) { - ; // full-color overlay - } else { - fl_overlay_depth = pfd.cColorBits; // used by gl_color() - if (fl_overlay_depth > 8) fl_overlay_depth = 8; - COLORREF palette[256]; - int n = (1<valid(0); - return; -} - -int Fl_WinAPI_Gl_Window_Driver::can_do_overlay() { - if (!g()) { - g( find(mode(), alist()) ); - if (!g()) return 0; - } - return (g()->pfd.bReserved & 15) != 0; -} - -int Fl_WinAPI_Gl_Window_Driver::overlay_color(Fl_Color i) { - if (Fl_Xlib_Graphics_Driver::fl_overlay && fl_overlay_depth) { - if (fl_overlay_depth < 8) { - // only black & white produce the expected colors. This could - // be improved by fixing the colormap set in Fl_Gl_Overlay.cxx - int size = 1<= size-2) glIndexi(size-1); - else glIndexi(i); - } else { - glIndexi(i ? i : FL_GRAY_RAMP); - } - return 1; - } - return 0; -} - -#endif // HAVE_GL_OVERLAY - - -float Fl_WinAPI_Gl_Window_Driver::pixels_per_unit() -{ - int ns = Fl_Window_Driver::driver(pWindow)->screen_num(); - return Fl::screen_driver()->scale(ns); -} - - -int Fl_WinAPI_Gl_Window_Driver::mode_(int m, const int *a) { - int oldmode = mode(); - pWindow->context(0); - mode( m); alist(a); - if (pWindow->shown()) { - g( find(m, a) ); - if (!g() || (oldmode^m)&(FL_DOUBLE|FL_STEREO)) { - pWindow->hide(); - pWindow->show(); - } - } else { - g(0); - } - return 1; -} - -void Fl_WinAPI_Gl_Window_Driver::make_current_after() { -#if USE_COLORMAP - if (fl_palette) { - fl_GetDC(fl_xid(pWindow)); - SelectPalette((HDC)fl_graphics_driver->gc(), fl_palette, FALSE); - RealizePalette((HDC)fl_graphics_driver->gc()); - } -#endif // USE_COLORMAP -} - -//#define HAVE_GL_OVERLAY 1 //test only - -void Fl_WinAPI_Gl_Window_Driver::swap_buffers() { -# if HAVE_GL_OVERLAY - // Do not swap the overlay, to match GLX: - BOOL ret = wglSwapLayerBuffers(Fl_WinAPI_Window_Driver::driver(pWindow)->private_dc, WGL_SWAP_MAIN_PLANE); - DWORD err = GetLastError(); -# else - SwapBuffers(Fl_WinAPI_Window_Driver::driver(pWindow)->private_dc); -# endif -} - - -// Start of swap_interval implementation in the three possibel ways for X11 - -// -1 = not yet initialized, 0 = none found, 1 = GLX, 2 = MESA, 3 = SGI -static signed char swap_interval_type = -1; - -typedef const char *(WINAPI *WGL_Get_Extension_String_Proc)(); -typedef BOOL (WINAPI *WGL_Swap_Iterval_Proc)(int interval); -typedef int (WINAPI *WGL_Get_Swap_Iterval_Proc)(); - -static WGL_Swap_Iterval_Proc wglSwapIntervalEXT = NULL; -static WGL_Get_Swap_Iterval_Proc wglGetSwapIntervalEXT = NULL; - -static void init_swap_interval() { - if (swap_interval_type != -1) - return; - swap_interval_type = 0; - WGL_Get_Extension_String_Proc wglGetExtensionsStringEXT = NULL; - wglGetExtensionsStringEXT = (WGL_Get_Extension_String_Proc)wglGetProcAddress("wglGetExtensionsStringEXT"); - if (!wglGetExtensionsStringEXT) - return; - const char *extensions = wglGetExtensionsStringEXT(); - if (extensions && strstr(extensions, "WGL_EXT_swap_control")) { - wglSwapIntervalEXT = (WGL_Swap_Iterval_Proc)wglGetProcAddress("wglSwapIntervalEXT"); - wglGetSwapIntervalEXT = (WGL_Get_Swap_Iterval_Proc)wglGetProcAddress("wglGetSwapIntervalEXT"); - swap_interval_type = 1; - } -} - -void Fl_WinAPI_Gl_Window_Driver::swap_interval(int interval) { - if (swap_interval_type == -1) - init_swap_interval(); - if (swap_interval_type == 1) { - if (wglSwapIntervalEXT) - wglSwapIntervalEXT(interval); - } -} - -int Fl_WinAPI_Gl_Window_Driver::swap_interval() const { - if (swap_interval_type == -1) - init_swap_interval(); - int interval = -1; - if (swap_interval_type == 1) { - if (wglGetSwapIntervalEXT) - interval = wglGetSwapIntervalEXT(); - } - return interval; -} - -// end of swap_interval implementation - -#if HAVE_GL_OVERLAY -#endif - -int Fl_WinAPI_Gl_Window_Driver::flush_begin(char& valid_f_) { -#if HAVE_GL_OVERLAY - char save_valid_f = valid_f_; - // Draw into hardware overlay planes if they are damaged: - if (overlay() && overlay() != pWindow - && (pWindow->damage()&(FL_DAMAGE_OVERLAY|FL_DAMAGE_EXPOSE) || !save_valid_f & 1)) { - set_gl_context(pWindow, (GLContext)overlay()); - if (fl_overlay_depth) - wglRealizeLayerPalette(Fl_WinAPI_Window_Driver::driver(pWindow)->private_dc, 1, TRUE); - glDisable(GL_SCISSOR_TEST); - glClear(GL_COLOR_BUFFER_BIT); - Fl_Xlib_Graphics_Driver::fl_overlay = 1; - draw_overlay(); - Fl_Xlib_Graphics_Driver::fl_overlay = 0; - valid_f_ = save_valid_f; - wglSwapLayerBuffers(Fl_WinAPI_Window_Driver::driver(pWindow)->private_dc, WGL_SWAP_OVERLAY1); - // if only the overlay was damaged we are done, leave main layer alone: - if (pWindow->damage() == FL_DAMAGE_OVERLAY) { - return 1; - } - } -#endif - return 0; -} - -void* Fl_WinAPI_Gl_Window_Driver::GetProcAddress(const char *procName) { - return (void*)wglGetProcAddress((LPCSTR)procName); -} - - -void Fl_WinAPI_Gl_Window_Driver::draw_string_legacy(const char* str, int n) { - draw_string_legacy_get_list(str, n); -} - -int Fl_WinAPI_Gl_Window_Driver::genlistsize() { - return 0x10000; -} - -void Fl_WinAPI_Gl_Window_Driver::gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize) { - if (!fl_fontsize->listbase) { - fl_fontsize->listbase = glGenLists(genlistsize()); - } - glListBase(fl_fontsize->listbase); -} - -void Fl_WinAPI_Gl_Window_Driver::get_list(Fl_Font_Descriptor *fd, int r) { - Fl_GDI_Font_Descriptor* gl_fd = (Fl_GDI_Font_Descriptor*)fd; - if (gl_fd->glok[r]) return; - gl_fd->glok[r] = 1; - unsigned int ii = r * 0x400; - HFONT oldFid = (HFONT)SelectObject((HDC)fl_graphics_driver->gc(), gl_fd->fid); - wglUseFontBitmapsW((HDC)fl_graphics_driver->gc(), ii, 0x400, gl_fd->listbase+ii); - SelectObject((HDC)fl_graphics_driver->gc(), oldFid); -} - - -typedef void (WINAPI *glUseProgram_type)(GLint); -static glUseProgram_type glUseProgram_f = NULL; - -void Fl_WinAPI_Gl_Window_Driver::switch_to_GL1() { - if (!glUseProgram_f) { - glUseProgram_f = (glUseProgram_type)GetProcAddress("glUseProgram"); - } - glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_prog); - if (current_prog) glUseProgram_f(0); -} - -void Fl_WinAPI_Gl_Window_Driver::switch_back() { - if (current_prog) glUseProgram_f((GLuint)current_prog); -} - - -class Fl_WinAPI_Gl_Plugin : public Fl_WinAPI_Plugin { -public: - Fl_WinAPI_Gl_Plugin() : Fl_WinAPI_Plugin(name()) { } - const char *name() override { return "gl.winapi.fltk.org"; } - void invalidate(Fl_Window *w) override { - w->as_gl_window()->valid(0); - } -}; - - -static Fl_WinAPI_Gl_Plugin Gl_Invalidate_Plugin; - - -FL_EXPORT HGLRC fl_win32_glcontext(GLContext rc) { return (HGLRC)rc; } - -#endif // HAVE_GL diff --git a/src/drivers/WinAPI/Fl_WinAPI_Pen_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Pen_Driver.cxx deleted file mode 100644 index 06cc1e477..000000000 --- a/src/drivers/WinAPI/Fl_WinAPI_Pen_Driver.cxx +++ /dev/null @@ -1,518 +0,0 @@ -// -// Definition of Windows Pen/Tablet event driver. -// -// Copyright 2025-2026 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 -// - -// Note: We require Windows 8 or later features for Pen/Tablet support. -// Defining WINVER and _WIN32_WINNT to 0x0602 *may* be required on some -// Windows build platforms. Must be done before all #include's. - -#if !defined(WINVER) || (WINVER < 0x0602) -# ifdef WINVER -# undef WINVER -# endif -# define WINVER 0x0602 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0602) -# ifdef _WIN32_WINNT -# undef _WIN32_WINNT -# endif -# define _WIN32_WINNT 0x0602 -#endif - -#include "src/drivers/Base/Fl_Base_Pen_Events.H" - -#include -#include -#include -#include "../../Fl_Screen_Driver.H" -#include -#include -#include -#include -// Some versions of MinGW now require us to explicitly include winerror to get S_OK defined -#include - -extern Fl_Window *fl_xmousewin; - -static constexpr uint8_t _FL_PEN = 0; // internal use -static constexpr uint8_t _FL_ERASER = 1; // internal use -static uint8_t device_type_ = _FL_PEN; - -static int _e_x_down = 0; -static int _e_y_down = 0; - -// Click counting state -static DWORD last_click_time_ = 0; -static int last_click_x_ = 0; -static int last_click_y_ = 0; -static Fl::Pen::State last_click_trigger_ = Fl::Pen::State::NONE; - -// The trait list keeps track of traits for every pen ID that appears while -// handling events. -// AppKit does not tell us what traits are available per pen or tablet, so -// we use the first 5 motion events to discover event values that are not -// the default value, and enter that knowledge into the traits database. -typedef std::map TraitList; -static TraitList trait_list_; -static int trait_countdown_ { 5 }; -static int current_pen_id_ { -1 }; -static Fl::Pen::Trait current_pen_trait_ { Fl::Pen::Trait::DRIVER_AVAILABLE }; -static Fl::Pen::Trait driver_traits_ { - Fl::Pen::Trait::DRIVER_AVAILABLE | Fl::Pen::Trait::PEN_ID | - Fl::Pen::Trait::ERASER | Fl::Pen::Trait::PRESSURE | - Fl::Pen::Trait::TILT_X | - Fl::Pen::Trait::TILT_Y | Fl::Pen::Trait::TWIST - // Notably missing: PROXIMITY, BARREL_PRESSURE -}; - -// Temporary storage of event data for the driver; -static Fl::Pen::EventData ev; - - -namespace Fl { - -// namespace Private { - -// // Global mouse position at mouse down event -// extern int e_x_down; -// extern int e_y_down; - -// }; // namespace Private - -namespace Pen { - -class Windows_Driver : public Driver { -public: - Windows_Driver() = default; - //virtual void subscribe(Fl_Widget* widget) override; - //virtual void unsubscribe(Fl_Widget* widget) override; - //virtual void release() override; - virtual Trait traits() override { return driver_traits_; } - virtual Trait pen_traits(int pen_id) override { - auto it = trait_list_.find(pen_id); - if (pen_id == 0) - return current_pen_trait_; - if (it == trait_list_.end()) { - return Trait::DRIVER_AVAILABLE; - } else { - return it->second; - } - } -}; - -Windows_Driver windows_driver; -Driver& driver { windows_driver }; - -} // namespace Pen - -} // namespace Fl - - -using namespace Fl::Pen; - -/* - Copy the event state. - */ -static void copy_state() { - Fl::Pen::State tr = (Fl::Pen::State)((uint32_t)Fl::Pen::e.state ^ (uint32_t)ev.state); - Fl::Pen::e = ev; - Fl::Pen::e.trigger = tr; - Fl::e_x = (int)ev.x; - Fl::e_y = (int)ev.y; - Fl::e_x_root = (int)ev.rx; - Fl::e_y_root = (int)ev.ry; -} - -/* - Check if coordinates are within the widget box. - Coordinates are in top_window space. We iterate up the hierarchy to ensure - that we handle subwindows correctly. - */ -static bool event_inside(Fl_Widget *w, double x, double y) { - if (w->as_window()) { - return ((x >= 0) && (y >= 0) && (x < w->w()) && (y < w->h())); - } else { - return ((x >= w->x()) && (y >= w->y()) && (x < w->x() + w->w()) && (y < w->y() + w->h())); - } -} - -/* - Find the widget under the pen event. - Search the subscriber list for widgets that are inside the same window, - are visible, and are within the give coordinates. Subwindow aware. - */ -static Fl_Widget *find_below_pen(Fl_Window *win, double x, double y) { - for (auto &sub: subscriber_list_) { - Fl_Widget *candidate = sub.second->widget(); - if (candidate && ((candidate == win) || (!candidate->as_window() && candidate->window() == win))) { - if (candidate->visible() && event_inside(candidate, x, y)) { - return candidate; - } - } - } - return nullptr; -} - -/* - Send the current event and event data to a widget. - Note: we will get the wrong coordinates if the widget is not a child of - the current event window (LEAVE events between windows). - */ -static int pen_send(Fl_Widget *w, int event, State trigger, bool &copied) { - // Copy most event data only once - if (!copied) { - copy_state(); - copied = true; - } - // Copy the top_window coordinates again as they may change when w changes - Fl::e_x = e.x = ev.x; - Fl::e_y = e.y = ev.y; - // Send the event. - e.trigger = trigger; - return w->handle(event); -} - -/* - Send an event to all subscribers. - */ -static int pen_send_all(int event, State trigger) { - bool copied = false; - // use local value because handler may still change ev values - for (auto &it: subscriber_list_) { - auto w = it.second->widget(); - if (w) - pen_send(w, event, trigger, copied); - } - return 1; -} - -/* - Convert the NSEvent button number to Fl::Pen::State, - */ -static State button_to_trigger(POINTER_BUTTON_CHANGE_TYPE button, bool down) { - switch (button) { - case POINTER_CHANGE_FIRSTBUTTON_DOWN: - case POINTER_CHANGE_FIRSTBUTTON_UP: - if ( (ev.state & (State::ERASER_DOWN | State::ERASER_HOVERS)) != State::NONE ) { - return down ? State::ERASER_DOWN : State::ERASER_HOVERS; - } else { - return down ? State::TIP_DOWN : State::TIP_HOVERS; - } - case POINTER_CHANGE_SECONDBUTTON_DOWN: - case POINTER_CHANGE_SECONDBUTTON_UP: - return State::BUTTON0; - case POINTER_CHANGE_THIRDBUTTON_DOWN: - case POINTER_CHANGE_THIRDBUTTON_UP: - return State::BUTTON1; - case POINTER_CHANGE_FOURTHBUTTON_DOWN: - case POINTER_CHANGE_FOURTHBUTTON_UP: - return State::BUTTON2; - case POINTER_CHANGE_FIFTHBUTTON_DOWN: - case POINTER_CHANGE_FIFTHBUTTON_UP: - return State::BUTTON3; - default: return State::NONE; - } -} - -/* - Handle events coming from the Win32 API. - WM_TABLET (Windows 2000 and up) - WM_POINTER (Windows 8 and up) - https://learn.microsoft.com/en-us/windows/win32/inputmsg/messages-and-notifications-portal - #if(WINVER >= 0x0602) ... #endif - \return -1 if we did not handle the event and want the main event handler to call DefWindowProc() - \return any other value that will then be return from WndProc() directly. - */ -LRESULT fl_win32_tablet_handler(MSG& msg) { - auto message = msg.message; - if (message < WM_NCPOINTERUPDATE || message > WM_POINTERROUTEDRELEASED) { - return -1; - } - - Fl_Window *eventWindow = fl_find(msg.hwnd); // can be nullptr - bool is_proximity = false; - bool is_down = false; - bool is_up = false; - bool is_motion = false; - - switch (msg.message) { - case WM_NCPOINTERDOWN: // pen pushed over window decoration, don't care - case WM_NCPOINTERUP: // pen released over window decoration, don't care - case WM_NCPOINTERUPDATE: // pen moved over decoration, don't care - case WM_POINTERACTIVATE: // shall the pointer activate an inactive window? - return -1; // let the system handle this forwarding this to DefWindowProc - - case WM_POINTERENTER: // pointer moved into window area from top or sides - is_proximity = true; - break; - case WM_POINTERLEAVE: // left window area to top or sides - is_proximity = true; - break; - - - case WM_POINTERDOWN: - is_down = true; - break; - case WM_POINTERUP: - is_up = true; - break; - case WM_POINTERUPDATE: - is_motion = true; - break; - - case WM_POINTERCAPTURECHANGED: - case WM_TOUCHHITTESTING: - case WM_POINTERWHEEL: - case WM_POINTERHWHEEL: - case DM_POINTERHITTEST: - case WM_POINTERROUTEDTO: - case WM_POINTERROUTEDAWAY: - case WM_POINTERROUTEDRELEASED: - default: - // printf("Windows message: msg=0x%04X wParam=0x%08X lParam=0x%08X\n", - // msg.message, (unsigned)msg.wParam, (unsigned)msg.lParam); - return -1; - } - // printf(" msg=0x%04X wParam=0x%08X lParam=0x%08X\n", - // msg.message, (unsigned)msg.wParam, (unsigned)msg.lParam); - - POINTER_PEN_INFO info; - BOOL has_position = GetPointerPenInfo( - GET_POINTERID_WPARAM(msg.wParam), - &info - ); - // if (has_position && info.pointerInfo.ButtonChangeType!=0) { - // printf(" pointerFlags: %08x [", (unsigned)info.pointerInfo.pointerFlags); - // if (info.pointerInfo.pointerFlags & POINTER_FLAG_FIRSTBUTTON) printf(" 1ST"); - // if (info.pointerInfo.pointerFlags & POINTER_FLAG_SECONDBUTTON) printf(" 2ND"); - // if (info.pointerInfo.pointerFlags & POINTER_FLAG_THIRDBUTTON) printf(" 3RD"); - // if (info.pointerInfo.pointerFlags & POINTER_FLAG_FOURTHBUTTON) printf(" 4TH"); - // if (info.pointerInfo.pointerFlags & POINTER_FLAG_FIFTHBUTTON) printf(" 5TH"); - // printf(" ]\n penFlags: %08x [", (unsigned)info.penFlags); - // if (info.penFlags & PEN_FLAG_BARREL) printf(" BARREL"); - // if (info.penFlags & PEN_FLAG_INVERTED) printf(" INVERTED"); - // if (info.penFlags & PEN_FLAG_ERASER) printf(" ERASER"); - // printf(" ]\n penMask: %08x ButtonChangeType: %d\n", - // (unsigned)info.penMask, info.pointerInfo.ButtonChangeType); - // } - - // Event has extended pen data set: - if (has_position) { - // Get the position data. - double s = Fl::screen_driver()->scale(0); - double ex = info.pointerInfo.ptPixelLocation.x/s; - double ey = info.pointerInfo.ptPixelLocation.y/s; - // Go from global coordinates to event window coordinates - Fl_Widget *p = eventWindow; - while (p) { - if (p->as_window()) { - ex -= p->x(); - ey -= p->y(); - } - p = p->parent(); - }; - ev.x = ex; - ev.y = ey; - ev.rx = info.pointerInfo.ptPixelLocation.x/s; - ev.ry = info.pointerInfo.ptPixelLocation.y/s; - if (!is_proximity) { - // Get the extended data. - if (info.penMask & PEN_MASK_PRESSURE) - ev.pressure = info.pressure / 1024.0; - if (info.penMask & PEN_MASK_TILT_X) - ev.tilt_x = -info.tiltX / 90.0; - if (info.penMask & PEN_MASK_TILT_Y) - ev.tilt_y = -info.tiltY / 90.0; - if (info.penMask & PEN_MASK_ROTATION) - ev.twist = info.rotation > 180 ? (info.rotation - 360) : info.rotation; - if (info.pointerInfo.pointerFlags & POINTER_FLAG_INCONTACT) - ev.proximity = 0.0; - else - ev.proximity = 1.0; - } - if (info.penFlags & PEN_FLAG_INVERTED) { - device_type_ = _FL_ERASER; - if (info.pointerInfo.pointerFlags & POINTER_FLAG_INCONTACT) - ev.state = State::ERASER_DOWN; - else - ev.state = State::ERASER_HOVERS; - } else { - device_type_ = _FL_PEN; - if (info.pointerInfo.pointerFlags & POINTER_FLAG_INCONTACT) - ev.state = State::TIP_DOWN; - else - ev.state = State::TIP_HOVERS; - } - // Add pen barrel button states - // Note: POINTER_FLAG_FIRSTBUTTON is the pen tip - // PEN_FLAG_BARREL and POINTER_FLAG_SECONDBUTTON both indicate the primary barrel button - if ((info.penFlags & PEN_FLAG_BARREL) || (info.pointerInfo.pointerFlags & POINTER_FLAG_SECONDBUTTON)) - ev.state |= State::BUTTON0; - // Note: the following code does not work very well with the Wayland driver - // More research is needed to find out how to get these button states reliably. - if (info.pointerInfo.pointerFlags & POINTER_FLAG_THIRDBUTTON) ev.state |= State::BUTTON1; - if (info.pointerInfo.pointerFlags & POINTER_FLAG_FOURTHBUTTON) ev.state |= State::BUTTON2; - if (info.pointerInfo.pointerFlags & POINTER_FLAG_FIFTHBUTTON) ev.state |= State::BUTTON3; - } - // printf(" %08x\n", (unsigned)ev.state); - if (is_proximity) { - ev.pen_id = GET_POINTERID_WPARAM(msg.wParam); - } - if ((msg.message == WM_POINTERENTER) || (msg.message == WM_POINTERLEAVE)) { - if (msg.message == WM_POINTERENTER) { - // Check if this is the first time we see this pen, or if the pen changed - if (current_pen_id_ != ev.pen_id) { - current_pen_id_ = ev.pen_id; - auto it = trait_list_.find(current_pen_id_); - if (it == trait_list_.end()) { // not found, create a new entry - trait_list_[current_pen_id_] = Trait::DRIVER_AVAILABLE; - trait_countdown_ = 5; - pen_send_all(Fl::Pen::DETECTED, State::NONE); - // printf("IN RANGE, NEW PEN\n"); - } else { - pen_send_all(Fl::Pen::CHANGED, State::NONE); - // printf("IN RANGE, CHANGED PEN\n"); - } - trait_list_[0] = trait_list_[current_pen_id_]; // set current pen traits - } else { - pen_send_all(Fl::Pen::IN_RANGE, State::NONE); - // printf("IN RANGE\n"); - } - } else { - pen_send_all(Fl::Pen::OUT_OF_RANGE, State::NONE); - // printf("OUT OF RANGE\n"); - } - } - - Fl_Widget *receiver = nullptr; - bool pushed = false; - bool event_data_copied = false; - - if (has_position) { - if (trait_countdown_) { - trait_countdown_--; - if (ev.tilt_x != 0.0) current_pen_trait_ |= Trait::TILT_X; - if (ev.tilt_y != 0.0) current_pen_trait_ |= Trait::TILT_Y; - if (ev.pressure != 1.0) current_pen_trait_ |= Trait::PRESSURE; - if (ev.barrel_pressure != 0.0) current_pen_trait_ |= Trait::BARREL_PRESSURE; - if (ev.pen_id != 0) current_pen_trait_ |= Trait::PEN_ID; - if (ev.twist != 0.0) current_pen_trait_ |= Trait::TWIST; - //if (ev.proximity != 0) current_pen_trait_ |= Trait::PROXIMITY; - trait_list_[current_pen_id_] = current_pen_trait_; - } - fl_xmousewin = eventWindow; - if (pushed_ && pushed_->widget() && (Fl::pushed() == pushed_->widget())) { - receiver = pushed_->widget(); - if (Fl::grab() && (Fl::grab() != receiver->top_window())) - return -1; - if (Fl::modal() && (Fl::modal() != receiver->top_window())) - return -1; - pushed = true; - } else { - if (Fl::grab() && (Fl::grab() != eventWindow)) - return -1; - if (Fl::modal() && (Fl::modal() != eventWindow)) - return -1; - auto bpen = below_pen_ ? below_pen_->widget() : nullptr; - auto bmouse = Fl::belowmouse(); - auto bpen_old = bmouse && (bmouse == bpen) ? bpen : nullptr; - auto bpen_now = find_below_pen(eventWindow, ev.x, ev.y); - - if (bpen_now != bpen_old) { - if (bpen_old) { - pen_send(bpen_old, Fl::Pen::LEAVE, State::NONE, event_data_copied); - } - below_pen_ = nullptr; - if (bpen_now) { - State state = (device_type_ == _FL_ERASER) ? State::ERASER_HOVERS : State::TIP_HOVERS; - if (pen_send(bpen_now, Fl::Pen::ENTER, state, event_data_copied)) { - below_pen_ = subscriber_list_[bpen_now]; - Fl::belowmouse(bpen_now); - } - } - } - - receiver = below_pen_ ? below_pen_->widget() : nullptr; - if (!receiver) - return -1; - } - } else { - // Proximity events were handled earlier. - } - - if (!receiver) - return -1; - - if (is_down) { - if (!pushed) { - pushed_ = subscriber_list_[receiver]; - Fl::pushed(receiver); - } - State trigger = button_to_trigger(info.pointerInfo.ButtonChangeType, true); - if (msg.message == WM_POINTERDOWN) { - Fl::e_is_click = 1; - _e_x_down = (int)ev.x; - _e_y_down = (int)ev.y; - - // Implement click counting using Windows system metrics - DWORD current_time = GetMessageTime(); - DWORD double_click_time = GetDoubleClickTime(); - int double_click_dx = GetSystemMetrics(SM_CXDOUBLECLK) / 2; - int double_click_dy = GetSystemMetrics(SM_CYDOUBLECLK) / 2; - - // Check if this is a multi-click: same trigger, within time and distance thresholds - if (trigger == last_click_trigger_ && - (current_time - last_click_time_) < double_click_time && - abs((int)ev.rx - last_click_x_) < double_click_dx && - abs((int)ev.ry - last_click_y_) < double_click_dy) { - Fl::e_clicks++; - } else { - Fl::e_clicks = 0; - } - - last_click_time_ = current_time; - last_click_x_ = (int)ev.rx; - last_click_y_ = (int)ev.ry; - last_click_trigger_ = trigger; - - pen_send(receiver, Fl::Pen::TOUCH, trigger, event_data_copied); - } else { - pen_send(receiver, Fl::Pen::BUTTON_PUSH, trigger, event_data_copied); - } - } else if (is_up) { - if ( (ev.state & State::ANY_DOWN) == State::NONE ) { - Fl::pushed(nullptr); - pushed_ = nullptr; - } - State trigger = button_to_trigger(info.pointerInfo.ButtonChangeType, true); - if (info.pointerInfo.ButtonChangeType == 0) - pen_send(receiver, Fl::Pen::LIFT, trigger, event_data_copied); - else - pen_send(receiver, Fl::Pen::BUTTON_RELEASE, trigger, event_data_copied); - } else if (is_motion) { - if ( Fl::e_is_click && - ( (fabs((int)ev.x - _e_x_down) > 5) || - (fabs((int)ev.y - _e_y_down) > 5) ) ) - Fl::e_is_click = 0; - if (pushed) { - pen_send(receiver, Fl::Pen::DRAW, State::NONE, event_data_copied); - } else { - pen_send(receiver, Fl::Pen::HOVER, State::NONE, event_data_copied); - } - } - // Always return 0 because at this point, we capture pen events and don't - // want mouse events anymore! - return 0; -} diff --git a/src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx deleted file mode 100644 index 4b74c76cb..000000000 --- a/src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx +++ /dev/null @@ -1,518 +0,0 @@ -// -// Printing support for Windows for the Fast Light Tool Kit (FLTK). -// -// Copyright 2010-2024 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 -// - -#include "../GDI/Fl_GDI_Graphics_Driver.H" -#include -#include -#include -#include -#include -#include -#include -#include // for fl_win32_xid() -#include // fl_strdup() -#include -#include // DocumentProperties(), OpenPrinter(), ClosePrinter() - -extern HWND fl_window; - -/** Support for printing on the Windows platform */ -class Fl_WinAPI_Printer_Driver : public Fl_Paged_Device { - friend class Fl_Printer; -protected: - int abortPrint; - PRINTDLG pd; - HDC hPr; - int prerr; - int left_margin; - int top_margin; - void absolute_printable_rect(int *x, int *y, int *w, int *h); - Fl_WinAPI_Printer_Driver(void); - int begin_job(int pagecount = 0, int *frompage = NULL, int *topage = NULL, char **perr_message = NULL) FL_OVERRIDE; - int begin_page (void) FL_OVERRIDE; - int printable_rect(int *w, int *h) FL_OVERRIDE; - void margins(int *left, int *top, int *right, int *bottom) FL_OVERRIDE; - void origin(int *x, int *y) FL_OVERRIDE; - void origin(int x, int y) FL_OVERRIDE; - void scale (float scale_x, float scale_y = 0.) FL_OVERRIDE; - void rotate(float angle) FL_OVERRIDE; - void translate(int x, int y) FL_OVERRIDE; - void untranslate(void) FL_OVERRIDE; - int end_page (void) FL_OVERRIDE; - void end_job (void) FL_OVERRIDE; - ~Fl_WinAPI_Printer_Driver(void); -}; - -Fl_WinAPI_Printer_Driver::Fl_WinAPI_Printer_Driver(void) : Fl_Paged_Device() { - hPr = NULL; - driver(new Fl_GDI_Printer_Graphics_Driver); -} - -Fl_Paged_Device* Fl_Printer::newPrinterDriver(void) -{ - return new Fl_WinAPI_Printer_Driver(); -} - - -Fl_WinAPI_Printer_Driver::~Fl_WinAPI_Printer_Driver(void) { - if (hPr) end_job(); - delete driver(); -} - -static void WIN_SetupPrinterDeviceContext(HDC prHDC) -{ - if ( !prHDC ) return; - - fl_window = 0; - SetGraphicsMode(prHDC, GM_ADVANCED); // to allow for rotations - SetMapMode(prHDC, MM_ANISOTROPIC); - SetTextAlign(prHDC, TA_BASELINE|TA_LEFT); - SetBkMode(prHDC, TRANSPARENT); - // this matches 720 logical units to the number of device units in 10 inches of paper - // thus the logical unit is the point (= 1/72 inch) - SetWindowExtEx(prHDC, 720, 720, NULL); - SetViewportExtEx(prHDC, 10*GetDeviceCaps(prHDC, LOGPIXELSX), 10*GetDeviceCaps(prHDC, LOGPIXELSY), NULL); -} - - -class Fl_PDF_GDI_File_Surface : public Fl_WinAPI_Printer_Driver -{ -private: - static LPSTR pdf_printer_name_; -public: - char *doc_fname; - Fl_PDF_GDI_File_Surface(); - ~Fl_PDF_GDI_File_Surface() { if (doc_fname) free(doc_fname); } - int begin_job(const char *defaultname, - char **perr_message = NULL); - int begin_job(int, int*, int *, char **) FL_OVERRIDE {return 1;} // don't use - int begin_document(const char* outname, - enum Fl_Paged_Device::Page_Format format, - enum Fl_Paged_Device::Page_Layout layout, - char **perr_message); - void end_job() FL_OVERRIDE; -}; - -LPSTR Fl_PDF_GDI_File_Surface::pdf_printer_name_ = _strdup("Microsoft Print to PDF"); - -Fl_PDF_GDI_File_Surface::Fl_PDF_GDI_File_Surface() { - driver(new Fl_GDI_Graphics_Driver()); - doc_fname = NULL; -} - -Fl_Paged_Device *Fl_PDF_File_Surface::new_platform_pdf_surface_(const char ***pfname) { - Fl_PDF_GDI_File_Surface *surf = new Fl_PDF_GDI_File_Surface(); - *pfname = (const char**)&surf->doc_fname; - return surf; -} - -int Fl_PDF_File_Surface::begin_job(const char* defaultfilename, - char **perr_message) { - return ((Fl_PDF_GDI_File_Surface*)platform_surface_)->begin_job(defaultfilename, perr_message); -} - -int Fl_PDF_File_Surface::begin_document(const char* defaultfilename, - enum Fl_Paged_Device::Page_Format format, - enum Fl_Paged_Device::Page_Layout layout, - char **perr_message) { - return ((Fl_PDF_GDI_File_Surface*)platform_surface_)->begin_document(defaultfilename, format, layout, perr_message); -} - - -int Fl_PDF_GDI_File_Surface::begin_job(const char *defaultfname, char **perr_message) { - int err = 0; - abortPrint = FALSE; - - HANDLE hPr2; - err = OpenPrinterA(pdf_printer_name_, &hPr2, NULL); - if (err == 0) { - if (perr_message) { - int l = 240; - *perr_message = new char[l]; - snprintf(*perr_message, l, - "Class Fl_PDF_File_Surface requires printer '%s' available in Windows 10+.", - pdf_printer_name_); - } - return 1; - } - HWND hwndOwner = fl_win32_xid(Fl::first_window()); - LONG count = DocumentPropertiesA(hwndOwner, hPr2, pdf_printer_name_, NULL, NULL, 0); - if (count <= 0) { ClosePrinter(hPr2); return 1; } - char *buffer = new char[count]; - DEVMODEA *pDevMode = (DEVMODEA*)buffer; - memset(buffer, 0, count); - pDevMode->dmSize = (WORD)count; - count = DocumentPropertiesA(hwndOwner, hPr2, pdf_printer_name_, pDevMode, NULL, DM_OUT_BUFFER | DM_IN_PROMPT); - ClosePrinter(hPr2); - if (count == IDCANCEL || count < 0) { delete[] buffer; return 1; } - - Fl_Native_File_Chooser fnfc; - fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); - fnfc.filter("PDF\t*.pdf\n"); - if (defaultfname && strlen(defaultfname) > 0) fnfc.preset_file(defaultfname); - fnfc.options(Fl_Native_File_Chooser::SAVEAS_CONFIRM); - if (fnfc.show() == 0) this->hPr = CreateDCA(NULL, pdf_printer_name_, NULL, pDevMode); - delete[] buffer; - if (!this->hPr) return 1; - DOCINFOW di; - wchar_t docName [256]; - wchar_t outName [256]; - fl_utf8towc("FLTK", 4, docName, 256); - fl_utf8towc(fnfc.filename(), (unsigned int)strlen(fnfc.filename()), outName, 256); - memset(&di, 0, sizeof(DOCINFOW)); - di.cbSize = sizeof(DOCINFOW); - di.lpszDocName = (LPCWSTR)docName; - di.lpszOutput = (LPCWSTR)outName; - err = StartDocW(this->hPr, &di); - if (err <= 0) { - DWORD dw = GetLastError(); - DeleteDC(this->hPr); - this->hPr = NULL; - if (dw != ERROR_CANCELLED) { - if (perr_message) { - int l = 40; - *perr_message = new char[l]; - snprintf(*perr_message, l, "Error %lu in StartDoc() call", dw); - } - return 2; - } - return 1; - } - x_offset = 0; - y_offset = 0; - WIN_SetupPrinterDeviceContext(this->hPr); - driver()->gc(this->hPr); - doc_fname = fl_strdup(fnfc.filename()); - return 0; -} - - -int Fl_PDF_GDI_File_Surface::begin_document(const char* outfname, - enum Fl_Paged_Device::Page_Format format, - enum Fl_Paged_Device::Page_Layout layout, - char **perr_message) { - int err = 0; - abortPrint = FALSE; - - DEVMODEA inDevMode; - memset(&inDevMode, 0, sizeof(DEVMODEA)); inDevMode.dmSize = sizeof(DEVMODEA); - inDevMode.dmOrientation = (layout == PORTRAIT ? DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE); - inDevMode.dmPaperSize = (format == A4 ? DMPAPER_A4 : DMPAPER_LETTER); - inDevMode.dmFields = DM_ORIENTATION | DM_PAPERSIZE ; - - this->hPr = CreateDCA(NULL, pdf_printer_name_, NULL, &inDevMode); - if (!this->hPr) { - if (perr_message) { - int l = 150; - *perr_message = new char[l]; - snprintf(*perr_message, l, "Class Fl_PDF_File_Surface requires printer '%s'.", - pdf_printer_name_); - } - return 2; - } - DOCINFOW di; - wchar_t docName[256]; - wchar_t outName[256]; - fl_utf8towc("FLTK", 4, docName, 256); - memset(&di, 0, sizeof(DOCINFOW)); - di.cbSize = sizeof(DOCINFOW); - di.lpszDocName = (LPCWSTR)docName; - di.lpszOutput = (LPCWSTR)outName; - fl_utf8towc(outfname, (unsigned int)strlen(outfname), outName, 256); - err = StartDocW(hPr, &di); - if (err <= 0) { - DWORD dw = GetLastError(); - DeleteDC(this->hPr); - this->hPr = NULL; - if (perr_message) { - int l = 50; - *perr_message = new char[l]; - snprintf(*perr_message, l, "Error %lu in StartDoc() call", dw); - } - return 2; - } - x_offset = 0; - y_offset = 0; - WIN_SetupPrinterDeviceContext(this->hPr); - driver()->gc(this->hPr); - doc_fname = fl_strdup(outfname); - return 0; -} - - -int Fl_WinAPI_Printer_Driver::begin_job (int pagecount, int *frompage, int *topage, char **perr_message) -// returns 0 iff OK -{ - if (pagecount == 0) pagecount = 10000; - DOCINFO di; - char docName [256]; - int err = 0; - - abortPrint = FALSE; - memset (&pd, 0, sizeof (PRINTDLG)); - pd.lStructSize = sizeof (PRINTDLG); - pd.hwndOwner = GetForegroundWindow(); - pd.Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE | PD_NOSELECTION; - pd.nMinPage = 1; - pd.nMaxPage = pagecount; - BOOL b = PrintDlg (&pd); - if (pd.hwndOwner) { // restore the correct state of mouse buttons and keyboard modifier keys (STR #3221) - WNDPROC windproc = (WNDPROC)GetWindowLongPtrW(pd.hwndOwner, GWLP_WNDPROC); - CallWindowProc(windproc, pd.hwndOwner, WM_ACTIVATEAPP, 1, 0); - } - if (b != 0) { - hPr = pd.hDC; - if (hPr != NULL) { - strcpy (docName, "FLTK"); - memset(&di, 0, sizeof(DOCINFO)); - di.cbSize = sizeof (DOCINFO); - di.lpszDocName = (LPCSTR) docName; - prerr = StartDoc (hPr, &di); - if (prerr < 1) { - abortPrint = TRUE; - DWORD dw = GetLastError(); - err = (dw == ERROR_CANCELLED ? 1 : 2); - if (perr_message && err == 2) { - wchar_t *lpMsgBuf; - DWORD retval = FormatMessageW( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - dw, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPWSTR) &lpMsgBuf, - 0, NULL); - if (retval) { - unsigned srclen = lstrlenW(lpMsgBuf); - while (srclen > 0 && (lpMsgBuf[srclen-1] == '\n' || lpMsgBuf[srclen-1] == '\r')) srclen--; - unsigned l = fl_utf8fromwc(NULL, 0, lpMsgBuf, srclen); - *perr_message = new char[l+51]; - snprintf(*perr_message, l+51, "begin_job() failed with error %lu: ", dw); - fl_utf8fromwc(*perr_message + strlen(*perr_message), l+1, lpMsgBuf, srclen); - LocalFree(lpMsgBuf); - } - } - } - } - } else { - err = 1; - } - if(!err) { - if((pd.Flags & PD_PAGENUMS) != 0 ) { - if (frompage) *frompage = pd.nFromPage; - if (topage) *topage = pd.nToPage; - } - else { - if (frompage) *frompage = 1; - if (topage) *topage = pagecount; - } - x_offset = 0; - y_offset = 0; - WIN_SetupPrinterDeviceContext (hPr); - driver()->gc(hPr); - } - return err; -} - -void Fl_PDF_GDI_File_Surface::end_job(void) -{ - if (hPr != NULL) { - if (! abortPrint) { - if (EndDoc (hPr) <= 0) { - fl_message ("Error in EndDoc() call"); - } - DeleteDC (hPr); - } - hPr = NULL; - } -} - -void Fl_WinAPI_Printer_Driver::end_job (void) -{ - if (hPr != NULL) { - if (! abortPrint) { - prerr = EndDoc (hPr); - if (prerr < 0) { - fl_alert ("EndDoc error %d", prerr); - } - } - DeleteDC (hPr); - if (pd.hDevMode != NULL) { - GlobalFree (pd.hDevMode); - } - if (pd.hDevNames != NULL) { - GlobalFree (pd.hDevNames); - } - } - hPr = NULL; -} - -void Fl_WinAPI_Printer_Driver::absolute_printable_rect(int *x, int *y, int *w, int *h) -{ - POINT physPageSize; - POINT pixelsPerInch; - XFORM transform; - - if (hPr == NULL) return; - HDC gc = (HDC)driver()->gc(); - GetWorldTransform(gc, &transform); - ModifyWorldTransform(gc, NULL, MWT_IDENTITY); - SetWindowOrgEx(gc, 0, 0, NULL); - - physPageSize.x = GetDeviceCaps(hPr, HORZRES); - physPageSize.y = GetDeviceCaps(hPr, VERTRES); - DPtoLP(hPr, &physPageSize, 1); - *w = physPageSize.x + 1; - *h = physPageSize.y + 1; - pixelsPerInch.x = GetDeviceCaps(hPr, LOGPIXELSX); - pixelsPerInch.y = GetDeviceCaps(hPr, LOGPIXELSY); - DPtoLP(hPr, &pixelsPerInch, 1); - left_margin = (pixelsPerInch.x / 4); - *w -= (pixelsPerInch.x / 2); - top_margin = (pixelsPerInch.y / 4); - *h -= (pixelsPerInch.y / 2); - - *x = left_margin; - *y = top_margin; - origin(x_offset, y_offset); - SetWorldTransform(gc, &transform); -} - -void Fl_WinAPI_Printer_Driver::margins(int *left, int *top, int *right, int *bottom) -{ - int x = 0, y = 0, w = 0, h = 0; - absolute_printable_rect(&x, &y, &w, &h); - if (left) *left = x; - if (top) *top = y; - if (right) *right = x; - if (bottom) *bottom = y; -} - -int Fl_WinAPI_Printer_Driver::printable_rect(int *w, int *h) -{ - int x, y; - absolute_printable_rect(&x, &y, w, h); - return 0; -} - -int Fl_WinAPI_Printer_Driver::begin_page (void) -{ - int rsult, w, h; - - rsult = 0; - if (hPr != NULL) { - Fl_Surface_Device::push_current(this); - WIN_SetupPrinterDeviceContext (hPr); - prerr = StartPage (hPr); - if (prerr < 0) { - Fl_Surface_Device::pop_current(); - fl_alert ("StartPage error %d", prerr); - rsult = 1; - } - printable_rect(&w, &h); - origin(0, 0); - fl_clip_region(0); - } - return rsult; -} - -void Fl_WinAPI_Printer_Driver::origin (int deltax, int deltay) -{ - SetWindowOrgEx( (HDC)driver()->gc(), - left_margin - deltax, - top_margin - deltay, NULL); - x_offset = deltax; - y_offset = deltay; -} - -void Fl_WinAPI_Printer_Driver::scale (float scalex, float scaley) -{ - if (scaley == 0.) scaley = scalex; - int w, h; - SetWindowExtEx((HDC)driver()->gc(), (int)(720 / scalex + 0.5), (int)(720 / scaley + 0.5), NULL); - printable_rect(&w, &h); - origin(0, 0); -} - -void Fl_WinAPI_Printer_Driver::rotate (float rot_angle) -{ - XFORM mat; - float angle; - angle = (float) - (rot_angle * M_PI / 180.); - mat.eM11 = (float)cos(angle); - mat.eM12 = (float)sin(angle); - mat.eM21 = - mat.eM12; - mat.eM22 = mat.eM11; - mat.eDx = mat.eDy = 0; - SetWorldTransform((HDC)driver()->gc(), &mat); -} - -int Fl_WinAPI_Printer_Driver::end_page (void) -{ - int rsult; - - rsult = 0; - if (hPr != NULL) { - Fl_Surface_Device::pop_current(); - prerr = EndPage (hPr); - if (prerr < 0) { - abortPrint = TRUE; - fl_alert ("EndPage error %d", prerr); - rsult = 1; - } - else { // make sure rotation is not transferred to next page - ModifyWorldTransform(hPr, NULL, MWT_IDENTITY); - } - } - return rsult; -} - -static int translate_stack_depth = 0; -const int translate_stack_max = 5; -static int translate_stack_x[translate_stack_max]; -static int translate_stack_y[translate_stack_max]; - -static void do_translate(int x, int y, HDC gc) -{ - XFORM tr; - tr.eM11 = tr.eM22 = 1; - tr.eM12 = tr.eM21 = 0; - tr.eDx = (FLOAT) x; - tr.eDy = (FLOAT) y; - ModifyWorldTransform(gc, &tr, MWT_LEFTMULTIPLY); -} - -void Fl_WinAPI_Printer_Driver::translate (int x, int y) -{ - do_translate(x, y, (HDC)driver()->gc()); - if (translate_stack_depth < translate_stack_max) { - translate_stack_x[translate_stack_depth] = x; - translate_stack_y[translate_stack_depth] = y; - translate_stack_depth++; - } -} - -void Fl_WinAPI_Printer_Driver::untranslate (void) -{ - if (translate_stack_depth > 0) { - translate_stack_depth--; - do_translate( - translate_stack_x[translate_stack_depth], - translate_stack_y[translate_stack_depth], (HDC)driver()->gc() ); - } -} - -void Fl_WinAPI_Printer_Driver::origin(int *x, int *y) -{ - Fl_Paged_Device::origin(x, y); -} - - diff --git a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H deleted file mode 100644 index b038fc5f1..000000000 --- a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H +++ /dev/null @@ -1,104 +0,0 @@ -// -// Windows screen interface for the Fast Light Tool Kit (FLTK). -// -// Copyright 2010-2022 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 -// - -/** - \file Fl_WinAPI_Screen_Driver.H - \brief Definition of Windows screen interface. - */ - -#ifndef FL_WINAPI_SCREEN_DRIVER_H -#define FL_WINAPI_SCREEN_DRIVER_H - -#include "../../Fl_Screen_Driver.H" -#include - -class Fl_Window; - - -class Fl_WinAPI_Screen_Driver : public Fl_Screen_Driver -{ -protected: - RECT screens[MAX_SCREENS]; - RECT work_area[MAX_SCREENS]; - float scale_of_screen[MAX_SCREENS]; - - static BOOL CALLBACK screen_cb(HMONITOR mon, HDC, LPRECT r, LPARAM); - BOOL screen_cb(HMONITOR mon, HDC, LPRECT r); - int get_mouse_unscaled(int &mx, int &my); - -public: - float dpi[MAX_SCREENS][2]; - enum APP_SCALING_CAPABILITY scaling_capability; - void update_scaling_capability(); - Fl_WinAPI_Screen_Driver(); - // --- display management - int visual(int flags) FL_OVERRIDE; - // --- screen configuration - void init() FL_OVERRIDE; - int x() FL_OVERRIDE; - int y() FL_OVERRIDE; - int w() FL_OVERRIDE; - int h() FL_OVERRIDE; - void screen_xywh(int &X, int &Y, int &W, int &H, int n) FL_OVERRIDE; - void screen_xywh_unscaled(int &X, int &Y, int &W, int &H, int n); - void screen_dpi(float &h, float &v, int n=0) FL_OVERRIDE; - int screen_num_unscaled(int x, int y); - void screen_work_area(int &X, int &Y, int &W, int &H, int n) FL_OVERRIDE; - // --- audible output - void beep(int type) FL_OVERRIDE; - // --- global events - void flush() FL_OVERRIDE; - void grab(Fl_Window* win) FL_OVERRIDE; - // --- global colors - void get_system_colors() FL_OVERRIDE; - int dnd(int unused) FL_OVERRIDE; - int compose(int &del) FL_OVERRIDE; - Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win, bool may_capture_subwins, bool *did_capture_subwins) FL_OVERRIDE; - Fl_RGB_Image *read_win_rectangle_unscaled(int X, int Y, int w, int h, Fl_Window *win); - int get_mouse(int &x, int &y) FL_OVERRIDE; - void enable_im() FL_OVERRIDE; - void disable_im() FL_OVERRIDE; - void open_display_platform() FL_OVERRIDE; - void offscreen_size(Fl_Offscreen off, int &width, int &height) FL_OVERRIDE; - APP_SCALING_CAPABILITY rescalable() FL_OVERRIDE { - return scaling_capability; - } - float scale(int n) FL_OVERRIDE { - return scale_of_screen[n]; - } - void scale(int n, float f) FL_OVERRIDE { - scale_of_screen[n] = f; - } - void desktop_scale_factor() FL_OVERRIDE; - void default_icons(const Fl_RGB_Image *icons[], int count) FL_OVERRIDE; - // this one is implemented in Fl_win32.cxx - void copy(const char *stuff, int len, int clipboard, const char *type) FL_OVERRIDE; - // this one is implemented in Fl_win32.cxx - void paste(Fl_Widget &receiver, int clipboard, const char *type) FL_OVERRIDE; - // this one is implemented in Fl_win32.cxx - int clipboard_contains(const char *type) FL_OVERRIDE; - // this one is implemented in Fl_win32.cxx - void clipboard_notify_change() FL_OVERRIDE; - // this one is implemented in Fl_win32.cxx - void set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win) FL_OVERRIDE; - // these two are implemented in Fl_get_key_win32.cxx - int event_key(int) FL_OVERRIDE; - int get_key(int) FL_OVERRIDE; - float base_scale(int numscreen) FL_OVERRIDE; -}; - - -#endif // FL_WINAPI_SCREEN_DRIVER_H diff --git a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx deleted file mode 100644 index b1ddc9f91..000000000 --- a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx +++ /dev/null @@ -1,493 +0,0 @@ -// -// Windows screen interface for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2022 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 -// - - -#include -#include "Fl_WinAPI_Screen_Driver.H" -#include "../GDI/Fl_Font.H" -#include -#include -#include -#include -#include - - -// these are set by Fl::args() and override any system colors: from Fl_get_system_colors.cxx -extern const char *fl_fg; -extern const char *fl_bg; -extern const char *fl_bg2; -// end of extern additions workaround - - -#if !defined(HMONITOR_DECLARED) && (_WIN32_WINNT < 0x0500) -# define COMPILE_MULTIMON_STUBS -# include -#endif // !HMONITOR_DECLARED && _WIN32_WINNT < 0x0500 - -static Fl_Text_Editor::Key_Binding extra_bindings[] = { - // Define Windows specific accelerators... - { 'y', FL_CTRL, Fl_Text_Editor::kf_redo ,0}, - { 0, 0, 0 ,0} -}; - - -Fl_WinAPI_Screen_Driver::Fl_WinAPI_Screen_Driver() : Fl_Screen_Driver() { - text_editor_extra_key_bindings = extra_bindings; - for (int i = 0; i < MAX_SCREENS; i++) scale_of_screen[i] = 1; - scaling_capability = SYSTEMWIDE_APP_SCALING; -} - -int Fl_WinAPI_Screen_Driver::visual(int flags) -{ - fl_GetDC(0); - if (flags & FL_DOUBLE) return 0; - HDC gc = (HDC)Fl_Graphics_Driver::default_driver().gc(); - if (!(flags & FL_INDEX) && - GetDeviceCaps(gc,BITSPIXEL) <= 8) return 0; - if ((flags & FL_RGB8) && GetDeviceCaps(gc,BITSPIXEL)<24) return 0; - return 1; -} - - -// We go the much more difficult route of individually picking some multi-screen -// functions from the USER32.DLL . If these functions are not available, we -// will gracefully fall back to single monitor support. -// -// If we were to insist on the existence of "EnumDisplayMonitors" and -// "GetMonitorInfoA", it would be impossible to use FLTK on Windows 2000 -// before SP2 or earlier. - -// BOOL EnumDisplayMonitors(HDC, LPCRECT, MONITORENUMPROC, LPARAM) -typedef BOOL(WINAPI* fl_edm_func)(HDC, LPCRECT, MONITORENUMPROC, LPARAM); -// BOOL GetMonitorInfo(HMONITOR, LPMONITORINFO) -typedef BOOL(WINAPI* fl_gmi_func)(HMONITOR, LPMONITORINFO); - -static fl_gmi_func fl_gmi = NULL; // used to get a proc pointer for GetMonitorInfoA - - -BOOL Fl_WinAPI_Screen_Driver::screen_cb(HMONITOR mon, HDC hdc, LPRECT r, LPARAM d) -{ - Fl_WinAPI_Screen_Driver *drv = (Fl_WinAPI_Screen_Driver*)d; - return drv->screen_cb(mon, hdc, r); -} - - -BOOL Fl_WinAPI_Screen_Driver::screen_cb(HMONITOR mon, HDC, LPRECT r) -{ - if (num_screens >= MAX_SCREENS) return TRUE; - - MONITORINFOEX mi; - mi.cbSize = sizeof(mi); - - // GetMonitorInfo(mon, &mi); - // (but we use our self-acquired function pointer instead) - if (fl_gmi(mon, &mi)) { - screens[num_screens] = mi.rcMonitor; - // If we also want to record the work area, we would also store mi.rcWork at this point - work_area[num_screens] = mi.rcWork; - num_screens++; - } - return TRUE; -} - - -void Fl_WinAPI_Screen_Driver::init() -{ - open_display(); - // Since not all versions of Windows include multiple monitor support, - // we do a run-time check for the required functions... - HMODULE hMod = GetModuleHandle("USER32.DLL"); - - if (hMod) { - // check that EnumDisplayMonitors is available - fl_edm_func fl_edm = (fl_edm_func)GetProcAddress(hMod, "EnumDisplayMonitors"); - - if (fl_edm) { - // we have EnumDisplayMonitors - do we also have GetMonitorInfoA ? - fl_gmi = (fl_gmi_func)GetProcAddress(hMod, "GetMonitorInfoA"); - if (fl_gmi) { - // We have GetMonitorInfoA, enumerate all the screens... - // EnumDisplayMonitors(0,0,screen_cb,0); - // (but we use our self-acquired function pointer instead) - // NOTE: num_screens is incremented in screen_cb so we must first reset it here... - num_screens = 0; - fl_edm(0, 0, screen_cb, (LPARAM)this); - return; - } - } - } - - // If we get here, assume we have 1 monitor... - num_screens = 1; - screens[0].top = 0; - screens[0].left = 0; - screens[0].right = GetSystemMetrics(SM_CXSCREEN); - screens[0].bottom = GetSystemMetrics(SM_CYSCREEN); - work_area[0] = screens[0]; -} - - -void Fl_WinAPI_Screen_Driver::screen_work_area(int &X, int &Y, int &W, int &H, int n) -{ - if (num_screens < 0) init(); - if (n < 0 || n >= num_screens) n = 0; - X = int(work_area[n].left/scale_of_screen[n]); - Y = int(work_area[n].top/scale_of_screen[n]); - W = int((work_area[n].right - work_area[n].left)/scale_of_screen[n]); - H = int((work_area[n].bottom - work_area[n].top)/scale_of_screen[n]); -} - - -void Fl_WinAPI_Screen_Driver::screen_xywh(int &X, int &Y, int &W, int &H, int n) -{ - if (num_screens < 0) init(); - - if ((n < 0) || (n >= num_screens)) - n = 0; - - if (num_screens > 0) { - X = int(screens[n].left/scale_of_screen[n]); - Y = int(screens[n].top/scale_of_screen[n]); - W = int((screens[n].right - screens[n].left)/scale_of_screen[n]); - H = int((screens[n].bottom - screens[n].top)/scale_of_screen[n]); - } else { - /* Fallback if something is broken... */ - X = 0; - Y = 0; - W = GetSystemMetrics(SM_CXSCREEN); - H = GetSystemMetrics(SM_CYSCREEN); - } -} - - -void Fl_WinAPI_Screen_Driver::screen_xywh_unscaled(int &X, int &Y, int &W, int &H, int n) { - if (num_screens < 0) init(); - if ((n < 0) || (n >= num_screens)) n = 0; - X = screens[n].left; - Y = screens[n].top; - W = screens[n].right - screens[n].left; - H = screens[n].bottom - screens[n].top; -}; - - -void Fl_WinAPI_Screen_Driver::screen_dpi(float &h, float &v, int n) -{ - if (num_screens < 0) init(); - h = v = 0.0f; - if (n >= 0 && n < num_screens) { - h = float(dpi[n][0]); - v = float(dpi[n][1]); - } -} - - -int Fl_WinAPI_Screen_Driver::x() -{ - /*RECT r; - - SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); - return r.left;*/ - int X, Y, W, H; - screen_work_area(X, Y, W, H, 0); - return X; -} - - -int Fl_WinAPI_Screen_Driver::y() -{ - /*RECT r; - - SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); - return r.top;*/ - int X, Y, W, H; - screen_work_area(X, Y, W, H, 0); - return Y; -} - - -int Fl_WinAPI_Screen_Driver::h() -{ - /*RECT r; - - SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); - return r.bottom - r.top;*/ - int X, Y, W, H; - screen_work_area(X, Y, W, H, 0); - return H; -} - - -int Fl_WinAPI_Screen_Driver::w() -{ - /*RECT r; - - SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); - return r.right - r.left;*/ - int X, Y, W, H; - screen_work_area(X, Y, W, H, 0); - return W; -} - - -// Implements fl_beep(). See documentation in src/fl_ask.cxx. -void Fl_WinAPI_Screen_Driver::beep(int type) -{ - switch (type) { - case FL_BEEP_QUESTION : - case FL_BEEP_PASSWORD : - MessageBeep(MB_ICONQUESTION); - break; - case FL_BEEP_MESSAGE : - MessageBeep(MB_ICONASTERISK); - break; - case FL_BEEP_NOTIFICATION : - MessageBeep(MB_ICONASTERISK); - break; - case FL_BEEP_ERROR : - MessageBeep(MB_ICONERROR); - break; - default : - MessageBeep(0xFFFFFFFF); - break; - } -} - - -void Fl_WinAPI_Screen_Driver::flush() -{ - GdiFlush(); -} - - -extern void fl_fix_focus(); // in Fl.cxx - -// We have to keep track of whether we have captured the mouse, since -// Windows shows little respect for this... Grep for fl_capture to -// see where and how this is used. -extern HWND fl_capture; - - -void Fl_WinAPI_Screen_Driver::grab(Fl_Window* win) -{ - if (win) { - if (!Fl::grab_) { - SetActiveWindow(fl_capture = fl_xid(Fl::first_window())); - SetCapture(fl_capture); - } - Fl::grab_ = win; - } else { - if (Fl::grab_) { - fl_capture = 0; - ReleaseCapture(); - Fl::grab_ = 0; - fl_fix_focus(); - } - } -} - - -static void set_selection_color(uchar r, uchar g, uchar b) -{ - Fl::set_color(FL_SELECTION_COLOR,r,g,b); -} - - -static void getsyscolor(int what, const char* arg, void (*func)(uchar,uchar,uchar)) -{ - if (arg) { - uchar r,g,b; - if (!fl_parse_color(arg, r,g,b)) - Fl::error("Unknown color: %s", arg); - else - func(r,g,b); - } else { - DWORD x = GetSysColor(what); - func(uchar(x&255), uchar(x>>8), uchar(x>>16)); - } -} - - -void Fl_WinAPI_Screen_Driver::get_system_colors() -{ - if (!bg2_set) getsyscolor(COLOR_WINDOW, fl_bg2,Fl::background2); - if (!fg_set) getsyscolor(COLOR_WINDOWTEXT, fl_fg, Fl::foreground); - if (!bg_set) getsyscolor(COLOR_BTNFACE, fl_bg, Fl::background); - getsyscolor(COLOR_HIGHLIGHT, 0, set_selection_color); -} - - -int Fl_WinAPI_Screen_Driver::compose(int &del) { - unsigned char ascii = (unsigned char)Fl::e_text[0]; - /* WARNING: The [AltGr] key on international keyboards sets FL_CTRL. - 2nd line in condition below asks [AltGr] key (a.k.a. VK_RMENU) not to be down. - */ - int condition = (Fl::e_state & (FL_ALT | FL_META | FL_CTRL)) && !(ascii & 128) && - !( (Fl::e_state & FL_CTRL) && (GetAsyncKeyState(VK_RMENU) >> 15) ); - if (condition) { // this stuff is to be treated as a function key - del = 0; - return 0; - } - del = Fl::compose_state; - Fl::compose_state = 0; - // Only insert non-control characters: - if ( (!Fl::compose_state) && ! (ascii & ~31 && ascii!=127)) { - return 0; - } - return 1; -} - - -Fl_RGB_Image * // O - image or NULL if failed -Fl_WinAPI_Screen_Driver::read_win_rectangle( - int X, // I - Left position - int Y, // I - Top position - int w, // I - Width of area to read - int h, // I - Height of area to read - Fl_Window *win, // I - window to capture from or NULL to capture from current offscreen - bool may_capture_subwins, bool *did_capture_subwins) -{ - float s = Fl_Surface_Device::surface()->driver()->scale(); - int ws, hs; - if (int(s) == s) { ws = w * int(s); hs = h * int(s);} - else { - ws = Fl_Scalable_Graphics_Driver::floor(X+w, s) - Fl_Scalable_Graphics_Driver::floor(X, s), - hs = Fl_Scalable_Graphics_Driver::floor(Y+h, s) - Fl_Scalable_Graphics_Driver::floor(Y, s); - if (ws < 1) ws = 1; - if (hs < 1) hs = 1; - } - return read_win_rectangle_unscaled(Fl_Scalable_Graphics_Driver::floor(X, s), Fl_Scalable_Graphics_Driver::floor(Y, s), ws, hs, win); -} - -Fl_RGB_Image *Fl_WinAPI_Screen_Driver::read_win_rectangle_unscaled(int X, int Y, int w, int h, Fl_Window *win) -{ - // Depth of image is always 3 here - - // Grab all of the pixels in the image... - - // Assure that we are not trying to read non-existing data. If it is so, the - // function should still work, but the out-of-bounds part of the image is - // untouched (initialized with the alpha value or 0 (black), resp.). - - int ww = w; // We need the original width for output data line size - - int shift_x = 0; // X target shift if X modified - int shift_y = 0; // Y target shift if X modified - - if (X < 0) { - shift_x = -X; - w += X; - X = 0; - } - if (Y < 0) { - shift_y = -Y; - h += Y; - Y = 0; - } - - if (h < 1 || w < 1) return 0; // nothing to copy - - // Allocate and initialize the image data array - size_t arraySize = ((size_t)w * h) * 3; - uchar *p = new uchar[arraySize]; - memset(p, 0, arraySize); - - int line_size = ((3*w+3)/4) * 4; // each line is aligned on a DWORD (4 bytes) - uchar *dib = new uchar[line_size*h]; // create temporary buffer to read DIB - - // fill in bitmap info for GetDIBits - - BITMAPINFO bi; - bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bi.bmiHeader.biWidth = w; - bi.bmiHeader.biHeight = -h; // negative => top-down DIB - bi.bmiHeader.biPlanes = 1; - bi.bmiHeader.biBitCount = 24; // 24 bits RGB - bi.bmiHeader.biCompression = BI_RGB; - bi.bmiHeader.biSizeImage = 0; - bi.bmiHeader.biXPelsPerMeter = 0; - bi.bmiHeader.biYPelsPerMeter = 0; - bi.bmiHeader.biClrUsed = 0; - bi.bmiHeader.biClrImportant = 0; - - // copy bitmap from original DC (Window, Fl_Offscreen, ...) - if (win && Fl_Window::current() != win) win->make_current(); - HDC gc = (HDC)fl_graphics_driver->gc(); - HDC hdc = CreateCompatibleDC(gc); - HBITMAP hbm = CreateCompatibleBitmap(gc,w,h); - - int save_dc = SaveDC(hdc); // save context for cleanup - SelectObject(hdc,hbm); // select bitmap - BitBlt(hdc,0,0,w,h,gc,X,Y,SRCCOPY); // copy image section to DDB - - // copy RGB image data to the allocated DIB - - GetDIBits(hdc, hbm, 0, h, dib, (BITMAPINFO *)&bi, DIB_RGB_COLORS); - - // finally copy the image data to the user buffer - - for (int j = 0; jalloc_array = 1; - return rgb; -} - - -void Fl_WinAPI_Screen_Driver::offscreen_size(Fl_Offscreen off, int &width, int &height) -{ - BITMAP bitmap; - if ( GetObject((HBITMAP)off, sizeof(BITMAP), &bitmap) ) { - width = bitmap.bmWidth; - height = bitmap.bmHeight; - } -} - -//NOTICE: returns -1 if x,y is not in any screen -int Fl_WinAPI_Screen_Driver::screen_num_unscaled(int x, int y) -{ - int screen = -1; - if (num_screens < 0) init(); - for (int i = 0; i < num_screens; i ++) { - if (x >= screens[i].left && x < screens[i].right && - y >= screens[i].top && y < screens[i].bottom) { - screen = i; - break; - } - } - return screen; -} - - -float Fl_WinAPI_Screen_Driver::base_scale(int numscreen) { - return float(dpi[numscreen][0] / 96.); -} diff --git a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_System_Driver.H deleted file mode 100644 index 016cad9fa..000000000 --- a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.H +++ /dev/null @@ -1,124 +0,0 @@ -// -// Windows system driver for the Fast Light Tool Kit (FLTK). -// -// Copyright 2010-2022 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 -// - -/** - \file Fl_WinAPI_System_Driver.H - \brief Definition of Windows system driver. - */ - -#ifndef FL_WINAPI_SYSTEM_DRIVER_H -#define FL_WINAPI_SYSTEM_DRIVER_H - -#include "../../Fl_System_Driver.H" -#include -#include // strdup - -/* - Move everything here that manages the system interface. - - There is exactly one system driver. - - - filename and pathname management - - directory and file access - - system time and system timer - - multithreading - - string management - */ - -class Fl_WinAPI_System_Driver : public Fl_System_Driver -{ -public: - void warning(const char *format, va_list args) FL_OVERRIDE; - void error(const char *format, va_list args) FL_OVERRIDE; - void fatal(const char *format, va_list args) FL_OVERRIDE; - char *utf2mbcs(const char *s) FL_OVERRIDE; - char *getenv(const char *var) FL_OVERRIDE; - int putenv(const char *var) FL_OVERRIDE; - int open(const char *fnam, int oflags, int pmode) FL_OVERRIDE; - int open_ext(const char *fnam, int binary, int oflags, int pmode) FL_OVERRIDE; - FILE *fopen(const char *fnam, const char *mode) FL_OVERRIDE; - int system(const char *cmd) FL_OVERRIDE; - int execvp(const char *file, char *const *argv) FL_OVERRIDE; - int chmod(const char *fnam, int mode) FL_OVERRIDE; - int access(const char *fnam, int mode) FL_OVERRIDE; - int flstat(const char *fnam, struct stat *b) FL_OVERRIDE; - char *getcwd(char *b, int l) FL_OVERRIDE; - int chdir(const char *path) FL_OVERRIDE; - int unlink(const char *fnam) FL_OVERRIDE; - int mkdir(const char *fnam, int mode) FL_OVERRIDE; - int rmdir(const char *fnam) FL_OVERRIDE; - int rename(const char *fnam, const char *newnam) FL_OVERRIDE; - // Windows commandline argument conversion to UTF-8 - int args_to_utf8(int argc, char ** &argv) FL_OVERRIDE; - // Windows specific UTF-8 conversions - unsigned utf8towc(const char *src, unsigned srclen, wchar_t* dst, unsigned dstlen) FL_OVERRIDE; - unsigned utf8fromwc(char *dst, unsigned dstlen, const wchar_t* src, unsigned srclen) FL_OVERRIDE; - int utf8locale() FL_OVERRIDE; - unsigned utf8to_mb(const char *src, unsigned srclen, char *dst, unsigned dstlen) FL_OVERRIDE; - unsigned utf8from_mb(char *dst, unsigned dstlen, const char *src, unsigned srclen) FL_OVERRIDE; - - int clocale_vprintf(FILE *output, const char *format, va_list args) FL_OVERRIDE; - int clocale_vsnprintf(char *output, size_t output_size, const char *format, va_list args) FL_OVERRIDE; - int clocale_vsscanf(const char *input, const char *format, va_list args) FL_OVERRIDE; - int filename_list(const char *d, dirent ***list, - int (*sort)(struct dirent **, struct dirent **), - char *errmsg=NULL, int errmsg_sz=0) FL_OVERRIDE; - int filename_expand(char *to,int tolen, const char *from) FL_OVERRIDE; - int filename_relative(char *to, int tolen, const char *from, const char *base) FL_OVERRIDE; - int filename_absolute(char *to, int tolen, const char *from, const char *base) FL_OVERRIDE; - int filename_isdir(const char *n) FL_OVERRIDE; - int filename_isdir_quick(const char *n) FL_OVERRIDE; - const char *filename_ext(const char *buf) FL_OVERRIDE; - int open_uri(const char *uri, char *msg, int msglen) FL_OVERRIDE; - int use_recent_tooltip_fix() FL_OVERRIDE {return 1;} - int file_browser_load_filesystem(Fl_File_Browser *browser, char *filename, int lname, Fl_File_Icon *icon) FL_OVERRIDE; - int file_browser_load_directory(const char *directory, char *filename, size_t name_size, - dirent ***pfiles, Fl_File_Sort_F *sort, - char *errmsg=NULL, int errmsg_sz=0) FL_OVERRIDE; - void newUUID(char *uuidBuffer) FL_OVERRIDE; - char *preference_rootnode(Fl_Preferences *prefs, Fl_Preferences::Root root, const char *vendor, - const char *application) FL_OVERRIDE; - void *load(const char *filename) FL_OVERRIDE; - void png_extra_rgba_processing(unsigned char *array, int w, int h) FL_OVERRIDE; - const char *next_dir_sep(const char *start) FL_OVERRIDE; - // these 3 are implemented in Fl_lock.cxx - void awake(void*) FL_OVERRIDE; - int lock() FL_OVERRIDE; - void unlock() FL_OVERRIDE; - // this one is implemented in Fl_win32.cxx - void* thread_message() FL_OVERRIDE; - int file_type(const char *filename) FL_OVERRIDE; - const char *home_directory_name() FL_OVERRIDE; - const char *filesystems_label() FL_OVERRIDE { return "My Computer"; } - int backslash_as_slash() FL_OVERRIDE {return 1;} - int colon_is_drive() FL_OVERRIDE {return 1;} - int case_insensitive_filenames() FL_OVERRIDE {return 1;} - // this one is implemented in Fl_win32.cxx - const char *filename_name(const char *buf) FL_OVERRIDE; - void add_fd(int fd, int when, Fl_FD_Handler cb, void* = 0) FL_OVERRIDE; - void add_fd(int fd, Fl_FD_Handler cb, void* = 0) FL_OVERRIDE; - void remove_fd(int, int when) FL_OVERRIDE; - void remove_fd(int) FL_OVERRIDE; - void gettime(time_t *sec, int *usec) FL_OVERRIDE; - char* strdup(const char *s) FL_OVERRIDE { return ::_strdup(s); } - void lock_ring() FL_OVERRIDE; - void unlock_ring() FL_OVERRIDE; - double wait(double time_to_wait) FL_OVERRIDE; - int ready() FL_OVERRIDE; - int close_fd(int fd) FL_OVERRIDE; -}; - -#endif // FL_WINAPI_SYSTEM_DRIVER_H diff --git a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx deleted file mode 100644 index 9eab455df..000000000 --- a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx +++ /dev/null @@ -1,1134 +0,0 @@ -// -// Definition of Windows system driver for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2025 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 -// - -#include -#include -#include "Fl_WinAPI_System_Driver.H" -#include -#include -#include -#include -#include -#include "../../flstring.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// We must define _WIN32_IE at least to 0x0500 before inclusion of 'shlobj.h' to enable -// the declaration of SHGFP_TYPE_CURRENT for some older versions of MinGW, notably -// header versions 5.3.0 and earlier, whereas 5.4.2 seems to define _WIN32_IE as needed. -#if !(defined _WIN32_IE) || (_WIN32_IE < 0x0500) -# undef _WIN32_IE -# define _WIN32_IE 0x0500 -#endif /* _WIN32_WINNT checks */ - -#include - -// function pointer for the UuidCreate Function -// RPC_STATUS RPC_ENTRY UuidCreate(UUID __RPC_FAR *Uuid); -typedef RPC_STATUS (WINAPI *uuid_func)(UUID __RPC_FAR *Uuid); - -// Apparently Borland C++ defines DIRECTORY in , which -// interferes with the Fl_File_Icon enumeration of the same name. -# ifdef DIRECTORY -# undef DIRECTORY -# endif // DIRECTORY - -#ifdef __CYGWIN__ -# include -#endif - -// Optional helper function to debug Fl_WinAPI_System_Driver::home_directory_name() -#ifndef DEBUG_HOME_DIRECTORY_NAME -#define DEBUG_HOME_DIRECTORY_NAME 0 -#endif -#if DEBUG_HOME_DIRECTORY_NAME -static void print_env(const char *ev) { - const char *val = getenv(ev); - printf("%-30.30s = \"%s\"\n", ev, val ? val : ""); - fflush(stdout); -} -#endif // DEBUG_HOME_DIRECTORY_NAME - -static inline int isdirsep(char c) { return c == '/' || c == '\\'; } - -static wchar_t *mbwbuf = NULL; -static wchar_t *wbuf = NULL; -static wchar_t *wbuf1 = NULL; - -extern "C" { - int fl_scandir(const char *dirname, struct dirent ***namelist, - int (*select)(struct dirent *), - int (*compar)(struct dirent **, struct dirent **), - char *errmsg, int errmsg_len); -} - -/* - Convert UTF-8 string to Windows wide character encoding (UTF-16). - - This helper function is used throughout this file to convert UTF-8 - strings to Windows specific UTF-16 encoding for filenames, paths, or - other strings to be used by system functions. - - The input string can be a null-terminated string or its length can be - provided by the optional argument 'lg'. If 'lg' is omitted or less than 0 - (default = -1) the string length is determined with strlen(), otherwise - 'lg' takes precedence. Zero (0) is a valid string length (an empty string). - - The argument 'wbuf' must have been initialized with NULL or a previous - call to malloc() or realloc(). - - If the converted string doesn't fit into the allocated size of 'wbuf' or if - 'wbuf' is NULL a new buffer is allocated with realloc(). Hence the pointer - 'wbuf' can be shared among multiple calls to this function if it has been - initialized with NULL (or malloc or realloc) before the first call. - - The return value is either the old value of 'wbuf' (if the string fits) - or a pointer to the (re)allocated buffer. - - Pseudo doxygen docs (static function intentionally not documented): - - param[in] utf8 input string (UTF-8) - param[in,out] wbuf in: pointer to output string buffer or NULL - out: new string (the pointer may be changed) - param[in] lg optional: input string length (default = -1) - - returns pointer to string buffer -*/ -static wchar_t *utf8_to_wchar(const char *utf8, wchar_t *&wbuf, int lg = -1) { - unsigned len = (lg >= 0) ? (unsigned)lg : (unsigned)strlen(utf8); - unsigned wn = fl_utf8toUtf16(utf8, len, NULL, 0) + 1; // Query length - wbuf = (wchar_t *)realloc(wbuf, sizeof(wchar_t) * wn); - wn = fl_utf8toUtf16(utf8, len, (unsigned short *)wbuf, wn); // Convert string - wbuf[wn] = 0; - return wbuf; -} - -/* - Convert a Windows wide character (UTF-16) string to UTF-8 encoding. - - This helper function is used throughout this file to convert Windows - wide character strings as returned by system functions to UTF-8 - encoding for internal usage. - - The argument 'utf8' must have been initialized with NULL or a previous - call to malloc() or realloc(). - - If the converted string doesn't fit into the allocated size of 'utf8' or if - 'utf8' is NULL a new buffer is allocated with realloc(). Hence the pointer - 'utf8' can be shared among multiple calls to this function if it has been - initialized with NULL (or malloc or realloc) before the first call. - Ideally every call to this function has its own static pointer though. - - The return value is either the old value of 'utf8' (if the string fits) - or a pointer at the (re)allocated buffer. - - Pseudo doxygen docs (static function intentionally not documented): - - param[in] wstr input string (wide character, UTF-16) - param[in,out] utf8 in: pointer to output string buffer - out: new string (pointer may be changed) - - returns pointer to string buffer -*/ -static char *wchar_to_utf8(const wchar_t *wstr, char *&utf8) { - unsigned len = (unsigned)wcslen(wstr); - unsigned wn = fl_utf8fromwc(NULL, 0, wstr, len) + 1; // query length - utf8 = (char *)realloc(utf8, wn); - wn = fl_utf8fromwc(utf8, wn, wstr, len); // convert string - utf8[wn] = 0; - return utf8; -} - -void Fl_WinAPI_System_Driver::warning(const char *format, va_list args) { - // Show nothing for warnings under Windows... -} - -void Fl_WinAPI_System_Driver::error(const char *format, va_list args) { - char buf[1024]; - vsnprintf(buf, 1024, format, args); - MessageBox(0, buf, "Error", MB_ICONEXCLAMATION | MB_SYSTEMMODAL); -} - -void Fl_WinAPI_System_Driver::fatal(const char *format, va_list args) { - char buf[1024]; - vsnprintf(buf, 1024, format, args); - MessageBox(0, buf, "Error", MB_ICONSTOP | MB_SYSTEMMODAL); - ::exit(1); -} - -char *Fl_WinAPI_System_Driver::utf2mbcs(const char *utf8) { - static char *buf = NULL; - if (!utf8) return NULL; - - unsigned len = (unsigned)strlen(utf8); - - unsigned wn = fl_utf8toUtf16(utf8, len, NULL, 0) + 7; // Query length - mbwbuf = (wchar_t *)realloc(mbwbuf, sizeof(wchar_t) * wn); - len = fl_utf8toUtf16(utf8, len, (unsigned short *)mbwbuf, wn); // Convert string - mbwbuf[len] = 0; - - buf = (char*)realloc(buf, len * 6 + 2); - len = (unsigned)wcstombs(buf, mbwbuf, len * 6); - buf[len] = 0; - buf[len+1] = 0; // in case the result is a UTF-16 string - return buf; -} - -char *Fl_WinAPI_System_Driver::getenv(const char *var) { - static char *buf = NULL; - wchar_t *ret = _wgetenv(utf8_to_wchar(var, wbuf)); - if (!ret) return NULL; - return wchar_to_utf8(ret, buf); -} - -int Fl_WinAPI_System_Driver::putenv(const char *var) { - unsigned len = (unsigned)strlen(var); - unsigned wn = fl_utf8toUtf16(var, len, NULL, 0) + 1; // Query length - wchar_t *wbuf = (wchar_t *)malloc(sizeof(wchar_t) * wn); - wn = fl_utf8toUtf16(var, len, (unsigned short *)wbuf, wn); - wbuf[wn] = 0; - int ret = _wputenv(wbuf); - free(wbuf); - return ret; -} - -int Fl_WinAPI_System_Driver::open(const char *fnam, int oflags, int pmode) { - utf8_to_wchar(fnam, wbuf); - if (pmode == -1) return _wopen(wbuf, oflags); - else return _wopen(wbuf, oflags, pmode); -} - -int Fl_WinAPI_System_Driver::open_ext(const char *fnam, int binary, int oflags, int pmode) { - if (oflags == 0) oflags = _O_RDONLY; - oflags |= (binary ? _O_BINARY : _O_TEXT); - return this->open(fnam, oflags, pmode); -} - -FILE *Fl_WinAPI_System_Driver::fopen(const char *fnam, const char *mode) { - utf8_to_wchar(fnam, wbuf); - utf8_to_wchar(mode, wbuf1); - return _wfopen(wbuf, wbuf1); -} - -int Fl_WinAPI_System_Driver::system(const char *cmd) { - return _wsystem(utf8_to_wchar(cmd, wbuf)); -} - -int Fl_WinAPI_System_Driver::execvp(const char *file, char *const *argv) { - int n = 0; - while (argv[n]) n++; // count args - wchar_t **ar = (wchar_t **)calloc(sizeof(wchar_t *), n + 1); - // convert arguments first; trailing NULL provided by calloc() - for (int i = 0; i < n; i++) - ar[i] = utf8_to_wchar(argv[i], ar[i]); // alloc and assign - // convert executable file and execute it ... - utf8_to_wchar(file, wbuf); - _wexecvp(wbuf, ar); // STR #3040 - // clean up (reached only if _wexecvp() failed) - for (int i = 0; i < n; i++) - free(ar[i]); - free(ar); - return -1; // STR #3040 -} - -int Fl_WinAPI_System_Driver::chmod(const char *fnam, int mode) { - return _wchmod(utf8_to_wchar(fnam, wbuf), mode); -} - -int Fl_WinAPI_System_Driver::access(const char *fnam, int mode) { - return _waccess(utf8_to_wchar(fnam, wbuf), mode); -} - -int Fl_WinAPI_System_Driver::flstat(const char *fnam, struct stat *b) { - - // remove trailing '/' or '\' - unsigned len = (unsigned)strlen(fnam); - if (len > 0 && (fnam[len-1] == '/' || fnam[len-1] == '\\')) - len--; - // convert filename and execute _wstat() - return _wstat(utf8_to_wchar(fnam, wbuf, len), (struct _stat *)b); -} - -char *Fl_WinAPI_System_Driver::getcwd(char *buf, int len) { - - static wchar_t *wbuf = NULL; - wbuf = (wchar_t *)realloc(wbuf, sizeof(wchar_t) * (len + 1)); - wchar_t *ret = _wgetcwd(wbuf, len); - if (!ret) return NULL; - - unsigned dstlen = (unsigned)len; - len = (int)wcslen(wbuf); - dstlen = fl_utf8fromwc(buf, dstlen, wbuf, (unsigned)len); - buf[dstlen] = 0; - return buf; -} - -int Fl_WinAPI_System_Driver::chdir(const char *path) { - return _wchdir(utf8_to_wchar(path, wbuf)); -} - -int Fl_WinAPI_System_Driver::unlink(const char *fnam) { - return _wunlink(utf8_to_wchar(fnam, wbuf)); -} - -int Fl_WinAPI_System_Driver::mkdir(const char *fnam, int mode) { - return _wmkdir(utf8_to_wchar(fnam, wbuf)); -} - -int Fl_WinAPI_System_Driver::rmdir(const char *fnam) { - return _wrmdir(utf8_to_wchar(fnam, wbuf)); -} - -int Fl_WinAPI_System_Driver::rename(const char *fnam, const char *newnam) { - utf8_to_wchar(fnam, wbuf); - utf8_to_wchar(newnam, wbuf1); - return _wrename(wbuf, wbuf1); -} - -// See Fl::args_to_utf8() -int Fl_WinAPI_System_Driver::args_to_utf8(int argc, char ** &argv) { - int i; - - // Convert the command line arguments to UTF-8 - LPWSTR *wideArgv = CommandLineToArgvW(GetCommandLineW(), &argc); - argv = (char **)malloc((argc + 1) * sizeof(char *)); - for (i = 0; i < argc; i++) { - // find the required size of the buffer - int u8size = WideCharToMultiByte(CP_UTF8, // CodePage - 0, // dwFlags - wideArgv[i], // lpWideCharStr - -1, // cchWideChar - NULL, // lpMultiByteStr - 0, // cbMultiByte - NULL, // lpDefaultChar - NULL); // lpUsedDefaultChar - if (u8size > 0) { - char *strbuf = (char*)::malloc(u8size); - int ret = WideCharToMultiByte(CP_UTF8, // CodePage - 0, // dwFlags - wideArgv[i], // lpWideCharStr - -1, // cchWideChar - strbuf, // lpMultiByteStr - u8size, // cbMultiByte - NULL, // lpDefaultChar - NULL); // lpUsedDefaultChar - - if (ret) { - argv[i] = strbuf; - } else { - argv[i] = _strdup(""); - ::free(strbuf); - } - } else { - argv[i] = _strdup(""); - } - } - argv[argc] = NULL; // required NULL pointer at end of list - - // Free the wide character string array - LocalFree(wideArgv); - - // Note: the allocated memory or argv[] will not be free'd by the system - // on exit. This does not constitute a memory leak. - - return argc; -} - - -// Two Windows-specific functions fl_utf8_to_locale() and fl_locale_to_utf8() -// from file fl_utf8.cxx are put here for API compatibility - -static char *buf = NULL; -static int buf_len = 0; -static unsigned short *wbufa = NULL; -unsigned int fl_codepage = 0; - - -// FIXME: This should *maybe* return 'const char *' instead of 'char *' -char *fl_utf8_to_locale(const char *s, int len, UINT codepage) -{ - if (!s) return (char *)""; - int l = 0; - unsigned wn = fl_utf8toUtf16(s, len, NULL, 0); // Query length - wn = wn * 2 + 1; - if (wn >= (unsigned)buf_len) { - buf_len = wn; - buf = (char*) realloc(buf, buf_len); - wbufa = (unsigned short*) realloc(wbufa, buf_len * sizeof(short)); - } - if (codepage < 1) codepage = fl_codepage; - l = fl_utf8toUtf16(s, len, wbufa, wn); // Convert string - wbufa[l] = 0; - buf[l] = 0; - l = WideCharToMultiByte(codepage, 0, (WCHAR*)wbufa, l, buf, buf_len, NULL, NULL); - if (l < 0) l = 0; - buf[l] = 0; - return buf; -} - -// FIXME: This should maybe return 'const char *' instead of 'char *' -char *fl_locale_to_utf8(const char *s, int len, UINT codepage) -{ - if (!s) return (char *)""; - int l = 0; - if (buf_len < len * 5 + 1) { - buf_len = len * 5 + 1; - buf = (char*) realloc(buf, buf_len); - wbufa = (unsigned short*) realloc(wbufa, buf_len * sizeof(short)); - } - if (codepage < 1) codepage = fl_codepage; - buf[l] = 0; - - l = MultiByteToWideChar(codepage, 0, s, len, (WCHAR*)wbufa, buf_len); - if (l < 0) l = 0; - wbufa[l] = 0; - l = fl_utf8fromwc(buf, buf_len, (wchar_t*)wbufa, l); - buf[l] = 0; - return buf; -} - -/////////////////////////////////// - -unsigned Fl_WinAPI_System_Driver::utf8towc(const char *src, unsigned srclen, wchar_t *dst, unsigned dstlen) { - return fl_utf8toUtf16(src, srclen, (unsigned short*)dst, dstlen); -} - -unsigned Fl_WinAPI_System_Driver::utf8fromwc(char *dst, unsigned dstlen, const wchar_t *src, unsigned srclen) { - unsigned i = 0; - unsigned count = 0; - if (dstlen) for (;;) { - unsigned ucs; - if (i >= srclen) { - dst[count] = 0; - return count; - } - ucs = src[i++]; - if (ucs < 0x80U) { - dst[count++] = ucs; - if (count >= dstlen) {dst[count-1] = 0; break;} - } else if (ucs < 0x800U) { /* 2 bytes */ - if (count+2 >= dstlen) {dst[count] = 0; count += 2; break;} - dst[count++] = 0xc0 | (ucs >> 6); - dst[count++] = 0x80 | (ucs & 0x3F); - } else if (ucs >= 0xd800 && ucs <= 0xdbff && i < srclen && - src[i] >= 0xdc00 && src[i] <= 0xdfff) { - /* surrogate pair */ - unsigned ucs2 = src[i++]; - ucs = 0x10000U + ((ucs&0x3ff)<<10) + (ucs2&0x3ff); - /* all surrogate pairs turn into 4-byte UTF-8 */ - if (count+4 >= dstlen) {dst[count] = 0; count += 4; break;} - dst[count++] = 0xf0 | (ucs >> 18); - dst[count++] = 0x80 | ((ucs >> 12) & 0x3F); - dst[count++] = 0x80 | ((ucs >> 6) & 0x3F); - dst[count++] = 0x80 | (ucs & 0x3F); - } else { - /* all others are 3 bytes: */ - if (count+3 >= dstlen) {dst[count] = 0; count += 3; break;} - dst[count++] = 0xe0 | (ucs >> 12); - dst[count++] = 0x80 | ((ucs >> 6) & 0x3F); - dst[count++] = 0x80 | (ucs & 0x3F); - } - } - /* we filled dst, measure the rest: */ - while (i < srclen) { - unsigned ucs = src[i++]; - if (ucs < 0x80U) { - count++; - } else if (ucs < 0x800U) { /* 2 bytes */ - count += 2; - } else if (ucs >= 0xd800 && ucs <= 0xdbff && i < srclen-1 && - src[i+1] >= 0xdc00 && src[i+1] <= 0xdfff) { - /* surrogate pair */ - ++i; - count += 4; - } else { - count += 3; - } - } - return count; -} - -int Fl_WinAPI_System_Driver::utf8locale() -{ - static int ret = (GetACP() == CP_UTF8); - return ret; -} - -unsigned Fl_WinAPI_System_Driver::utf8to_mb(const char *src, unsigned srclen, char *dst, unsigned dstlen) { - wchar_t lbuf[1024]; - wchar_t *buf = lbuf; - unsigned length = fl_utf8towc(src, srclen, buf, 1024); - unsigned ret; - if (length >= 1024) { - buf = (wchar_t*)(malloc((length+1)*sizeof(wchar_t))); - fl_utf8towc(src, srclen, buf, length+1); - } - if (dstlen) { - // apparently this does not null-terminate, even though msdn documentation claims it does: - ret = - WideCharToMultiByte(GetACP(), 0, buf, length, dst, dstlen, 0, 0); - dst[ret] = 0; - } - // if it overflows or measuring length, get the actual length: - if (dstlen==0 || ret >= dstlen-1) - ret = WideCharToMultiByte(GetACP(), 0, buf, length, 0, 0, 0, 0); - if (buf != lbuf) free(buf); - return ret; -} - -unsigned Fl_WinAPI_System_Driver::utf8from_mb(char *dst, unsigned dstlen, const char *src, unsigned srclen) { - wchar_t lbuf[1024]; - wchar_t *buf = lbuf; - unsigned length; - unsigned ret; - length = MultiByteToWideChar(GetACP(), 0, src, srclen, buf, 1024); - if ((length == 0)&&(GetLastError()==ERROR_INSUFFICIENT_BUFFER)) { - length = MultiByteToWideChar(GetACP(), 0, src, srclen, 0, 0); - buf = (wchar_t*)(malloc(length*sizeof(wchar_t))); - MultiByteToWideChar(GetACP(), 0, src, srclen, buf, length); - } - ret = fl_utf8fromwc(dst, dstlen, buf, length); - if (buf != lbuf) free((void*)buf); - return ret; -} - -#if defined(_MSC_VER) && (_MSC_VER >= 1400 /*Visual Studio 2005*/) -static _locale_t c_locale = NULL; -#endif - -int Fl_WinAPI_System_Driver::clocale_vprintf(FILE *output, const char *format, va_list args) { -#if defined(_MSC_VER) && (_MSC_VER >= 1400 /*Visual Studio 2005*/) - if (!c_locale) - c_locale = _create_locale(LC_NUMERIC, "C"); - int retval = _vfprintf_l(output, format, c_locale, args); -#else - char *saved_locale = setlocale(LC_NUMERIC, NULL); - setlocale(LC_NUMERIC, "C"); - int retval = vfprintf(output, format, args); - setlocale(LC_NUMERIC, saved_locale); -#endif - return retval; -} - -int Fl_WinAPI_System_Driver::clocale_vsnprintf(char *output, size_t output_size, const char *format, va_list args) { -#if defined(_MSC_VER) && (_MSC_VER >= 1400 /*Visual Studio 2005*/) - if (!c_locale) - c_locale = _create_locale(LC_NUMERIC, "C"); - int retval = _vsnprintf_l(output, output_size, format, c_locale, args); -#else - char *saved_locale = setlocale(LC_NUMERIC, NULL); - setlocale(LC_NUMERIC, "C"); - int retval = vsnprintf(output, output_size, format, args); - setlocale(LC_NUMERIC, saved_locale); -#endif - return retval; -} - -int Fl_WinAPI_System_Driver::clocale_vsscanf(const char *input, const char *format, va_list args) { - char *saved_locale = setlocale(LC_NUMERIC, NULL); - setlocale(LC_NUMERIC, "C"); - int retval = vsscanf(input, format, args); - setlocale(LC_NUMERIC, saved_locale); - return retval; -} - - -int Fl_WinAPI_System_Driver::filename_list(const char *d, dirent ***list, - int (*sort)(struct dirent **, struct dirent **), - char *errmsg, int errmsg_sz) { - // For Windows we have a special scandir implementation that uses - // the Win32 "wide" functions for lookup, avoiding the code page mess - // entirely. It also fixes up the trailing '/'. - return fl_scandir(d, list, 0, sort, errmsg, errmsg_sz); -} - -int Fl_WinAPI_System_Driver::filename_expand(char *to, int tolen, const char *from) { - char *temp = new char[tolen]; - strlcpy(temp,from, tolen); - char *start = temp; - char *end = temp+strlen(temp); - int ret = 0; - for (char *a=temp; a= tolen) end += tolen - (end+1-e+t); - memmove(a+t, e, end+1-e); - end = a+t+(end-e); - *end = '\0'; - memcpy(a, value, t); - ret++; - } else { - a = e+1; - if (*e == '\\') {*e = '/'; ret++;} // ha ha! - } - } - strlcpy(to, start, tolen); - delete[] temp; - return ret; -} - -int // O - 0 if no change, 1 if changed -Fl_WinAPI_System_Driver::filename_relative(char *to, // O - Relative filename - int tolen, // I - Size of "to" buffer - const char *dest_dir, // I - Absolute filename - const char *base_dir) // I - Find path relative to this path -{ - // Find the relative path from base_dir to dest_dir. - // Both paths must be absolute and well formed (contain no /../ and /./ segments). - - // return if any of the pointers is NULL - if (!to || !dest_dir || !base_dir) { - return 0; - } - - // if there is a drive letter, make sure both paths use the same drive - if ( (unsigned)base_dir[0] < 128 && isalpha(base_dir[0]) && base_dir[1] == ':' - && (unsigned)dest_dir[0] < 128 && isalpha(dest_dir[0]) && dest_dir[1] == ':') { - if (tolower(base_dir[0]) != tolower(dest_dir[0])) { - strlcpy(to, dest_dir, tolen); - return 0; - } - // same drive, so skip to the start of the path - base_dir += 2; - dest_dir += 2; - } - - // return if `base_dir` or `dest_dir` is not an absolute path - if (!isdirsep(*base_dir) || !isdirsep(*dest_dir)) { - strlcpy(to, dest_dir, tolen); - return 0; - } - - const char *base_i = base_dir; // iterator through the base directory string - const char *base_s = base_dir; // pointer to the last dir separator found - const char *dest_i = dest_dir; // iterator through the destination directory - const char *dest_s = dest_dir; // pointer to the last dir separator found - - // compare both path names until we find a difference - for (;;) { -#if 0 // case sensitive - base_i++; - dest_i++; - char b = *base_i, d = *dest_i; -#else // case insensitive - base_i += fl_utf8len1(*base_i); - int b = fl_tolower(fl_utf8decode(base_i, NULL, NULL)); - dest_i += fl_utf8len1(*dest_i); - int d = fl_tolower(fl_utf8decode(dest_i, NULL, NULL)); -#endif - int b0 = (b == 0) || (isdirsep(b)); - int d0 = (d == 0) || (isdirsep(d)); - if (b0 && d0) { - base_s = base_i; - dest_s = dest_i; - } - if (b == 0 || d == 0) - break; - if (b != d) - break; - } - // base_s and dest_s point at the last separator we found - // base_i and dest_i point at the first character that differs - - // test for the exact same string and return "." if so - if ( (base_i[0] == 0 || (isdirsep(base_i[0]) && base_i[1] == 0)) - && (dest_i[0] == 0 || (isdirsep(dest_i[0]) && dest_i[1] == 0))) { - strlcpy(to, ".", tolen); - return 0; - } - - // prepare the destination buffer - to[0] = '\0'; - to[tolen - 1] = '\0'; - - // count the directory segments remaining in `base_dir` - int n_up = 0; - for (;;) { - char b = *base_s++; - if (b == 0) - break; - if (isdirsep(b) && *base_s) - n_up++; - } - - // now add a "previous dir" sequence for every following slash in the cwd - if (n_up > 0) - strlcat(to, "..", tolen); - for (; n_up > 1; --n_up) - strlcat(to, "/..", tolen); - - // finally add the differing path from "from" - if (*dest_s) { - if (n_up) - strlcat(to, "/", tolen); - strlcat(to, dest_s + 1, tolen); - } - - return 1; -} - -int Fl_WinAPI_System_Driver::filename_absolute(char *to, int tolen, const char *from, const char *base) { - if (isdirsep(*from) || *from == '|' || from[1]==':' || !base) { - strlcpy(to, from, tolen); - return 0; - } - char *a; - char *temp = new char[tolen]; - const char *start = from; - strlcpy(temp, base, tolen); - for (a = temp; *a; a++) if (*a=='\\') *a = '/'; // ha ha - /* remove trailing '/' in current working directory */ - if (isdirsep(*(a-1))) a--; - /* remove intermediate . and .. names: */ - while (*start == '.') { - if (start[1]=='.' && (isdirsep(start[2]) || start[2]==0) ) { - // found "..", remove the last directory segment form cwd - char *b; - for (b = a-1; b >= temp && !isdirsep(*b); b--) {/*empty*/} - if (b < temp) break; - a = b; - if (start[2] == 0) - start += 2; - else - start += 3; - } else if (isdirsep(start[1])) { - // found "./" in path, just skip it - start += 2; - } else if (!start[1]) { - // found "." at end of path, just skip it - start ++; - break; - } else - break; - } - *a++ = '/'; - strlcpy(a,start,tolen - (a - temp)); - strlcpy(to, temp, tolen); - delete[] temp; - return 1; -} - -int Fl_WinAPI_System_Driver::filename_isdir(const char *n) { - char fn[4]; // used for drive letter only: "X:/" - int length = (int)strlen(n); - // Strip trailing slash from name... - if (length > 0 && isdirsep(n[length - 1])) - length --; - if (length < 1) - return 0; - - // This workaround brought to you by the fine folks at Microsoft! - // (read lots of sarcasm in that...) - - if (length == 2 && isalpha(n[0]) && n[1] == ':') { // trailing '/' already "removed" - // Always use "X:/" for drive letters - fn[0] = n[0]; - strcpy(fn + 1, ":/"); - n = fn; - length = 3; - } - - // convert filename to wide chars using *length* - utf8_to_wchar(n, wbuf, length); - - DWORD fa = GetFileAttributesW(wbuf); - return (fa != INVALID_FILE_ATTRIBUTES) && (fa & FILE_ATTRIBUTE_DIRECTORY); -} - -int Fl_WinAPI_System_Driver::filename_isdir_quick(const char *n) { - // Do a quick optimization for filenames with a trailing slash... - if (*n && isdirsep(n[strlen(n) - 1])) return 1; - return filename_isdir(n); -} - -const char *Fl_WinAPI_System_Driver::filename_ext(const char *buf) { - const char *q = 0; - const char *p = buf; - for (p = buf; *p; p++) { - if (isdirsep(*p) ) q = 0; - else if (*p == '.') q = p; - } - return q ? q : p; -} - -int Fl_WinAPI_System_Driver::open_uri(const char *uri, char *msg, int msglen) { - if (msg) snprintf(msg, msglen, "open %s", uri); - return (int)(ShellExecute(HWND_DESKTOP, "open", uri, NULL, NULL, SW_SHOW) > (void *)32); -} - -int Fl_WinAPI_System_Driver::file_browser_load_filesystem(Fl_File_Browser *browser, char *filename, - int lname, Fl_File_Icon *icon) { - int num_files = 0; -# ifdef __CYGWIN__ - // - // Cygwin provides an implementation of setmntent() to get the list - // of available drives... - // - FILE *m = setmntent("/-not-used-", "r"); - struct mntent *p; - while ((p = getmntent (m)) != NULL) { - browser->add(p->mnt_dir, icon); - num_files ++; - } - endmntent(m); -# else - // - // Normal Windows code uses drive bits... - // - DWORD drives; // Drive available bits - drives = GetLogicalDrives(); - for (int i = 'A'; i <= 'Z'; i ++, drives >>= 1) { - if (drives & 1) { - snprintf(filename, lname, "%c:/", i); - if (i < 'C') // see also: GetDriveType and GetVolumeInformation in Windows - browser->add(filename, icon); - else - browser->add(filename, icon); - num_files ++; - } - } -# endif // __CYGWIN__ - return num_files; -} - -int Fl_WinAPI_System_Driver::file_browser_load_directory(const char *directory, char *filename, - size_t name_size, dirent ***pfiles, - Fl_File_Sort_F *sort, - char *errmsg, int errmsg_sz) -{ - strlcpy(filename, directory, name_size); - int i = (int) (strlen(filename) - 1); - if (i == 2 && filename[1] == ':' && - (filename[2] == '/' || filename[2] == '\\')) - filename[2] = '/'; - else if (filename[i] != '/' && filename[i] != '\\') - strlcat(filename, "/", name_size); - return filename_list(filename, pfiles, sort, errmsg, errmsg_sz); -} - -void Fl_WinAPI_System_Driver::newUUID(char *uuidBuffer) -{ - // First try and use the win API function UuidCreate(), but if that is not - // available, fall back to making something up from scratch. - // We do not want to link against the Rpcrt4.dll, as we will rarely use it, - // so we load the DLL dynamically, if it is available, and work from there. - static HMODULE hMod = NULL; - UUID ud; - UUID *pu = &ud; - int got_uuid = 0; - - if (!hMod) { // first time in? - hMod = LoadLibrary("Rpcrt4.dll"); - } - - if (hMod) { // do we have a usable handle to Rpcrt4.dll? - uuid_func uuid_crt = (uuid_func)GetProcAddress(hMod, "UuidCreate"); - if (uuid_crt != NULL) { - RPC_STATUS rpc_res = uuid_crt(pu); - if ( // is the return status OK for our needs? - (rpc_res == RPC_S_OK) || // all is well - (rpc_res == RPC_S_UUID_LOCAL_ONLY) || // only unique to this machine - (rpc_res == RPC_S_UUID_NO_ADDRESS) // probably only locally unique - ) { - got_uuid = -1; - snprintf(uuidBuffer, 36+1, "%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", - pu->Data1, pu->Data2, pu->Data3, pu->Data4[0], pu->Data4[1], - pu->Data4[2], pu->Data4[3], pu->Data4[4], - pu->Data4[5], pu->Data4[6], pu->Data4[7]); - } - } - } - if (got_uuid == 0) { // did not make a UUID - use fallback logic - unsigned char b[16]; - time_t t = time(0); // first 4 byte - b[0] = (unsigned char)t; - b[1] = (unsigned char)(t>>8); - b[2] = (unsigned char)(t>>16); - b[3] = (unsigned char)(t>>24); - int r = rand(); // four more bytes - b[4] = (unsigned char)r; - b[5] = (unsigned char)(r>>8); - b[6] = (unsigned char)(r>>16); - b[7] = (unsigned char)(r>>24); - // Now we try to find 4 more "random" bytes. We extract the - // lower 4 bytes from the address of t - it is created on the - // stack so *might* be in a different place each time... - // This is now done via a union to make it compile OK on 64-bit systems. - union { void *pv; unsigned char a[sizeof(void*)]; } v; - v.pv = (void *)(&t); - // NOTE: This assume that all WinXX systems are little-endian - b[8] = v.a[0]; - b[9] = v.a[1]; - b[10] = v.a[2]; - b[11] = v.a[3]; - TCHAR name[MAX_COMPUTERNAME_LENGTH + 1]; // only used to make last four bytes - DWORD nSize = MAX_COMPUTERNAME_LENGTH + 1; - // GetComputerName() does not depend on any extra libs, and returns something - // analogous to gethostname() - GetComputerName(name, &nSize); - // use the first 4 TCHAR's of the name to create the last 4 bytes of our UUID - for (int ii = 0; ii < 4; ii++) { - b[12 + ii] = (unsigned char)name[ii]; - } - snprintf(uuidBuffer, 36+1, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", - b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], - b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]); - } -} - -/* - Note: `prefs` can be NULL! - */ -char *Fl_WinAPI_System_Driver::preference_rootnode(Fl_Preferences * /*prefs*/, Fl_Preferences::Root root, const char *vendor, - const char *application) -{ - static char *filename = 0L; - // make enough room for a UTF-16 pathname - if (!filename) filename = (char*)::malloc(2 * FL_PATH_MAX); - HRESULT res; - - // https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetfolderpathw - - int appdata = CSIDL_APPDATA; // assume user preferences - if ((root & Fl_Preferences::ROOT_MASK) == Fl_Preferences::SYSTEM) - appdata = CSIDL_COMMON_APPDATA; // use system preferences - - res = SHGetFolderPathW(NULL, // hwnd: Reserved! - appdata, // csidl: User or common Application Data (Roaming) - NULL, // hToken (unused) - SHGFP_TYPE_CURRENT, // dwFlags: use current, potentially redirected path - (LPWSTR)filename); // out: filename in Windows wide string encoding - if (res != S_OK) { - // don't write data into some arbitrary directory! Just return NULL. - return 0L; - } - - // convert the path from Windows wide character (UTF-16) to UTF-8 - // FIXME: can this be simplified? Don't allocate/copy/move/free more than necessary! - char *buf = NULL; - wchar_to_utf8((wchar_t *)filename, buf); // allocates buf for conversion - strcpy(filename, buf); - free(buf); - - // Make sure that the parameters are not NULL - if ( (vendor==0L) || (vendor[0]==0) ) - vendor = "unknown"; - if ( (application==0L) || (application[0]==0) ) - application = "unknown"; - - // append vendor, application, and ".prefs", and convert '\' to '/' - snprintf(filename + strlen(filename), FL_PATH_MAX - strlen(filename), - "/%s/%s.prefs", vendor, application); - for (char *s = filename; *s; s++) if (*s == '\\') *s = '/'; - return filename; -} - -void *Fl_WinAPI_System_Driver::load(const char *filename) { - return LoadLibraryW(utf8_to_wchar(filename, wbuf)); -} - -void Fl_WinAPI_System_Driver::png_extra_rgba_processing(unsigned char *ptr, int w, int h) -{ - // Some Windows graphics drivers don't honor transparency when RGB == white - // Convert RGB to 0 when alpha == 0... - for (int i = w * h; i > 0; i --, ptr += 4) { - if (!ptr[3]) ptr[0] = ptr[1] = ptr[2] = 0; - } -} - -const char *Fl_WinAPI_System_Driver::next_dir_sep(const char *start) -{ - const char *p = strchr(start, '/'); - if (!p) p = strchr(start, '\\'); - return p; -} - -int Fl_WinAPI_System_Driver::file_type(const char *filename) -{ - int filetype; - if (filename[strlen(filename) - 1] == '/') - filetype = Fl_File_Icon::DIRECTORY; - else if (filename_isdir(filename)) - filetype = Fl_File_Icon::DIRECTORY; - else - filetype = Fl_File_Icon::PLAIN; - return filetype; -} - -// Note: the result is cached in a static variable -const char *Fl_WinAPI_System_Driver::home_directory_name() -{ - static std::string home; - if (!home.empty()) - return home.c_str(); - -#if (DEBUG_HOME_DIRECTORY_NAME) - print_env("HOMEDRIVE"); - print_env("HOMEPATH"); - print_env("UserProfile"); - print_env("HOME"); -#endif - - // Implement various ways to retrieve the HOME path. - // Note, from `man getenv`: - // "The implementation of getenv() is not required to be reentrant. - // The string pointed to by the return value of getenv() may be statically - // allocated, and can be modified by a subsequent call to getenv()...". - // Tests show that this is the case in some MinGW implementations. - - if (home.empty()) { - const char *home_drive = getenv("HOMEDRIVE"); - if (home_drive) { - home = home_drive; // copy *before* calling getenv() again, see above - const char *home_path = getenv("HOMEPATH"); - if (home_path) { - home.append(home_path); - } else { - home.clear(); // reset - } // home_path - } // home_drive - } // empty() - - if (home.empty()) { - const char *h = getenv("UserProfile"); - if (h) - home = h; - } - - if (home.empty()) { - const char *h = getenv("HOME"); - if (h) - home = h; - } - if (home.empty()) { - home = "~/"; // last resort - } - // Make path canonical. - for (char& c : home) { - if (c == '\\') - c = '/'; - } -#if (DEBUG_HOME_DIRECTORY_NAME) - printf("home_directory_name() returns \"%s\"\n", home.c_str()); - fflush(stdout); -#endif - return home.c_str(); -} - -void Fl_WinAPI_System_Driver::gettime(time_t *sec, int *usec) { - struct _timeb t; - _ftime(&t); - *sec = t.time; - *usec = t.millitm * 1000; -} - -// -// Code for lock support -// - -// These pointers are in Fl_win32.cxx: -extern void (*fl_lock_function)(); -extern void (*fl_unlock_function)(); - -// The main thread's ID -static DWORD main_thread; - -// Microsoft's version of a MUTEX... -static CRITICAL_SECTION cs; -static CRITICAL_SECTION *cs_ring; - -void Fl_WinAPI_System_Driver::unlock_ring() { - LeaveCriticalSection(cs_ring); -} - -void Fl_WinAPI_System_Driver::lock_ring() { - if (!cs_ring) { - cs_ring = (CRITICAL_SECTION*)malloc(sizeof(CRITICAL_SECTION)); - InitializeCriticalSection(cs_ring); - } - EnterCriticalSection(cs_ring); -} - -// -// 'unlock_function()' - Release the lock. -// - -static void unlock_function() { - LeaveCriticalSection(&cs); -} - -// -// 'lock_function()' - Get the lock. -// - -static void lock_function() { - EnterCriticalSection(&cs); -} - -int Fl_WinAPI_System_Driver::lock() { - if (!main_thread) InitializeCriticalSection(&cs); - - lock_function(); - - if (!main_thread) { - fl_lock_function = lock_function; - fl_unlock_function = unlock_function; - main_thread = GetCurrentThreadId(); - } - return 0; -} - -void Fl_WinAPI_System_Driver::unlock() { - unlock_function(); -} - -void Fl_WinAPI_System_Driver::awake(void* msg) { - PostThreadMessage( main_thread, fl_wake_msg, (WPARAM)msg, 0); -} - -int Fl_WinAPI_System_Driver::close_fd(int fd) { - return _close(fd); -} diff --git a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H deleted file mode 100644 index 3cf26b67c..000000000 --- a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H +++ /dev/null @@ -1,131 +0,0 @@ -// -// Definition of Windows window driver -// for the Fast Light Tool Kit (FLTK). -// -// Copyright 2010-2022 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 -// - -/** - \file Fl_WinAPI_Window_Driver.H - \brief Definition of Windows window driver. - */ - -#ifndef FL_WINAPI_WINDOW_DRIVER_H -#define FL_WINAPI_WINDOW_DRIVER_H - -#include -#include "../../Fl_Window_Driver.H" -#include - -/* - Move everything here that manages the native window interface. - - There is one window driver for each Fl_Window. Window drivers manage window - actions such as resizing, events, decoration, fullscreen modes, etc. . All - drawing and rendering is managed by the Surface device and the associated - graphics driver. - - - window specific event handling - - window types and styles, depth, etc. - - decorations - - ? where do we handle the interface between OpenGL/DirectX and Cocoa/Windows/Glx? - */ - - - -class Fl_WinAPI_Window_Driver : public Fl_Window_Driver -{ - struct icon_data { - const void *legacy_icon; - Fl_RGB_Image **icons; - int count; - HICON big_icon; - HICON small_icon; - }; - struct shape_data_type { - int lw_; ///< width of shape image - int lh_; ///< height of shape image - Fl_Image* shape_; ///< shape image - Fl_Bitmap *effective_bitmap_; ///< auxiliary bitmap image - } *shape_data_; -private: - void shape_bitmap_(Fl_Image* b); - void shape_alpha_(Fl_Image* img, int offset) FL_OVERRIDE; -public: - Fl_WinAPI_Window_Driver(Fl_Window*); - ~Fl_WinAPI_Window_Driver(); - static inline Fl_WinAPI_Window_Driver* driver(const Fl_Window *w) {return (Fl_WinAPI_Window_Driver*)Fl_Window_Driver::driver(w);} - HDC private_dc; // used for OpenGL - RECT border_width_title_bar_height(int &bx, int &by, int &bt); - - struct icon_data *icon_; - HCURSOR cursor; - int custom_cursor; - void set_minmax(LPMINMAXINFO minmax); - int fake_X_wm(int &X, int &Y, int &bt, int &bx, int &by, DWORD style = 0, DWORD styleEx = 0); - void make_fullscreen(int X, int Y, int W, int H); - // --- window data - int decorated_w() FL_OVERRIDE; - int decorated_h() FL_OVERRIDE; - const Fl_Image* shape() FL_OVERRIDE; - - // --- window management - void makeWindow() FL_OVERRIDE; - void size_range() FL_OVERRIDE { - // currently nothing to do - } - void flush_double() FL_OVERRIDE; - void flush_overlay() FL_OVERRIDE; - void draw_begin() FL_OVERRIDE; - void make_current() FL_OVERRIDE; - void show() FL_OVERRIDE; - void label(const char *name,const char *iname) FL_OVERRIDE; - void resize(int X,int Y,int W,int H) FL_OVERRIDE; - void hide() FL_OVERRIDE; - void map() FL_OVERRIDE; - void unmap() FL_OVERRIDE; - void fullscreen_on() FL_OVERRIDE; - void fullscreen_off(int X, int Y, int W, int H) FL_OVERRIDE; - void maximize() FL_OVERRIDE; - void un_maximize() FL_OVERRIDE; - bool maximize_needs_hide() FL_OVERRIDE { return true; } - void iconize() FL_OVERRIDE; - void decoration_sizes(int *top, int *left, int *right, int *bottom) FL_OVERRIDE; - // --- window cursor stuff - int set_cursor(Fl_Cursor) FL_OVERRIDE; - int set_cursor(const Fl_RGB_Image*, int, int) FL_OVERRIDE; - - void shape(const Fl_Image* img) FL_OVERRIDE; - void icons(const Fl_RGB_Image *icons[], int count) FL_OVERRIDE; - const void *icon() const FL_OVERRIDE; - void icon(const void * ic) FL_OVERRIDE; - void free_icons() FL_OVERRIDE; - void set_icons(); // driver-internal support function - // this one is implemented in Fl_win32.cxx - void capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right) FL_OVERRIDE; - int scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, - void (*draw_area)(void*, int,int,int,int), void* data) FL_OVERRIDE; -}; - - -class Fl_WinAPI_Plugin : public Fl_Plugin { -public: - Fl_WinAPI_Plugin(const char *pluginName) : Fl_Plugin(klass(), pluginName) { } - virtual const char *klass() { return "winapi.fltk.org"; } - virtual const char *name() = 0; - virtual void invalidate(Fl_Window*) = 0; -}; - - -#endif // FL_WINAPI_WINDOW_DRIVER_H diff --git a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx deleted file mode 100644 index 4b27753bf..000000000 --- a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx +++ /dev/null @@ -1,731 +0,0 @@ -// -// Definition of Windows window driver for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2025 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 -// - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "Fl_WinAPI_Window_Driver.H" -#include "Fl_WinAPI_Screen_Driver.H" -#include "../GDI/Fl_GDI_Graphics_Driver.H" -#include -#include -#include // for ceil() - -#if USE_COLORMAP -extern HPALETTE fl_select_palette(void); // in fl_color_win32.cxx -#endif - - -Fl_WinAPI_Window_Driver::Fl_WinAPI_Window_Driver(Fl_Window *win) -: Fl_Window_Driver(win) -{ - icon_ = new icon_data; - shape_data_ = NULL; - memset(icon_, 0, sizeof(icon_data)); - cursor = NULL; - screen_num_ = -1; -} - - -Fl_WinAPI_Window_Driver::~Fl_WinAPI_Window_Driver() -{ - if (shape_data_) { - delete shape_data_->effective_bitmap_; - delete shape_data_; - } - delete icon_; -} - - -//FILE*LOG=fopen("log.log","w"); - - -RECT // frame of the decorated window in screen coordinates - Fl_WinAPI_Window_Driver::border_width_title_bar_height( - int &bx, // left and right border width - int &by, // bottom border height (=bx) - int &bt // height of window title bar - ) -{ - Fl_Window *win = pWindow; - 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); - } - int width, height; - RECT rc; - GetClientRect(fl_xid(win), &rc); - width = rc.right; - height = rc.bottom; - bx = (r.right - r.left - width)/2; - if (bx < 1) bx = 1; - by = bx; - bt = r.bottom - r.top - height - 2 * by; - } - return r; -} - - -// --- window data - -int Fl_WinAPI_Window_Driver::decorated_w() -{ - int bt, bx, by; - float s = Fl::screen_driver()->scale(screen_num()); - border_width_title_bar_height(bx, by, bt); - int mini_bx = int(bx/s); if (mini_bx < 1) mini_bx = 1; - return w() + 2 * mini_bx; -} - -int Fl_WinAPI_Window_Driver::decorated_h() -{ - int bt, bx, by; - border_width_title_bar_height(bx, by, bt); - float s = Fl::screen_driver()->scale(screen_num()); - int mini_by = int(by / s); if (mini_by < 1) mini_by = 1; - return h() + int((bt + by) / s) + mini_by; -} - - -// --- window management - - - -void Fl_WinAPI_Window_Driver::shape_bitmap_(Fl_Image* b) { - shape_data_->shape_ = b; -} - -void Fl_WinAPI_Window_Driver::shape_alpha_(Fl_Image* img, int offset) { - int i, j, d = img->d(), w = img->w(), h = img->h(), bytesperrow = (w+7)/8; - unsigned u; - uchar byte, onebit; - // build an Fl_Bitmap covering the non-fully transparent/black part of the image - const uchar* bits = new uchar[h*bytesperrow]; // to store the bitmap - const uchar* alpha = (const uchar*)*img->data() + offset; // points to alpha value of rgba pixels - for (i = 0; i < h; i++) { - uchar *p = (uchar*)bits + i * bytesperrow; - byte = 0; - onebit = 1; - for (j = 0; j < w; j++) { - if (d == 3) { - u = *alpha; - u += *(alpha+1); - u += *(alpha+2); - } - else u = *alpha; - if (u > 0) { // if the pixel is not fully transparent/black - byte |= onebit; // turn on the corresponding bit of the bitmap - } - onebit = onebit << 1; // move the single set bit one position to the left - if (onebit == 0 || j == w-1) { - onebit = 1; - *p++ = byte; // store in bitmap one pack of bits - byte = 0; - } - alpha += d; // point to alpha value of next pixel - } - } - Fl_Bitmap* bitmap = new Fl_Bitmap(bits, w, h); - bitmap->alloc_array = 1; - shape_bitmap_(bitmap); - shape_data_->effective_bitmap_ = bitmap; - shape_data_->shape_ = img; -} - -void Fl_WinAPI_Window_Driver::shape(const Fl_Image* img) { - if (shape_data_) { - if (shape_data_->effective_bitmap_) { delete shape_data_->effective_bitmap_; } - } - else { - shape_data_ = new shape_data_type; - } - memset(shape_data_, 0, sizeof(shape_data_type)); - pWindow->border(false); - int d = img->d(); - if (d && img->count() >= 2) { - shape_pixmap_((Fl_Image*)img); - shape_data_->shape_ = (Fl_Image*)img; - } - else if (d == 0) shape_bitmap_((Fl_Image*)img); - else if (d == 2 || d == 4) shape_alpha_((Fl_Image*)img, d - 1); - else if ((d == 1 || d == 3) && img->count() == 1) shape_alpha_((Fl_Image*)img, 0); -} - - -static inline BYTE bit(int x) { return (BYTE)(1 << (x%8)); } - -static HRGN bitmap2region(Fl_Image* image) { - HRGN hRgn = 0; - /* Does this need to be dynamically determined, perhaps? */ - const int ALLOC_UNIT = 100; - DWORD maxRects = ALLOC_UNIT; - - RGNDATA* pData = (RGNDATA*)malloc(sizeof(RGNDATAHEADER)+(sizeof(RECT)*maxRects)); - pData->rdh.dwSize = sizeof(RGNDATAHEADER); - pData->rdh.iType = RDH_RECTANGLES; - pData->rdh.nCount = pData->rdh.nRgnSize = 0; - SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0); - - const int bytesPerLine = (image->w() + 7)/8; - BYTE* p, *data = (BYTE*)*image->data(); - for (int y = 0; y < image->h(); y++) { - // each row, left to right - for (int x = 0; x < image->w(); x++) { - int x0 = x; - while (x < image->w()) { - p = data + x / 8; - if (!((*p) & bit(x))) break; // transparent pixel - x++; - } - if (x > x0) { - RECT *pr; - /* Add the pixels (x0, y) to (x, y+1) as a new rectangle - * in the region - */ - if (pData->rdh.nCount >= maxRects) { - maxRects += ALLOC_UNIT; - pData = (RGNDATA*)realloc(pData, sizeof(RGNDATAHEADER) - + (sizeof(RECT)*maxRects)); - } - pr = (RECT*)&pData->Buffer; - SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1); - if (x0 < pData->rdh.rcBound.left) - pData->rdh.rcBound.left = x0; - if (y < pData->rdh.rcBound.top) - pData->rdh.rcBound.top = y; - if (x > pData->rdh.rcBound.right) - pData->rdh.rcBound.right = x; - if (y+1 > pData->rdh.rcBound.bottom) - pData->rdh.rcBound.bottom = y+1; - pData->rdh.nCount++; - /* On Windows98, ExtCreateRegion() may fail if the - * number of rectangles is too large (ie: > - * 4000). Therefore, we have to create the region by - * multiple steps. - */ - if (pData->rdh.nCount == 2000) { - HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) - + (sizeof(RECT)*maxRects), pData); - if (hRgn) { - CombineRgn(hRgn, hRgn, h, RGN_OR); - DeleteObject(h); - } else - hRgn = h; - pData->rdh.nCount = 0; - SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0); - } - } - } - /* Go to next row */ - data += bytesPerLine; - } - /* Create or extend the region with the remaining rectangles*/ - HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) - + (sizeof(RECT)*maxRects), pData); - if (hRgn) { - CombineRgn(hRgn, hRgn, h, RGN_OR); - DeleteObject(h); - } else hRgn = h; - free(pData); // I've created the region so I can free this now, right? - return hRgn; -} - - -void Fl_WinAPI_Window_Driver::draw_begin() -{ - if (shape_data_) { - float s = Fl::screen_driver()->scale(screen_num()); - if ((shape_data_->lw_ != s*w() || shape_data_->lh_ != s*h()) && shape_data_->shape_) { - // size of window has changed since last time - shape_data_->lw_ = int(s * w()); - shape_data_->lh_ = int(s * h()); - Fl_Image* temp = shape_data_->effective_bitmap_ ? shape_data_->effective_bitmap_ : shape_data_->shape_; - temp = temp->copy(shape_data_->lw_, shape_data_->lh_); - HRGN region = bitmap2region(temp); - SetWindowRgn(fl_xid(pWindow), region, TRUE); // the system deletes the region when it's no longer needed - delete temp; - } - } -} - - -void Fl_WinAPI_Window_Driver::flush_double() -{ - if (!shown()) return; - pWindow->make_current(); // make sure fl_gc is non-zero - Fl_X *i = Fl_X::flx(pWindow); - if (!i) return; // window not yet created - - if (!other_xid) { - other_xid = new Fl_Image_Surface(w(), h(), 1); - pWindow->clear_damage(FL_DAMAGE_ALL); - } - if (pWindow->damage() & ~FL_DAMAGE_EXPOSE) { - fl_clip_region(i->region); i->region = 0; -#if 0 /* Short form that transiently changes the current Fl_Surface_Device */ - Fl_Surface_Device::push_current(other_xid); - fl_graphics_driver->clip_region( 0 ); - draw(); - Fl_Surface_Device::pop_current(); -#else - /* Alternative form that avoids changing the current Fl_Surface_Device. - The code run in the window draw() method can call Fl_Surface_Device::surface() - and conclude that it's drawing to the display, which is ultimately true - for an Fl_Double_Window. - */ - HDC sgc = fl_gc; - fl_gc = fl_makeDC((HBITMAP)other_xid->offscreen()); - int savedc = SaveDC(fl_gc); - fl_graphics_driver->gc(fl_gc); - fl_graphics_driver->restore_clip(); // duplicate clip region into new gc -# if defined(FLTK_HAVE_CAIROEXT) - if (Fl::cairo_autolink_context()) Fl::cairo_make_current(pWindow); -# endif - draw(); - RestoreDC(fl_gc, savedc); - DeleteDC(fl_gc); - fl_graphics_driver->gc(sgc); -#endif - } - int X = 0, Y = 0, W = 0, H = 0; - fl_clip_box(0, 0, w(), h(), X, Y, W, H); - if (other_xid) fl_copy_offscreen(X, Y, W, H, other_xid->offscreen(), X, Y); -} - - -void Fl_WinAPI_Window_Driver::flush_overlay() -{ - Fl_Overlay_Window *oWindow = pWindow->as_overlay_window(); - - if (!shown()) return; - pWindow->make_current(); // make sure fl_gc is non-zero - Fl_X *i = Fl_X::flx(pWindow); - if (!i) return; // window not yet created - - int eraseoverlay = (pWindow->damage()&FL_DAMAGE_OVERLAY); - pWindow->clear_damage((uchar)(pWindow->damage()&~FL_DAMAGE_OVERLAY)); - - if (!other_xid) { - other_xid = new Fl_Image_Surface(w(), h(), 1); - pWindow->clear_damage(FL_DAMAGE_ALL); - } - if (pWindow->damage() & ~FL_DAMAGE_EXPOSE) { - fl_clip_region(i->region); i->region = 0; - Fl_Surface_Device::push_current(other_xid); - fl_graphics_driver->clip_region(0); - draw(); - Fl_Surface_Device::pop_current(); - } - - if (eraseoverlay) fl_clip_region(0); - int X, Y, W, H; fl_clip_box(0, 0, w(), h(), X, Y, W, H); - if (other_xid) fl_copy_offscreen(X, Y, W, H, other_xid->offscreen(), X, Y); - - if (overlay() == oWindow) oWindow->draw_overlay(); -} - - -void Fl_WinAPI_Window_Driver::icons(const Fl_RGB_Image *icons[], int count) { - free_icons(); - - if (count > 0) { - icon_->icons = new Fl_RGB_Image*[count]; - icon_->count = count; - // FIXME: Fl_RGB_Image lacks const modifiers on methods - for (int i = 0;i < count;i++) { - icon_->icons[i] = (Fl_RGB_Image*)((Fl_RGB_Image*)icons[i])->copy(); - icon_->icons[i]->normalize(); - } - } - - if (Fl_X::flx(pWindow)) - set_icons(); -} - -const void *Fl_WinAPI_Window_Driver::icon() const { - return icon_->legacy_icon; -} - -void Fl_WinAPI_Window_Driver::icon(const void * ic) { - free_icons(); - icon_->legacy_icon = ic; -} - -void Fl_WinAPI_Window_Driver::free_icons() { - int i; - icon_->legacy_icon = 0L; - if (icon_->icons) { - for (i = 0;i < icon_->count;i++) - delete icon_->icons[i]; - delete [] icon_->icons; - icon_->icons = 0L; - } - icon_->count = 0; - if (icon_->big_icon) - DestroyIcon(icon_->big_icon); - if (icon_->small_icon) - DestroyIcon(icon_->small_icon); - icon_->big_icon = NULL; - icon_->small_icon = NULL; -} - - -void Fl_WinAPI_Window_Driver::make_current() { - fl_GetDC(fl_xid(pWindow)); - -#if USE_COLORMAP - // Windows maintains a hardware and software color palette; the - // SelectPalette() call updates the current soft->hard mapping - // for all drawing calls, so we must select it here before any - // code does any drawing... - fl_select_palette(); -#endif // USE_COLORMAP - - fl_graphics_driver->clip_region(0); - ((Fl_GDI_Graphics_Driver*)fl_graphics_driver)->scale(Fl::screen_driver()->scale(screen_num())); -#if defined(FLTK_HAVE_CAIROEXT) - if (Fl::cairo_autolink_context()) Fl::cairo_make_current(pWindow); -#endif -} - -void Fl_WinAPI_Window_Driver::label(const char *name,const char *iname) { - if (shown() && !parent()) { - if (!name) name = ""; - size_t l = strlen(name); - // WCHAR *lab = (WCHAR*) malloc((l + 1) * sizeof(short)); - // l = fl_utf2unicode((unsigned char*)name, l, (wchar_t*)lab); - unsigned wlen = fl_utf8toUtf16(name, (unsigned) l, NULL, 0); // Pass NULL to query length - wlen++; - unsigned short * lab = (unsigned short*)malloc(sizeof(unsigned short)*wlen); - wlen = fl_utf8toUtf16(name, (unsigned) l, lab, wlen); - lab[wlen] = 0; - SetWindowTextW(fl_xid(pWindow), (WCHAR *)lab); - free(lab); - } -} - - -extern void fl_clipboard_notify_retarget(HWND wnd); -extern void fl_update_clipboard(void); -extern char fl_i_own_selection[2]; - -void Fl_WinAPI_Window_Driver::hide() { - Fl_X* ip = Fl_X::flx(pWindow); - // STR#3079: if there remains a window and a non-modal window, and the window is deleted, - // the app remains running without any apparent window. - // Bug mechanism: hiding an owner window unmaps the owned (non-modal) window(s) - // but does not delete it(them) in FLTK. - // Fix for it: - // when hiding a window, build list of windows it owns, and do hide/show on them. - int count = 0; - Fl_Window *win, **doit = NULL; - for (win = Fl::first_window(); win && ip; win = Fl::next_window(win)) { - if (win->non_modal() && GetWindow(fl_xid(win), GW_OWNER) == (HWND)ip->xid) { - count++; - } - } - if (count) { - doit = new Fl_Window*[count]; - count = 0; - for (win = Fl::first_window(); win && ip; win = Fl::next_window(win)) { - if (win->non_modal() && GetWindow(fl_xid(win), GW_OWNER) == (HWND)ip->xid) { - doit[count++] = win; - } - } - } - - if (hide_common()) { - delete[] doit; // note: `count` and `doit` may be NULL (see PR #241) - return; - } - - // Issue #569: undo RegisterDragDrop() - RevokeDragDrop((HWND)ip->xid); - - fl_i_own_selection[1] = 0; // issue #1233 - - // make sure any custom icons get freed - // icons(NULL, 0); // free_icons() is called by the Fl_Window destructor - // this little trick keeps the current clipboard alive, even if we are about - // to destroy the window that owns the selection. - if (GetClipboardOwner() == (HWND)ip->xid) - fl_update_clipboard(); - // Make sure we unlink this window from the clipboard chain - fl_clipboard_notify_retarget((HWND)ip->xid); - // Send a message to myself so that I'll get out of the event loop... - PostMessage((HWND)ip->xid, WM_APP, 0, 0); - if (private_dc) fl_release_dc((HWND)ip->xid, private_dc); - if ((HWND)ip->xid == fl_window && fl_graphics_driver->gc()) { - fl_release_dc(fl_window, (HDC)fl_graphics_driver->gc()); - fl_window = (HWND)-1; - fl_graphics_driver->gc(0); -# ifdef FLTK_HAVE_CAIROEXT - if (Fl::cairo_autolink_context()) Fl::cairo_make_current((Fl_Window*) 0); -# endif - } - - if (ip->region) Fl_Graphics_Driver::default_driver().XDestroyRegion(ip->region); - - // this little trickery seems to avoid the popup window stacking problem - HWND p = GetForegroundWindow(); - if (p==GetParent((HWND)ip->xid)) { - ShowWindow((HWND)ip->xid, SW_HIDE); - ShowWindow(p, SW_SHOWNA); - } - DestroyWindow((HWND)ip->xid); - // end of fix for STR#3079 - if (count) { - int ii; - for (ii = 0; ii < count; ii++) doit[ii]->hide(); - for (ii = 0; ii < count; ii++) { - if (ii != 0) doit[0]->show(); // Fix for STR#3165 - doit[ii]->show(); - } - } - delete[] doit; // note: `count` and `doit` may be NULL (see PR #241) - - // Try to stop the annoying "raise another program" behavior - if (pWindow->non_modal() && Fl::first_window() && Fl::first_window()->shown()) - Fl::first_window()->show(); - delete ip; - screen_num_ = -1; -} - - -void Fl_WinAPI_Window_Driver::map() { - ShowWindow(fl_xid(pWindow), SW_RESTORE); // extra map calls are harmless -} - - -void Fl_WinAPI_Window_Driver::unmap() { - ShowWindow(fl_xid(pWindow), SW_HIDE); -} - -#if !defined(FL_DOXYGEN) // FIXME - silence Doxygen warning - -void Fl_WinAPI_Window_Driver::make_fullscreen(int X, int Y, int W, int H) { - HWND xid = fl_xid(pWindow); - int top, bottom, left, right; - int sx, sy, sw, sh; - - top = fullscreen_screen_top(); - bottom = fullscreen_screen_bottom(); - left = fullscreen_screen_left(); - right = fullscreen_screen_right(); - - if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) { - top = screen_num(); - bottom = top; - left = top; - right = top; - } - - Fl_WinAPI_Screen_Driver *scr_dr = (Fl_WinAPI_Screen_Driver*)Fl::screen_driver(); - scr_dr->screen_xywh_unscaled(sx, Y, sw, sh, top); - scr_dr->screen_xywh_unscaled(sx, sy, sw, sh, bottom); - H = sy + sh - Y; - scr_dr->screen_xywh_unscaled(X, sy, sw, sh, left); - scr_dr->screen_xywh_unscaled(sx, sy, sw, sh, right); - W = sx + sw - X; - - DWORD flags = GetWindowLong(xid, GWL_STYLE); - flags = flags & ~(WS_THICKFRAME|WS_CAPTION); - SetWindowLong(xid, GWL_STYLE, flags); - - // SWP_NOSENDCHANGING is so that we can override size limits - SetWindowPos(xid, HWND_TOP, X, Y, W, H, SWP_NOSENDCHANGING | SWP_FRAMECHANGED); -} - -#endif // !defined(FL_DOXYGEN) // FIXME - silence Doxygen warning - - -void Fl_WinAPI_Window_Driver::fullscreen_on() { - pWindow->_set_fullscreen(); - make_fullscreen(x(), y(), w(), h()); - Fl::handle(FL_FULLSCREEN, pWindow); -} - - -void Fl_WinAPI_Window_Driver::fullscreen_off(int X, int Y, int W, int H) { - pWindow->_clear_fullscreen(); - DWORD style = GetWindowLong(fl_xid(pWindow), GWL_STYLE); - if (pWindow->border()) style |= WS_THICKFRAME | WS_SYSMENU | WS_MAXIMIZEBOX | WS_CAPTION; - // Remove the xid temporarily so that Fl_WinAPI_Window_Driver::fake_X_wm() behaves like it - // does in Fl_WinAPI_Window_Driver::makeWindow(). - HWND xid = fl_xid(pWindow); - Fl_X::flx(pWindow)->xid = 0; - int wx, wy, bt, bx, by; - switch (fake_X_wm(wx, wy, bt, bx, by, style)) { - case 0: - break; - case 1: - style |= WS_CAPTION; - break; - case 2: - /*if (border()) { - style |= WS_THICKFRAME | WS_CAPTION; - }*/ - break; - } - Fl_X::flx(pWindow)->xid = (fl_uintptr_t)xid; - SetWindowLong(fl_xid(pWindow), GWL_STYLE, style); - if (!pWindow->maximize_active()) { - // compute window position and size in scaled units - float s = Fl::screen_driver()->scale(screen_num()); - int scaledX = int(ceil(X*s)), scaledY= int(ceil(Y*s)), scaledW = int(ceil(W*s)), scaledH = int(ceil(H*s)); - // Adjust for decorations (but not if that puts the decorations - // outside the screen) - if ((X != x()) || (Y != y())) { - scaledX -= bx; - scaledY -= by+bt; - } - scaledW += bx*2; - scaledH += by*2+bt; - SetWindowPos(fl_xid(pWindow), 0, scaledX, scaledY, scaledW, scaledH, - SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED); - } else { - int WX, WY, WW, WH; - ((Fl_WinAPI_Screen_Driver*)Fl::screen_driver())->screen_xywh_unscaled(WX, WY, WW, WH, screen_num()); - SetWindowPos(fl_xid(pWindow), 0, WX, WY, WW, WH, - SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED); - } - Fl::handle(FL_FULLSCREEN, pWindow); -} - - -void Fl_WinAPI_Window_Driver::maximize() { - if (!border()) return Fl_Window_Driver::maximize(); - ShowWindow(fl_xid(pWindow), SW_SHOWMAXIMIZED); -} - -void Fl_WinAPI_Window_Driver::un_maximize() { - if (!border()) return Fl_Window_Driver::un_maximize(); - ShowWindow(fl_xid(pWindow), SW_SHOWNORMAL); -} - - -void Fl_WinAPI_Window_Driver::iconize() { - ShowWindow(fl_xid(pWindow), SW_SHOWMINNOACTIVE); -} - - -void Fl_WinAPI_Window_Driver::decoration_sizes(int *top, int *left, int *right, int *bottom) { - int minw, minh, maxw, maxh, set; - set = pWindow->get_size_range(&minw, &minh, &maxw, &maxh, NULL, NULL, NULL); - if (set && (maxw != minw || maxh != minh)) { - *left = *right = GetSystemMetrics(SM_CXSIZEFRAME); - *top = *bottom = GetSystemMetrics(SM_CYSIZEFRAME); - } else { - *left = *right = GetSystemMetrics(SM_CXFIXEDFRAME); - *top = *bottom = GetSystemMetrics(SM_CYFIXEDFRAME); - } - *top += GetSystemMetrics(SM_CYCAPTION); -} - -int Fl_WinAPI_Window_Driver::scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, - void (*draw_area)(void*, int,int,int,int), void* data) -{ - typedef int (WINAPI* fl_GetRandomRgn_func)(HDC, HRGN, INT); - static fl_GetRandomRgn_func fl_GetRandomRgn = 0L; - static char first_time = 1; - // We will have to do some Region magic now, so let's see if the - // required function is available (and it should be starting w/Win95) - if (first_time) { - HMODULE hMod = GetModuleHandle("GDI32.DLL"); - if (hMod) { - fl_GetRandomRgn = (fl_GetRandomRgn_func)GetProcAddress(hMod, "GetRandomRgn"); - } - first_time = 0; - } - float s = Fl::screen_driver()->scale(screen_num()); - src_x = int(src_x * s); src_y = int(src_y * s); - src_w = int(src_w * s); src_h = int(src_h * s); - dest_x = int(dest_x * s); dest_y = int(dest_y * s); - // Now check if the source scrolling area is fully visible. - // If it is, we will do a quick scroll and just update the - // newly exposed area. If it is not, we go the safe route and - // re-render the full area instead. - // Note 1: we could go and find the areas that are actually - // obscured and recursively call fl_scroll for the newly found - // rectangles. However, this practice would rely on the - // elements of the undocumented Rgn structure. - // Note 2: although this method should take care of most - // multi-screen solutions, it will not solve issues scrolling - // from a different resolution screen onto another. - // Note 3: this has been tested with image maps, too. - HDC gc = (HDC)fl_graphics_driver->gc(); - if (fl_GetRandomRgn) { - // get the DC region minus all overlapping windows - HRGN sys_rgn = CreateRectRgn(0, 0, 0, 0); - fl_GetRandomRgn(gc, sys_rgn, 4); - // now get the source scrolling rectangle - HRGN src_rgn = CreateRectRgn(src_x, src_y, src_x+src_w, src_y+src_h); - POINT offset = { 0, 0 }; - if (GetDCOrgEx(gc, &offset)) { - OffsetRgn(src_rgn, offset.x, offset.y); - } - // see if all source pixels are available in the system region - // Note: we could be a bit more merciful and subtract the - // scroll destination region as well. - HRGN dst_rgn = CreateRectRgn(0, 0, 0, 0); - int r = CombineRgn(dst_rgn, src_rgn, sys_rgn, RGN_DIFF); - DeleteObject(dst_rgn); - DeleteObject(src_rgn); - DeleteObject(sys_rgn); - if (r != NULLREGION) { - return 1; - } - } - // Great, we can do an accelerated scroll instead of re-rendering - BitBlt(gc, dest_x, dest_y, src_w, src_h, gc, src_x, src_y,SRCCOPY); - return 0; -} - - -const Fl_Image* Fl_WinAPI_Window_Driver::shape() { - return shape_data_ ? shape_data_->shape_ : NULL; -} - - -HWND fl_win32_xid(const Fl_Window *win) { - return (HWND)Fl_Window_Driver::xid(win); -} - - -Fl_Window *fl_win32_find(HWND xid) { - return Fl_Window_Driver::find((fl_uintptr_t)xid); -} diff --git a/src/drivers/WinAPI/fl_WinAPI_platform_init.cxx b/src/drivers/WinAPI/fl_WinAPI_platform_init.cxx deleted file mode 100644 index b5ffe2449..000000000 --- a/src/drivers/WinAPI/fl_WinAPI_platform_init.cxx +++ /dev/null @@ -1,85 +0,0 @@ -// -// Windows-specific code to initialize Windows support. -// -// Copyright 2022 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 -// - - -#include "../GDI/Fl_GDI_Copy_Surface_Driver.H" -#include "../GDI/Fl_GDI_Graphics_Driver.H" -#include "Fl_WinAPI_Screen_Driver.H" -#include "Fl_WinAPI_System_Driver.H" -#include "Fl_WinAPI_Window_Driver.H" -#include "../GDI/Fl_GDI_Image_Surface_Driver.H" -#include "../Base/Fl_Base_Pen_Events.H" - - -Fl_Copy_Surface_Driver *Fl_Copy_Surface_Driver::newCopySurfaceDriver(int w, int h) -{ - return new Fl_GDI_Copy_Surface_Driver(w, h); -} - - -Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver() -{ -#if USE_GDIPLUS - // Initialize GDI+. - static Gdiplus::GdiplusStartupInput gdiplusStartupInput; - if (Fl_GDIplus_Graphics_Driver::gdiplus_state_ == Fl_GDIplus_Graphics_Driver::STATE_CLOSED) { - Fl_GDIplus_Graphics_Driver::gdiplus_state_ = Fl_GDIplus_Graphics_Driver::STATE_STARTUP; - Gdiplus::Status ret = GdiplusStartup(&Fl_GDIplus_Graphics_Driver::gdiplus_token_, &gdiplusStartupInput, NULL); - if (ret == 0) { // 0 is same as Gdiplus::Status::Ok, but old mingw64 barks at that - Fl_GDIplus_Graphics_Driver::gdiplus_state_ = Fl_GDIplus_Graphics_Driver::STATE_OPEN; - } else { - Fl::warning("GdiplusStartup failed with error code %d.", ret); - Fl_GDIplus_Graphics_Driver::gdiplus_state_ = Fl_GDIplus_Graphics_Driver::STATE_CLOSED; - return new Fl_GDI_Graphics_Driver(); - } - } else if (Fl_GDIplus_Graphics_Driver::gdiplus_state_ == Fl_GDIplus_Graphics_Driver::STATE_OPEN) { -// Fl::warning("GdiplusStartup() called, but driver is already open."); - } else if (Fl_GDIplus_Graphics_Driver::gdiplus_state_ == Fl_GDIplus_Graphics_Driver::STATE_SHUTDOWN) { -// Fl::warning("GdiplusStartup() called while driver is shutting down."); - } else if (Fl_GDIplus_Graphics_Driver::gdiplus_state_ == Fl_GDIplus_Graphics_Driver::STATE_STARTUP) { -// Fl::warning("GdiplusStartup() called recursively."); - } - Fl_Graphics_Driver *driver = new Fl_GDIplus_Graphics_Driver(); - return driver; -#else - return new Fl_GDI_Graphics_Driver(); -#endif -} - - -Fl_Screen_Driver *Fl_Screen_Driver::newScreenDriver() -{ - return new Fl_WinAPI_Screen_Driver(); -} - - -Fl_System_Driver *Fl_System_Driver::newSystemDriver() -{ - return new Fl_WinAPI_System_Driver(); -} - - -Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w) -{ - return new Fl_WinAPI_Window_Driver(w); -} - - -Fl_Image_Surface_Driver *Fl_Image_Surface_Driver::newImageSurfaceDriver(int w, int h, int high_res, Fl_Offscreen off) -{ - return new Fl_GDI_Image_Surface_Driver(w, h, high_res, off); -} - -- cgit v1.2.3