WIP: Add native Wayland support for Linux (#13197)

* Add runtime display backend detection for Wayland support

Add LinuxDisplayBackend utility to detect X11 vs Wayland at runtime
using GDK_IS_X11_DISPLAY / GDK_IS_WAYLAND_DISPLAY macros. This is
the foundation for removing the forced GDK_BACKEND=x11 and enabling
native Wayland support.

- New files: LinuxDisplayBackend.hpp/.cpp with get_linux_display_backend(),
  is_running_on_wayland(), and is_running_on_x11()
- Propagate wxHAVE_GDK_X11 / wxHAVE_GDK_WAYLAND from FindGTK3.cmake
  as compile definitions to libslic3r_gui
- No-op on non-Linux platforms (returns Unknown / false)

* Fix Phase 1 code quality: pragma once, source ordering, static cache

* Make X11 initialization conditional for Wayland support

Remove the unconditional GDK_BACKEND=x11 force that blocked native
Wayland. Replace with conditional logic:

- EGL safety fallback: re-force X11 only when wxUSE_GLCANVAS_EGL is
  off and WAYLAND_DISPLAY is set, with a warning log
- XInitThreads() only called when DISPLAY is set (X11 in use)
- __GLX_VENDOR_LIBRARY_NAME only set when DISPLAY is present (GLX-specific)
- WEBKIT_DISABLE_COMPOSITING_MODE only set under XWayland (both
  DISPLAY and WAYLAND_DISPLAY present)
- Guard X11/Xlib.h include with __has_include for robustness
- Restore display validation to accept either DISPLAY or WAYLAND_DISPLAY

This is Phase 2 of the Wayland support plan.

* Fix Phase 2: safer EGL macro check, add clarifying comments

* Add GLAD2 library and replace GLEW linkage in build system

Set up GLAD2 as a static library to replace GLEW for OpenGL loading.
GLAD2 supports both GLX and EGL, which is required for Wayland support.

- Create src/glad/ with pre-generated GLAD2 sources (GL 4.6 compat)
- Add src/glad/CMakeLists.txt building glad as a static library
- Wire glad into src/CMakeLists.txt before libvgcode
- Modify libvgcode to use shared glad for GL path (keeps local copy
  only for GLES2/Emscripten) to avoid duplicate symbol conflicts
- Replace GLEW::GLEW with glad in libslic3r_gui link libraries

Note: GLEW is kept in deps for OpenCSG. Code migration from GL/glew.h
to glad/gl.h headers will follow in Phase 3B+3C.

* Fix Phase 3A+3D: libvgcode GLAD include, dead files, dlopen dep, OpenGL link var

* Migrate from GLEW to GLAD: replace headers and API calls across codebase

Replace all #include <GL/glew.h> with <glad/gl.h> across 49 source files.
Migrate GLEW API calls to GLAD equivalents:
- glewInit/glewExperimental -> gladLoaderLoadGL()
- GLEW_EXT_* / GLEW_ARB_* extension checks -> GLAD_GL_EXT_* / GLAD_GL_ARB_*
- Remove GLEW-specific EGL/GLX mismatch #error guards (not needed with GLAD)
- Replace unavailable EXT symbols with core GL equivalents in
  GLCanvas3D.cpp (GL_MAX_SAMPLES, glRenderbufferStorageMultisample,
  glBlitFramebuffer, GL_READ/DRAW_FRAMEBUFFER)
- Update log messages from glewInit to gladLoadGL

* Fix Phase 3B+3C: remove GLEW find, clean EXT symbols, update attribution

- Remove find_package(GLEW) block from root CMakeLists.txt since GLEW
  is no longer linked by any main application code
- Remove "glew" from SLIC3R_STATIC option description
- Replace all remaining EXT framebuffer symbols with core equivalents
  in render_thumbnail_framebuffer_ext and _rectangular_selection_picking_pass
- Update AboutDialog credits from GLEW to GLAD

* Enable EGL in wxWidgets and add runtime GLX/EGL selection for Wayland

- Set wxUSE_GLCANVAS_EGL=ON in wxWidgets build and Flatpak manifest
- Add PreferGLX() call on X11 sessions for driver compatibility
- Remove Phase 2 safety fallback (EGL is now always compiled in)
- Guard SwapBuffers against hidden canvases to prevent Wayland stalls

* Fix Phase 4: move PreferGLX to app startup, fix FPS counter guard

Move wxGLCanvas::PreferGLX() from OpenGLManager::create_wxglcanvas()
(static initializer) to GUI_App::on_init_inner() before any wxGLCanvas
is constructed. This prevents a race where SkipPartCanvas could trigger
wxGLBackend::Init() before the GLX preference is set. The new location
also adds explicit is_running_on_wayland() detection with a warning for
unknown backends.

Move increment_fps_counter() inside the IsShownOnScreen() guard so FPS
is only counted when a frame is actually swapped.

* Update GLFW from 3.3.7 to 3.4 for runtime Wayland/X11 backend selection

Replace the compile-time GLFW_USE_WAYLAND flag (which locked to a single
backend) with GLFW 3.4's GLFW_BUILD_WAYLAND + GLFW_BUILD_X11 flags that
build both backends and auto-select at runtime based on the available
display server. This enables the CLI thumbnail renderer to work on both
Wayland and X11 sessions without separate builds.

* wayland: Fix UI call sites that rely on global screen coordinates

On Wayland, wxGetMousePosition() returns (0,0) and SetPosition() is a
no-op for top-level windows. Fix the highest-impact call sites:

- GLCanvas3D: Use cached m_mouse.position from event handlers instead
  of wxGetMousePosition() + ScreenToClient() in get_local_mouse_position()
- Plater: Use event-relative coords via ClientToScreen(e.GetPosition())
  instead of wxGetMousePosition() in 3 leave-window handlers
- BBLTopbar: Use event.GetPosition() and FindToolByPosition() directly
  in mouse handlers instead of wxGetMousePosition()/FindToolByCurrentPosition()
- Search: Use focus-based dismiss logic on Wayland instead of
  wxGetMousePosition()-based rect checks in SearchDialog and
  SearchObjectDialog
- GUI_App: Skip SetPosition() in window_pos_restore() on Wayland where
  it is a no-op; still restore size and maximize state
- Button: Position tooltip relative to button widget via ClientToScreen
  instead of wxGetMousePosition()

* Fix SearchDialog Wayland dismiss: guard against search_line focus

* flatpak: Add Wayland socket permission for native Wayland support

* spec

* Fix crash on Wayland when wxWidgets lacks EGL support

Restore the safety fallback that forces GDK_BACKEND=x11 when wxWidgets
was not built with wxUSE_GLCANVAS_EGL=ON. Without this, the GLX backend
tries to access a non-existent X11 display on native Wayland, crashing
in wxGLCanvas::IsDisplaySupported() with SIGSEGV at offset 0xe4.

Also add a defense-in-depth guard in detect_multisample() that skips
the IsDisplaySupported call entirely on Wayland without EGL.

Root cause: deps/wxWidgets must be rebuilt after enabling EGL. The
compile-time check in OrcaSlicer.cpp detects the mismatch and falls
back safely.

* Fix EGL detection: use wxHAS_EGL instead of wxUSE_GLCANVAS_EGL

wxUSE_GLCANVAS_EGL is a CMake build option, NOT a C++ preprocessor
macro. The actual macro defined in wxWidgets setup.h is wxHAS_EGL.
All compile-time EGL checks were using the wrong macro, causing
the safety fallback to always trigger even with a properly built
EGL-enabled wxWidgets.

* Fix GL function pointers invalidated on Wayland/EGL

gladLoaderLoadGL() dlopen's libGL.so.1 to resolve GL function pointers
via dlsym, then immediately dlclose's the handle. On X11/GLX this is
fine because the GLX context keeps libGL.so mapped. On Wayland/EGL,
nothing else holds libGL.so open, so dlclose unmaps it and all function
pointers become dangling — causing SIGSEGV on the first GL call.

Fix: on Wayland, use gladLoadGL(eglGetProcAddress) which resolves
function pointers through the EGL loader without opening/closing
libGL.so.

* fix crash on start and various rendering issues

* fix crash on close

* small refactor

* move GPU selection to desktop file

* clean up a bit

* clean up more

* fix appimage error
This commit is contained in:
SoftFever
2026-04-13 19:45:39 +08:00
committed by GitHub
parent 2553d37236
commit 3e4af2c723
83 changed files with 3485 additions and 239 deletions
+1 -11
View File
@@ -117,7 +117,7 @@ else()
set(SLIC3R_STATIC_INITIAL 1)
endif()
option(SLIC3R_STATIC "Compile OrcaSlicer with static libraries (Boost, TBB, glew)" ${SLIC3R_STATIC_INITIAL})
option(SLIC3R_STATIC "Compile OrcaSlicer with static libraries (Boost, TBB)" ${SLIC3R_STATIC_INITIAL})
option(SLIC3R_GUI "Compile OrcaSlicer with GUI components (OpenGL, wxWidgets)" 1)
option(SLIC3R_FHS "Assume OrcaSlicer is to be installed in a FHS directory structure" 0)
option(SLIC3R_PROFILE "Compile OrcaSlicer with an invasive Shiny profiler" 0)
@@ -694,16 +694,6 @@ if(APPLE AND CMAKE_VERSION VERSION_GREATER_EQUAL "4.0")
set(OPENGL_LIBRARIES "-framework OpenGL" CACHE STRING "OpenGL framework" FORCE)
endif()
set(GLEW_ROOT "${CMAKE_PREFIX_PATH}")
message("GLEW_ROOT: ${GLEW_ROOT}")
# Find glew or use bundled version
if (SLIC3R_STATIC AND NOT SLIC3R_STATIC_EXCLUDE_GLEW)
set(GLEW_USE_STATIC_LIBS ON)
set(GLEW_VERBOSE ON)
endif()
find_package(GLEW REQUIRED)
find_package(glfw3 REQUIRED)
# Find the Cereal serialization library
-2
View File
@@ -343,7 +343,6 @@ function run_in_docker() {
-e "CI=true"
-e "GITHUB_ACTIONS=true"
-e "GITHUB_WORKSPACE=${container_workspace}"
-e "GIT_CEILING_DIRECTORIES=${container_workspace}/deps/build"
-e "RUNNER_OS=Linux"
-e "RUNNER_TEMP=/tmp"
-e "HOST_UID=${host_uid}"
@@ -423,7 +422,6 @@ fi
sudo -H -u "${HOST_USER}" env \
CMAKE_BUILD_PARALLEL_LEVEL="${CMAKE_BUILD_PARALLEL_LEVEL-}" \
GITHUB_WORKSPACE="${GITHUB_WORKSPACE}" \
GIT_CEILING_DIRECTORIES="${GIT_CEILING_DIRECTORIES-}" \
ORCA_UPDATER_SIG_KEY="${ORCA_UPDATER_SIG_KEY-}" \
bash -c '
set -e
+6 -8
View File
@@ -6,22 +6,20 @@ else()
set(_build_static ON)
endif()
set(_glfw_platform_args "")
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(_glfw_use_wayland "-DGLFW_USE_WAYLAND=ON")
else()
set(_glfw_use_wayland "-DGLFW_USE_WAYLAND=FF")
set(_glfw_platform_args -DGLFW_BUILD_WAYLAND=ON -DGLFW_BUILD_X11=ON)
endif()
orcaslicer_add_cmake_project(GLFW
URL https://github.com/glfw/glfw/archive/refs/tags/3.3.7.zip
URL_HASH SHA256=e02d956935e5b9fb4abf90e2c2e07c9a0526d7eacae8ee5353484c69a2a76cd0
#DEPENDS dep_Boost
URL https://github.com/glfw/glfw/archive/refs/tags/3.4.zip
URL_HASH SHA256=a133ddc3d3c66143eba9035621db8e0bcf34dba1ee9514a9e23e96afd39fd57a
CMAKE_ARGS
-DBUILD_SHARED_LIBS=${_build_shared}
-DGLFW_BUILD_DOCS=OFF
-DGLFW_BUILD_EXAMPLES=OFF
-DGLFW_BUILD_TESTS=OFF
${_glfw_use_wayland}
-DGLFW_BUILD_TESTS=OFF
${_glfw_platform_args}
)
if (MSVC)
+1 -1
View File
@@ -38,7 +38,7 @@ orcaslicer_add_cmake_project(
-DwxUSE_DETECT_SM=OFF
-DwxUSE_PRIVATE_FONTS=ON
-DwxUSE_OPENGL=ON
-DwxUSE_GLCANVAS_EGL=OFF
-DwxUSE_GLCANVAS_EGL=ON
-DwxUSE_WEBREQUEST=ON
-DwxUSE_WEBVIEW=ON
${_wx_edge}
+1 -3
View File
@@ -13,9 +13,7 @@ appimage_is_host_library() {
libgstreamer-1.0.so*|libgst*.so*|libsoup-*.so*|libwebkit2gtk-*.so*|libjavascriptcoregtk-*.so*|libsecret-1.so*|libmanette-0.2.so*|libenchant-2.so*|libhyphen.so*|libtasn1.so*|\
libfontconfig.so*|libfreetype.so*|libharfbuzz*.so*|libfribidi.so*|libgraphite2.so*|libthai.so*|libdatrie.so*|libepoxy.so*|libpixman-1.so*|\
libstdc++.so*|libgcc_s.so*|libatomic.so*|libdbus-1.so*|libuuid.so*|libffi.so*|libselinux.so*|libmount.so*|libblkid.so*|libpcre2-*.so*|libsystemd.so*|libcap.so*|libseccomp.so*|\
libexpat.so*|libz.so*|liblzma.so*|libdeflate.so*|libzstd.so*|libpng*.so*|libjpeg.so*|libtiff.so*|libwebp*.so*|libwoff2*.so*|libjbig.so*|libLerc.so*|liblcms2.so*|libjxl*.so*|libhwy.so*|libsharpyuv.so*|\
libxml2.so*|libxslt.so*|libsqlite3.so*|libicu*.so*|libpsl.so*|libnghttp2.so*|libbrotli*.so*|libidn2.so*|libunistring.so*|libgcrypt.so*|libgpg-error.so*|\
libgssapi_krb5.so*|libkrb5.so*|libkrb5support.so*|libk5crypto.so*|libcom_err.so*|libkeyutils.so*|liborc-0.4.so*|libgudev-1.0.so*)
liborc-0.4.so*|libgudev-1.0.so*)
return 0
;;
*)
@@ -17,6 +17,7 @@ build-options:
finish-args:
- --share=ipc
- --socket=x11
- --socket=wayland
- --share=network
- --device=all
- --filesystem=home
@@ -99,7 +100,7 @@ modules:
- -DwxUSE_DETECT_SM=OFF
- -DwxUSE_PRIVATE_FONTS=ON
- -DwxUSE_OPENGL=ON
- -DwxUSE_GLCANVAS_EGL=OFF
- -DwxUSE_GLCANVAS_EGL=ON
- -DwxUSE_WEBREQUEST=ON
- -DwxUSE_WEBVIEW=ON
- -DwxUSE_WEBVIEW_EDGE=OFF
@@ -186,10 +187,10 @@ modules:
sha256: a378e9a39e718e289102c20d45632f873bfdc58a7a5f924246ea4b176e185f1e
dest: external-packages/Qhull
# GLFW 3.3.7
# GLFW 3.4
- type: file
url: https://github.com/glfw/glfw/archive/refs/tags/3.3.7.zip
sha256: e02d956935e5b9fb4abf90e2c2e07c9a0526d7eacae8ee5353484c69a2a76cd0
url: https://github.com/glfw/glfw/archive/refs/tags/3.4.zip
sha256: a133ddc3d3c66143eba9035621db8e0bcf34dba1ee9514a9e23e96afd39fd57a
dest: external-packages/GLFW
# OpenCSG 1.4.2
+1
View File
@@ -14,6 +14,7 @@ find_package(libnoise REQUIRED)
add_subdirectory(libslic3r)
if (SLIC3R_GUI)
add_subdirectory(glad)
# imgui, imguizmo, and hidapi are now included from deps_src
add_subdirectory(libvgcode)
+41 -29
View File
@@ -88,7 +88,9 @@ using namespace nlohmann;
#include <GLFW/glfw3.h>
#ifdef __WXGTK__
#if __has_include(<X11/Xlib.h>)
#include <X11/Xlib.h>
#endif
#include <unistd.h>
#endif
@@ -1183,30 +1185,42 @@ int CLI::run(int argc, char **argv)
save_main_thread_id();
#ifdef __WXGTK__
// On Linux, wxGTK has no support for Wayland, and the app crashes on
// startup if gtk3 is used. This env var has to be set explicitly to
// instruct the window manager to fall back to X server mode.
::setenv("GDK_BACKEND", "x11", /* replace */ true);
// Safety fallback: if wxWidgets was not built with EGL support, native
// Wayland will crash in wxGLCanvas::IsDisplaySupported() because the GLX
// backend cannot access an X11 display. Force X11 mode in that case.
// NOTE: Do NOT remove this block even after enabling wxHAS_EGL
// in the build — it protects against builds where deps were not rebuilt.
#if !defined(wxHAS_EGL) || !wxHAS_EGL
{
const char* wayland_env = ::getenv("WAYLAND_DISPLAY");
if (wayland_env && *wayland_env) {
BOOST_LOG_TRIVIAL(warning) << "Wayland detected but wxWidgets has no EGL support (wxHAS_EGL is OFF). Forcing X11 backend.";
::setenv("GDK_BACKEND", "x11", true);
}
}
#endif
// WebKit2GTK's compositing mode can fail under XWayland, causing WebViews
// (like the Setup Wizard) to render blank or freeze. Disabling compositing
// mode forces software rendering, which works reliably on all backends.
::setenv("WEBKIT_DISABLE_COMPOSITING_MODE", "1", /* replace */ false);
// On Linux dual-GPU systems, request the high-performance discrete GPU.
// DRI_PRIME=1 handles AMD and nouveau (open-source NVIDIA) PRIME setups.
::setenv("DRI_PRIME", "1", /* replace */ false);
// For NVIDIA proprietary driver PRIME render offload, set additional variables.
// Only set if the NVIDIA kernel module is loaded to avoid breaking systems without NVIDIA.
if (::access("/proc/driver/nvidia/version", F_OK) == 0) {
::setenv("__NV_PRIME_RENDER_OFFLOAD", "1", /* replace */ false);
::setenv("__GLX_VENDOR_LIBRARY_NAME", "nvidia", /* replace */ false);
// WebKit2GTK compositing can fail under XWayland. Only disable it when
// both DISPLAY and WAYLAND_DISPLAY are set (i.e., XWayland is in use).
// On pure X11 or native Wayland, compositing is left enabled.
{
const char* display_env_wk = ::getenv("DISPLAY");
const char* wayland_env_wk = ::getenv("WAYLAND_DISPLAY");
if (display_env_wk && *display_env_wk && wayland_env_wk && *wayland_env_wk) {
::setenv("WEBKIT_DISABLE_COMPOSITING_MODE", "1", /* replace */ false);
}
}
// Also on Linux, we need to tell Xlib that we will be using threads,
// lest we crash when we fire up GStreamer.
XInitThreads();
// XInitThreads is needed before GStreamer may use Xlib. On native
// Wayland without DISPLAY, GStreamer uses waylandsink (no Xlib).
#if __has_include(<X11/Xlib.h>)
{
const char* display_env = ::getenv("DISPLAY");
if (display_env && *display_env) {
XInitThreads();
}
}
#endif
#endif
// Switch boost::filesystem to utf8.
@@ -1280,19 +1294,17 @@ int CLI::run(int argc, char **argv)
if (start_gui) {
BOOST_LOG_TRIVIAL(info) << "no action, start gui directly" << std::endl;
#ifdef SLIC3R_GUI
/*#if !defined(_WIN32) && !defined(__APPLE__)
#if !defined(_WIN32) && !defined(__APPLE__)
// likely some linux / unix system
const char *display = boost::nowide::getenv("DISPLAY");
// const char *wayland_display = boost::nowide::getenv("WAYLAND_DISPLAY");
//if (! ((display && *display) || (wayland_display && *wayland_display))) {
if (! (display && *display)) {
// DISPLAY not set.
boost::nowide::cerr << "DISPLAY not set, GUI mode not available." << std::endl << std::endl;
const char *wayland_display = boost::nowide::getenv("WAYLAND_DISPLAY");
if (! ((display && *display) || (wayland_display && *wayland_display))) {
boost::nowide::cerr << "Neither DISPLAY nor WAYLAND_DISPLAY set, GUI mode not available." << std::endl << std::endl;
this->print_help(false);
// Indicate an error.
return 1;
}
#endif // some linux / unix system*/
#endif // some linux / unix system
Slic3r::GUI::GUI_InitParams params;
params.argc = argc;
params.argv = argv;
@@ -6453,7 +6465,7 @@ int CLI::run(int argc, char **argv)
BOOST_LOG_TRIVIAL(error) << "init opengl failed! skip thumbnail generating" << std::endl;
}
else {
BOOST_LOG_TRIVIAL(info) << "glewInit Success." << std::endl;
BOOST_LOG_TRIVIAL(info) << "gladLoadGL Success." << std::endl;
GLVolumeCollection glvolume_collection;
Model &model = m_models[0];
int obj_extruder_id = 1, volume_extruder_id = 1;
@@ -1,9 +0,0 @@
[Desktop Entry]
Name=Bambu GCode viewer
Exec=orca-slicer --gcodeviewer %F
Icon=OrcaSlicer-gcodeviewer
Terminal=false
Type=Application
MimeType=text/x.gcode;
Categories=Graphics;3DGraphics;
Keywords=3D;Printing;Slicer;
@@ -23,6 +23,8 @@ Name=@SLIC3R_APP_KEY@
Exec=AppRun %F
Icon=@SLIC3R_APP_KEY@
Type=Application
PrefersNonDefaultGPU=true
X-KDE-RunOnDiscreteGpu=true
Categories=Utility;
MimeType=model/stl;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;application/x-amf;
EOF
@@ -5,6 +5,8 @@ Icon=OrcaSlicer
Exec=orca-slicer %U
Terminal=false
Type=Application
PrefersNonDefaultGPU=true
X-KDE-RunOnDiscreteGpu=true
MimeType=model/stl;model/3mf;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;application/x-amf;x-scheme-handler/orcaslicer;model/step;
Categories=Graphics;3DGraphics;Engineering;
Keywords=3D;Printing;Slicer;slice;3D;printer;convert;gcode;stl;obj;amf;SLA
+3
View File
@@ -0,0 +1,3 @@
add_library(glad STATIC src/gl.c)
target_include_directories(glad PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(glad PRIVATE ${CMAKE_DL_LIBS})
+311
View File
@@ -0,0 +1,311 @@
#ifndef __khrplatform_h_
#define __khrplatform_h_
/*
** Copyright (c) 2008-2018 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
/* Khronos platform-specific types and definitions.
*
* The master copy of khrplatform.h is maintained in the Khronos EGL
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
* The last semantic modification to khrplatform.h was at commit ID:
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
*
* Adopters may modify this file to suit their platform. Adopters are
* encouraged to submit platform specific modifications to the Khronos
* group so that they can be included in future versions of this file.
* Please submit changes by filing pull requests or issues on
* the EGL Registry repository linked above.
*
*
* See the Implementer's Guidelines for information about where this file
* should be located on your system and for more details of its use:
* http://www.khronos.org/registry/implementers_guide.pdf
*
* This file should be included as
* #include <KHR/khrplatform.h>
* by Khronos client API header files that use its types and defines.
*
* The types in khrplatform.h should only be used to define API-specific types.
*
* Types defined in khrplatform.h:
* khronos_int8_t signed 8 bit
* khronos_uint8_t unsigned 8 bit
* khronos_int16_t signed 16 bit
* khronos_uint16_t unsigned 16 bit
* khronos_int32_t signed 32 bit
* khronos_uint32_t unsigned 32 bit
* khronos_int64_t signed 64 bit
* khronos_uint64_t unsigned 64 bit
* khronos_intptr_t signed same number of bits as a pointer
* khronos_uintptr_t unsigned same number of bits as a pointer
* khronos_ssize_t signed size
* khronos_usize_t unsigned size
* khronos_float_t signed 32 bit floating point
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
* nanoseconds
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
* khronos_boolean_enum_t enumerated boolean type. This should
* only be used as a base type when a client API's boolean type is
* an enum. Client APIs which use an integer or other type for
* booleans cannot use this as the base type for their boolean.
*
* Tokens defined in khrplatform.h:
*
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
*
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
*
* Calling convention macros defined in this file:
* KHRONOS_APICALL
* KHRONOS_APIENTRY
* KHRONOS_APIATTRIBUTES
*
* These may be used in function prototypes as:
*
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
* int arg1,
* int arg2) KHRONOS_APIATTRIBUTES;
*/
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
# define KHRONOS_STATIC 1
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APICALL
*-------------------------------------------------------------------------
* This precedes the return type of the function in the function prototype.
*/
#if defined(KHRONOS_STATIC)
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
* header compatible with static linking. */
# define KHRONOS_APICALL
#elif defined(_WIN32)
# define KHRONOS_APICALL __declspec(dllimport)
#elif defined (__SYMBIAN32__)
# define KHRONOS_APICALL IMPORT_C
#elif defined(__ANDROID__)
# define KHRONOS_APICALL __attribute__((visibility("default")))
#else
# define KHRONOS_APICALL
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIENTRY
*-------------------------------------------------------------------------
* This follows the return type of the function and precedes the function
* name in the function prototype.
*/
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
/* Win32 but not WinCE */
# define KHRONOS_APIENTRY __stdcall
#else
# define KHRONOS_APIENTRY
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIATTRIBUTES
*-------------------------------------------------------------------------
* This follows the closing parenthesis of the function prototype arguments.
*/
#if defined (__ARMCC_2__)
#define KHRONOS_APIATTRIBUTES __softfp
#else
#define KHRONOS_APIATTRIBUTES
#endif
/*-------------------------------------------------------------------------
* basic type definitions
*-----------------------------------------------------------------------*/
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
/*
* Using <stdint.h>
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
/*
* To support platform where unsigned long cannot be used interchangeably with
* inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
* Ideally, we could just use (u)intptr_t everywhere, but this could result in
* ABI breakage if khronos_uintptr_t is changed from unsigned long to
* unsigned long long or similar (this results in different C++ name mangling).
* To avoid changes for existing platforms, we restrict usage of intptr_t to
* platforms where the size of a pointer is larger than the size of long.
*/
#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
#define KHRONOS_USE_INTPTR_T
#endif
#endif
#elif defined(__VMS ) || defined(__sgi)
/*
* Using <inttypes.h>
*/
#include <inttypes.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
/*
* Win32
*/
typedef __int32 khronos_int32_t;
typedef unsigned __int32 khronos_uint32_t;
typedef __int64 khronos_int64_t;
typedef unsigned __int64 khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(__sun__) || defined(__digital__)
/*
* Sun or Digital
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#if defined(__arch64__) || defined(_LP64)
typedef long int khronos_int64_t;
typedef unsigned long int khronos_uint64_t;
#else
typedef long long int khronos_int64_t;
typedef unsigned long long int khronos_uint64_t;
#endif /* __arch64__ */
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif 0
/*
* Hypothetical platform with no float or int64 support
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#define KHRONOS_SUPPORT_INT64 0
#define KHRONOS_SUPPORT_FLOAT 0
#else
/*
* Generic fallback
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#endif
/*
* Types that are (so far) the same on all platforms
*/
typedef signed char khronos_int8_t;
typedef unsigned char khronos_uint8_t;
typedef signed short int khronos_int16_t;
typedef unsigned short int khronos_uint16_t;
/*
* Types that differ between LLP64 and LP64 architectures - in LLP64,
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
* to be the only LLP64 architecture in current use.
*/
#ifdef KHRONOS_USE_INTPTR_T
typedef intptr_t khronos_intptr_t;
typedef uintptr_t khronos_uintptr_t;
#elif defined(_WIN64)
typedef signed long long int khronos_intptr_t;
typedef unsigned long long int khronos_uintptr_t;
#else
typedef signed long int khronos_intptr_t;
typedef unsigned long int khronos_uintptr_t;
#endif
#if defined(_WIN64)
typedef signed long long int khronos_ssize_t;
typedef unsigned long long int khronos_usize_t;
#else
typedef signed long int khronos_ssize_t;
typedef unsigned long int khronos_usize_t;
#endif
#if KHRONOS_SUPPORT_FLOAT
/*
* Float type
*/
typedef float khronos_float_t;
#endif
#if KHRONOS_SUPPORT_INT64
/* Time types
*
* These types can be used to represent a time interval in nanoseconds or
* an absolute Unadjusted System Time. Unadjusted System Time is the number
* of nanoseconds since some arbitrary system event (e.g. since the last
* time the system booted). The Unadjusted System Time is an unsigned
* 64 bit value that wraps back to 0 every 584 years. Time intervals
* may be either signed or unsigned.
*/
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
typedef khronos_int64_t khronos_stime_nanoseconds_t;
#endif
/*
* Dummy value used to pad enum types to 32 bits.
*/
#ifndef KHRONOS_MAX_ENUM
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
#endif
/*
* Enumerated boolean type
*
* Values other than zero should be considered to be true. Therefore
* comparisons should not be made against KHRONOS_TRUE.
*/
typedef enum {
KHRONOS_FALSE = 0,
KHRONOS_TRUE = 1,
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
} khronos_boolean_enum_t;
#endif /* __khrplatform_h_ */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+7 -6
View File
@@ -9,11 +9,8 @@ if (EMSCRIPTEN OR SLIC3R_OPENGL_ES)
glad/src/gles2.c
)
else ()
set(GLAD_SOURCES
glad/include/glad/gl.h
glad/include/KHR/khrplatform.h
glad/src/gl.c
)
# Use shared GLAD library for GL; no local sources needed
set(GLAD_SOURCES "")
endif ()
set(LIBVGCODE_SOURCES
@@ -77,4 +74,8 @@ if (WIN32)
endif ()
# glad includes
include_directories(glad/include)
if (EMSCRIPTEN OR SLIC3R_OPENGL_ES)
target_include_directories(libvgcode PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/glad/include)
else ()
target_link_libraries(libvgcode PUBLIC glad)
endif ()
+2 -2
View File
@@ -7,9 +7,9 @@
// OpenGL loader
#ifdef ENABLE_OPENGL_ES
#include "../glad/include/glad/gles2.h"
#include <glad/gles2.h>
#else
#include "../glad/include/glad/gl.h"
#include <glad/gl.h>
#endif // ENABLE_OPENGL_ES
#include <string>
+11 -1
View File
@@ -301,6 +301,8 @@ set(SLIC3R_GUI_SOURCES
GUI/KBShortcutsDialog.hpp
GUI/LibVGCode/LibVGCodeWrapper.hpp
GUI/LibVGCode/LibVGCodeWrapper.cpp
GUI/LinuxDisplayBackend.cpp
GUI/LinuxDisplayBackend.hpp
GUI/MainFrame.cpp
GUI/MainFrame.hpp
GUI/MarkdownTip.cpp
@@ -736,7 +738,7 @@ else()
set(_opengl_link_lib OpenGL::GL)
endif()
target_link_libraries(libslic3r_gui libslic3r cereal::cereal imgui imguizmo minilzo libvgcode md4c-html GLEW::GLEW OpenGL::GL hidapi ${wxWidgets_LIBRARIES} glfw libcurl OpenSSL::SSL OpenSSL::Crypto noise::noise)
target_link_libraries(libslic3r_gui libslic3r cereal::cereal imgui imguizmo minilzo libvgcode md4c-html glad ${_opengl_link_lib} hidapi ${wxWidgets_LIBRARIES} glfw libcurl OpenSSL::SSL OpenSSL::Crypto noise::noise)
if (MSVC)
@@ -797,6 +799,14 @@ if (UNIX AND NOT APPLE)
target_include_directories(libslic3r_gui SYSTEM PRIVATE ${GTK${SLIC3R_GTK}_INCLUDE_DIRS} ${LIBSECRET_INCLUDE_DIRS} ${webkit2gtk_INCLUDE_DIRS})
target_link_libraries(libslic3r_gui ${GTK${SLIC3R_GTK}_LIBRARIES} fontconfig ${LIBSECRET_LIBRARIES})
# Propagate GDK backend detection results as compile definitions so that
# LinuxDisplayBackend.cpp can include the right GDK headers.
if (wxHAVE_GDK_X11)
target_compile_definitions(libslic3r_gui PRIVATE wxHAVE_GDK_X11)
endif ()
if (wxHAVE_GDK_WAYLAND)
target_compile_definitions(libslic3r_gui PRIVATE wxHAVE_GDK_WAYLAND)
endif ()
# We add GStreamer for bambu:/// support.
pkg_check_modules(GSTREAMER REQUIRED gstreamer-1.0)
+1 -1
View File
@@ -15,7 +15,7 @@
#include "Plater.hpp"
#include "Camera.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem/operations.hpp>
+1 -1
View File
@@ -1,4 +1,4 @@
#include <GL/glew.h>
#include <glad/gl.h>
#include "3DScene.hpp"
#include "GLShader.hpp"
+1 -1
View File
@@ -94,7 +94,7 @@ void CopyrightsDialog::fill_entries()
{ "Eigen3", "", "http://eigen.tuxfamily.org" },
{ "Expat", "", "http://www.libexpat.org" },
{ "fast_float", "", "https://github.com/fastfloat/fast_float" },
{ "GLEW (The OpenGL Extension Wrangler Library)", "", "http://glew.sourceforge.net" },
{ "GLAD (Multi-Language GL Loader-Generator)", "", "https://github.com/Dav1dde/glad" },
{ "GLFW", "", "https://www.glfw.org" },
{ "GNU gettext", "", "https://www.gnu.org/software/gettext" },
{ "ImGUI", "", "https://github.com/ocornut/imgui" },
+31 -8
View File
@@ -6,6 +6,9 @@
#include "I18N.hpp"
#include "GUI_App.hpp"
#include "GUI.hpp"
#ifdef __WXGTK__
#include "LinuxDisplayBackend.hpp"
#endif
#include "wxExtensions.hpp"
#include "Plater.hpp"
#include "MainFrame.hpp"
@@ -56,9 +59,9 @@ CenteredTitle::CenteredTitle(wxWindow* parent)
wxString ellipsized = wxControl::Ellipsize(m_title, dc, wxELLIPSIZE_END, wxMax(0, rect.GetWidth() - FromDIP(8)));
int y = rect.y + (rect.height - textHeight) / 2;
int x = rect.x + (ellipsized != m_title) // is ellipsized
int x = rect.x + ((ellipsized != m_title) // is ellipsized
? FromDIP(4) // align to left when clipped
: (rect.width - dc.GetTextExtent(m_title).GetWidth()) / 2; // centered when has available space
: (rect.width - dc.GetTextExtent(m_title).GetWidth()) / 2); // centered when has available space
dc.DrawText(ellipsized, x, y);
});
@@ -346,6 +349,10 @@ void BBLTopbar::Init(wxFrame* parent)
this->Bind(wxEVT_LEFT_DCLICK, &BBLTopbar::OnMouseLeftDClock, this);
this->Bind(wxEVT_LEFT_DOWN, &BBLTopbar::OnMouseLeftDown, this);
this->Bind(wxEVT_LEFT_UP, &BBLTopbar::OnMouseLeftUp, this);
this->Bind(wxEVT_LEAVE_WINDOW, [this](wxMouseEvent& event) {
m_last_mouse_position = wxDefaultPosition;
event.Skip();
});
this->Bind(wxEVT_AUITOOLBAR_TOOL_DROPDOWN, &BBLTopbar::OnOpenProject, this, wxID_OPEN);
this->Bind(wxEVT_AUITOOLBAR_TOOL_DROPDOWN, &BBLTopbar::OnSaveProject, this, wxID_SAVE);
this->Bind(wxEVT_AUITOOLBAR_TOOL_DROPDOWN, &BBLTopbar::OnRedo, this, wxID_REDO);
@@ -589,8 +596,9 @@ void BBLTopbar::OnCloseFrame(wxAuiToolBarEvent& event)
void BBLTopbar::OnMouseLeftDClock(wxMouseEvent& mouse)
{
wxPoint mouse_pos = ::wxGetMousePosition();
wxAuiToolBarItem* item = this->FindToolByCurrentPosition();
m_last_mouse_position = mouse.GetPosition();
wxPoint mouse_pos = this->ClientToScreen(mouse.GetPosition());
wxAuiToolBarItem* item = this->FindToolByPosition(mouse.GetX(), mouse.GetY());
// check whether mouse is not on any tool item
if (item != NULL && item->GetWindow() != m_title_ctrl) {
mouse.Skip();
@@ -658,9 +666,12 @@ void BBLTopbar::OnCalibToolItem(wxAuiToolBarEvent &evt)
void BBLTopbar::OnMouseLeftDown(wxMouseEvent& event)
{
wxPoint mouse_pos = ::wxGetMousePosition();
m_last_mouse_position = event.GetPosition();
// Use event-relative coords converted to screen, instead of wxGetMousePosition()
// which returns (0,0) on Wayland for global screen coordinates.
wxPoint mouse_pos = this->ClientToScreen(event.GetPosition());
wxPoint frame_pos = m_frame->GetScreenPosition();
wxAuiToolBarItem* item = this->FindToolByCurrentPosition();
wxAuiToolBarItem* item = this->FindToolByPosition(event.GetX(), event.GetY());
m_delta = mouse_pos - frame_pos;
if (item == NULL || item->GetWindow() == m_title_ctrl)
@@ -688,7 +699,8 @@ void BBLTopbar::OnMouseLeftDown(wxMouseEvent& event)
void BBLTopbar::OnMouseLeftUp(wxMouseEvent& event)
{
wxPoint mouse_pos = ::wxGetMousePosition();
m_last_mouse_position = event.GetPosition();
wxPoint mouse_pos = this->ClientToScreen(event.GetPosition());
if (HasCapture())
{
ReleaseMouse();
@@ -699,7 +711,10 @@ void BBLTopbar::OnMouseLeftUp(wxMouseEvent& event)
void BBLTopbar::OnMouseMotion(wxMouseEvent& event)
{
wxPoint mouse_pos = ::wxGetMousePosition();
m_last_mouse_position = event.GetPosition();
// Use event-relative coords converted to screen, instead of wxGetMousePosition()
// which returns (0,0) on Wayland for global screen coordinates.
wxPoint mouse_pos = this->ClientToScreen(event.GetPosition());
if (!HasCapture()) {
//m_frame->OnMouseMotion(event);
@@ -743,6 +758,14 @@ void BBLTopbar::OnMenuClose(wxMenuEvent& event)
wxAuiToolBarItem* BBLTopbar::FindToolByCurrentPosition()
{
if (m_last_mouse_position != wxDefaultPosition && GetClientRect().Contains(m_last_mouse_position))
return this->FindToolByPosition(m_last_mouse_position.x, m_last_mouse_position.y);
#ifdef __WXGTK__
if (Slic3r::GUI::is_running_on_wayland())
return nullptr;
#endif
wxPoint mouse_pos = ::wxGetMousePosition();
wxPoint client_pos = this->ScreenToClient(mouse_pos);
return this->FindToolByPosition(client_pos.x, client_pos.y);
+1
View File
@@ -85,6 +85,7 @@ private:
wxAuiToolBarItem* m_dropdown_menu_item;
wxRect m_normalRect;
wxPoint m_delta;
wxPoint m_last_mouse_position{wxDefaultPosition};
wxMenu m_top_menu;
wxMenu* m_file_menu;
wxMenu m_calib_menu;
+1 -1
View File
@@ -13,7 +13,7 @@
#include <wx/mstream.h>
#include <wx/rawbmp.h>
#endif /* __WXGTK2__ */
#include <GL/glew.h>
#include <glad/gl.h>
#define NANOSVG_IMPLEMENTATION
#include "nanosvg/nanosvg.h"
#define NANOSVGRAST_IMPLEMENTATION
+1 -1
View File
@@ -8,7 +8,7 @@
#include "Plater.hpp"
#endif // ENABLE_CAMERA_STATISTICS
#include <GL/glew.h>
#include <glad/gl.h>
namespace Slic3r {
namespace GUI {
@@ -336,6 +336,8 @@ void DesktopIntegrationDialog::perform_desktop_integration()
"Exec=\"%3%\" %%F\n"
"Terminal=false\n"
"Type=Application\n"
"PrefersNonDefaultGPU=true\n"
"X-KDE-RunOnDiscreteGpu=true\n"
"MimeType=model/stl;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;application/x-amf;\n"
"Categories=Graphics;3DGraphics;Engineering;\n"
"Keywords=3D;Printing;Slicer;slice;3D;printer;convert;gcode;stl;obj;amf;SLA\n"
@@ -405,6 +407,8 @@ void DesktopIntegrationDialog::perform_desktop_integration()
"Exec=\"%3%\" --gcodeviewer %%F\n"
"Terminal=false\n"
"Type=Application\n"
"PrefersNonDefaultGPU=true\n"
"X-KDE-RunOnDiscreteGpu=true\n"
"MimeType=text/x.gcode;\n"
"Categories=Graphics;3DGraphics;\n"
"Keywords=3D;Printing;Slicer;\n"
+1 -1
View File
@@ -32,7 +32,7 @@
#endif // ENABLE_ACTUAL_SPEED_DEBUG
#include <imgui/imgui_internal.h>
#include <GL/glew.h>
#include <glad/gl.h>
#include <boost/log/trivial.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/nowide/cstdio.hpp>
+52 -49
View File
@@ -44,7 +44,7 @@
#include "slic3r/Utils/RetinaHelper.hpp"
#endif
#include <GL/glew.h>
#include <glad/gl.h>
#include <wx/glcanvas.h>
#include <wx/bitmap.h>
@@ -2194,8 +2194,12 @@ void GLCanvas3D::render(bool only_init)
wxGetApp().imgui()->render();
m_canvas->SwapBuffers();
m_render_stats.increment_fps_counter();
// On Wayland, eglSwapBuffers blocks when the canvas is hidden or
// occluded. Skip the swap to avoid stalling the render loop.
if (m_canvas->IsShownOnScreen()) {
m_canvas->SwapBuffers();
m_render_stats.increment_fps_counter();
}
}
void GLCanvas3D::render_thumbnail(ThumbnailData & thumbnail_data,
@@ -4816,14 +4820,13 @@ Vec2d GLCanvas3D::get_local_mouse_position() const
if (m_canvas == nullptr)
return Vec2d::Zero();
wxPoint mouse_pos = m_canvas->ScreenToClient(wxGetMousePosition());
const double factor =
#if ENABLE_RETINA_GL
m_retina_helper->get_scale_factor();
#else
1.0;
#endif
return Vec2d(factor * mouse_pos.x, factor * mouse_pos.y);
// Use the cached mouse position from event handlers (m_mouse.position)
// instead of wxGetMousePosition() + ScreenToClient(), because
// wxGetMousePosition() returns (0,0) on Wayland for global coords.
// m_mouse.position already stores local canvas coordinates (set from
// event.GetX(), event.GetY()) and is already scaled by the retina factor
// in on_mouse(), so we can return it directly.
return m_mouse.position;
}
void GLCanvas3D::set_tooltip(const std::string& tooltip)
@@ -6387,21 +6390,21 @@ void GLCanvas3D::render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data,
// glsafe(::glEnable(GL_MULTISAMPLE));
GLint max_samples;
glsafe(::glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_samples));
glsafe(::glGetIntegerv(GL_MAX_SAMPLES, &max_samples));
GLsizei num_samples = max_samples / 2;
GLuint render_fbo;
glsafe(::glGenFramebuffersEXT(1, &render_fbo));
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, render_fbo));
glsafe(::glGenFramebuffers(1, &render_fbo));
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, render_fbo));
GLuint render_tex = 0;
GLuint render_tex_buffer = 0;
if (multisample) {
// use renderbuffer instead of texture to avoid the need to use glTexImage2DMultisample which is available only since OpenGL 3.2
glsafe(::glGenRenderbuffersEXT(1, &render_tex_buffer));
glsafe(::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, render_tex_buffer));
glsafe(::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, num_samples, GL_RGBA8, w, h));
glsafe(::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, render_tex_buffer));
glsafe(::glGenRenderbuffers(1, &render_tex_buffer));
glsafe(::glBindRenderbuffer(GL_RENDERBUFFER, render_tex_buffer));
glsafe(::glRenderbufferStorageMultisample(GL_RENDERBUFFER, num_samples, GL_RGBA8, w, h));
glsafe(::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, render_tex_buffer));
}
else {
glsafe(::glGenTextures(1, &render_tex));
@@ -6409,31 +6412,31 @@ void GLCanvas3D::render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data,
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, render_tex, 0));
glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, render_tex, 0));
}
GLuint render_depth;
glsafe(::glGenRenderbuffersEXT(1, &render_depth));
glsafe(::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, render_depth));
glsafe(::glGenRenderbuffers(1, &render_depth));
glsafe(::glBindRenderbuffer(GL_RENDERBUFFER, render_depth));
if (multisample)
glsafe(::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, num_samples, GL_DEPTH_COMPONENT24, w, h));
glsafe(::glRenderbufferStorageMultisample(GL_RENDERBUFFER, num_samples, GL_DEPTH_COMPONENT24, w, h));
else
glsafe(::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, w, h));
glsafe(::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w, h));
glsafe(::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, render_depth));
glsafe(::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, render_depth));
GLenum drawBufs[] = { GL_COLOR_ATTACHMENT0 };
glsafe(::glDrawBuffers(1, drawBufs));
if (::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT) {
if (::glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {
render_thumbnail_internal(thumbnail_data, thumbnail_params, partplate_list, model_objects, volumes, extruder_colors, shader, camera_type, camera_view_angle_type,
for_picking,
ban_light);
if (multisample) {
GLuint resolve_fbo;
glsafe(::glGenFramebuffersEXT(1, &resolve_fbo));
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, resolve_fbo));
glsafe(::glGenFramebuffers(1, &resolve_fbo));
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, resolve_fbo));
GLuint resolve_tex;
glsafe(::glGenTextures(1, &resolve_tex));
@@ -6441,21 +6444,21 @@ void GLCanvas3D::render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data,
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
glsafe(::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, resolve_tex, 0));
glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolve_tex, 0));
glsafe(::glDrawBuffers(1, drawBufs));
if (::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT) {
glsafe(::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, render_fbo));
glsafe(::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, resolve_fbo));
glsafe(::glBlitFramebufferEXT(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_LINEAR));
if (::glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {
glsafe(::glBindFramebuffer(GL_READ_FRAMEBUFFER, render_fbo));
glsafe(::glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolve_fbo));
glsafe(::glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_LINEAR));
glsafe(::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, resolve_fbo));
glsafe(::glBindFramebuffer(GL_READ_FRAMEBUFFER, resolve_fbo));
glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
}
glsafe(::glDeleteTextures(1, &resolve_tex));
glsafe(::glDeleteFramebuffersEXT(1, &resolve_fbo));
glsafe(::glDeleteFramebuffers(1, &resolve_fbo));
}
else
glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
@@ -6465,13 +6468,13 @@ void GLCanvas3D::render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data,
#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
}
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
glsafe(::glDeleteRenderbuffersEXT(1, &render_depth));
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, 0));
glsafe(::glDeleteRenderbuffers(1, &render_depth));
if (render_tex_buffer != 0)
glsafe(::glDeleteRenderbuffersEXT(1, &render_tex_buffer));
glsafe(::glDeleteRenderbuffers(1, &render_tex_buffer));
if (render_tex != 0)
glsafe(::glDeleteTextures(1, &render_tex));
glsafe(::glDeleteFramebuffersEXT(1, &render_fbo));
glsafe(::glDeleteFramebuffers(1, &render_fbo));
//if (!multisample)
// glsafe(::glDisable(GL_MULTISAMPLE));
@@ -7248,8 +7251,8 @@ void GLCanvas3D::_rectangular_selection_picking_pass()
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, render_fbo));
}
else {
glsafe(::glGenFramebuffersEXT(1, &render_fbo));
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, render_fbo));
glsafe(::glGenFramebuffers(1, &render_fbo));
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, render_fbo));
}
glsafe(::glGenTextures(1, &render_tex));
glsafe(::glBindTexture(GL_TEXTURE_2D, render_tex));
@@ -7264,11 +7267,11 @@ void GLCanvas3D::_rectangular_selection_picking_pass()
glsafe(::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, render_depth));
}
else {
glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, render_tex, 0));
glsafe(::glGenRenderbuffersEXT(1, &render_depth));
glsafe(::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, render_depth));
glsafe(::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height));
glsafe(::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, render_depth));
glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, render_tex, 0));
glsafe(::glGenRenderbuffers(1, &render_depth));
glsafe(::glBindRenderbuffer(GL_RENDERBUFFER, render_depth));
glsafe(::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height));
glsafe(::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, render_depth));
}
const GLenum drawBufs[] = { GL_COLOR_ATTACHMENT0 };
glsafe(::glDrawBuffers(1, drawBufs));
@@ -7277,7 +7280,7 @@ void GLCanvas3D::_rectangular_selection_picking_pass()
use_framebuffer = false;
}
else {
if (::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
if (::glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
use_framebuffer = false;
}
}
@@ -7388,11 +7391,11 @@ void GLCanvas3D::_rectangular_selection_picking_pass()
glsafe(::glDeleteFramebuffers(1, &render_fbo));
}
else if (framebuffers_type == OpenGLManager::EFramebufferType::Ext) {
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, 0));
if (render_depth != 0)
glsafe(::glDeleteRenderbuffersEXT(1, &render_depth));
glsafe(::glDeleteRenderbuffers(1, &render_depth));
if (render_fbo != 0)
glsafe(::glDeleteFramebuffersEXT(1, &render_fbo));
glsafe(::glDeleteFramebuffers(1, &render_fbo));
}
if (render_tex != 0)
+1 -1
View File
@@ -954,7 +954,7 @@ public:
Camera::ViewAngleType camera_view_angle_type = Camera::ViewAngleType::Iso,
bool for_picking = false,
bool ban_light = false);
// render thumbnail using an off-screen framebuffer when GLEW_EXT_framebuffer_object is supported
// render thumbnail using an off-screen framebuffer when GL_EXT_framebuffer_object is supported
static void render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params,
PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<ColorRGBA>& extruder_colors,
GLShaderProgram * shader,
+1 -1
View File
@@ -20,7 +20,7 @@
#include <igl/per_vertex_normals.h>
#endif // ENABLE_SMOOTH_NORMALS
#include <GL/glew.h>
#include <glad/gl.h>
namespace Slic3r {
namespace GUI {
+1 -1
View File
@@ -7,7 +7,7 @@
#include "Plater.hpp"
#include <igl/project.h>
#include <GL/glew.h>
#include <glad/gl.h>
namespace Slic3r {
namespace GUI {
+1 -1
View File
@@ -7,7 +7,7 @@
#include "libslic3r/Color.hpp"
#include <boost/nowide/fstream.hpp>
#include <GL/glew.h>
#include <glad/gl.h>
#include <cassert>
#include <boost/log/trivial.hpp>
+1 -1
View File
@@ -9,7 +9,7 @@
#include <string_view>
using namespace std::literals;
#include <GL/glew.h>
#include <glad/gl.h>
namespace Slic3r {
+1 -1
View File
@@ -11,7 +11,7 @@
#include "GUI_App.hpp"
#include "GLModel.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
#include <wx/image.h>
#include <boost/filesystem.hpp>
+28 -2
View File
@@ -161,6 +161,10 @@ typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS2)(
#include <boost/nowide/fstream.hpp>
#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG
#ifdef __WXGTK__
#include "LinuxDisplayBackend.hpp"
#endif
// Needed for forcing menu icons back under gtk2 and gtk3
#if defined(__WXGTK20__) || defined(__WXGTK3__)
#include <gtk/gtk.h>
@@ -909,6 +913,8 @@ void GUI_App::post_init()
}
else {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << "Found glcontext not ready, postpone the init";
plater_->canvas3D()->enable_render(true);
plater_->canvas3D()->set_as_dirty();
}
//#endif
if (is_editor())
@@ -2303,7 +2309,8 @@ bool GUI_App::init_opengl()
{
#ifdef __linux__
bool status = m_opengl_mgr.init_gl();
m_opengl_initialized = true;
if (status)
m_opengl_initialized = true;
return status;
#else
return m_opengl_mgr.init_gl();
@@ -3091,6 +3098,20 @@ bool GUI_App::on_init_inner()
// Let the libslic3r know the callback, which will translate messages on demand.
Slic3r::I18N::set_translate_callback(libslic3r_translate_callback);
#if defined(__WXGTK__) && wxHAS_EGL
// Configure GL backend before any wxGLCanvas is created.
// On X11, prefer GLX for maximum driver compatibility.
// On Wayland, EGL is used by default (only option).
if (Slic3r::GUI::is_running_on_x11()) {
wxGLCanvas::PreferGLX();
BOOST_LOG_TRIVIAL(info) << "X11 detected, using GLX for OpenGL context";
} else if (Slic3r::GUI::is_running_on_wayland()) {
BOOST_LOG_TRIVIAL(info) << "Wayland detected, using EGL for OpenGL context";
} else {
BOOST_LOG_TRIVIAL(warning) << "Unknown display backend, defaulting to EGL";
}
#endif
BOOST_LOG_TRIVIAL(info) << "create the main window";
mainframe = new MainFrame();
// hide settings tabs after first Layout
@@ -7708,7 +7729,12 @@ bool GUI_App::window_pos_restore(wxTopLevelWindow* window, const std::string &na
}
const wxRect& rect = metrics->get_rect();
window->SetPosition(rect.GetPosition());
#if defined(__WXGTK__)
// On Wayland, SetPosition() is a no-op for top-level windows.
// Only restore size and maximize state.
if (!Slic3r::GUI::is_running_on_wayland())
#endif
window->SetPosition(rect.GetPosition());
window->SetSize(rect.GetSize());
window->Maximize(metrics->get_maximized());
return true;
+7
View File
@@ -1153,6 +1153,7 @@ void ObjectList::update_name_in_list(int obj_idx, int vol_idx) const
void ObjectList::selection_changed()
{
if (wxGetApp().is_closing()) return;
if (m_prevent_list_events) return;
fix_multiselection_conflicts();
@@ -3456,6 +3457,9 @@ void ObjectList::changed_object(const int obj_idx/* = -1*/) const
void ObjectList::part_selection_changed()
{
if (wxGetApp().is_closing())
return;
if (m_extruder_editor) m_extruder_editor->Hide();
int obj_idx = -1;
int volume_id = -1;
@@ -4656,6 +4660,9 @@ int ObjectList::get_selected_layers_range_idx() const
void ObjectList::update_selections()
{
if (wxGetApp().is_closing())
return;
const Selection& selection = scene_selection();
wxDataViewItemArray sels;
+3
View File
@@ -86,6 +86,9 @@ bool ObjectSettings::update_settings_list()
m_settings_list_sizer->Clear(true);
m_og_settings.resize(0);
if (wxGetApp().is_closing())
return false;
auto objects_ctrl = wxGetApp().obj_list();
auto objects_model = wxGetApp().obj_list()->GetModel();
auto config = wxGetApp().obj_list()->config();
+1 -1
View File
@@ -2,7 +2,7 @@
#include "GLGizmoAdvancedCut.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
#include <wx/button.h>
#include <wx/checkbox.h>
+1 -1
View File
@@ -12,7 +12,7 @@
#include <numeric>
#include <GL/glew.h>
#include <glad/gl.h>
#include <tbb/parallel_for.h>
#include <future>
+1 -1
View File
@@ -1,7 +1,7 @@
#include "GLGizmoBase.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/Plater.hpp"
+1 -1
View File
@@ -1,5 +1,5 @@
#include "GLGizmoBrimEars.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
#include "slic3r/GUI/GLCanvas3D.hpp"
#include "slic3r/GUI/Camera.hpp"
#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp"
+1 -1
View File
@@ -1,7 +1,7 @@
#include "GLGizmoCut.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
#include <algorithm>
+1 -1
View File
@@ -50,7 +50,7 @@
#include <cereal/types/string.hpp>
#include <cereal/archives/binary.hpp>
#include <GL/glew.h>
#include <glad/gl.h>
#include <chrono> // measure enumeration of fonts
// uncomment for easier debug
+1 -1
View File
@@ -19,7 +19,7 @@
#include "libslic3r/TextConfiguration.hpp"
#include <imgui/imgui.h>
#include <GL/glew.h>
#include <glad/gl.h>
class wxFont;
namespace Slic3r{
@@ -9,7 +9,7 @@
#include "slic3r/GUI/ImGuiWrapper.hpp"
#include "slic3r/GUI/Plater.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
#ifdef __WINDOWS__
#include <windows.h>
+1 -1
View File
@@ -15,7 +15,7 @@
#include "slic3r/GUI/GUI.hpp"
#include "slic3r/Utils/UndoRedo.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
#include <boost/log/trivial.hpp>
+1 -1
View File
@@ -9,7 +9,7 @@
#include <numeric>
#include <GL/glew.h>
#include <glad/gl.h>
namespace Slic3r {
namespace GUI {
+1 -1
View File
@@ -11,7 +11,7 @@
#include "slic3r/GUI/Plater.hpp"
#include "slic3r/Utils/UndoRedo.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
#include <algorithm>
namespace Slic3r::GUI {
+1 -1
View File
@@ -3,7 +3,7 @@
#include "slic3r/GUI/Camera.hpp"
#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/GUI_ObjectSettings.hpp"
+1 -1
View File
@@ -12,7 +12,7 @@
#include <numeric>
#include <GL/glew.h>
#include <glad/gl.h>
#include <tbb/parallel_for.h>
@@ -15,7 +15,7 @@
#include "slic3r/Utils/UndoRedo.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
namespace Slic3r::GUI {
+1 -1
View File
@@ -6,7 +6,7 @@
#include "libslic3r/AppConfig.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
#include <wx/utils.h>
+1 -1
View File
@@ -2,7 +2,7 @@
#include "slic3r/GUI/GLCanvas3D.hpp"
#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/Camera.hpp"
+1 -1
View File
@@ -10,7 +10,7 @@
#include "libslic3r/Model.hpp"
#include <cereal/types/vector.hpp>
#include <GL/glew.h>
#include <glad/gl.h>
#include <memory>
+1 -1
View File
@@ -9,7 +9,7 @@
#include "libslic3r/PresetBundle.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
namespace Slic3r {
namespace GUI {
+1 -1
View File
@@ -32,7 +32,7 @@
#include <wx/display.h> // detection of change DPI
#include <boost/log/trivial.hpp>
#include <GL/glew.h>
#include <glad/gl.h>
#include <chrono> // measure enumeration of fonts
#include <sstream> // save for svg
#include <array>
+1 -1
View File
@@ -19,7 +19,7 @@
#include "libslic3r/Model.hpp"
#include <imgui/imgui.h>
#include <GL/glew.h>
#include <glad/gl.h>
namespace Slic3r{
class ModelVolume;
+1 -1
View File
@@ -3,7 +3,7 @@
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/Plater.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
#include <wx/utils.h>
+1 -1
View File
@@ -11,7 +11,7 @@
#include "slic3r/GUI/GUI.hpp"
#include "slic3r/Utils/UndoRedo.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
namespace Slic3r::GUI {
+1 -1
View File
@@ -11,7 +11,7 @@
#include "libslic3r/Model.hpp"
#include "libslic3r/QuadricEdgeCollapse.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
#include <thread>
+1 -1
View File
@@ -6,7 +6,7 @@
#include "slic3r/GUI/MainFrame.hpp"
#include "slic3r/Utils/UndoRedo.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
#include <wx/msgdlg.h>
#include <wx/settings.h>
+1 -1
View File
@@ -16,7 +16,7 @@
#include <boost/log/trivial.hpp>
#include <GL/glew.h>
#include <glad/gl.h>
#ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS
+1 -1
View File
@@ -10,7 +10,7 @@
#include "libslic3r/PresetBundle.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
namespace Slic3r {
namespace GUI {
+2 -2
View File
@@ -1,7 +1,7 @@
#include "IMToolbar.hpp"
#include "3DScene.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
#include <imgui/imgui_internal.h>
#include <imgui/imgui.h>
@@ -87,7 +87,7 @@ bool IMReturnToolbar::init()
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
glsafe(::glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
if (compress && GLEW_EXT_texture_compression_s3tc)
if (compress && GLAD_GL_EXT_texture_compression_s3tc)
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, data.width, data.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
else
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, data.width, data.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
+1 -1
View File
@@ -9,7 +9,7 @@
#include "libslic3r/Utils.hpp" // ScopeGuard
#include "3DScene.hpp" // glsafe
#include "GL/glew.h"
#include <glad/gl.h>
#define STB_RECT_PACK_IMPLEMENTATION
#include "imgui/imstb_rectpack.h" // distribute rectangles
+2 -2
View File
@@ -18,7 +18,7 @@
#include <wx/clipbrd.h>
#include <wx/debug.h>
#include <GL/glew.h>
#include <glad/gl.h>
#ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS
@@ -2839,7 +2839,7 @@ void ImGuiWrapper::init_font(bool compress)
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
glsafe(::glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
if (compress && GLEW_EXT_texture_compression_s3tc)
if (compress && GLAD_GL_EXT_texture_compression_s3tc)
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
else
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
@@ -3,7 +3,7 @@
#include <vector>
#include <string>
#include <GL/glew.h>
#include <glad/gl.h>
#include <wx/string.h>
#include <wx/fontenc.h>
#include "Job.hpp"
+53
View File
@@ -0,0 +1,53 @@
#include "LinuxDisplayBackend.hpp"
#if defined(__WXGTK__)
#include <gdk/gdk.h>
#ifdef wxHAVE_GDK_X11
#include <gdk/gdkx.h>
#endif
#ifdef wxHAVE_GDK_WAYLAND
#include <gdk/gdkwayland.h>
#endif
namespace Slic3r {
namespace GUI {
LinuxDisplayBackend get_linux_display_backend()
{
static const LinuxDisplayBackend backend = []() -> LinuxDisplayBackend {
GdkDisplay *display = gdk_display_get_default();
if (!display)
return LinuxDisplayBackend::Unknown;
#ifdef wxHAVE_GDK_WAYLAND
if (GDK_IS_WAYLAND_DISPLAY(display))
return LinuxDisplayBackend::Wayland;
#endif
#ifdef wxHAVE_GDK_X11
if (GDK_IS_X11_DISPLAY(display))
return LinuxDisplayBackend::X11;
#endif
return LinuxDisplayBackend::Unknown;
}();
return backend;
}
bool is_running_on_wayland()
{
return get_linux_display_backend() == LinuxDisplayBackend::Wayland;
}
bool is_running_on_x11()
{
return get_linux_display_backend() == LinuxDisplayBackend::X11;
}
} // namespace GUI
} // namespace Slic3r
#endif // defined(__WXGTK__)
+19
View File
@@ -0,0 +1,19 @@
#pragma once
namespace Slic3r {
namespace GUI {
#if defined(__WXGTK__)
enum class LinuxDisplayBackend { X11, Wayland, Unknown };
// Detect which display backend is in use at runtime.
// Must be called after gtk_init() / wxWidgets initialization.
LinuxDisplayBackend get_linux_display_backend();
// Convenience predicates.
bool is_running_on_wayland();
bool is_running_on_x11();
#endif // defined(__WXGTK__)
} // namespace GUI
} // namespace Slic3r
+2
View File
@@ -586,6 +586,8 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
#endif
MarkdownTip::ExitTip();
// Prevent queued selection/UI refresh work from running as normal during reset.
wxGetApp().set_closing(true);
m_plater->reset();
this->shutdown();
+1 -1
View File
@@ -14,7 +14,7 @@
#include "slic3r/GUI/CameraUtils.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
#include <igl/unproject.h>
+42 -21
View File
@@ -7,7 +7,7 @@
#include "libslic3r/Platform.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
@@ -22,16 +22,11 @@
#include "../Utils/MacDarkMode.hpp"
#endif // __APPLE__
// Verify GLEW and wxWidgets use the same OpenGL backend (EGL vs GLX).
// A mismatch causes rendering failures: GLEW's function loading must match
// the context type created by wxWidgets.
#if defined(__linux__)
#if defined(GLEW_EGL) && (!defined(wxUSE_GLCANVAS_EGL) || !wxUSE_GLCANVAS_EGL)
#error "OpenGL backend mismatch: GLEW has EGL support enabled but wxWidgets does not. Ensure GLEW_USE_EGL and wxUSE_GLCANVAS_EGL are both ON or both OFF."
#endif
#if !defined(GLEW_EGL) && defined(wxUSE_GLCANVAS_EGL) && wxUSE_GLCANVAS_EGL
#error "OpenGL backend mismatch: wxWidgets has EGL support enabled but GLEW does not. Ensure GLEW_USE_EGL and wxUSE_GLCANVAS_EGL are both ON or both OFF."
#endif
#ifdef __WXGTK__
#include "LinuxDisplayBackend.hpp"
#ifdef wxHAS_EGL
#include <EGL/egl.h>
#endif
#endif
namespace Slic3r {
@@ -121,12 +116,12 @@ void OpenGLManager::GLInfo::detect() const
if (Slic3r::total_physical_memory() / (1024 * 1024 * 1024) < 6)
*max_tex_size /= 2;
if (GLEW_EXT_texture_filter_anisotropic) {
if (GLAD_GL_EXT_texture_filter_anisotropic) {
float* max_anisotropy = const_cast<float*>(&m_max_anisotropy);
glsafe(::glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy));
}
if (!GLEW_ARB_compatibility)
if (!GLAD_GL_ARB_compatibility)
*const_cast<bool*>(&m_core_profile) = true;
*const_cast<bool*>(&m_detected) = true;
@@ -245,24 +240,36 @@ OpenGLManager::~OpenGLManager()
bool OpenGLManager::init_gl(bool popup_error)
{
if (!m_gl_initialized) {
glewExperimental = true;
GLenum result = glewInit();
if (result != GLEW_OK) {
BOOST_LOG_TRIVIAL(error) << "Unable to init glew library, Error: " << glewGetErrorString(result);
int version = 0;
#if defined(__WXGTK__) && defined(wxHAS_EGL)
if (is_running_on_wayland()) {
// On EGL/Wayland, gladLoaderLoadGL() dlopen's libGL.so then
// immediately dlclose's it. Since nothing else holds libGL.so
// open (unlike GLX where the context keeps it loaded), the
// library gets unmapped and all function pointers become invalid.
// Use eglGetProcAddress directly to avoid this.
version = gladLoadGL((GLADloadfunc)eglGetProcAddress);
} else
#endif
{
version = gladLoaderLoadGL();
}
if (version == 0) {
BOOST_LOG_TRIVIAL(error) << "Unable to init GLAD OpenGL loader";
return false;
}
//BOOST_LOG_TRIVIAL(info) << "glewInit Success."<< std::endl;
BOOST_LOG_TRIVIAL(info) << "GLAD loaded OpenGL " << GLAD_VERSION_MAJOR(version) << "." << GLAD_VERSION_MINOR(version);
m_gl_initialized = true;
if (GLEW_EXT_texture_compression_s3tc)
if (GLAD_GL_EXT_texture_compression_s3tc)
s_compressed_textures_supported = true;
else
s_compressed_textures_supported = false;
if (GLEW_ARB_framebuffer_object) {
if (GLAD_GL_ARB_framebuffer_object) {
s_framebuffers_type = EFramebufferType::Arb;
BOOST_LOG_TRIVIAL(info) << "Found Framebuffer Type ARB."<< std::endl;
}
else if (GLEW_EXT_framebuffer_object) {
else if (GLAD_GL_EXT_framebuffer_object) {
BOOST_LOG_TRIVIAL(info) << "Found Framebuffer Type Ext."<< std::endl;
s_framebuffers_type = EFramebufferType::Ext;
}
@@ -438,6 +445,20 @@ void OpenGLManager::detect_multisample(int* attribList)
{
int wxVersion = wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + wxRELEASE_NUMBER;
bool enable_multisample = wxVersion >= 30003;
#if defined(__WXGTK__)
// On Wayland, wxGLCanvas::IsDisplaySupported() requires the EGL backend.
// If wxWidgets was built without EGL, the GLX backend will crash trying
// to access a non-existent X11 display. Disable multisample in that case.
if (is_running_on_wayland()) {
#if !defined(wxHAS_EGL) || !wxHAS_EGL
BOOST_LOG_TRIVIAL(warning) << "Wayland without EGL: disabling multisample detection";
s_multisample = EMultisampleState::Disabled;
return;
#endif
}
#endif
s_multisample =
enable_multisample &&
// Disable multi-sampling on ChromeOS, as the OpenGL virtualization swaps Red/Blue channels with multi-sampling enabled,
+34 -8
View File
@@ -5,7 +5,7 @@
#include <string>
#include <regex>
#include <future>
#include <GL/glew.h>
#include <glad/gl.h>
#include <boost/algorithm/string.hpp>
#include <boost/optional.hpp>
#include <boost/filesystem/path.hpp>
@@ -1076,9 +1076,12 @@ void PartPlate::render_icon_texture(GLModel &buffer, GLTexture &texture)
void PartPlate::render_plate_name_texture()
{
if (m_name_texture.get_id() == 0)
if (m_plate_name_edit_icon.mesh_raycaster == nullptr)
generate_plate_name_texture();
if (m_name_texture.get_id() == 0)
return;
GLuint tex_id = (GLuint)m_name_texture.get_id();
glsafe(::glBindTexture(GL_TEXTURE_2D, tex_id));
m_plate_name_icon.render();
@@ -1469,6 +1472,9 @@ void PartPlate::render_right_arrow(const ColorRGBA render_color, bool use_lighti
static void register_model_for_picking(GLCanvas3D &canvas, PickingModel &model, int id)
{
if (model.mesh_raycaster == nullptr)
return;
canvas.add_raycaster_for_picking(SceneRaycaster::EType::Bed, id, *model.mesh_raycaster, Transform3d::Identity());
}
@@ -1483,7 +1489,10 @@ void PartPlate::register_raycasters_for_picking(GLCanvas3D &canvas)
register_model_for_picking(canvas, m_plate_settings_icon, picking_id_component(5));
canvas.remove_raycasters_for_picking(SceneRaycaster::EType::Bed, picking_id_component(6));
register_model_for_picking(canvas, m_plate_name_edit_icon, picking_id_component(6));
// Plate-name edit picking is built lazily together with the plate-name texture.
// During reset / reload_scene the icon may not have a raycaster yet, which is valid.
if (m_plate_name_edit_icon.mesh_raycaster != nullptr)
register_model_for_picking(canvas, m_plate_name_edit_icon, picking_id_component(6));
register_model_for_picking(canvas, m_move_front_icon, picking_id_component(7));
// Only register filament map button for H2D (dual-extruder Bambu Lab) printers
@@ -2233,7 +2242,7 @@ void PartPlate::clear(bool clear_sliced_result)
m_ready_for_slice = true;
update_slice_result_valid_state(false);
}
m_name_texture.reset();
invalidate_plate_name_texture();
return;
}
@@ -2323,6 +2332,10 @@ Vec3d PartPlate::get_center_origin()
void PartPlate::generate_plate_name_texture()
{
auto canvas = this->m_partplate_list->m_plater->get_view3D_canvas3D();
if (canvas == nullptr)
return;
m_plate_name_icon.reset();
// generate m_name_texture texture from m_name with generate_from_text_string
@@ -2335,8 +2348,10 @@ void PartPlate::generate_plate_name_texture()
wxFont* font = &l;
wxColour foreground(0xf2, 0x75, 0x4e, 0xff);
if (!m_name_texture.generate_from_text_string(text.ToUTF8().data(), *font, *wxBLACK, foreground))
if (!m_name_texture.generate_from_text_string(text.ToUTF8().data(), *font, *wxBLACK, foreground)) {
BOOST_LOG_TRIVIAL(error) << "PartPlate::generate_plate_name_texture(): generate_from_text_string() failed";
return;
}
ExPolygon poly;
auto bed_ext = get_extents(m_shape);
@@ -2360,11 +2375,22 @@ void PartPlate::generate_plate_name_texture()
if (!init_model_from_poly(m_plate_name_icon, poly, GROUND_Z))
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to generate geometry buffers for icons\n";
auto canvas = this->m_partplate_list->m_plater->get_view3D_canvas3D();
canvas->remove_raycasters_for_picking(SceneRaycaster::EType::Bed, picking_id_component(6));
calc_vertex_for_plate_name_edit_icon(&m_name_texture, 0, m_plate_name_edit_icon);
register_model_for_picking(*canvas, m_plate_name_edit_icon, picking_id_component(6));
}
void PartPlate::invalidate_plate_name_texture()
{
m_plate_name_edit_icon.mesh_raycaster.reset();
auto canvas = (m_plater != nullptr) ? m_plater->get_view3D_canvas3D() : nullptr;
if (canvas != nullptr) {
canvas->remove_raycasters_for_picking(SceneRaycaster::EType::Bed, picking_id_component(6));
canvas->set_as_dirty();
}
}
void PartPlate::set_plate_name(const std::string& name)
{
// compare if name equal to m_name, case sensitive
@@ -2375,7 +2401,7 @@ void PartPlate::set_plate_name(const std::string& name)
if (m_print != nullptr)
m_print->set_plate_name(name);
generate_plate_name_texture();
invalidate_plate_name_texture();
}
//get the print's object, result and index
@@ -3148,7 +3174,7 @@ bool PartPlate::set_shape(const Pointfs& shape, const Pointfs& exclude_areas, co
calc_vertex_for_number(0, false, m_plate_idx_icon);
// calc vertex for plate name
generate_plate_name_texture();
invalidate_plate_name_texture();
}
}
+1
View File
@@ -200,6 +200,7 @@ private:
void render_icons(bool bottom, bool only_name = false, int hover_id = -1);
void render_only_numbers(bool bottom);
void render_plate_name_texture();
void invalidate_plate_name_texture();
void register_raycasters_for_picking(GLCanvas3D& canvas);
int picking_id_component(int idx) const;
+95 -9
View File
@@ -75,6 +75,9 @@
#include "GUI_App.hpp"
#include "GuiColor.hpp"
#include "GUI_ObjectList.hpp"
#ifdef __WXGTK__
#include "LinuxDisplayBackend.hpp"
#endif
#include "GUI_Utils.hpp"
#include "GUI_Factories.hpp"
#include "wxExtensions.hpp"
@@ -348,6 +351,57 @@ void SlicedInfo::SetTextAndShow(SlicedInfoIdx idx, const wxString& text, const w
static wxString temp_dir;
namespace {
#ifdef __WXGTK__
wxString sanitize_window_layout_for_wayland(const wxString& layout, bool* removed_floating_state = nullptr)
{
if (!Slic3r::GUI::is_running_on_wayland() || layout.empty()) {
if (removed_floating_state != nullptr)
*removed_floating_state = false;
return layout;
}
static const std::regex state_pattern(R"(state=(\d+);)");
constexpr unsigned int disabled_wayland_flags =
static_cast<unsigned int>(wxAuiPaneInfo::optionFloating) |
static_cast<unsigned int>(wxAuiPaneInfo::optionFloatable);
const std::string input = layout.utf8_string();
std::string output;
output.reserve(input.size());
bool modified = false;
std::smatch match;
auto search_start = input.cbegin();
while (std::regex_search(search_start, input.cend(), match, state_pattern)) {
output.append(search_start, match[0].first);
try {
const unsigned long state = std::stoul(match[1].str());
const unsigned long sanitized_state = state & ~static_cast<unsigned long>(disabled_wayland_flags);
modified = modified || sanitized_state != state;
output += "state=" + std::to_string(sanitized_state) + ";";
} catch (const std::exception&) {
output += match[0].str();
}
search_start = match[0].second;
}
output.append(search_start, input.cend());
if (removed_floating_state != nullptr)
*removed_floating_state = modified;
return modified ? wxString::FromUTF8(output) : layout;
}
#endif
} // namespace
// Sidebar / private
enum class ActionButtonType : int {
@@ -1781,7 +1835,11 @@ Sidebar::Sidebar(Plater *parent)
e.Skip();
});
w->Bind(wxEVT_LEAVE_WINDOW, [this, panel_color](wxMouseEvent &e) {
wxWindow* next_w = wxFindWindowAtPoint(wxGetMousePosition());
// Use event-relative coords instead of wxGetMousePosition() which
// returns (0,0) on Wayland for global screen coordinates.
wxWindow* evtObj = dynamic_cast<wxWindow*>(e.GetEventObject());
wxPoint screenPos = evtObj ? evtObj->ClientToScreen(e.GetPosition()) : wxGetMousePosition();
wxWindow* next_w = wxFindWindowAtPoint(screenPos);
if (!next_w || !p->panel_printer_preset->IsDescendant(next_w)){
if(!p->combo_printer->HasFocus())
p->panel_printer_preset->SetBorderColor(panel_color.bd_normal);
@@ -1843,7 +1901,11 @@ Sidebar::Sidebar(Plater *parent)
e.Skip();
});
w->Bind(wxEVT_LEAVE_WINDOW, [this, panel_color](wxMouseEvent &e) {
wxWindow* next_w = wxFindWindowAtPoint(wxGetMousePosition());
// Use event-relative coords instead of wxGetMousePosition() which
// returns (0,0) on Wayland for global screen coordinates.
wxWindow* evtObj = dynamic_cast<wxWindow*>(e.GetEventObject());
wxPoint screenPos = evtObj ? evtObj->ClientToScreen(e.GetPosition()) : wxGetMousePosition();
wxWindow* next_w = wxFindWindowAtPoint(screenPos);
if (!p->combo_nozzle_dia->HasFocus() && (!next_w || !p->panel_nozzle_dia->IsDescendant(next_w)))
p->panel_nozzle_dia->SetBorderColor(panel_color.bd_normal);
e.Skip();
@@ -1913,7 +1975,11 @@ Sidebar::Sidebar(Plater *parent)
e.Skip();
});
w->Bind(wxEVT_LEAVE_WINDOW, [this, w, panel_color](wxMouseEvent &e) {
wxWindow* next_w = wxFindWindowAtPoint(wxGetMousePosition());
// Use event-relative coords instead of wxGetMousePosition() which
// returns (0,0) on Wayland for global screen coordinates.
wxWindow* evtObj = dynamic_cast<wxWindow*>(e.GetEventObject());
wxPoint screenPos = evtObj ? evtObj->ClientToScreen(e.GetPosition()) : wxGetMousePosition();
wxWindow* next_w = wxFindWindowAtPoint(screenPos);
if (!p->combo_printer_bed->HasFocus() && (!next_w || !p->panel_printer_bed->IsDescendant(next_w)))
p->panel_printer_bed->SetBorderColor(panel_color.bd_normal);
if(w == p->image_printer_bed)
@@ -4835,8 +4901,16 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
{
m_is_dark = wxGetApp().app_config->get("dark_color_mode") == "1";
#ifdef __WXGTK__
const bool disable_wayland_floating = Slic3r::GUI::is_running_on_wayland();
#endif
m_aui_mgr.SetManagedWindow(q);
m_aui_mgr.SetDockSizeConstraint(1, 1);
#ifdef __WXGTK__
if (disable_wayland_floating)
m_aui_mgr.SetFlags(m_aui_mgr.GetFlags() & ~wxAUI_MGR_ALLOW_FLOATING);
#endif
//m_aui_mgr.GetArtProvider()->SetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE, 0);
//m_aui_mgr.GetArtProvider()->SetMetric(wxAUI_DOCKART_SASH_SIZE, 2);
m_aui_mgr.GetArtProvider()->SetMetric(wxAUI_DOCKART_CAPTION_SIZE, 18);
@@ -4928,7 +5002,6 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
.CloseButton(false)
.TopDockable(false)
.BottomDockable(false)
.Floatable(true)
.BestSize(wxSize(39 * wxGetApp().em_unit(), 90 * wxGetApp().em_unit())));
auto* panel_sizer = new wxBoxSizer(wxHORIZONTAL);
@@ -4947,7 +5020,19 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
const auto cfg = wxGetApp().app_config;
wxString layout = wxString::FromUTF8(cfg->get("window_layout"));
if (!layout.empty()) {
m_aui_mgr.LoadPerspective(layout, false);
bool removed_floating_state = false;
#ifdef __WXGTK__
if (disable_wayland_floating)
layout = sanitize_window_layout_for_wayland(layout, &removed_floating_state);
#endif
if (!m_aui_mgr.LoadPerspective(layout, false)) {
BOOST_LOG_TRIVIAL(warning) << "Failed to restore saved window layout";
m_aui_mgr.LoadPerspective(m_default_window_layout, false);
} else if (removed_floating_state) {
BOOST_LOG_TRIVIAL(info) << "Removed floating AUI state from saved window layout for Wayland";
}
sidebar_layout.is_collapsed = !sidebar.IsShown();
}
@@ -8886,11 +8971,9 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice)
wxPanel* old_panel = current_panel;
//#if BBL_HAS_FIRST_PAGE
if (!old_panel) {
//BBS: only switch to the first panel when visible
// Wayland may report the first canvas as not yet shown while the frame is still mapping.
// Keep the panel switch anyway so handlers are bound and the first paint can initialize GL later.
panel->Show();
//dynamic_cast<View3D *>(panel)->get_canvas3d()->render();
if (!panel->IsShownOnScreen())
return;
}
//#endif
current_panel = panel;
@@ -10050,6 +10133,9 @@ void Plater::priv::on_action_split_volumes(SimpleEvent&)
void Plater::priv::on_object_select(SimpleEvent& evt)
{
if (wxGetApp().is_closing())
return;
wxGetApp().obj_list()->update_selections();
selection_changed();
}
+47 -6
View File
@@ -22,6 +22,10 @@
#include "imgui/imconfig.h"
#if defined(__WXGTK__)
#include "LinuxDisplayBackend.hpp"
#endif
using boost::optional;
namespace Slic3r {
@@ -33,6 +37,17 @@ wxDEFINE_EVENT(wxCUSTOMEVT_JUMP_TO_OBJECT, wxCommandEvent);
using GUI::from_u8;
using GUI::into_u8;
namespace {
bool focus_left_popup(wxWindow* popup, wxWindow* focus_window, wxWindow* related_window_1 = nullptr,
wxWindow* related_window_2 = nullptr, wxWindow* related_window_3 = nullptr)
{
return focus_window != popup && !popup->IsDescendant(focus_window) && focus_window != related_window_1 &&
focus_window != related_window_2 && focus_window != related_window_3;
}
} // namespace
namespace Search {
static char marker_by_type(Preset::Type type, PrinterTechnology pt)
@@ -674,11 +689,24 @@ void SearchDialog::OnDismiss() { }
void SearchDialog::Dismiss()
{
auto pos = wxGetMousePosition();
auto focus_window = wxWindow::FindFocus();
if (!focus_window)
if (!focus_window) {
Die();
else if (!m_event_tag->GetScreenRect().Contains(pos) && !this->GetScreenRect().Contains(pos) && !m_search_item_tag->GetScreenRect().Contains(pos)) {
return;
}
#if defined(__WXGTK__)
// On Wayland, wxGetMousePosition() returns unreliable global coords.
// Rely on focus tracking instead: if focus moved to a window outside
// this dialog and its related controls, dismiss.
if (Slic3r::GUI::is_running_on_wayland()) {
if (focus_left_popup(this, focus_window, m_event_tag, m_search_item_tag, search_line)) {
Die();
}
return;
}
#endif
auto pos = wxGetMousePosition();
if (!m_event_tag->GetScreenRect().Contains(pos) && !this->GetScreenRect().Contains(pos) && !m_search_item_tag->GetScreenRect().Contains(pos)) {
Die();
}
}
@@ -904,11 +932,24 @@ void SearchObjectDialog::OnDismiss() {}
void SearchObjectDialog::Dismiss()
{
auto pos = wxGetMousePosition();
auto focus_window = wxWindow::FindFocus();
if (!focus_window)
if (!focus_window) {
Die();
else if (!search_line->GetScreenRect().Contains(pos) && !this->GetScreenRect().Contains(pos)) {
return;
}
#if defined(__WXGTK__)
// On Wayland, wxGetMousePosition() returns unreliable global coords.
// Rely on focus tracking instead: if focus moved to a window outside
// this dialog and its related controls, dismiss.
if (Slic3r::GUI::is_running_on_wayland()) {
if (focus_left_popup(this, focus_window, search_line)) {
Die();
}
return;
}
#endif
auto pos = wxGetMousePosition();
if (!search_line->GetScreenRect().Contains(pos) && !this->GetScreenRect().Contains(pos)) {
Die();
}
}
+1 -1
View File
@@ -18,7 +18,7 @@
#include "libslic3r/BuildVolume.hpp"
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
#include <GL/glew.h>
#include <glad/gl.h>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/log/trivial.hpp>
+26 -1
View File
@@ -17,6 +17,9 @@
#include "GUI_App.hpp"
#include "GUI_Utils.hpp"
#include "I18N.hpp"
#ifdef __WXGTK__
#include "LinuxDisplayBackend.hpp"
#endif
#include "MainFrame.hpp"
#include "MsgDialog.hpp"
#include "OpenGLManager.hpp"
@@ -28,7 +31,7 @@
#include <boost/property_tree/json_parser.hpp>
#include <boost/uuid/detail/md5.hpp>
#include "GL/glew.h"
#include <glad/gl.h>
#include <wx/display.h>
#include <wx/htmllbox.h>
@@ -420,6 +423,28 @@ static std::string generate_system_info_json()
data_node.put("Linux_DistroID", distro_id);
data_node.put("Linux_DistroVer", distro_ver);
data_node.put("Linux_Wayland", wxGetEnv("WAYLAND_DISPLAY", nullptr));
#ifdef __WXGTK__
const LinuxDisplayBackend display_backend = get_linux_display_backend();
const char* display_backend_name = "unknown";
const char* gl_backend_hint = "Unknown";
switch (display_backend) {
case LinuxDisplayBackend::Wayland:
display_backend_name = "wayland";
gl_backend_hint = "EGL";
break;
case LinuxDisplayBackend::X11:
display_backend_name = "x11";
gl_backend_hint = "GLX";
break;
default:
break;
}
data_node.put("Linux_DisplayBackend", display_backend_name);
data_node.put("Linux_GLBackendHint", gl_backend_hint);
#else
data_node.put("Linux_DisplayBackend", "unknown");
data_node.put("Linux_GLBackendHint", "Unknown");
#endif
#endif
data_node.put("wxWidgets", wxVERSION_NUM_DOT_STRING);
#ifdef __WXGTK__
+1 -1
View File
@@ -1,4 +1,4 @@
#include <GL/glew.h>
#include <glad/gl.h>
#include "SkipPartCanvas.hpp"
#include <opencv2/opencv.hpp>
+1 -1
View File
@@ -1,6 +1,6 @@
#include "TextLines.hpp"
#include <GL/glew.h>
#include <glad/gl.h>
#include "libslic3r/Model.hpp"
+3 -1
View File
@@ -516,7 +516,9 @@ void Button::OnParentMotion(wxMouseEvent& event)
tipWindow->SetLabel(tip);
}
tipWindow->Position(wxGetMousePosition(), wxSize(0, 0));
// Position tooltip relative to the button widget itself rather than
// using wxGetMousePosition() which returns (0,0) on Wayland.
tipWindow->Position(this->ClientToScreen(wxPoint(0, 0)), this->GetSize());
tipWindow->Popup();
}
else
+1 -1
View File
@@ -1,6 +1,6 @@
#include "EmbossStyleManager.hpp"
#include <optional>
#include <GL/glew.h> // Imgui texture
#include <glad/gl.h> // Imgui texture
#include <imgui/imgui_internal.h> // ImTextCharFromUtf8
#include <libslic3r/AppConfig.hpp>
#include <libslic3r/Utils.hpp> // ScopeGuard
+1 -1
View File
@@ -7,7 +7,7 @@
#include <functional>
#include <imgui/imgui.h>
#include <wx/font.h>
#include <GL/glew.h>
#include <glad/gl.h>
#include <libslic3r/BoundingBox.hpp>
#include <libslic3r/Emboss.hpp>
#include <libslic3r/TextConfiguration.hpp>