feat(print): add initial Windows printing support via GDI#20828
feat(print): add initial Windows printing support via GDI#20828adinjithj wants to merge 5 commits intodarktable-org:masterfrom
Conversation
Add a Windows-native print backend (win_print.c) implementing the
same API as the CUPS backend. Uses Windows GDI for printer discovery,
paper enumeration, and bitmap printing.
- Printer discovery via EnumPrinters()
- Paper sizes via DeviceCapabilities()
- Printer metrics via GetDeviceCaps()
- PDF printing via ShellExecute("print")
- Color management defaults to sRGB
Build system updated to conditionally compile the Windows backend
when BUILD_PRINT is enabled on Windows, and the CUPS backend on
Linux/macOS.
Refs: darktable-org#19856
There was a problem hiding this comment.
Pull request overview
Adds a Windows-native printing backend to enable print mode on Windows builds, aligning with the existing CUPS-based print API used on Linux/macOS.
Changes:
- Introduces
src/common/win_print.cimplementing printer discovery, paper enumeration, and PDF printing via Windows APIs. - Updates CMake logic to build print view/settings modules based on
BUILD_PRINT(notCUPS_FOUND), and selects CUPS vs Windows backend per-platform. - Enables
BUILD_PRINTon Windows by removing the forced disable in the top-level CMake.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
src/views/CMakeLists.txt |
Build print view module when BUILD_PRINT is enabled. |
src/libs/CMakeLists.txt |
Build print settings module when BUILD_PRINT is enabled. |
src/common/win_print.c |
New Windows print backend implementation using WinSpool/GDI + ShellExecute. |
src/CMakeLists.txt |
Chooses Windows backend on WIN32, CUPS backend otherwise, and adjusts link libs/defines. |
CMakeLists.txt |
Stops forcibly disabling BUILD_PRINT on Windows. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Add missing <shellapi.h> include for ShellExecuteW - Switch from ANSI (A) to wide (W) Win32 APIs for proper UTF-8 support via g_utf8_to_utf16/g_utf16_to_utf8 conversion - Use "WINSPOOL" as driver name in CreateDCW for reliable DC creation - Fix printer status filter to check PAUSED, OFFLINE, NOT_AVAILABLE in addition to ERROR - Check _cancel flag during printer enumeration loop for proper abort support - Use "printto" verb with printer name in ShellExecuteW to target the user-selected printer instead of system default - Fix sort_papers to use g_list_sort() instead of g_list_sort_with_data() to match its 2-argument signature - Add gdi32 and shell32 to Windows link libraries in CMakeLists
TurboGit
left a comment
There was a problem hiding this comment.
Thanks for working on this. Definitly something missing on Windows and we had many user requests about this.
The CI fails with:
D:/a/darktable/darktable/src/src/common/printing.c: In function 'dt_printing_setup_image':
D:/a/darktable/darktable/src/src/common/printing.c:332:16: error: 'pos.x' may be used uninitialized [-Werror=maybe-uninitialized]
332 | dt_image_pos pos;
| ^~~
compilation terminated due to -Wfatal-errors.
cc1.exe: all warnings being treated as errors
I let you look at the Copilot report.
| @@ -0,0 +1,472 @@ | |||
| /* | |||
| This file is part of darktable, | |||
| Copyright (C) 2025 darktable developers. | |||
TurboGit
left a comment
There was a problem hiding this comment.
Another GitLab CI compilation issue:
D:/a/_temp/msys64/ucrt64/include/libsecret-1 -isystem D:/a/_temp/msys64/ucrt64/include/GraphicsMagick -isystem D:/a/_temp/msys64/ucrt64/include/osmgpsmap-1.0 -isystem D:/a/_temp/msys64/ucrt64/include/libsoup-3.0 -isystem D:/a/_temp/msys64/ucrt64/include/Imath -isystem D:/a/_temp/msys64/ucrt64/include/OpenEXR -Wall -Wno-format -Wshadow -Wtype-limits -Wvla -Wold-style-declaration -Wmaybe-uninitialized -Wno-unknown-pragmas -Wno-error=varargs -Wno-format-truncation -Wno-error=address-of-packed-member -fopenmp -march=native -msse2 -g -mfpmath=sse -O3 -DNDEBUG -O3 -ffast-math -fno-finite-math-only -fexpensive-optimizations -std=c99 -DUNICODE -D_UNICODE -Werror -Wfatal-errors -MD -MT bin/CMakeFiles/lib_darktable.dir/common/win_print.c.obj -MF bin\CMakeFiles\lib_darktable.dir\common\win_print.c.obj.d -o bin/CMakeFiles/lib_darktable.dir/common/win_print.c.obj -c D:/a/darktable/darktable/src/src/common/win_print.c
In file included from D:/a/darktable/darktable/src/src/win/win.h:5,
from D:/a/darktable/darktable/src/src/common/darktable.h:33,
from D:/a/darktable/darktable/src/src/common/color_harmony.h:21,
from D:/a/darktable/darktable/src/src/common/image.h:21,
from D:/a/darktable/darktable/src/src/common/win_print.c:33:
D:/a/_temp/msys64/ucrt64/include/winsock2.h:15:2: error: #warning Please include winsock2.h before windows.h [-Werror=cpp]
15 | #warning Please include winsock2.h before windows.h
| ^~~~~~~
compilation terminated due to -Wfatal-errors.
cc1.exe: all warnings being treated as errors
|
okay i have to take a better look on this |
|
@adinjithj : Sure no urgency, I have set this to draft for now. Ping me when you think it is in a reviewable state. TIA. |
The Windows API requires that winsock2.h must be included before windows.h to avoid conflicts. This fix reorders the includes in win_print.c so that: - winsock2.h is first - windows.h follows - Other headers follow in logical groups This resolves the MSYS2/Windows CI build failure with: 'winsock2.h:15: error: #warning Please include winsock2.h before windows.h' The entire win_print.c is guarded by #ifdef _WIN32, so this change only affects Windows builds and is safe for Linux/macOS where the file is not compiled.
…ackend Address potential NULL pointer dereferences when encoding conversion fails: - Check wprinter before CreateDCW in dt_get_printer_info() - Check name_utf8 before logging skipped printers - Check name_utf8 before using in dt_get_printer_info() - Check paper_name_utf8 before copying to struct - Check both wfilename and wprinter before ShellExecuteW() Also fix malloc -> g_malloc0 in paper enumeration for consistency with project's glib allocation pattern. These changes prevent crashes if g_utf16_to_utf8() or g_utf8_to_utf16() encounter encoding errors or OOM conditions.
TurboGit
left a comment
There was a problem hiding this comment.
I have spotted many routines just duplicated from cups_print.c. This should be avoided and have the code shared with cups_print.c.
Also, can you clarify how the printer profile (ICC) is handled on Windows?
| g_free(wprinter); | ||
| } | ||
|
|
||
| void dt_get_print_layout(const dt_print_info_t *prt, |
There was a problem hiding this comment.
If I'm not mistaken this is the very same code as dt_get_print_layout found in cups_print.c. Why is it duplicated here?
| } | ||
| } | ||
|
|
||
| dt_paper_info_t *dt_get_paper(GList *papers, |
There was a problem hiding this comment.
Very same code as in cups_print.c I think. Should not be duplicated.
| _cancel = 1; | ||
| } | ||
|
|
||
| void dt_printers_discovery(void (*cb)(dt_printer_info_t *pr, void *user_data), |
There was a problem hiding this comment.
Almost same code as in cups_print.c. Only _cancel = 0 is new here, if really needed should be added into cups_print.c too.
| } | ||
|
|
||
| // initialize the pinfo structure | ||
| void dt_init_print_info(dt_print_info_t *pinfo) |
Add a Windows-native print backend (win_print.c) implementing the same API as the CUPS backend. Uses Windows GDI for printer discovery, paper enumeration, and bitmap printing.
Build system updated to conditionally compile the Windows backend when BUILD_PRINT is enabled on Windows, and the CUPS backend on Linux/macOS.
Refs: #19856