libjxl

FORK: libjxl patches used on blog
git clone https://git.neptards.moe/blog/libjxl.git
Log | Files | Refs | Submodules | README | LICENSE

icc_detect_x11.cc (2529B)


      1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
      2 //
      3 // Use of this source code is governed by a BSD-style
      4 // license that can be found in the LICENSE file.
      5 
      6 // clang-format off
      7 #include "tools/icc_detect/icc_detect.h"
      8 // clang-format on
      9 
     10 #include <stdint.h>
     11 #include <stdlib.h>
     12 #include <xcb/xcb.h>
     13 
     14 #include <memory>
     15 
     16 // clang-format off
     17 #include <QApplication>
     18 #include <X11/Xlib.h>
     19 // clang-format on
     20 
     21 namespace jpegxl {
     22 namespace tools {
     23 
     24 namespace {
     25 
     26 constexpr char kIccProfileAtomName[] = "_ICC_PROFILE";
     27 constexpr uint32_t kMaxIccProfileSize = 1 << 24;
     28 
     29 struct FreeDeleter {
     30   void operator()(void* const p) const { std::free(p); }
     31 };
     32 template <typename T>
     33 using XcbUniquePtr = std::unique_ptr<T, FreeDeleter>;
     34 
     35 }  // namespace
     36 
     37 QByteArray GetMonitorIccProfile(const QWidget* const widget) {
     38   Q_UNUSED(widget)
     39   auto* const qX11App =
     40       qGuiApp->nativeInterface<QNativeInterface::QX11Application>();
     41   if (qX11App == nullptr) {
     42     return QByteArray();
     43   }
     44   xcb_connection_t* const connection = qX11App->connection();
     45   if (connection == nullptr) {
     46     return QByteArray();
     47   }
     48 
     49   const int screenNumber = DefaultScreen(qX11App->display());
     50 
     51   const xcb_intern_atom_cookie_t atomRequest =
     52       xcb_intern_atom(connection, /*only_if_exists=*/1,
     53                       sizeof kIccProfileAtomName - 1, kIccProfileAtomName);
     54   const XcbUniquePtr<xcb_intern_atom_reply_t> atomReply(
     55       xcb_intern_atom_reply(connection, atomRequest, nullptr));
     56   if (atomReply == nullptr) {
     57     return QByteArray();
     58   }
     59   const xcb_atom_t iccProfileAtom = atomReply->atom;
     60 
     61   const xcb_screen_t* screen = nullptr;
     62   int i = 0;
     63   for (xcb_screen_iterator_t it =
     64            xcb_setup_roots_iterator(xcb_get_setup(connection));
     65        it.rem; xcb_screen_next(&it)) {
     66     if (i == screenNumber) {
     67       screen = it.data;
     68       break;
     69     }
     70     ++i;
     71   }
     72   if (screen == nullptr) {
     73     return QByteArray();
     74   }
     75   const xcb_get_property_cookie_t profileRequest = xcb_get_property(
     76       connection, /*_delete=*/0, screen->root, iccProfileAtom,
     77       XCB_GET_PROPERTY_TYPE_ANY, /*long_offset=*/0, kMaxIccProfileSize);
     78   const XcbUniquePtr<xcb_get_property_reply_t> profile(
     79       xcb_get_property_reply(connection, profileRequest, nullptr));
     80   if (profile == nullptr || profile->bytes_after > 0) {
     81     return QByteArray();
     82   }
     83 
     84   return QByteArray(
     85       reinterpret_cast<const char*>(xcb_get_property_value(profile.get())),
     86       xcb_get_property_value_length(profile.get()));
     87 }
     88 
     89 }  // namespace tools
     90 }  // namespace jpegxl