9 #ifndef zakero_Xenium_h
10 #define zakero_Xenium_h
187 #include <unordered_map>
190 #include <linux/input-event-codes.h>
194 #include <xcb/xcb_icccm.h>
195 #include <xcb/randr.h>
200 #define explicit explicit_
230 #define ZAKERO_XENIUM__ERROR_DATA \
231 X(Error_None , 0 , "No Error" ) \
232 X(Error_Unknown , 1 , "An unknown error has occurred" ) \
233 X(Error_Connection_Failed , 2 , "Failed due to socket, pipe, or other stream errors" ) \
234 X(Error_Extension_Not_Supported , 3 , "The requested XCB extension is not supported" ) \
235 X(Error_Invalid_Display_Name , 4 , "An error occured while parsing the X11 display name" ) \
236 X(Error_Invalid_Screen , 5 , "The X11 server does not have a screen matching the display" ) \
237 X(Error_Minimum_Size_Greater_Than_Maximum_Size , 6 , "The minimum window size is larger than the maximum window size." ) \
238 X(Error_Not_Enough_Memory , 7 , "Insufficient memory" ) \
239 X(Error_Request_Too_Long , 8 , "The request was longer than what is excepted by the X11 server" ) \
240 X(Error_Window_Size_Too_Small , 9 , "The window size was too small." ) \
241 X(Error_RandR_CRTC_Info_Not_Found , 10 , "XCB RandR CRTC Information was not found" ) \
242 X(Error_RandR_Invalid_CRTC_Id , 11 , "XCB RandR CRTC ID is not valid" ) \
243 X(Error_RandR_Invalid_Output_Id , 12 , "XCB RandR Output ID is not valid" ) \
244 X(Error_RandR_Not_Available , 13 , "XCB RandR extenstion is not available" ) \
245 X(Error_RandR_Output_Info_Is_Incomplete , 14 , "XCB RandR Output Information does not have enough data" ) \
246 X(Error_RandR_Output_Info_Not_Found , 15 , "XCB RandR Output Information was not found" ) \
247 X(Error_RandR_Screen_Resources_Not_Found , 16 , "XCB RandR could not locate any screen resources" ) \
248 X(Error_RandR_Version_Too_Old , 17 , "XCB RandR version is too old" ) \
249 X(Error_Xcb_Fullscreen_Not_Available , 18 , "The XCB Window Manager does not support fullscreen windows." ) \
250 X(Error_Xcb_Hidden_Not_Available , 19 , "The XCB Window Manager does not support hiding windows." ) \
251 X(Error_Xcb_Maximized_Window_Not_Available , 20 , "The XCB Window Manager does not support maximized windows." ) \
252 X(Error_Xcb_NETWM_State_Not_Available , 21 , "The XCB NETWM protocol extention is not supported." ) \
253 X(Error_Xcb_WM_Delete_Window_Not_Available , 22 , "The XCB Window Manager does not support the delete protocol." ) \
254 X(Error_Xcb_WM_Protocols_Not_Available , 23 , "The XCB Window Manager protocols are not available." ) \
255 X(Error_Xcb_Xkb_Not_Available , 24 , "The XCB XKB Extiension v1.0 is not available." ) \
266 #define X(name_, val_, mesg_) \
267 static constexpr int name_ = val_;
268 ZAKERO_XENIUM__ERROR_DATA
271 static constexpr int32_t Window_Size_Minimum = 100;
406 [[nodiscard]] static
Xenium*
connect(const std::
string&) noexcept;
407 [[nodiscard]] static
Xenium*
connect(std::error_code&) noexcept;
408 [[nodiscard]] static
Xenium*
connect(const std::
string&, std::error_code&) noexcept;
424 std::string name =
"";
429 uint32_t physical_width_mm = 0;
430 uint32_t physical_height_mm = 0;
431 int32_t subpixel = 0;
432 int32_t transform = 0;
433 float pixels_per_mm_horizontal = 0.0;
434 float pixels_per_mm_vertical = 0.0;
443 using OutputId = uint32_t;
445 using LambdaOutputId = std::function<void(
const Xenium::OutputId)>;
447 using VectorOutputId = std::vector<Xenium::OutputId>;
452 [[nodiscard]] Xenium::VectorOutputId
outputVector() const noexcept;
514 void classSet(
const std::string&) noexcept;
515 void titleSet(
const std::string&) noexcept;
563 [[nodiscard]] std::error_code
minimize() noexcept;
600 [[nodiscard]] uint32_t
time()
const noexcept;
607 uint8_t* frame_buffer;
611 size_t frame_buffer_length;
634 void disconnect() noexcept;
639 [[nodiscard]] std::error_code init(xcb_connection_t*,
int) noexcept;
647 std::jthread event_loop;
648 std::atomic<
bool> event_loop_is_running;
652 void eventLoopStart() noexcept;
653 static
void eventLoop(std::stop_token,
Xenium*) noexcept;
662 Xenium::LambdaOutputId output_on_add = {};
663 Xenium::LambdaOutputId output_on_change = {};
664 Xenium::LambdaOutputId output_on_remove = {};
665 Xenium::Map_OutputId_Output output_map = {};
666 mutable std::mutex output_mutex = {};
670 [[nodiscard]]
const Xenium::Output&
output(
const int16_t,
const int16_t, Xenium::OutputId&) noexcept;
671 [[nodiscard]] std::error_code outputInit() noexcept;
672 [[nodiscard]] std::error_code outputAdd(xcb_randr_crtc_t, xcb_randr_output_t) noexcept;
673 void outputAdd(const xcb_randr_get_crtc_info_reply_t*, const xcb_randr_get_output_info_reply_t*) noexcept;
678 std::mutex xenium_window_mutex = {};
682 [[nodiscard]] std::pair<float, float> convertPixelToMm(
const Xenium::Output&, int32_t, int32_t)
const noexcept;
683 [[nodiscard]] std::pair<float, float> convertPixelToPercent(
const Xenium::Output&, int32_t, int32_t)
const noexcept;
684 [[nodiscard]] std::pair<int32_t, int32_t> convertMmToPixel(
const Xenium::Output&,
float,
float)
const noexcept;
685 [[nodiscard]] std::pair<int32_t, int32_t> convertPercentToPixel(
const Xenium::Output&,
float,
float)
const noexcept;
700 uint32_t decorations;
705 struct WindowCreateData
707 std::promise<void> barrier;
708 std::error_code error;
710 Xenium::OutputId output_id;
711 xcb_atom_t atom_close_request;
713 Xenium::SizeUnit size_unit;
714 Xenium::SizeMm size_mm;
715 Xenium::SizePercent size_percent;
716 Xenium::SizePixel size_pixel;
718 xcb_create_window_value_list_t& value_list;
721 struct WindowDestroyData
723 std::promise<void> barrier;
728 struct WindowDeleteData
731 xcb_atom_t atom_close_request = XCB_ATOM_NONE;
734 struct WindowSizeData
736 Xenium::SizeMm mm = { };
737 Xenium::SizeMm mm_minimum = { };
738 Xenium::SizeMm mm_maximum = { };
740 Xenium::SizePercent percent = { };
741 Xenium::SizePercent percent_minimum = { };
742 Xenium::SizePercent percent_maximum = { };
744 Xenium::SizePixel pixel = { };
745 Xenium::SizePixel pixel_minimum = { };
746 Xenium::SizePixel pixel_maximum = { };
748 Xenium::SizeUnit unit = { };
751 struct WindowModeData
757 struct WindowDecorationsData
763 struct WindowOnButtonData
770 struct WindowOnEnterData
777 struct WindowOnMotionData
784 struct WindowKeyboardData
790 using WindowDecorationsMap = std::unordered_map<Xenium::WindowId, Xenium::WindowDecorationsData>;
791 using WindowDeleteMap = std::unordered_map<Xenium::WindowId, Xenium::WindowDeleteData>;
792 using WindowFocusMap = std::unordered_map<Xenium::WindowId, Xenium::LambdaBool>;
793 using WindowKeyboard = std::unordered_map<Xenium::WindowId, Xenium::WindowKeyboardData>;
794 using WindowMap = std::unordered_map<Xenium::WindowId, Xenium::Window*>;
795 using WindowModeMap = std::unordered_map<Xenium::WindowId, Xenium::WindowModeData>;
796 using WindowOnAxisMap = std::unordered_map<Xenium::WindowId, Xenium::LambdaAxis>;
797 using WindowOnButtonMap = std::unordered_map<Xenium::WindowId, Xenium::WindowOnButtonData>;
798 using WindowOnEnterMap = std::unordered_map<Xenium::WindowId, Xenium::WindowOnEnterData>;
799 using WindowOnKeyMap = std::unordered_map<Xenium::WindowId, Xenium::LambdaKey>;
800 using WindowOnLeaveMap = std::unordered_map<Xenium::WindowId, Xenium::Lambda>;
801 using WindowOnMotionMap = std::unordered_map<Xenium::WindowId, Xenium::WindowOnMotionData>;
802 using WindowOutputMap = std::unordered_map<Xenium::WindowId, Xenium::OutputId>;
803 using WindowReadyMap = std::unordered_map<Xenium::WindowId, bool>;
804 using WindowSizeMap = std::unordered_map<Xenium::WindowId, Xenium::WindowSizeData>;
805 using WindowToCreate = std::vector<Xenium::WindowCreateData*>;
806 using WindowToDestroy = std::vector<Xenium::WindowDestroyData*>;
810 Xenium::WindowDecorationsMap window_decorations_map = {};
811 Xenium::WindowDeleteMap window_delete_map = {};
812 Xenium::WindowFocusMap window_focus_map = {};
813 Xenium::WindowKeyboard window_keyboard = {};
814 Xenium::WindowMap window_map = {};
815 Xenium::WindowModeMap window_mode_map = {};
816 Xenium::WindowOnAxisMap window_on_axis_map = {};
817 Xenium::WindowOnButtonMap window_on_button_map = {};
818 Xenium::WindowOnEnterMap window_on_enter_map = {};
819 Xenium::WindowOnKeyMap window_on_key_map = {};
820 Xenium::WindowOnLeaveMap window_on_leave_map = {};
821 Xenium::WindowOnMotionMap window_on_motion_map = {};
822 Xenium::WindowOutputMap window_output_map = {};
823 Xenium::WindowReadyMap window_ready_map = {};
824 Xenium::WindowSizeMap window_size_map = {};
825 Xenium::WindowToCreate window_to_create = {};
826 Xenium::WindowToDestroy window_to_destroy = {};
830 [[nodiscard]] std::error_code windowBorder(
const Xenium::WindowId,
const bool) noexcept;
831 void windowCreateAddToQueue(Xenium::WindowCreateData*) noexcept;
832 void windowDestroyAddToQueue(Xenium::WindowDestroyData*) noexcept;
833 [[nodiscard]] std::error_code windowLocationSet(
const Xenium::WindowId,
const Xenium::PointPixel&) noexcept;
834 [[nodiscard]] std::error_code windowMinimize(
const Xenium::WindowId) noexcept;
836 bool windowPropertySet(
Xenium::WindowId,
const xcb_atom_t,
const xcb_atom_t, xcb_generic_error_t&) noexcept;
837 bool windowPropertySet(
Xenium::WindowId,
const xcb_atom_t,
const std::string&, xcb_generic_error_t&) noexcept;
840 void windowResizeTo(
const Xenium::Output&, Xenium::WindowSizeData&,
const xcb_configure_notify_event_t*) noexcept;
841 std::error_code windowSizeSet(
const Xenium::WindowId,
const Xenium::SizePixel&) noexcept;
842 [[nodiscard]] std::error_code windowSizeSetMinMax(
const Xenium::WindowId,
const int32_t,
const int32_t,
const int32_t,
const int32_t) noexcept;
843 std::error_code windowSizeSetMinMax(
const Xenium::Output&,
const Xenium::WindowId, Xenium::WindowSizeData&) noexcept;
848 xcb_connection_t* connection =
nullptr;
849 const xcb_setup_t* setup =
nullptr;
850 xcb_screen_t* screen =
nullptr;
854 void xcbEvent(
const xcb_button_press_event_t*) noexcept;
855 void xcbEvent(
const xcb_client_message_event_t*) noexcept;
856 void xcbEvent(
const xcb_configure_notify_event_t*) noexcept;
857 void xcbEvent(
const xcb_enter_notify_event_t*) noexcept;
858 void xcbEvent(
const xcb_expose_event_t*) noexcept;
859 void xcbEvent(
const xcb_focus_in_event_t*) noexcept;
860 void xcbEvent(
const xcb_gravity_notify_event_t*) noexcept;
861 void xcbEvent(
const xcb_key_press_event_t*) noexcept;
862 void xcbEvent(
const xcb_map_notify_event_t*) noexcept;
863 void xcbEvent(
const xcb_motion_notify_event_t*) noexcept;
864 void xcbEvent(
const xcb_property_notify_event_t*) noexcept;
865 void xcbEvent(
const xcb_reparent_notify_event_t*) noexcept;
866 void xcbEvent(
const xcb_unmap_notify_event_t*) noexcept;
868 void xcbWindowCreate(Xenium::WindowCreateData*) noexcept;
869 [[nodiscard]] std::error_code xcbWindowCreateValidate(Xenium::WindowCreateData*) noexcept;
870 [[nodiscard]] std::error_code xcbWindowCreateClient(Xenium::WindowCreateData*) noexcept;
871 [[nodiscard]] std::error_code xcbWindowCreateInit(Xenium::WindowCreateData*) noexcept;
872 void xcbWindowDestroy(Xenium::WindowDestroyData*) noexcept;
877 xcb_atom_t atom_motif_wm_hints = XCB_ATOM_NONE;
878 xcb_atom_t atom_net_frame_extents = XCB_ATOM_NONE;
879 xcb_atom_t atom_net_wm_state = XCB_ATOM_NONE;
880 xcb_atom_t atom_net_wm_state_fullscreen = XCB_ATOM_NONE;
881 xcb_atom_t atom_net_wm_state_hidden = XCB_ATOM_NONE;
882 xcb_atom_t atom_net_wm_state_maximized_horz = XCB_ATOM_NONE;
883 xcb_atom_t atom_net_wm_state_maximized_vert = XCB_ATOM_NONE;
884 xcb_atom_t atom_wm_change_state = XCB_ATOM_NONE;
885 xcb_atom_t atom_wm_delete_window = XCB_ATOM_NONE;
886 xcb_atom_t atom_wm_protocols = XCB_ATOM_NONE;
890 [[nodiscard]] std::error_code atomInit() noexcept;
891 [[nodiscard]] xcb_atom_t atomCreateDeleteWindow(const
WindowId, xcb_generic_error_t&) noexcept;
892 [[nodiscard]] std::
string atomName(const xcb_atom_t) noexcept;
893 [[nodiscard]] std::vector<xcb_atom_t> atomValueAtom(const Xenium::
WindowId, const xcb_atom_t, xcb_generic_error_t&) noexcept;
894 [[nodiscard]] std::vector<int32_t> atomValueData(const Xenium::
WindowId, const xcb_atom_t, const xcb_atom_t, const
size_t, xcb_generic_error_t&) noexcept;
895 [[nodiscard]] xcb_atom_t internAtom(const std::
string&, const
bool, xcb_generic_error_t&) noexcept;
896 [[nodiscard]] xcb_intern_atom_cookie_t internAtomRequest(const std::
string&, const
bool = true) noexcept;
897 [[nodiscard]] xcb_atom_t internAtomReply(const xcb_intern_atom_cookie_t, xcb_generic_error_t&) noexcept;
902 int randr_error_base = 0;
903 int randr_event_base = 0;
904 int randr_query_version_major = 0;
905 int randr_query_version_minor = 0;
909 [[nodiscard]] std::error_code randrInit() noexcept;
910 void randrEvent(const xcb_randr_crtc_change_t*) noexcept;
911 void randrEvent(const xcb_randr_output_change_t*) noexcept;
912 void randrEvent(const xcb_randr_notify_event_t*) noexcept;
913 void randrEvent(const xcb_randr_screen_change_notify_event_t*) noexcept;
920 uint32_t repeat_delay_ms = 600;
921 uint32_t repeat_interval_ms = 50;
926 Xenium::Key key = { 0, 0, Xenium::KeyState::Released };
927 Xenium::KeyModifier modifier = { 0 };
929 uint32_t repeat_time = { 0 };
932 using KeyDataArray = std::array<Xenium::KeyData, 256>;
936 Xenium::KeyDataArray key_data_array = { };
937 Xenium::KeyModifier key_modifier = { 0 };
938 Xenium::XkbControls xkb_controls = { };
939 uint16_t xkb_modifier_pressed = 0;
943 [[nodiscard]] std::error_code xkbInit() noexcept;
944 inline
void keyDataArrayClear() noexcept;
945 inline
void keyDataArrayProcess() noexcept;
946 void xkbControlsUpdate() noexcept;
947 void xkbIndicatorStateUpdate() noexcept;
952 [[nodiscard]]
bool requestCheckHasError(const xcb_void_cookie_t&, xcb_generic_error_t&) noexcept;
956 Xenium(const Xenium&) = delete;
957 Xenium& operator=(const Xenium&) = delete;
963 [[nodiscard]] std::
string to_string(const std::vector<xcb_atom_t>&) noexcept;
964 [[nodiscard]] std::
string to_string(const std::vector<int32_t>&) noexcept;
965 [[nodiscard]] std::
string to_string(const xcb_generic_error_t&) noexcept;
966 [[nodiscard]] std::
string to_string(const xcb_button_press_event_t&) noexcept;
967 [[nodiscard]] std::
string to_string(const xcb_client_message_event_t&) noexcept;
968 [[nodiscard]] std::
string to_string(const xcb_configure_notify_event_t&) noexcept;
969 [[nodiscard]] std::
string to_string(const xcb_enter_notify_event_t&) noexcept;
970 [[nodiscard]] std::
string to_string(const xcb_expose_event_t&) noexcept;
971 [[nodiscard]] std::
string to_string(const xcb_focus_in_event_t&) noexcept;
972 [[nodiscard]] std::
string to_string(const xcb_generic_event_t&) noexcept;
973 [[nodiscard]] std::
string to_string(const xcb_gravity_notify_event_t&) noexcept;
974 [[nodiscard]] std::
string to_string(const xcb_key_press_event_t&) noexcept;
975 [[nodiscard]] std::
string to_string(const xcb_map_notify_event_t&) noexcept;
976 [[nodiscard]] std::
string to_string(const xcb_motion_notify_event_t&) noexcept;
977 [[nodiscard]] std::
string to_string(const xcb_property_notify_event_t&) noexcept;
978 [[nodiscard]] std::
string to_string(const xcb_reparent_notify_event_t&) noexcept;
979 [[nodiscard]] std::
string to_string(const xcb_unmap_notify_event_t&) noexcept;
980 [[nodiscard]] std::
string to_string(const xcb_format_t&) noexcept;
981 [[nodiscard]] std::
string to_string(const xcb_screen_t&) noexcept;
982 [[nodiscard]] std::
string to_string(const xcb_setup_t&) noexcept;
983 [[nodiscard]] std::
string to_string(const xcb_randr_screen_change_notify_event_t&) noexcept;
984 [[nodiscard]] std::
string to_string(const Xenium::Key&) noexcept;
985 [[nodiscard]] std::
string to_string(const Xenium::KeyModifier&) noexcept;
986 [[nodiscard]] std::
string to_string(const Xenium::
KeyState) noexcept;
987 [[nodiscard]] std::
string to_string(const Xenium::Output&) noexcept;
988 [[nodiscard]] std::
string to_string(const Xenium::PointMm) noexcept;
989 [[nodiscard]] std::
string to_string(const Xenium::PointPercent) noexcept;
990 [[nodiscard]] std::
string to_string(const Xenium::PointPixel) noexcept;
991 [[nodiscard]] std::
string to_string(const Xenium::PointerAxis&) noexcept;
993 [[nodiscard]] std::
string to_string(const Xenium::
PointerAxisType) noexcept;
994 [[nodiscard]] std::
string to_string(const Xenium::PointerButton&) noexcept;
996 [[nodiscard]] std::
string to_string(const Xenium::SizeMm&) noexcept;
997 [[nodiscard]] std::
string to_string(const Xenium::SizePercent&) noexcept;
998 [[nodiscard]] std::
string to_string(const Xenium::SizePixel&) noexcept;
1000 [[nodiscard]] std::
string to_string(const Xenium::
WindowMode) noexcept;
1008 #ifdef ZAKERO_XENIUM_IMPLEMENTATION
1018 #ifdef ZAKERO__DOXYGEN_DEFINE_DOCS
1041 #define ZAKERO_XENIUM_IMPLEMENTATION
1051 #define ZAKERO_XENIUM_ENABLE_DEBUG
1061 #define ZAKERO_XENIUM_ENABLE_SAFE_MODE
1068 #ifndef _NET_WM_STATE_REMOVE
1072 #define _NET_WM_STATE_REMOVE 0
1075 #ifndef _NET_WM_STATE_ADD
1079 #define _NET_WM_STATE_ADD 1
1082 #ifndef _NET_WM_STATE_TOGGLE
1086 #define _NET_WM_STATE_TOGGLE 2
1104 #ifdef ZAKERO_XENIUM_ENABLE_DEBUG
1105 #define ZAKERO_XENIUM__DEBUG_ENABLED true
1107 #define ZAKERO_XENIUM__DEBUG_ENABLED false
1125 #ifdef ZAKERO_XENIUM_ENABLE_DEBUG
1126 #define ZAKERO_XENIUM__DEBUG_DISABLED false
1128 #define ZAKERO_XENIUM__DEBUG_DISABLED true
1144 #ifndef ZAKERO_XENIUM_DEBUG_STREAM
1145 #define ZAKERO_XENIUM_DEBUG_STREAM std::cerr
1166 #define ZAKERO_XENIUM__DEBUG \
1167 if(ZAKERO_XENIUM__DEBUG_DISABLED) {} \
1168 else ZAKERO_XENIUM_DEBUG_STREAM \
1169 << "pid(" << std::to_string(int64_t(ZAKERO_PID)) \
1170 << ") " __FILE__ "(" \
1171 << std::to_string(__LINE__) \
1173 << __PRETTY_FUNCTION__ \
1192 #define ZAKERO_XENIUM__DEBUG_VAR(var_) \
1193 ZAKERO_XENIUM__DEBUG \
1194 << #var_ << ": " << var_ \
1212 #define ZAKERO_XENIUM__DEBUG_BOOL(var_) \
1213 ZAKERO_XENIUM__DEBUG \
1214 << #var_ << ": " << std::boolalpha << var_ \
1232 #define ZAKERO_XENIUM__DEBUG_ERROR(var_) \
1233 ZAKERO_XENIUM__DEBUG \
1234 << "Error: " << var_ \
1245 #define ZAKERO_XENIUM__OUTPUT_SUBPIXEL \
1246 X(XCB_RENDER_SUB_PIXEL_UNKNOWN , "Unkown Geometry" ) \
1247 X(XCB_RENDER_SUB_PIXEL_HORIZONTAL_RGB , "Horizontal RGB" ) \
1248 X(XCB_RENDER_SUB_PIXEL_HORIZONTAL_BGR , "Horizontal BGR" ) \
1249 X(XCB_RENDER_SUB_PIXEL_VERTICAL_RGB , "Vertical RGB" ) \
1250 X(XCB_RENDER_SUB_PIXEL_VERTICAL_BGR , "Vertical BGR" ) \
1251 X(XCB_RENDER_SUB_PIXEL_NONE , "No Geometry" ) \
1258 #define ZAKERO_XENIUM__OUTPUT_TRANSFORM \
1259 X(XCB_RANDR_TRANSFORM_UNIT , "Unit" ) \
1260 X(XCB_RANDR_TRANSFORM_SCALE_UP , "Scale Up" ) \
1261 X(XCB_RANDR_TRANSFORM_SCALE_DOWN , "Scale Down" ) \
1262 X(XCB_RANDR_TRANSFORM_PROJECTIVE , "Projective" ) \
1276 #define ZAKERO_XENIUM__ERROR(err_) std::error_code(err_, XeniumErrorCategory)
1432 constexpr uint32_t Size_Max = (uint32_t)std::numeric_limits<int32_t>::max();
1439 constexpr uint32_t XCB_XKB_INDICATOR_STATE_CAPSLOCK = 0x00000001;
1444 constexpr uint32_t XCB_XKB_INDICATOR_STATE_NUMLOCK = 0x00000002;
1449 constexpr std::array<uint32_t, 8> Pointer_Button_Event_Code =
1463 const uint32_t Default_Value_Mask = 0
1468 | XCB_CW_BIT_GRAVITY
1469 | XCB_CW_WIN_GRAVITY
1470 | XCB_CW_BACKING_STORE
1484 xcb_create_window_value_list_t Default_Value_List =
1485 { .background_pixmap = XCB_BACK_PIXMAP_NONE
1486 , .background_pixel = 0
1487 , .border_pixmap = XCB_BACK_PIXMAP_NONE
1489 , .bit_gravity = XCB_GRAVITY_CENTER
1490 , .win_gravity = XCB_GRAVITY_NORTH_EAST
1491 , .backing_store = XCB_BACKING_STORE_NOT_USEFUL
1492 , .backing_planes = 0
1493 , .backing_pixel = 0
1494 , .override_redirect = 0
1497 | XCB_EVENT_MASK_KEY_PRESS
1498 | XCB_EVENT_MASK_KEY_RELEASE
1499 | XCB_EVENT_MASK_BUTTON_PRESS
1500 | XCB_EVENT_MASK_BUTTON_RELEASE
1501 | XCB_EVENT_MASK_ENTER_WINDOW
1502 | XCB_EVENT_MASK_LEAVE_WINDOW
1503 | XCB_EVENT_MASK_POINTER_MOTION
1512 | XCB_EVENT_MASK_EXPOSURE
1514 | XCB_EVENT_MASK_STRUCTURE_NOTIFY
1518 | XCB_EVENT_MASK_FOCUS_CHANGE
1519 | XCB_EVENT_MASK_PROPERTY_CHANGE
1522 , .do_not_propogate_mask = XCB_EVENT_MASK_NO_EVENT
1523 , .colormap = XCB_COPY_FROM_PARENT
1537 class XeniumErrorCategory_
1538 :
public std::error_category
1547 constexpr XeniumErrorCategory_() noexcept
1556 const char* name()
const noexcept
override
1558 return "zakero.Xenium";
1567 std::string message(
int condition
1568 )
const noexcept
override
1572 #define X(name_, val_, mesg_) \
1573 case val_: return mesg_;
1574 ZAKERO_XENIUM__ERROR_DATA
1578 return "Unknown error condition";
1580 } XeniumErrorCategory;
1588 Xenium::LambdaKey LambdaKey_DoNothing = [](
const Xenium::Key&,
const Xenium::KeyModifier&) noexcept {};
1589 Xenium::LambdaAxis LambdaAxis_DoNothing = [](
const Xenium::PointerAxis&,
const Xenium::KeyModifier&) noexcept {};
1590 Xenium::LambdaButtonMm LambdaButtonMm_DoNothing = [](
const Xenium::PointerButton&,
const Xenium::PointMm&,
const Xenium::KeyModifier&) noexcept {};
1591 Xenium::LambdaButtonPercent LambdaButtonPercent_DoNothing = [](
const Xenium::PointerButton&,
const Xenium::PointPercent&,
const Xenium::KeyModifier&) noexcept {};
1592 Xenium::LambdaButtonPixel LambdaButtonPixel_DoNothing = [](
const Xenium::PointerButton&,
const Xenium::PointPixel&,
const Xenium::KeyModifier&) noexcept {};
1593 Xenium::LambdaPointMm LambdaPointMm_DoNothing = [](
const Xenium::PointMm&,
const Xenium::KeyModifier&) noexcept {};
1594 Xenium::LambdaPointPercent LambdaPointPercent_DoNothing = [](
const Xenium::PointPercent&,
const Xenium::KeyModifier&) noexcept {};
1595 Xenium::LambdaPointPixel LambdaPointPixel_DoNothing = [](
const Xenium::PointPixel&,
const Xenium::KeyModifier&) noexcept {};
1597 Xenium::LambdaOutputId LambdaOutputId_DoNothing = [](
const Xenium::OutputId) noexcept {};
1616 std::error_code convertConnectionError(
int xcb_error_code
1619 switch(xcb_error_code)
1622 return ZAKERO_XENIUM__ERROR(Xenium::Error_None);
1624 case XCB_CONN_ERROR:
1625 return ZAKERO_XENIUM__ERROR(Xenium::Error_Connection_Failed);
1627 case XCB_CONN_CLOSED_EXT_NOTSUPPORTED:
1628 return ZAKERO_XENIUM__ERROR(Xenium::Error_Extension_Not_Supported);
1630 case XCB_CONN_CLOSED_MEM_INSUFFICIENT:
1631 return ZAKERO_XENIUM__ERROR(Xenium::Error_Not_Enough_Memory);
1633 case XCB_CONN_CLOSED_REQ_LEN_EXCEED:
1634 return ZAKERO_XENIUM__ERROR(Xenium::Error_Request_Too_Long);
1636 case XCB_CONN_CLOSED_PARSE_ERR:
1637 return ZAKERO_XENIUM__ERROR(Xenium::Error_Invalid_Display_Name);
1639 case XCB_CONN_CLOSED_INVALID_SCREEN:
1640 return ZAKERO_XENIUM__ERROR(Xenium::Error_Invalid_Screen);
1643 return ZAKERO_XENIUM__ERROR(Xenium::Error_Unknown);
1662 std::error_code validateMinMax(
const Type& min
1672 return ZAKERO_XENIUM__ERROR(Xenium::Error_Window_Size_Too_Small);
1676 && (min.width > max.width)
1679 return ZAKERO_XENIUM__ERROR(Xenium::Error_Minimum_Size_Greater_Than_Maximum_Size);
1683 && (min.height > max.height)
1686 return ZAKERO_XENIUM__ERROR(Xenium::Error_Minimum_Size_Greater_Than_Maximum_Size);
1689 return ZAKERO_XENIUM__ERROR(Xenium::Error_None);
2347 Xenium::Xenium() noexcept
2349 , event_loop_is_running(
false)
2365 if(event_loop_is_running || event_loop.joinable())
2367 event_loop.request_stop();
2398 std::error_code error;
2427 std::error_code error;
2490 , std::error_code& error
2493 const char* display_name =
nullptr;
2495 if(display.empty() ==
false)
2497 display_name = display.c_str();
2501 int screen_number = 0;
2502 xcb_connection_t* connection = xcb_connect(display_name, &screen_number);
2503 int xcb_error = xcb_connection_has_error(connection);
2506 error = convertConnectionError(xcb_error);
2508 ZAKERO_XENIUM__DEBUG_ERROR(error);
2516 error = xenium->init(connection, screen_number);
2521 ZAKERO_XENIUM__DEBUG_ERROR(error);
2526 xenium->eventLoopStart();
2528 error = xenium->atomInit();
2533 ZAKERO_XENIUM__DEBUG_ERROR(error);
2538 error = ZAKERO_XENIUM__ERROR(Error_None);
2551 void Xenium::disconnect() noexcept
2553 this->setup =
nullptr;
2557 xcb_disconnect(this->connection);
2558 connection =
nullptr;
2572 std::error_code Xenium::init(xcb_connection_t* connection
2576 this->connection = connection;
2579 this->setup = xcb_get_setup(this->connection);
2580 ZAKERO_XENIUM__DEBUG_VAR(
to_string(*setup));
2583 xcb_screen_iterator_t screen_iterator = xcb_setup_roots_iterator(this->setup);
2585 for(
int i = 0; i < screen_number; i++)
2587 xcb_screen_next(&screen_iterator);
2590 this->screen = screen_iterator.data;
2591 ZAKERO_XENIUM__DEBUG_VAR(
to_string(*screen));
2594 std::error_code error;
2599 ZAKERO_XENIUM__DEBUG_ERROR(error);
2605 error = randrInit();
2608 ZAKERO_XENIUM__DEBUG_ERROR(error);
2613 error = outputInit();
2616 ZAKERO_XENIUM__DEBUG_ERROR(error);
2621 return ZAKERO_XENIUM__ERROR(Error_None);
2638 void Xenium::eventLoopStart() noexcept
2640 event_loop = std::jthread(&Xenium::eventLoop,
this);
2642 while(event_loop_is_running.load() ==
false)
2645 std::this_thread::sleep_for(std::chrono::nanoseconds(42));
2669 void Xenium::eventLoop(std::stop_token thread_token
2673 const int Randr_Notify_Event = xenium->randr_event_base + XCB_RANDR_NOTIFY;
2675 xcb_generic_event_t*
event =
nullptr;
2677 xenium->event_loop_is_running.store(
true);
2680 while(thread_token.stop_requested() ==
false)
2685 event = xcb_poll_for_event(xenium->connection);
2687 if(event ==
nullptr)
2693 xenium->keyDataArrayProcess();
2698 switch(event->response_type & 0x7f)
2700 case XCB_CLIENT_MESSAGE:
2702 (xcb_client_message_event_t*)event
2708 case XCB_BUTTON_PRESS:
2710 case XCB_BUTTON_RELEASE:
2712 (xcb_button_press_event_t*)event
2718 case XCB_ENTER_NOTIFY: [[fallthrough]];
2719 case XCB_LEAVE_NOTIFY:
2721 (xcb_enter_notify_event_t*)event
2728 (xcb_expose_event_t*)event
2733 case XCB_FOCUS_IN: [[fallthrough]];
2736 (xcb_focus_in_event_t*)event
2742 case XCB_KEY_PRESS: [[fallthrough]];
2743 case XCB_KEY_RELEASE:
2745 (xcb_key_press_event_t*)event
2750 case XCB_MOTION_NOTIFY:
2752 (xcb_motion_notify_event_t*)event
2757 case XCB_PROPERTY_NOTIFY:
2759 (xcb_property_notify_event_t*)event
2764 case XCB_CONFIGURE_NOTIFY:
2766 (xcb_configure_notify_event_t*)event
2770 case XCB_GRAVITY_NOTIFY:
2772 (xcb_gravity_notify_event_t*)event
2776 case XCB_MAP_NOTIFY:
2778 (xcb_map_notify_event_t*)event
2782 case XCB_REPARENT_NOTIFY:
2784 (xcb_reparent_notify_event_t*)event
2788 case XCB_UNMAP_NOTIFY:
2790 (xcb_unmap_notify_event_t*)event
2796 if(event->response_type == Randr_Notify_Event)
2798 ZAKERO_XENIUM__DEBUG <<
"RandR Event: " <<
to_string(*event) <<
'\n';
2800 (xcb_randr_notify_event_t*)event
2805 ZAKERO_XENIUM__DEBUG <<
"Unknown Event: " <<
to_string(*event) <<
'\n';
2834 xenium->xenium_window_mutex.lock();
2836 for(Xenium::WindowCreateData* window_data : xenium->window_to_create)
2838 xenium->xcbWindowCreate(window_data);
2839 window_data->barrier.set_value();
2842 xenium->window_to_create.clear();
2844 for(Xenium::WindowDestroyData* window_data : xenium->window_to_destroy)
2846 xenium->xcbWindowDestroy(window_data);
2847 window_data->barrier.set_value();
2850 xenium->window_to_destroy.clear();
2852 xenium->xenium_window_mutex.unlock();
2854 std::this_thread::yield();
2857 xenium->event_loop_is_running.store(
false);
2873 return xkb_controls.repeat_delay_ms;
2886 return 1000 / xkb_controls.repeat_interval_ms;
2907 std::lock_guard<std::mutex> lock(output_mutex);
2909 if(output_map.contains(output_id) ==
false)
2911 ZAKERO_XENIUM__DEBUG
2912 <<
"Invalid output_id: "
2913 << std::to_string(output_id)
2919 return output_map.at(output_id);
2934 Xenium::VectorOutputId vector(output_map.size());
2937 std::lock_guard<std::mutex> lock(output_mutex);
2939 for(
const auto& iter : output_map)
2941 vector.push_back(iter.first);
2960 switch(subpixel_format)
2962 #define X(value_, name_) \
2963 case value_: return name_;
2964 ZAKERO_XENIUM__OUTPUT_SUBPIXEL
2985 #define X(value_, name_) \
2986 case value_: return name_;
2987 ZAKERO_XENIUM__OUTPUT_TRANSFORM
3006 std::lock_guard<std::mutex> lock(output_mutex);
3008 if(output_map.contains(output_id) ==
false)
3010 return { point.time, 0, 0 };
3015 auto p = convertPixelToMm(
output, point.
x, point.y);
3017 return { point.time, p.first, p.second };
3033 std::lock_guard<std::mutex> lock(output_mutex);
3035 if(output_map.contains(output_id) ==
false)
3037 return { point.time, 0, 0 };
3042 auto p = convertPixelToPercent(
output, point.
x, point.y);
3044 return { point.time, p.first, p.second };
3060 std::lock_guard<std::mutex> lock(output_mutex);
3062 if(output_map.contains(output_id) ==
false)
3064 return { point.time, 0, 0 };
3069 auto p = convertMmToPixel(
output, point.
x, point.y);
3071 return { point.time, p.first, p.second };
3087 std::lock_guard<std::mutex> lock(output_mutex);
3089 if(output_map.contains(output_id) ==
false)
3091 return { point.time, 0, 0 };
3096 auto p = convertPercentToPixel(
output, point.
x, point.y);
3098 return { point.time, p.first, p.second };
3114 std::lock_guard<std::mutex> lock(output_mutex);
3116 if(output_map.contains(output_id) ==
false)
3123 auto p = convertPixelToMm(
output, size.
width, size.height);
3125 return { p.first, p.second };
3141 std::lock_guard<std::mutex> lock(output_mutex);
3143 if(output_map.contains(output_id) ==
false)
3150 auto p = convertPixelToPercent(
output, size.
width, size.height);
3152 return { p.first, p.second };
3167 std::lock_guard<std::mutex> lock(output_mutex);
3169 if(output_map.contains(output_id) ==
false)
3176 auto p = convertMmToPixel(
output, size.
width, size.height);
3178 return { p.first, p.second };
3193 std::lock_guard<std::mutex> lock(output_mutex);
3195 if(output_map.contains(output_id) ==
false)
3202 auto p = convertPercentToPixel(
output, size.
width, size.height);
3204 return { p.first, p.second };
3218 if(lambda ==
nullptr)
3220 output_on_add = LambdaOutputId_DoNothing;
3224 output_on_add = lambda;
3239 if(lambda ==
nullptr)
3241 output_on_change = LambdaOutputId_DoNothing;
3245 output_on_change = lambda;
3260 if(lambda ==
nullptr)
3262 output_on_remove = LambdaOutputId_DoNothing;
3266 output_on_remove = lambda;
3295 , OutputId& output_id
3298 for(
const auto& iter : output_map)
3300 const Output&
output = iter.second;
3308 output_id = iter.first;
3314 uint64_t distance = std::numeric_limits<uint64_t>::max();
3316 for(
const auto& iter : output_map)
3318 const Output&
output = iter.second;
3323 uint64_t dist = std::abs(x - output_x) + std::abs(y - output_y);
3327 output_id = iter.first;
3331 return output_map[output_id];
3343 std::error_code Xenium::outputInit() noexcept
3345 xcb_generic_error_t* xcb_generic_error =
nullptr;
3347 xcb_randr_get_screen_resources_current_reply_t* screen_resources =
3348 xcb_randr_get_screen_resources_current_reply(this->connection
3349 , xcb_randr_get_screen_resources_current(this->connection
3350 , this->screen->root
3352 , &xcb_generic_error
3355 if(screen_resources ==
nullptr)
3357 ZAKERO_XENIUM__DEBUG_ERROR(
3358 ZAKERO_XENIUM__ERROR(Error_RandR_Screen_Resources_Not_Found)
3361 return ZAKERO_XENIUM__ERROR(Error_RandR_Screen_Resources_Not_Found);
3364 xcb_randr_output_t* output_list =
3365 xcb_randr_get_screen_resources_current_outputs(screen_resources
3368 int output_list_size =
3369 xcb_randr_get_screen_resources_current_outputs_length(screen_resources
3372 # if ZAKERO_XENIUM__DEBUG_ENABLED
3373 if(output_list_size == 0)
3375 ZAKERO_XENIUM__DEBUG
3376 <<
"No outputs where found in the Screen Resources"
3381 for(
int i = 0; i < output_list_size; i++)
3383 xcb_randr_get_output_info_reply_t* output_info =
3384 xcb_randr_get_output_info_reply(this->connection
3385 , xcb_randr_get_output_info(this->connection
3387 , screen_resources->config_timestamp
3389 , &xcb_generic_error
3392 if(output_info ==
nullptr
3393 || output_info->connection != XCB_RANDR_CONNECTION_CONNECTED
3394 || output_info->crtc == XCB_NONE
3402 xcb_randr_get_crtc_info_reply_t* crtc_info =
3403 xcb_randr_get_crtc_info_reply(this->connection
3404 , xcb_randr_get_crtc_info(this->connection
3406 , screen_resources->config_timestamp
3408 , &xcb_generic_error
3411 if(crtc_info ==
nullptr)
3420 if(output_info->mm_width == 0 || output_info->mm_height == 0)
3422 ZAKERO_XENIUM__DEBUG_ERROR(
3423 ZAKERO_XENIUM__ERROR(Error_RandR_Output_Info_Is_Incomplete)
3426 const float pixels_per_mm_horizontal = (float)this->screen->width_in_pixels / this->screen->width_in_millimeters;
3427 const float pixels_per_mm_vertical = (
float)this->screen->height_in_pixels / this->screen->height_in_millimeters;
3429 output_info->mm_width = crtc_info->width / pixels_per_mm_horizontal;
3430 output_info->mm_height = crtc_info->height / pixels_per_mm_vertical;
3433 outputAdd(crtc_info, output_info);
3439 free(screen_resources);
3441 return ZAKERO_XENIUM__ERROR(Error_None);
3454 std::error_code Xenium::outputAdd(xcb_randr_crtc_t randr_crtc
3455 , xcb_randr_output_t randr_output
3458 if(randr_crtc == XCB_NONE)
3460 ZAKERO_XENIUM__DEBUG_ERROR(
3461 ZAKERO_XENIUM__ERROR(Error_RandR_Invalid_CRTC_Id)
3464 return ZAKERO_XENIUM__ERROR(Error_RandR_Invalid_CRTC_Id);
3467 if(randr_output == XCB_NONE)
3469 ZAKERO_XENIUM__DEBUG_ERROR(
3470 ZAKERO_XENIUM__ERROR(Error_RandR_Invalid_Output_Id)
3473 return ZAKERO_XENIUM__ERROR(Error_RandR_Invalid_Output_Id);
3476 xcb_generic_error_t* xcb_generic_error =
nullptr;
3478 xcb_randr_get_screen_resources_current_reply_t* screen_resources =
3479 xcb_randr_get_screen_resources_current_reply(this->connection
3480 , xcb_randr_get_screen_resources_current(this->connection
3481 , this->screen->root
3483 , &xcb_generic_error
3486 if(screen_resources ==
nullptr)
3488 ZAKERO_XENIUM__DEBUG_ERROR(
3489 ZAKERO_XENIUM__ERROR(Error_RandR_Screen_Resources_Not_Found)
3492 return ZAKERO_XENIUM__ERROR(Error_RandR_Screen_Resources_Not_Found);
3495 xcb_randr_get_output_info_reply_t* output_info =
3496 xcb_randr_get_output_info_reply(this->connection
3497 , xcb_randr_get_output_info(this->connection
3499 , screen_resources->config_timestamp
3501 , &xcb_generic_error
3504 if(output_info ==
nullptr)
3506 free(screen_resources);
3508 ZAKERO_XENIUM__DEBUG_ERROR(
3509 ZAKERO_XENIUM__ERROR(Error_RandR_Output_Info_Not_Found)
3512 return ZAKERO_XENIUM__ERROR(Error_RandR_Output_Info_Not_Found);
3515 xcb_randr_get_crtc_info_reply_t* crtc_info =
3516 xcb_randr_get_crtc_info_reply(this->connection
3517 , xcb_randr_get_crtc_info(this->connection
3519 , screen_resources->config_timestamp
3521 , &xcb_generic_error
3524 if(crtc_info ==
nullptr)
3527 free(screen_resources);
3529 ZAKERO_XENIUM__DEBUG_ERROR(
3530 ZAKERO_XENIUM__ERROR(Error_RandR_CRTC_Info_Not_Found)
3533 return ZAKERO_XENIUM__ERROR(Error_RandR_CRTC_Info_Not_Found);
3538 if(output_info->mm_width == 0 || output_info->mm_height == 0)
3540 ZAKERO_XENIUM__DEBUG_ERROR(
3541 ZAKERO_XENIUM__ERROR(Error_RandR_Output_Info_Is_Incomplete)
3544 const float pixels_per_mm_horizontal = (float)this->screen->width_in_pixels / this->screen->width_in_millimeters;
3545 const float pixels_per_mm_vertical = (
float)this->screen->height_in_pixels / this->screen->height_in_millimeters;
3547 output_info->mm_width = crtc_info->width / pixels_per_mm_horizontal;
3548 output_info->mm_height = crtc_info->height / pixels_per_mm_vertical;
3551 outputAdd(crtc_info, output_info);
3555 free(screen_resources);
3557 return ZAKERO_XENIUM__ERROR(Error_None);
3567 void Xenium::outputAdd(
const xcb_randr_get_crtc_info_reply_t* crtc_info
3568 ,
const xcb_randr_get_output_info_reply_t* output_info
3571 const std::string output_name(
3572 (
const char*)xcb_randr_get_output_info_name(output_info),
3573 xcb_randr_get_output_info_name_length(output_info)
3576 OutputId output_id = output_info->crtc;
3578 this->output_map[output_id] =
3579 { .name = output_name
3584 , .width = crtc_info->width
3585 , .height = crtc_info->height
3586 , .physical_width_mm = output_info->mm_width
3587 , .physical_height_mm = output_info->mm_height
3588 , .subpixel = output_info->subpixel_order
3591 , .transform = crtc_info->rotation
3592 , .pixels_per_mm_horizontal = (float)crtc_info->width / output_info->mm_width
3593 , .pixels_per_mm_vertical = (
float)crtc_info->height / output_info->mm_height
3596 ZAKERO_XENIUM__DEBUG_VAR(output_id)
3597 ZAKERO_XENIUM__DEBUG_VAR(this->output_map[output_id].name)
3612 std::pair<float, float> Xenium::convertPixelToMm(
const Xenium::Output&
output
3635 std::pair<float, float> Xenium::convertPixelToPercent(
const Xenium::Output&
output
3655 std::pair<int32_t, int32_t> Xenium::convertMmToPixel(
const Xenium::Output&
output
3664 { int32_t(xw * ratio_h)
3665 , int32_t(yh * ratio_v)
3678 std::pair<int32_t, int32_t> Xenium::convertPercentToPixel(
const Xenium::Output&
output
3708 , std::error_code& error
3711 return windowCreate(size, Default_Value_Mask, Default_Value_List, error);
3734 ,
const uint32_t value_mask
3735 , xcb_create_window_value_list_t& value_list
3736 , std::error_code& error
3739 Xenium::WindowCreateData data =
3744 , .atom_close_request = 0
3746 , .size_unit = Xenium::SizeUnit::Millimeter
3747 , .size_mm = size_mm
3748 , .size_percent = {}
3750 , .value_mask = value_mask
3751 , .value_list = value_list
3754 std::future<void> barrier = data.barrier.get_future();
3756 windowCreateAddToQueue(&data);
3764 ZAKERO_XENIUM__DEBUG_ERROR(error);
3771 windowReadyWait(data.window_id);
3794 , std::error_code& error
3797 return windowCreate(size, Default_Value_Mask, Default_Value_List, error);
3819 ,
const uint32_t value_mask
3820 , xcb_create_window_value_list_t& value_list
3821 , std::error_code& error
3824 Xenium::WindowCreateData data =
3829 , .atom_close_request = 0
3831 , .size_unit = Xenium::SizeUnit::Percent
3833 , .size_percent = size_percent
3835 , .value_mask = value_mask
3836 , .value_list = value_list
3839 std::future<void> barrier = data.barrier.get_future();
3841 windowCreateAddToQueue(&data);
3849 ZAKERO_XENIUM__DEBUG_ERROR(error);
3856 windowReadyWait(data.window_id);
3878 , std::error_code& error
3881 return windowCreate(size, Default_Value_Mask, Default_Value_List, error);
3903 ,
const uint32_t value_mask
3904 , xcb_create_window_value_list_t& value_list
3905 , std::error_code& error
3908 Xenium::WindowCreateData data =
3913 , .atom_close_request = 0
3915 , .size_unit = Xenium::SizeUnit::Pixel
3917 , .size_percent = {}
3918 , .size_pixel = size_pixel
3919 , .value_mask = value_mask
3920 , .value_list = value_list
3923 std::future<void> barrier = data.barrier.get_future();
3925 windowCreateAddToQueue(&data);
3933 ZAKERO_XENIUM__DEBUG_ERROR(error);
3940 windowReadyWait(data.window_id);
3955 std::error_code Xenium::windowBorder(
const WindowId window_id
3959 MotifWmHints hints_data =
3962 , .decorations = enable
3967 xcb_void_cookie_t void_cookie =
3968 xcb_change_property_checked(this->connection
3969 , XCB_PROP_MODE_REPLACE
3971 , atom_motif_wm_hints
3972 , atom_motif_wm_hints
3978 xcb_generic_error_t generic_error;
3980 if(requestCheckHasError(void_cookie, generic_error))
3982 ZAKERO_XENIUM__DEBUG_VAR(to_string(generic_error));
3984 return ZAKERO_XENIUM__ERROR(Error_Unknown);
3987 return ZAKERO_XENIUM__ERROR(Error_None);
3994 void Xenium::windowCreateAddToQueue(Xenium::WindowCreateData* window_data
3997 xenium_window_mutex.lock();
3999 window_to_create.push_back(window_data);
4001 xenium_window_mutex.unlock();
4008 void Xenium::windowDestroyAddToQueue(Xenium::WindowDestroyData* window_data
4011 xenium_window_mutex.lock();
4013 window_to_destroy.push_back(window_data);
4015 xenium_window_mutex.unlock();
4028 std::error_code Xenium::windowLocationSet(
const WindowId window_id
4029 ,
const Xenium::PointPixel& point
4032 xcb_configure_window_value_list_t value_list =
4042 xcb_void_cookie_t void_cookie =
4043 xcb_configure_window_aux_checked(this->connection
4046 | XCB_CONFIG_WINDOW_X
4047 | XCB_CONFIG_WINDOW_Y
4051 xcb_generic_error_t generic_error;
4052 if(requestCheckHasError(void_cookie, generic_error))
4054 ZAKERO_XENIUM__DEBUG_VAR(
to_string(generic_error));
4056 return ZAKERO_XENIUM__ERROR(Error_Unknown);
4059 return ZAKERO_XENIUM__ERROR(Error_None);
4074 xcb_client_message_event_t
event =
4075 { .response_type = XCB_CLIENT_MESSAGE
4078 , .window = window_id
4079 , .type = atom_wm_change_state
4082 event.data.data32[0] = XCB_ICCCM_WM_STATE_ICONIC;
4084 xcb_send_event(this->connection
4086 , this->screen->root
4087 , XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY
4088 , (
const char*)&event
4091 xcb_flush(this->connection);
4093 return ZAKERO_XENIUM__ERROR(Error_None);
4111 xcb_client_message_event_t
event =
4112 { .response_type = XCB_CLIENT_MESSAGE
4115 , .window = window_id
4116 , .type = atom_net_wm_state
4120 if(current_mode == Xenium::WindowMode::Normal)
4128 if(current_mode == Xenium::WindowMode::Fullscreen)
4130 event.data.data32[1] = atom_net_wm_state_fullscreen;
4131 event.data.data32[2] = 0;
4135 event.data.data32[1] = atom_net_wm_state_maximized_horz;
4136 event.data.data32[2] = atom_net_wm_state_maximized_vert;
4139 xcb_send_event(this->connection
4141 , this->screen->root
4142 , XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY
4143 , (
const char*)&event
4147 if(new_mode == Xenium::WindowMode::Normal)
4155 if(new_mode == Xenium::WindowMode::Fullscreen)
4157 event.data.data32[1] = atom_net_wm_state_fullscreen;
4158 event.data.data32[2] = 0;
4162 event.data.data32[1] = atom_net_wm_state_maximized_horz;
4163 event.data.data32[2] = atom_net_wm_state_maximized_vert;
4166 xcb_send_event(this->connection
4168 , this->screen->root
4169 , XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY
4170 , (
const char*)&event
4174 xcb_flush(this->connection);
4176 return ZAKERO_XENIUM__ERROR(Error_None);
4191 bool Xenium::windowPropertySet(
WindowId window_id
4192 ,
const xcb_atom_t property
4193 ,
const xcb_atom_t value
4194 , xcb_generic_error_t& generic_error
4197 xcb_void_cookie_t void_cookie =
4198 xcb_change_property_checked(this->connection
4199 , XCB_PROP_MODE_REPLACE
4208 if(requestCheckHasError(void_cookie, generic_error))
4210 ZAKERO_XENIUM__DEBUG_VAR(
to_string(generic_error));
4229 bool Xenium::windowPropertySet(
WindowId window_id
4230 ,
const xcb_atom_t property
4231 ,
const std::string& value
4232 , xcb_generic_error_t& generic_error
4235 xcb_void_cookie_t void_cookie =
4236 xcb_change_property_checked(this->connection
4237 , XCB_PROP_MODE_REPLACE
4245 if(requestCheckHasError(void_cookie, generic_error))
4247 ZAKERO_XENIUM__DEBUG_VAR(
to_string(generic_error));
4265 void Xenium::windowReadySet(
const WindowId window_id
4268 window_ready_map[window_id] =
true;
4281 void Xenium::windowReadyWait(
const WindowId window_id
4284 xcb_map_window(this->connection, window_id);
4285 xcb_flush(this->connection);
4287 while(window_ready_map[window_id] ==
false)
4300 void Xenium::windowResizeTo(
const Output&
output
4301 , Xenium::WindowSizeData& window_size
4302 ,
const xcb_configure_notify_event_t* event
4305 bool update_size =
false;
4307 if(window_size.unit == SizeUnit::Millimeter)
4309 auto pixel = convertMmToPixel(
output
4310 , window_size.mm.
width
4311 , window_size.mm.height
4314 if(pixel.first != window_size.pixel.width
4315 || pixel.second != window_size.pixel.height
4321 window_size.pixel = {pixel.first, pixel.second};
4323 auto percent = convertPixelToPercent(
output
4324 , window_size.pixel.
width
4325 , window_size.pixel.height
4327 window_size.percent = {percent.first, percent.second};
4329 else if(window_size.unit == SizeUnit::Percent)
4331 auto pixel = convertPercentToPixel(
output
4332 , window_size.percent.
width
4333 , window_size.percent.height
4336 if(pixel.first != window_size.pixel.width
4337 || pixel.second != window_size.pixel.height
4341 window_size.pixel = {pixel.first, pixel.second};
4344 auto mm = convertPixelToMm(
output
4345 , window_size.pixel.
width
4346 , window_size.pixel.height
4349 window_size.mm = {mm.first, mm.second};
4353 if(event->width != window_size.pixel.width
4354 || event->height != window_size.pixel.height
4360 window_size.pixel = {
event->width,
event->height};
4362 auto mm = convertPixelToMm(
output
4363 , window_size.pixel.
width
4364 , window_size.pixel.height
4366 window_size.mm = {mm.first, mm.second};
4368 auto percent = convertPixelToPercent(
output
4369 , window_size.pixel.
width
4370 , window_size.pixel.height
4372 window_size.percent = {percent.first, percent.second};
4375 windowSizeSetMinMax(
output, event->window, window_size);
4379 window_size.pixel_lambda(window_size.pixel);
4380 window_size.percent_lambda(window_size.percent);
4381 window_size.mm_lambda(window_size.mm);
4383 windowSizeSet(event->window, window_size.pixel);
4395 std::error_code Xenium::windowSizeSet(
const WindowId window_id
4396 ,
const Xenium::SizePixel& size
4399 xcb_configure_window_value_list_t value_list =
4402 , .width = (uint32_t)size.width
4403 , .height = (uint32_t)size.height
4409 xcb_void_cookie_t void_cookie =
4410 xcb_configure_window_aux_checked(this->connection
4413 | XCB_CONFIG_WINDOW_WIDTH
4414 | XCB_CONFIG_WINDOW_HEIGHT
4418 xcb_generic_error_t generic_error;
4419 if(requestCheckHasError(void_cookie, generic_error))
4421 ZAKERO_XENIUM__DEBUG_VAR(
to_string(generic_error));
4423 return ZAKERO_XENIUM__ERROR(Error_Unknown);
4426 return ZAKERO_XENIUM__ERROR(Error_None);
4438 std::error_code Xenium::windowSizeSetMinMax(
const WindowId window_id
4439 ,
const int32_t min_width
4440 ,
const int32_t min_height
4441 ,
const int32_t max_width
4442 ,
const int32_t max_height
4445 xcb_get_property_cookie_t property_cookie =
4446 xcb_get_property(this->connection
4449 , XCB_ATOM_WM_NORMAL_HINTS
4450 , XCB_ATOM_WM_SIZE_HINTS
4455 xcb_generic_error_t* error_ptr =
nullptr;
4456 xcb_get_property_reply_t* property_reply =
4457 xcb_get_property_reply(this->connection
4463 ZAKERO_XENIUM__DEBUG <<
"Error: " <<
to_string(*error_ptr) <<
'\n';
4465 return ZAKERO_XENIUM__ERROR(Error_Unknown);
4468 xcb_size_hints_t* size_hints =
4469 (xcb_size_hints_t*)xcb_get_property_value(property_reply);
4471 if(min_width == 0 && min_height == 0)
4473 size_hints->flags &= (~XCB_ICCCM_SIZE_HINT_P_MIN_SIZE);
4477 size_hints->flags |= XCB_ICCCM_SIZE_HINT_P_MIN_SIZE;
4480 size_hints->min_width = min_width;
4481 size_hints->min_height = min_height;
4483 if(max_width == 0 && max_height == 0)
4485 size_hints->flags &= (~XCB_ICCCM_SIZE_HINT_P_MAX_SIZE);
4489 size_hints->flags |= XCB_ICCCM_SIZE_HINT_P_MAX_SIZE;
4492 size_hints->max_width = max_width;
4493 size_hints->max_height = max_height;
4495 xcb_void_cookie_t cookie =
4496 xcb_change_property_checked(this->connection
4497 , XCB_PROP_MODE_REPLACE
4499 , XCB_ATOM_WM_NORMAL_HINTS
4500 , XCB_ATOM_WM_SIZE_HINTS
4506 xcb_generic_error_t generic_error;
4508 if(requestCheckHasError(cookie, generic_error))
4510 ZAKERO_XENIUM__DEBUG <<
"Error: " <<
to_string(generic_error) <<
'\n';
4512 return ZAKERO_XENIUM__ERROR(Error_Unknown);
4515 return ZAKERO_XENIUM__ERROR(Error_None);
4537 std::error_code Xenium::windowSizeSetMinMax(
const Xenium::Output&
output
4539 , Xenium::WindowSizeData& window_size
4542 if(window_size.unit == SizeUnit::Millimeter)
4545 auto pixel = convertMmToPixel(
output
4546 , window_size.mm_minimum.
width
4547 , window_size.mm_minimum.height
4549 window_size.pixel_minimum = {pixel.first, pixel.second};
4551 auto percent = convertPixelToPercent(
output
4552 , window_size.pixel_minimum.
width
4553 , window_size.pixel_minimum.height
4555 window_size.percent_minimum = {percent.first, percent.second};
4558 pixel = convertMmToPixel(
output
4559 , window_size.mm_maximum.
width
4560 , window_size.mm_maximum.height
4562 window_size.pixel_maximum = {pixel.first, pixel.second};
4564 percent = convertPixelToPercent(
output
4565 , window_size.pixel_maximum.
width
4566 , window_size.pixel_maximum.height
4568 window_size.percent_maximum = {percent.first, percent.second};
4570 else if(window_size.unit == SizeUnit::Percent)
4573 auto pixel = convertPercentToPixel(
output
4574 , window_size.percent_minimum.
width
4575 , window_size.percent_minimum.height
4577 window_size.pixel_minimum = {pixel.first, pixel.second};
4579 auto mm = convertPixelToMm(
output
4580 , window_size.pixel_minimum.
width
4581 , window_size.pixel_minimum.height
4583 window_size.mm_minimum = {mm.first, mm.second};
4586 pixel = convertPercentToPixel(
output
4587 , window_size.percent_maximum.
width
4588 , window_size.percent_maximum.height
4590 window_size.pixel_maximum = {pixel.first, pixel.second};
4592 mm = convertPixelToMm(
output
4593 , window_size.pixel_maximum.
width
4594 , window_size.pixel_maximum.height
4596 window_size.mm_maximum = {mm.first, mm.second};
4601 auto mm = convertPixelToMm(
output
4602 , window_size.pixel_minimum.
width
4603 , window_size.pixel_minimum.height
4605 window_size.mm_minimum = {mm.first, mm.second};
4607 auto percent = convertPixelToPercent(
output
4608 , window_size.pixel_minimum.
width
4609 , window_size.pixel_minimum.height
4611 window_size.percent_minimum = {percent.first, percent.second};
4614 mm = convertPixelToMm(
output
4615 , window_size.pixel_maximum.
width
4616 , window_size.pixel_maximum.height
4618 window_size.mm_maximum = {mm.first, mm.second};
4620 percent = convertPixelToPercent(
output
4621 , window_size.pixel_maximum.
width
4622 , window_size.pixel_maximum.height
4624 window_size.percent_maximum = {percent.first, percent.second};
4628 std::error_code error;
4630 error = windowSizeSetMinMax(window_id
4631 , window_size.pixel_minimum.width, window_size.pixel_minimum.height
4632 , window_size.pixel_maximum.width, window_size.pixel_maximum.height
4635 # if ZAKERO_XENIUM__DEBUG_ENABLED
4638 ZAKERO_XENIUM__DEBUG_ERROR(error);
4651 void Xenium::xcbEvent(
const xcb_button_press_event_t* event
4656 const WindowId window_id =
event->event;
4658 uint32_t button_code =
event->detail;
4660 if(button_code <= 3 || button_code >= 8)
4666 else if(button_code >= 8)
4675 PointerButton button =
4676 { .code = Pointer_Button_Event_Code[button_code]
4677 , .state =
event->response_type == XCB_BUTTON_PRESS
4678 ? Xenium::PointerButtonState::Pressed
4679 : Xenium::PointerButtonState::Released
4682 OutputId output_id = window_output_map[window_id];
4683 Output
output = output_map.at(output_id);
4685 PointPixel point_pixel = {0,
event->event_x,
event->event_y};
4687 auto mm = convertPixelToMm(
output
4691 PointMm point_mm = {0, mm.first, mm.second};
4693 Xenium::WindowSizeData& window_size = window_size_map[window_id];
4694 PointPercent point_percent =
4696 , (float)event->event_x / (
float)window_size.pixel.width
4697 , (float)event->event_y / (
float)window_size.pixel.height
4700 window_on_button_map[window_id].lambda_mm(button, point_mm, key_modifier);
4701 window_on_button_map[window_id].lambda_percent(button, point_percent, key_modifier);
4702 window_on_button_map[window_id].lambda_pixel(button, point_pixel, key_modifier);
4704 else if(event->response_type == XCB_BUTTON_PRESS)
4706 if(button_code == 4 || button_code == 5)
4708 PointerAxis pointer_axis =
4709 { .time =
event->time
4710 , .steps = button_code == 4 ? -1 : 1
4711 , .distance = button_code == 4 ? -15.0f : 15.0f
4712 , .source = PointerAxisSource::Wheel
4713 , .type = PointerAxisType::Vertical
4716 window_on_axis_map[window_id](pointer_axis, key_modifier);
4718 else if(button_code == 6 || button_code == 7)
4720 PointerAxis pointer_axis =
4721 { .time =
event->time
4722 , .steps = button_code == 6 ? -1 : 1
4723 , .distance = button_code == 6 ? -15.0f : 15.0f
4724 , .source = PointerAxisSource::Wheel
4725 , .type = PointerAxisType::Horizontal
4728 window_on_axis_map[window_id](pointer_axis, key_modifier);
4737 void Xenium::xcbEvent(
const xcb_client_message_event_t* event
4741 if(window_delete_map.contains(event->window))
4743 WindowDeleteData& window_delete = window_delete_map[
event->window];
4744 if(event->data.data32[0] == window_delete.atom_close_request)
4746 window_delete.close_request_lambda();
4775 void Xenium::xcbEvent(
const xcb_configure_notify_event_t* event
4779 if((event->response_type & 0x80) == 0)
4785 const WindowId window_id =
event->window;
4787 auto iter = window_size_map.find(window_id);
4789 if(iter == std::end(window_size_map))
4794 Xenium::WindowSizeData& window_size = iter->second;
4797 const Output&
output = this->
output(event->x, event->y, output_id);
4799 if(window_output_map[window_id] != output_id)
4801 window_output_map[window_id] = output_id;
4803 windowResizeTo(
output, window_size, event);
4808 if(window_size.pixel.width == event->width
4809 && window_size.pixel.height == event->height
4815 window_size.pixel = {
event->width,
event->height};
4817 auto mm = convertPixelToMm(
output
4818 , window_size.pixel.
width
4819 , window_size.pixel.height
4821 window_size.mm = {mm.first, mm.second};
4823 auto percent = convertPixelToPercent(
output
4824 , window_size.pixel.
width
4825 , window_size.pixel.height
4827 window_size.percent = {percent.first, percent.second};
4829 window_size.pixel_lambda(window_size.pixel);
4830 window_size.percent_lambda(window_size.percent);
4831 window_size.mm_lambda(window_size.mm);
4842 void Xenium::xcbEvent(
const xcb_enter_notify_event_t* event
4847 const WindowId window_id =
event->event;
4849 if(event->response_type == XCB_LEAVE_NOTIFY)
4851 window_on_leave_map[window_id]();
4852 window_keyboard[window_id].on_leave();
4856 xkbIndicatorStateUpdate();
4858 OutputId output_id = window_output_map[window_id];
4859 Output
output = output_map.at(output_id);
4861 PointPixel point_pixel = {0,
event->event_x,
event->event_y};
4863 auto mm = convertPixelToMm(
output
4867 PointMm point_mm = {0, mm.first, mm.second};
4869 Xenium::WindowSizeData& window_size = window_size_map[window_id];
4870 PointPercent point_percent =
4872 , (float)event->event_x / (
float)window_size.pixel.width
4873 , (float)event->event_y / (
float)window_size.pixel.height
4876 window_on_enter_map[window_id].lambda_mm(point_mm, key_modifier);
4877 window_on_enter_map[window_id].lambda_percent(point_percent, key_modifier);
4878 window_on_enter_map[window_id].lambda_pixel(point_pixel, key_modifier);
4880 window_keyboard[window_id].on_enter();
4887 void Xenium::xcbEvent(
const xcb_expose_event_t* event
4891 windowReadySet(event->window);
4898 void Xenium::xcbEvent(
const xcb_focus_in_event_t* event
4903 const WindowId window_id =
event->event;
4905 if(window_focus_map.contains(window_id) ==
false)
4910 if(event->response_type == XCB_FOCUS_IN)
4912 xkbControlsUpdate();
4913 xkbIndicatorStateUpdate();
4914 window_focus_map[window_id](
true);
4918 keyDataArrayClear();
4919 window_focus_map[window_id](
false);
4927 void Xenium::xcbEvent(
const xcb_gravity_notify_event_t*
4961 void Xenium::xcbEvent(
const xcb_key_press_event_t* event
4966 uint32_t key_code = (uint32_t)event->detail - 8;
4968 constexpr uint16_t CapsLock = 0b0000'0010'0000'0000;
4969 constexpr uint16_t NumLock = 0b0000'0001'0000'0000;
4970 constexpr uint16_t Alt_Left = 0b0000'0000'1000'0000;
4971 constexpr uint16_t Alt_Right = 0b0000'0000'0100'0000;
4972 constexpr uint16_t Control_Left = 0b0000'0000'0010'0000;
4973 constexpr uint16_t Control_Right = 0b0000'0000'0001'0000;
4974 constexpr uint16_t Meta_Left = 0b0000'0000'0000'1000;
4975 constexpr uint16_t Meta_Right = 0b0000'0000'0000'0100;
4976 constexpr uint16_t Shift_Left = 0b0000'0000'0000'0010;
4977 constexpr uint16_t Shift_Right = 0b0000'0000'0000'0001;
4979 if(event->response_type == XCB_KEY_PRESS)
4984 xkbIndicatorStateUpdate();
4985 xkb_modifier_pressed |= CapsLock;
4989 xkbIndicatorStateUpdate();
4990 xkb_modifier_pressed |= NumLock;
4994 xkb_modifier_pressed |= Alt_Left;
4998 xkb_modifier_pressed |= Alt_Right;
5002 xkb_modifier_pressed |= Control_Left;
5006 xkb_modifier_pressed |= Control_Right;
5010 xkb_modifier_pressed |= Meta_Left;
5014 xkb_modifier_pressed |= Meta_Right;
5018 xkb_modifier_pressed |= Shift_Left;
5021 case KEY_RIGHTSHIFT:
5022 xkb_modifier_pressed |= Shift_Right;
5031 xkbIndicatorStateUpdate();
5032 xkb_modifier_pressed &= (~CapsLock);
5036 xkbIndicatorStateUpdate();
5037 xkb_modifier_pressed &= (~NumLock);
5041 xkb_modifier_pressed &= (~Alt_Left);
5045 xkb_modifier_pressed &= (~Alt_Right);
5049 xkb_modifier_pressed &= (~Control_Left);
5053 xkb_modifier_pressed &= (~Control_Right);
5057 xkb_modifier_pressed &= (~Meta_Left);
5061 xkb_modifier_pressed &= (~Meta_Right);
5065 xkb_modifier_pressed &= (~Shift_Left);
5068 case KEY_RIGHTSHIFT:
5069 xkb_modifier_pressed &= (~Shift_Right);
5074 key_modifier.pressed = 0;
5076 if(xkb_modifier_pressed & CapsLock)
5081 if(xkb_modifier_pressed & NumLock)
5086 if(xkb_modifier_pressed & (Alt_Left | Alt_Right))
5091 if(xkb_modifier_pressed & (Control_Left | Control_Right))
5096 if(xkb_modifier_pressed & (Meta_Left | Meta_Right))
5101 if(xkb_modifier_pressed & (Shift_Left | Shift_Right))
5106 const WindowId window_id =
event->event;
5108 key_data_array[key_code].window_id = window_id;
5110 Key& key = key_data_array[key_code].key;
5111 key.code = key_code;
5113 if(event->response_type == XCB_KEY_PRESS)
5115 key_data_array[key_code].modifier = key_modifier;
5117 if(key.time == event->time)
5119 key.state = KeyState::Repeat;
5123 key.time =
event->time;
5124 key.state = KeyState::Pressed;
5126 key_data_array[key_code].repeat_time =
5127 event->time + xkb_controls.repeat_delay_ms
5130 window_on_key_map[window_id](key, key_modifier);
5142 else if(key.time != 0)
5144 key.time =
event->time;
5145 key.state = KeyState::Released;
5147 key_data_array[key_code].modifier = key_modifier;
5155 void Xenium::xcbEvent(
const xcb_map_notify_event_t*
5165 void Xenium::xcbEvent(
const xcb_motion_notify_event_t* event
5170 const WindowId window_id =
event->event;
5172 OutputId output_id = window_output_map[window_id];
5173 Output
output = output_map.at(output_id);
5175 PointPixel point_pixel = {0,
event->event_x,
event->event_y};
5177 auto mm = convertPixelToMm(
output
5181 PointMm point_mm = {0, mm.first, mm.second};
5183 Xenium::WindowSizeData& window_size = window_size_map[window_id];
5184 PointPercent point_percent =
5186 , (float)event->event_x / (
float)window_size.pixel.width
5187 , (float)event->event_y / (
float)window_size.pixel.height
5190 window_on_motion_map[window_id].lambda_mm(point_mm, key_modifier);
5191 window_on_motion_map[window_id].lambda_percent(point_percent, key_modifier);
5192 window_on_motion_map[window_id].lambda_pixel(point_pixel, key_modifier);
5199 void Xenium::xcbEvent(
const xcb_property_notify_event_t* event
5204 xcb_generic_error_t generic_error;
5206 if(event->atom == atom_net_frame_extents)
5208 std::vector<int32_t> atom_data = Xenium::atomValueData(event->window
5209 , atom_net_frame_extents
5223 { .left = atom_data[0]
5224 , .right = atom_data[1]
5225 , .top = atom_data[2]
5226 , .bottom = atom_data[3]
5229 WindowDecorationsData& window = window_decorations_map[
event->window];
5233 if(frame_extents.left == 0
5234 && frame_extents.right == 0
5235 && frame_extents.top == 0
5236 && frame_extents.bottom == 0
5239 window.window_decorations = WindowDecorations::Client_Side;
5243 window.window_decorations = WindowDecorations::Server_Side;
5246 if(window.window_decorations != window_decorations)
5248 window.lambda(window.window_decorations);
5254 if(event->atom == atom_net_wm_state)
5256 std::vector<xcb_atom_t> value =
5257 atomValueAtom(event->window, event->atom, generic_error);
5259 WindowMode new_window_mode = WindowMode::Normal;
5261 if(zakero::vectorContains(value, atom_net_wm_state_maximized_horz)
5262 && zakero::vectorContains(value, atom_net_wm_state_maximized_vert)
5265 new_window_mode = WindowMode::Maximized;
5267 else if(zakero::vectorContains(value, atom_net_wm_state_fullscreen))
5269 new_window_mode = WindowMode::Fullscreen;
5272 if(window_mode_map.contains(event->window))
5274 WindowModeData& data = window_mode_map[
event->window];
5276 if(data.window_mode != new_window_mode)
5278 data.window_mode = new_window_mode;
5279 lambda = data.lambda;
5282 lambda(new_window_mode);
5292 void Xenium::xcbEvent(
const xcb_reparent_notify_event_t*
5302 void Xenium::xcbEvent(
const xcb_unmap_notify_event_t*
5316 void Xenium::xcbWindowCreate(Xenium::WindowCreateData* window_data
5319 window_data->error = xcbWindowCreateValidate(window_data);
5320 if(window_data->error)
5322 ZAKERO_XENIUM__DEBUG_ERROR(window_data->error);
5327 window_data->error = xcbWindowCreateClient(window_data);
5328 if(window_data->error)
5330 ZAKERO_XENIUM__DEBUG_ERROR(window_data->error);
5332 Xenium::WindowDestroyData data =
5334 , .window_id = window_data->window_id
5335 , .gc = window_data->gc
5338 xcbWindowDestroy(&data);
5343 window_data->error = xcbWindowCreateInit(window_data);
5344 if(window_data->error)
5346 ZAKERO_XENIUM__DEBUG_ERROR(window_data->error);
5348 Xenium::WindowDestroyData data =
5350 , .window_id = window_data->window_id
5351 , .gc = window_data->gc
5354 xcbWindowDestroy(&data);
5370 std::error_code Xenium::xcbWindowCreateValidate(Xenium::WindowCreateData* window_data
5373 window_data->output_id = output_map.begin()->first;
5374 Xenium::Output&
output = output_map.begin()->second;
5376 Xenium::SizePixel size_pixel;
5378 if(window_data->size_unit == Xenium::SizeUnit::Millimeter)
5380 auto pixel = convertMmToPixel(
output
5381 , window_data->size_mm.
width
5382 , window_data->size_mm.height
5384 size_pixel = {pixel.first, pixel.second};
5386 else if(window_data->size_unit == Xenium::SizeUnit::Percent)
5388 auto pixel = convertPercentToPixel(
output
5389 , window_data->size_percent.
width
5390 , window_data->size_percent.height
5392 size_pixel = {pixel.first, pixel.second};
5396 size_pixel = window_data->size_pixel;
5399 if((size_pixel.width < Window_Size_Minimum)
5400 || (size_pixel.width < Window_Size_Minimum)
5403 ZAKERO_XENIUM__DEBUG_ERROR(
5404 ZAKERO_XENIUM__ERROR(Error_Window_Size_Too_Small)
5407 return ZAKERO_XENIUM__ERROR(Error_Window_Size_Too_Small);
5410 if(window_data->size_unit == Xenium::SizeUnit::Millimeter)
5412 window_data->size_pixel = size_pixel;
5414 auto percent = convertPixelToPercent(
output
5415 , window_data->size_pixel.
width
5416 , window_data->size_pixel.height
5418 window_data->size_percent = {percent.first, percent.second};
5420 else if(window_data->size_unit == Xenium::SizeUnit::Percent)
5422 window_data->size_pixel = size_pixel;
5424 auto mm = convertPixelToMm(
output
5425 , window_data->size_pixel.
width
5426 , window_data->size_pixel.height
5428 window_data->size_mm = {mm.first, mm.second};
5432 auto mm = convertPixelToMm(
output
5433 , window_data->size_pixel.
width
5434 , window_data->size_pixel.height
5436 window_data->size_mm = {mm.first, mm.second};
5438 auto percent = convertPixelToPercent(
output
5439 , window_data->size_pixel.
width
5440 , window_data->size_pixel.height
5442 window_data->size_percent = {percent.first, percent.second};
5445 return ZAKERO_XENIUM__ERROR(Error_None);
5456 std::error_code Xenium::xcbWindowCreateClient(Xenium::WindowCreateData* data
5459 data->window_id = xcb_generate_id(this->connection);
5461 xcb_void_cookie_t cookie =
5462 xcb_create_window_aux_checked(this->connection
5463 , this->screen->root_depth
5465 , this->screen->root
5467 , data->size_pixel.width
5468 , data->size_pixel.height
5470 , XCB_WINDOW_CLASS_INPUT_OUTPUT
5471 , this->screen->root_visual
5476 xcb_generic_error_t generic_error;
5478 if(requestCheckHasError(cookie, generic_error))
5480 ZAKERO_XENIUM__DEBUG <<
"Error: " <<
to_string(generic_error) <<
'\n';
5482 data->window_id = 0;
5484 return ZAKERO_XENIUM__ERROR(Error_Unknown);
5487 data->atom_close_request = atomCreateDeleteWindow(data->window_id
5491 if(data->atom_close_request == XCB_ATOM_NONE)
5493 ZAKERO_XENIUM__DEBUG <<
"Error: " <<
to_string(generic_error) <<
'\n';
5495 return ZAKERO_XENIUM__ERROR(Error_Unknown);
5498 xcb_size_hints_t size_hints =
5510 , .min_aspect_num = 0
5511 , .min_aspect_den = 0
5512 , .max_aspect_num = 0
5513 , .max_aspect_den = 0
5519 xcb_change_property_checked(this->connection
5520 , XCB_PROP_MODE_REPLACE
5522 , XCB_ATOM_WM_NORMAL_HINTS
5523 , XCB_ATOM_WM_SIZE_HINTS
5529 if(requestCheckHasError(cookie, generic_error))
5531 ZAKERO_XENIUM__DEBUG <<
"Error: " <<
to_string(generic_error) <<
'\n';
5533 return ZAKERO_XENIUM__ERROR(Error_Unknown);
5536 data->gc = xcb_generate_id(this->connection);
5537 cookie = xcb_create_gc_checked(this->connection
5544 if(requestCheckHasError(cookie, generic_error))
5546 ZAKERO_XENIUM__DEBUG <<
"Error: " <<
to_string(generic_error) <<
'\n';
5550 return ZAKERO_XENIUM__ERROR(Error_Unknown);
5553 return ZAKERO_XENIUM__ERROR(Error_None);
5560 void Xenium::xcbWindowDestroy(Xenium::WindowDestroyData* window_data
5563 if(window_data->window_id == 0)
5568 if(window_data->gc != 0)
5570 xcb_free_gc(this->connection, window_data->gc);
5572 window_data->gc = 0;
5575 xcb_destroy_window(this->connection, window_data->window_id);
5577 window_decorations_map.erase(window_data->window_id);
5578 window_delete_map.erase(window_data->window_id);
5579 window_focus_map.erase(window_data->window_id);
5580 window_keyboard.erase(window_data->window_id);
5581 window_map.erase(window_data->window_id);
5582 window_mode_map.erase(window_data->window_id);
5583 window_on_axis_map.erase(window_data->window_id);
5584 window_on_button_map.erase(window_data->window_id);
5585 window_on_enter_map.erase(window_data->window_id);
5586 window_on_key_map.erase(window_data->window_id);
5587 window_on_leave_map.erase(window_data->window_id);
5588 window_on_motion_map.erase(window_data->window_id);
5589 window_output_map.erase(window_data->window_id);
5590 window_ready_map.erase(window_data->window_id);
5591 window_size_map.erase(window_data->window_id);
5593 window_data->window_id = 0;
5604 std::error_code Xenium::xcbWindowCreateInit(Xenium::WindowCreateData* data
5607 window_size_map[data->window_id] =
5608 { .mm = data->size_mm
5609 , .mm_minimum = {0, 0}
5610 , .mm_maximum = {0, 0}
5611 , .mm_lambda = LambdaSizeMm_DoNothing
5612 , .percent = data->size_percent
5613 , .percent_minimum = {0, 0}
5614 , .percent_maximum = {0, 0}
5615 , .percent_lambda = LambdaSizePercent_DoNothing
5616 , .pixel = data->size_pixel
5617 , .pixel_minimum = {0, 0}
5618 , .pixel_maximum = {0, 0}
5619 , .pixel_lambda = LambdaSizePixel_DoNothing
5620 , .unit = data->size_unit
5623 window_mode_map[data->window_id] =
5624 { .window_mode = WindowMode::Normal
5625 , .lambda = LambdaWindowMode_DoNothing
5628 window_output_map[data->window_id] = data->output_id;
5630 window_keyboard[data->window_id] =
5631 { .on_enter = Lambda_DoNothing
5632 , .on_leave = Lambda_DoNothing
5635 window_on_key_map[data->window_id] = LambdaKey_DoNothing;
5636 window_on_leave_map[data->window_id] = Lambda_DoNothing;
5637 window_on_axis_map[data->window_id] = LambdaAxis_DoNothing;
5639 window_on_motion_map[data->window_id] =
5640 { .lambda_mm = LambdaPointMm_DoNothing
5641 , .lambda_percent = LambdaPointPercent_DoNothing
5642 , .lambda_pixel = LambdaPointPixel_DoNothing
5645 window_on_button_map[data->window_id] =
5646 { .lambda_mm = LambdaButtonMm_DoNothing
5647 , .lambda_percent = LambdaButtonPercent_DoNothing
5648 , .lambda_pixel = LambdaButtonPixel_DoNothing
5651 window_on_enter_map[data->window_id] =
5652 { .lambda_mm = LambdaPointMm_DoNothing
5653 , .lambda_percent = LambdaPointPercent_DoNothing
5654 , .lambda_pixel = LambdaPointPixel_DoNothing
5657 window_decorations_map[data->window_id] =
5658 { .window_decorations = WindowDecorations::Server_Side
5659 , .lambda = LambdaWindowDecorations_DoNothing
5662 window_focus_map[data->window_id] = LambdaBool_DoNothing;
5664 window_delete_map[data->window_id] =
5665 { .close_request_lambda = Lambda_DoNothing
5666 , .atom_close_request = data->atom_close_request
5669 window_ready_map[data->window_id] =
false;
5671 return ZAKERO_XENIUM__ERROR(Error_None);
5685 std::error_code Xenium::atomInit() noexcept
5687 auto cookie_motif_wm_hints = internAtomRequest(
"_MOTIF_WM_HINTS");
5688 auto cookie_net_frame_extents = internAtomRequest(
"_NET_FRAME_EXTENTS");
5689 auto cookie_net_wm_state = internAtomRequest(
"_NET_WM_STATE");
5690 auto cookie_net_wm_state_fullscreen = internAtomRequest(
"_NET_WM_STATE_FULLSCREEN");
5691 auto cookie_net_wm_state_hidden = internAtomRequest(
"_NET_WM_STATE_HIDDEN");
5692 auto cookie_net_wm_state_maximized_horz = internAtomRequest(
"_NET_WM_STATE_MAXIMIZED_HORZ");
5693 auto cookie_net_wm_state_maximized_vert = internAtomRequest(
"_NET_WM_STATE_MAXIMIZED_VERT");
5694 auto cookie_wm_change_state = internAtomRequest(
"WM_CHANGE_STATE");
5695 auto cookie_wm_delete_window = internAtomRequest(
"WM_DELETE_WINDOW");
5696 auto cookie_wm_protocols = internAtomRequest(
"WM_PROTOCOLS");
5698 xcb_generic_error_t generic_error;
5700 atom_motif_wm_hints = internAtomReply(cookie_motif_wm_hints , generic_error);
5701 atom_net_frame_extents = internAtomReply(cookie_net_frame_extents , generic_error);
5702 atom_net_wm_state = internAtomReply(cookie_net_wm_state , generic_error);
5703 atom_net_wm_state_fullscreen = internAtomReply(cookie_net_wm_state_fullscreen , generic_error);
5704 atom_net_wm_state_hidden = internAtomReply(cookie_net_wm_state_hidden , generic_error);
5705 atom_net_wm_state_maximized_horz = internAtomReply(cookie_net_wm_state_maximized_horz , generic_error);
5706 atom_net_wm_state_maximized_vert = internAtomReply(cookie_net_wm_state_maximized_vert , generic_error);
5707 atom_wm_change_state = internAtomReply(cookie_wm_change_state , generic_error);
5708 atom_wm_delete_window = internAtomReply(cookie_wm_delete_window , generic_error);
5709 atom_wm_protocols = internAtomReply(cookie_wm_protocols , generic_error);
5711 if(atom_wm_delete_window == XCB_ATOM_NONE)
5713 ZAKERO_XENIUM__DEBUG_ERROR(
5714 ZAKERO_XENIUM__ERROR(Error_Xcb_WM_Delete_Window_Not_Available)
5717 return ZAKERO_XENIUM__ERROR(Error_Xcb_WM_Delete_Window_Not_Available);
5720 if(atom_wm_protocols == XCB_ATOM_NONE)
5722 ZAKERO_XENIUM__DEBUG_ERROR(
5723 ZAKERO_XENIUM__ERROR(Error_Xcb_WM_Protocols_Not_Available)
5726 return ZAKERO_XENIUM__ERROR(Error_Xcb_WM_Protocols_Not_Available);
5729 if(atom_net_wm_state == XCB_ATOM_NONE)
5731 ZAKERO_XENIUM__DEBUG_ERROR(
5732 ZAKERO_XENIUM__ERROR(Error_Xcb_NETWM_State_Not_Available)
5735 return ZAKERO_XENIUM__ERROR(Error_Xcb_NETWM_State_Not_Available);
5738 if(atom_net_wm_state_fullscreen == XCB_ATOM_NONE)
5740 ZAKERO_XENIUM__DEBUG_ERROR(
5741 ZAKERO_XENIUM__ERROR(Error_Xcb_Fullscreen_Not_Available)
5744 return ZAKERO_XENIUM__ERROR(Error_Xcb_Fullscreen_Not_Available);
5747 if(atom_net_wm_state_hidden == XCB_ATOM_NONE)
5749 ZAKERO_XENIUM__DEBUG_ERROR(
5750 ZAKERO_XENIUM__ERROR(Error_Xcb_Hidden_Not_Available)
5753 return ZAKERO_XENIUM__ERROR(Error_Xcb_Hidden_Not_Available);
5756 if((atom_net_wm_state_maximized_horz == XCB_ATOM_NONE)
5757 || (atom_net_wm_state_maximized_vert == XCB_ATOM_NONE)
5760 ZAKERO_XENIUM__DEBUG_ERROR(
5761 ZAKERO_XENIUM__ERROR(Error_Xcb_Maximized_Window_Not_Available)
5764 return ZAKERO_XENIUM__ERROR(Error_Xcb_Maximized_Window_Not_Available);
5767 return ZAKERO_XENIUM__ERROR(Error_None);
5784 xcb_atom_t Xenium::atomCreateDeleteWindow(
const WindowId window_id
5785 , xcb_generic_error_t& generic_error
5788 bool property_was_set = windowPropertySet(window_id
5790 , atom_wm_delete_window
5794 if(property_was_set ==
false)
5796 ZAKERO_XENIUM__DEBUG_VAR(
to_string(generic_error));
5797 return XCB_ATOM_NONE;
5800 return atom_wm_delete_window;
5815 std::string Xenium::atomName(
const xcb_atom_t atom
5818 if(atom == XCB_ATOM_NONE)
5823 xcb_get_atom_name_cookie_t cookie =
5824 xcb_get_atom_name(this->connection, atom);
5826 xcb_generic_error_t* error =
nullptr;
5828 xcb_get_atom_name_reply_t* reply =
5829 xcb_get_atom_name_reply(this->connection
5834 if(reply ==
nullptr)
5839 char* name = xcb_get_atom_name_name(reply);
5841 std::string atom_name(name);
5861 std::vector<xcb_atom_t> Xenium::atomValueAtom(
const WindowId window_id
5862 ,
const xcb_atom_t property_atom
5863 , xcb_generic_error_t& generic_error
5866 xcb_get_property_cookie_t property_cookie =
5867 xcb_get_property(this->connection
5876 xcb_generic_error_t* error =
nullptr;
5878 xcb_get_property_reply_t*
property =
5879 xcb_get_property_reply(this->connection
5884 if(property ==
nullptr)
5886 generic_error = *error;
5891 int length = xcb_get_property_value_length(property) / 4;
5893 std::vector<xcb_atom_t> retval(length);
5895 xcb_atom_t* value = (xcb_atom_t*)xcb_get_property_value(property);
5897 for(
int i = 0; i < length; i++)
5899 retval[i] = value[i];
5925 std::vector<int32_t> Xenium::atomValueData(
const WindowId window_id
5926 ,
const xcb_atom_t property_atom
5927 ,
const xcb_atom_t type
5928 ,
const size_t count
5929 , xcb_generic_error_t& generic_error
5932 xcb_get_property_cookie_t property_cookie =
5933 xcb_get_property(this->connection
5942 xcb_generic_error_t* error =
nullptr;
5944 xcb_get_property_reply_t*
property =
5945 xcb_get_property_reply(this->connection
5950 if(property ==
nullptr)
5952 generic_error = *error;
5957 int length = xcb_get_property_value_length(property) / 4;
5959 std::vector<int32_t> vector(length);
5961 int32_t* value = (int32_t*)xcb_get_property_value(property);
5963 for(
int i = 0; i < length; i++)
5965 vector[i] = value[i];
5992 xcb_atom_t Xenium::internAtom(
const std::string& atom_name
5993 ,
const bool create_if_needed
5994 , xcb_generic_error_t& generic_error
5997 xcb_generic_error_t* error =
nullptr;
5999 xcb_intern_atom_reply_t* atom_reply =
6000 xcb_intern_atom_reply(this->connection
6001 , xcb_intern_atom(this->connection
6004 , create_if_needed ? 0 : 1
6005 , atom_name.length()
6013 if(error !=
nullptr)
6015 atom = XCB_ATOM_NONE;
6016 generic_error = *error;
6019 ZAKERO_XENIUM__DEBUG <<
"Error: " <<
to_string(generic_error) <<
'\n';
6021 else if(atom_reply->atom == XCB_ATOM_NONE
6022 && atom_name !=
"XCB_ATOM_NONE"
6025 ZAKERO_XENIUM__DEBUG <<
"Error: Failed to get \""
6030 atom = XCB_ATOM_NONE;
6034 atom = atom_reply->atom;
6057 xcb_intern_atom_cookie_t Xenium::internAtomRequest(
const std::string& atom_name
6058 ,
const bool create_if_needed
6061 xcb_intern_atom_cookie_t cookie =
6062 xcb_intern_atom(this->connection
6066 , atom_name.length()
6085 xcb_atom_t Xenium::internAtomReply(
const xcb_intern_atom_cookie_t intern_atom_cookie
6086 , xcb_generic_error_t& generic_error
6089 xcb_generic_error_t* error =
nullptr;
6091 xcb_intern_atom_reply_t* atom_reply =
6092 xcb_intern_atom_reply(this->connection
6093 , intern_atom_cookie
6099 if(error !=
nullptr)
6101 atom = XCB_ATOM_NONE;
6102 generic_error = *error;
6105 ZAKERO_XENIUM__DEBUG <<
"Error: " <<
to_string(generic_error) <<
'\n';
6107 else if(atom_reply->atom == XCB_ATOM_NONE)
6109 ZAKERO_XENIUM__DEBUG <<
"Error: Failed to get atom.\n";
6111 atom = XCB_ATOM_NONE;
6115 atom = atom_reply->atom;
6134 std::error_code Xenium::randrInit() noexcept
6136 const xcb_query_extension_reply_t* randr =
6137 xcb_get_extension_data(this->connection, &xcb_randr_id);
6139 if(randr->present == 0)
6141 ZAKERO_XENIUM__DEBUG_ERROR(
6142 ZAKERO_XENIUM__ERROR(Error_RandR_Not_Available)
6145 return ZAKERO_XENIUM__ERROR(Error_RandR_Not_Available);
6148 randr_error_base = randr->first_error;
6149 randr_event_base = randr->first_event;
6151 xcb_generic_error_t* xcb_generic_error =
nullptr;
6153 xcb_randr_query_version_reply_t* randr_query_version =
6154 xcb_randr_query_version_reply(this->connection
6155 , xcb_randr_query_version(this->connection
6156 , std::numeric_limits<uint32_t>::max()
6157 , std::numeric_limits<uint32_t>::max()
6159 , &xcb_generic_error
6162 randr_query_version_major = randr_query_version->major_version;
6163 randr_query_version_minor = randr_query_version->minor_version;
6167 if(randr_query_version_major < 1
6168 || (randr_query_version_major == 1
6169 && randr_query_version_minor < 1
6173 ZAKERO_XENIUM__DEBUG_ERROR(
6174 ZAKERO_XENIUM__ERROR(Error_RandR_Version_Too_Old)
6177 return ZAKERO_XENIUM__ERROR(Error_RandR_Version_Too_Old);
6180 xcb_randr_select_input(this->connection
6181 , this->screen->root
6183 | XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE
6184 | XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE
6194 return ZAKERO_XENIUM__ERROR(Error_None);
6201 void Xenium::randrEvent(
const xcb_randr_crtc_change_t* event
6205 OutputId output_id =
event->crtc;
6207 if(this->screen->root != event->window
6208 || output_map.contains(output_id) ==
false
6214 Output&
output = output_map[output_id];
6235 output_on_change(output_id);
6242 void Xenium::randrEvent(
const xcb_randr_output_change_t* event
6247 if(this->screen->root != event->window)
6252 OutputId output_id =
event->crtc;
6254 if(event->connection == XCB_RANDR_CONNECTION_DISCONNECTED)
6256 if(output_map.contains(output_id))
6258 output_on_remove(output_id);
6261 std::lock_guard<std::mutex> lock(output_mutex);
6263 output_map.erase(output_id);
6265 else if((event->connection == XCB_RANDR_CONNECTION_CONNECTED)
6266 || (output_map.contains(output_id) ==
false)
6269 std::error_code error;
6271 std::lock_guard<std::mutex> lock(output_mutex);
6273 error = outputAdd(event->crtc, event->output);
6278 output_on_add(output_id);
6280 # if ZAKERO_XENIUM__DEBUG_ENABLED
6283 ZAKERO_XENIUM__DEBUG_ERROR(error);
6290 Output&
output = output_map[output_id];
6299 output_on_change(output_id);
6311 void Xenium::randrEvent(
const xcb_randr_notify_event_t* event
6314 switch(event->subCode)
6316 case XCB_RANDR_NOTIFY_CRTC_CHANGE:
6317 randrEvent(&event->u.cc);
6319 case XCB_RANDR_NOTIFY_OUTPUT_CHANGE:
6320 randrEvent(&event->u.oc);
6322 case XCB_RANDR_NOTIFY_OUTPUT_PROPERTY:
6325 case XCB_RANDR_NOTIFY_PROVIDER_CHANGE:
6328 case XCB_RANDR_NOTIFY_PROVIDER_PROPERTY:
6331 case XCB_RANDR_NOTIFY_RESOURCE_CHANGE:
6334 case XCB_RANDR_NOTIFY_LEASE:
6338 fprintf(stderr,
"Unhandled Sub-Event %d\n", event->subCode);
6346 void Xenium::randrEvent(
const xcb_randr_screen_change_notify_event_t*
6362 std::error_code Xenium::xkbInit() noexcept
6364 xcb_xkb_use_extension_reply_t* extension_reply =
6365 xcb_xkb_use_extension_reply(this->connection
6366 , xcb_xkb_use_extension(this->connection, 1, 0)
6370 if(extension_reply ==
nullptr)
6372 ZAKERO_XENIUM__DEBUG_ERROR(
6373 ZAKERO_XENIUM__ERROR(Error_Xcb_Xkb_Not_Available)
6376 return ZAKERO_XENIUM__ERROR(Error_Xcb_Xkb_Not_Available);
6379 free(extension_reply);
6381 return ZAKERO_XENIUM__ERROR(Error_None);
6392 void Xenium::keyDataArrayClear() noexcept
6396 for(
auto& key_data : key_data_array)
6398 Key& key = key_data.key;
6405 key.state = KeyState::Released;
6406 key.time = time_now;
6408 const KeyModifier& modifier = key_data.modifier;
6409 const WindowId& window_id = key_data.window_id;
6411 window_on_key_map[window_id](key, modifier);
6426 void Xenium::keyDataArrayProcess() noexcept
6428 for(
auto& key_data : key_data_array)
6430 Key& key = key_data.key;
6437 if(key.state == KeyState::Pressed)
6439 key.state = KeyState::Repeat;
6444 const WindowId& window_id = key_data.window_id;
6446 if(key.state == KeyState::Released)
6448 window_on_key_map[window_id](key, key_data.modifier);
6454 auto& repeat_time = key_data.repeat_time;
6458 if(key.state == KeyState::Repeat
6459 && repeat_time < time_now
6462 window_on_key_map[window_id](key, key_modifier);
6463 key.time = repeat_time;
6464 repeat_time += xkb_controls.repeat_interval_ms;
6475 void Xenium::xkbControlsUpdate() noexcept
6477 xcb_xkb_get_controls_reply_t* controls_reply =
6478 xcb_xkb_get_controls_reply(this->connection
6479 , xcb_xkb_get_controls(this->connection
6480 , XCB_XKB_ID_USE_CORE_KBD
6485 if(controls_reply ==
nullptr)
6490 xkb_controls.repeat_delay_ms = controls_reply->repeatDelay;
6491 xkb_controls.repeat_interval_ms = controls_reply->repeatInterval;
6493 free(controls_reply);
6500 void Xenium::xkbIndicatorStateUpdate() noexcept
6502 xcb_xkb_get_indicator_state_reply_t* reply =
6503 xcb_xkb_get_indicator_state_reply(this->connection
6504 , xcb_xkb_get_indicator_state(this->connection
6505 , XCB_XKB_ID_USE_CORE_KBD
6510 if(reply ==
nullptr)
6515 const uint32_t state = reply->state;
6519 key_modifier.locked = 0
6520 | (bool(state & XCB_XKB_INDICATOR_STATE_CAPSLOCK) * caps_lock)
6521 | (
bool(state & XCB_XKB_INDICATOR_STATE_NUMLOCK) * num_lock)
6543 bool Xenium::requestCheckHasError(
const xcb_void_cookie_t& void_cookie
6544 , xcb_generic_error_t& generic_error
6547 xcb_generic_error_t* error = xcb_request_check(this->connection, void_cookie);
6549 if(error !=
nullptr)
6551 std::cout <<
"requestCheck Error: " <<
to_string(*error) <<
'\n';
6553 generic_error = *error;
6668 , frame_buffer(nullptr)
6669 , frame_buffer_size{0, 0}
6670 , window_id(((WindowCreateData*)data)->window_id)
6671 , gc(((WindowCreateData*)data)->gc)
6672 , frame_buffer_length(0)
6683 Xenium::WindowDestroyData data =
6685 , .window_id = this->window_id
6689 std::future<void> barrier = data.barrier.get_future();
6691 xenium->windowDestroyAddToQueue(&data);
6724 xcb_generic_error_t generic_error;
6726 success = xenium->windowPropertySet(window_id
6732 if(success ==
false)
6734 ZAKERO_XENIUM__DEBUG_VAR(
to_string(generic_error));
6749 xcb_generic_error_t generic_error;
6751 success = xenium->windowPropertySet(window_id
6757 if(success ==
false)
6759 ZAKERO_XENIUM__DEBUG_VAR(
to_string(generic_error));
6780 WindowDeleteData& window_delete = xenium->window_delete_map[window_id];
6782 if(lambda ==
nullptr)
6784 window_delete.close_request_lambda = Lambda_DoNothing;
6788 window_delete.close_request_lambda = lambda;
6809 if(lambda ==
nullptr)
6811 xenium->window_focus_map[window_id] = LambdaBool_DoNothing;
6815 xenium->window_focus_map[window_id] = lambda;
6840 std::error_code error;
6842 if(decorations == WindowDecorations::Client_Side)
6845 error = xenium->windowBorder(window_id,
false);
6850 error = xenium->windowBorder(window_id,
true);
6853 # if ZAKERO_XENIUM__DEBUG_ENABLED
6856 ZAKERO_XENIUM__DEBUG_ERROR(error);
6874 WindowDecorationsData& window_decorations = xenium->window_decorations_map[window_id];
6878 window_decorations.lambda = lambda;
6882 window_decorations.lambda = LambdaWindowDecorations_DoNothing;
6909 std::lock_guard lock(xenium->output_mutex);
6911 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
6913 Xenium::WindowSizeData& window_size = xenium->window_size_map[window_id];
6914 window_size.unit = SizeUnit::Millimeter;
6916 auto pixel = xenium->convertMmToPixel(
output
6921 if(pixel.first < Window_Size_Minimum
6922 || pixel.second < Window_Size_Minimum
6925 return ZAKERO_XENIUM__ERROR(Error_Window_Size_Too_Small);
6928 if(pixel.first == window_size.pixel.width
6929 && pixel.second == window_size.pixel.height
6932 return ZAKERO_XENIUM__ERROR(Error_None);
6935 SizePixel size_pixel = {pixel.first, pixel.second};
6937 std::error_code error = xenium->windowSizeSet(window_id, size_pixel);
6939 # if ZAKERO_XENIUM__DEBUG_ENABLED
6942 ZAKERO_XENIUM__DEBUG_ERROR(error);
6970 std::lock_guard lock(xenium->output_mutex);
6972 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
6974 Xenium::WindowSizeData& window_size = xenium->window_size_map[window_id];
6975 window_size.unit = SizeUnit::Percent;
6977 auto pixel = xenium->convertPercentToPixel(
output
6982 if(pixel.first < Window_Size_Minimum
6983 || pixel.second < Window_Size_Minimum
6986 return ZAKERO_XENIUM__ERROR(Error_Window_Size_Too_Small);
6989 if(pixel.first == window_size.pixel.width
6990 && pixel.second == window_size.pixel.height
6993 return ZAKERO_XENIUM__ERROR(Error_None);
6996 SizePixel size_pixel = {pixel.first, pixel.second};
6998 std::error_code error = xenium->windowSizeSet(window_id, size_pixel);
7000 # if ZAKERO_XENIUM__DEBUG_ENABLED
7003 ZAKERO_XENIUM__DEBUG_ERROR(error);
7030 if(size.width < Window_Size_Minimum
7031 || size.height < Window_Size_Minimum
7034 return ZAKERO_XENIUM__ERROR(Error_Window_Size_Too_Small);
7037 Xenium::WindowSizeData& window_size = xenium->window_size_map[window_id];
7038 window_size.unit = Xenium::SizeUnit::Pixel;
7040 if(window_size.pixel.width == size.width
7041 && window_size.pixel.height == size.height
7044 return ZAKERO_XENIUM__ERROR(Error_None);
7047 std::error_code error = xenium->windowSizeSet(window_id, size);
7049 # if ZAKERO_XENIUM__DEBUG_ENABLED
7052 ZAKERO_XENIUM__DEBUG_ERROR(error);
7075 std::error_code error;
7077 error = validateMinMax<Xenium::SizeMm>(size_min, size_max);
7080 ZAKERO_XENIUM__DEBUG_ERROR(error);
7085 std::lock_guard lock(xenium->output_mutex);
7087 Xenium::WindowSizeData& window_size = xenium->window_size_map[window_id];
7089 window_size.unit = Xenium::SizeUnit::Millimeter;
7090 window_size.mm_minimum = size_min;
7091 window_size.mm_maximum = size_max;
7093 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
7095 error = xenium->windowSizeSetMinMax(
output, window_id, window_size);
7097 # if ZAKERO_XENIUM__DEBUG_ENABLED
7100 ZAKERO_XENIUM__DEBUG_ERROR(error);
7123 std::error_code error;
7125 error = validateMinMax<Xenium::SizePercent>(size_min, size_max);
7128 ZAKERO_XENIUM__DEBUG_ERROR(error);
7133 std::lock_guard lock(xenium->output_mutex);
7135 Xenium::WindowSizeData& window_size = xenium->window_size_map[window_id];
7137 window_size.unit = Xenium::SizeUnit::Percent;
7138 window_size.percent_minimum = size_min;
7139 window_size.percent_maximum = size_max;
7141 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
7143 error = xenium->windowSizeSetMinMax(
output, window_id, window_size);
7145 # if ZAKERO_XENIUM__DEBUG_ENABLED
7148 ZAKERO_XENIUM__DEBUG_ERROR(error);
7171 std::error_code error;
7173 error = validateMinMax<Xenium::SizePixel>(size_min, size_max);
7176 ZAKERO_XENIUM__DEBUG_ERROR(error);
7181 std::lock_guard lock(xenium->output_mutex);
7183 Xenium::WindowSizeData& window_size = xenium->window_size_map[window_id];
7185 window_size.unit = Xenium::SizeUnit::Pixel;
7186 window_size.pixel_minimum = size_min;
7187 window_size.pixel_maximum = size_max;
7189 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
7191 error = xenium->windowSizeSetMinMax(
output, window_id, window_size);
7193 # if ZAKERO_XENIUM__DEBUG_ENABLED
7196 ZAKERO_XENIUM__DEBUG_ERROR(error);
7220 Xenium::WindowSizeData& window_size = xenium->window_size_map[window_id];
7224 window_size.mm_lambda = lambda;
7228 window_size.mm_lambda = LambdaSizeMm_DoNothing;
7249 Xenium::WindowSizeData& window_size = xenium->window_size_map[window_id];
7253 window_size.percent_lambda = lambda;
7257 window_size.percent_lambda = LambdaSizePercent_DoNothing;
7278 Xenium::WindowSizeData& window_size = xenium->window_size_map[window_id];
7282 window_size.pixel_lambda = lambda;
7286 window_size.pixel_lambda = LambdaSizePixel_DoNothing;
7303 std::lock_guard lock(xenium->output_mutex);
7305 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
7307 auto value = xenium->convertPixelToMm(
output, point.
x, point.y);
7309 return {0, value.first, value.second};
7323 std::lock_guard lock(xenium->output_mutex);
7325 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
7327 auto value = xenium->convertPixelToPercent(
output, point.
x, point.y);
7329 return {0, value.first, value.second};
7343 std::lock_guard lock(xenium->output_mutex);
7345 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
7347 auto value = xenium->convertMmToPixel(
output, point.
x, point.y);
7349 return {0, value.first, value.second};
7363 std::lock_guard lock(xenium->output_mutex);
7365 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
7367 auto value = xenium->convertPercentToPixel(
output, point.
x, point.y);
7369 return {0, value.first, value.second};
7384 std::lock_guard lock(xenium->output_mutex);
7386 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
7388 auto value = xenium->convertPixelToMm(
output, size.
width, size.height);
7390 return {value.first, value.second};
7404 std::lock_guard lock(xenium->output_mutex);
7406 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
7408 auto value = xenium->convertPixelToPercent(
output, size.
width, size.height);
7410 return {value.first, value.second};
7424 std::lock_guard lock(xenium->output_mutex);
7426 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
7428 auto value = xenium->convertMmToPixel(
output, size.
width, size.height);
7430 return {value.first, value.second};
7444 std::lock_guard lock(xenium->output_mutex);
7446 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
7448 auto value = xenium->convertPercentToPixel(
output, size.
width, size.height);
7450 return {value.first, value.second};
7466 return xenium->window_mode_map[window_id].window_mode;
7481 return (window_mode == this->windowMode());
7498 Xenium::WindowModeData& data = xenium->window_mode_map[window_id];
7500 if(data.window_mode == window_mode)
7502 return ZAKERO_XENIUM__ERROR(Error_None);
7505 std::error_code error = xenium->windowModeSet(window_id
7512 ZAKERO_XENIUM__DEBUG_ERROR(error);
7517 data.window_mode = window_mode;
7519 return ZAKERO_XENIUM__ERROR(Error_None);
7532 Xenium::WindowModeData& data = xenium->window_mode_map[window_id];
7534 if(lambda ==
nullptr)
7536 data.lambda = LambdaWindowMode_DoNothing;
7540 data.lambda = lambda;
7556 std::error_code error = xenium->windowMinimize(window_id);
7558 # if ZAKERO_XENIUM__DEBUG_ENABLED
7561 ZAKERO_XENIUM__DEBUG_ERROR(error);
7582 if(lambda ==
nullptr)
7584 xenium->window_keyboard[window_id].on_enter = Lambda_DoNothing;
7588 xenium->window_keyboard[window_id].on_enter = lambda;
7601 if(lambda ==
nullptr)
7603 xenium->window_keyboard[window_id].on_leave = Lambda_DoNothing;
7607 xenium->window_keyboard[window_id].on_leave = lambda;
7622 if(lambda ==
nullptr)
7624 xenium->window_on_key_map[window_id] = LambdaKey_DoNothing;
7628 xenium->window_on_key_map[window_id] = lambda;
7644 if(lambda ==
nullptr)
7646 xenium->window_on_axis_map[window_id] = LambdaAxis_DoNothing;
7650 xenium->window_on_axis_map[window_id] = lambda;
7665 WindowOnButtonData& on_button = xenium->window_on_button_map[window_id];
7667 if(lambda ==
nullptr)
7669 on_button.lambda_mm = LambdaButtonMm_DoNothing;
7673 on_button.lambda_mm = lambda;
7688 WindowOnButtonData& on_button = xenium->window_on_button_map[window_id];
7690 if(lambda ==
nullptr)
7692 on_button.lambda_percent = LambdaButtonPercent_DoNothing;
7696 on_button.lambda_percent = lambda;
7712 WindowOnButtonData& on_button = xenium->window_on_button_map[window_id];
7714 if(lambda ==
nullptr)
7716 on_button.lambda_pixel = LambdaButtonPixel_DoNothing;
7720 on_button.lambda_pixel = lambda;
7738 WindowOnEnterData& on_enter = xenium->window_on_enter_map[window_id];
7740 if(lambda ==
nullptr)
7742 on_enter.lambda_mm = LambdaPointMm_DoNothing;
7746 on_enter.lambda_mm = lambda;
7764 WindowOnEnterData& on_enter = xenium->window_on_enter_map[window_id];
7766 if(lambda ==
nullptr)
7768 on_enter.lambda_percent = LambdaPointPercent_DoNothing;
7772 on_enter.lambda_percent = lambda;
7790 WindowOnEnterData& on_enter = xenium->window_on_enter_map[window_id];
7792 if(lambda ==
nullptr)
7794 on_enter.lambda_pixel = LambdaPointPixel_DoNothing;
7798 on_enter.lambda_pixel = lambda;
7813 if(lambda ==
nullptr)
7815 xenium->window_on_leave_map[window_id] = Lambda_DoNothing;
7819 xenium->window_on_leave_map[window_id] = lambda;
7834 WindowOnMotionData& on_motion = xenium->window_on_motion_map[window_id];
7836 if(lambda ==
nullptr)
7838 on_motion.lambda_mm = LambdaPointMm_DoNothing;
7842 on_motion.lambda_mm = lambda;
7857 WindowOnMotionData& on_motion = xenium->window_on_motion_map[window_id];
7859 if(lambda ==
nullptr)
7861 on_motion.lambda_percent = LambdaPointPercent_DoNothing;
7865 on_motion.lambda_percent = lambda;
7880 WindowOnMotionData& on_motion = xenium->window_on_motion_map[window_id];
7882 if(lambda ==
nullptr)
7884 on_motion.lambda_pixel = LambdaPointPixel_DoNothing;
7888 on_motion.lambda_pixel = lambda;
7979 frame_buffer_size = xenium->window_size_map[window_id].pixel;
7980 frame_buffer_length = frame_buffer_size.width * frame_buffer_size.height * 4;
7981 frame_buffer = (uint8_t*)malloc(
sizeof(uint8_t) * frame_buffer_length);
7983 image = frame_buffer;
7984 size = frame_buffer_size;
7986 return ZAKERO_XENIUM__ERROR(Error_None);
8008 xcb_put_image(xenium->connection
8009 , XCB_IMAGE_FORMAT_Z_PIXMAP
8012 , frame_buffer_size.width
8013 , frame_buffer_size.height
8017 , xenium->screen->root_depth
8018 , frame_buffer_length
8064 std::string
to_string(
const xcb_generic_error_t& generic_error
8067 return std::string()
8068 +
"{ \"response_type\": " + std::to_string(generic_error.response_type)
8069 +
", \"error_code\": " + std::to_string(generic_error.error_code)
8070 +
", \"sequence\": " + std::to_string(generic_error.sequence)
8071 +
", \"resource_id\": " + std::to_string(generic_error.resource_id)
8072 +
", \"minor_code\": " + std::to_string(generic_error.minor_code)
8073 +
", \"major_code\": " + std::to_string(generic_error.major_code)
8074 +
", \"full_sequence\": " + std::to_string(generic_error.full_sequence)
8084 std::string
to_string(
const xcb_randr_screen_change_notify_event_t& event
8087 return std::string()
8088 +
"{ \"response_type\": " + std::to_string(event.response_type)
8089 +
", \"rotation\": " + std::to_string(event.rotation)
8090 +
", \"sequence\": " + std::to_string(event.sequence)
8091 +
", \"timestamp\": " + std::to_string(event.timestamp)
8092 +
", \"config_timestamp\": " + std::to_string(event.config_timestamp)
8093 +
", \"root\": " + std::to_string(event.root)
8094 +
", \"request_window\": " + std::to_string(event.request_window)
8095 +
", \"sizeID\": " + std::to_string(event.sizeID)
8096 +
", \"subpixel_order\": " + std::to_string(event.subpixel_order)
8097 +
", \"width\": " + std::to_string(event.width)
8098 +
", \"height\": " + std::to_string(event.height)
8099 +
", \"mwidth\": " + std::to_string(event.mwidth)
8100 +
", \"mheight\": " + std::to_string(event.mheight)
8112 return std::string()
8113 +
"{ \"response_type\": " + std::to_string(event.response_type)
8114 +
", \"detail\": " + std::to_string(event.detail)
8115 +
", \"sequence\": " + std::to_string(event.sequence)
8116 +
", \"time\": " + std::to_string(event.time)
8117 +
", \"root\": " + std::to_string(event.root)
8118 +
", \"event\": " + std::to_string(event.event)
8119 +
", \"child\": " + std::to_string(event.child)
8120 +
", \"root_x\": " + std::to_string(event.root_x)
8121 +
", \"root_y\": " + std::to_string(event.root_y)
8122 +
", \"event_x\": " + std::to_string(event.event_x)
8123 +
", \"event_y\": " + std::to_string(event.event_y)
8124 +
", \"state\": " + std::to_string(event.state)
8125 +
", \"same_screen\": " + std::to_string(event.same_screen)
8126 +
", \"pad0\": " + std::to_string(event.pad0)
8136 std::string
to_string(
const xcb_client_message_event_t& event
8139 return std::string()
8140 +
"{ \"response_type\": " + std::to_string(event.response_type)
8141 +
", \"format\": " + std::to_string(event.format)
8142 +
", \"sequence\": " + std::to_string(event.sequence)
8143 +
", \"window\": " + std::to_string(event.window)
8144 +
", \"type\": " + std::to_string(event.type)
8145 +
", \"data\": [ 0x" + std::to_string(event.data.data8[ 0])
8146 +
", 0x" + std::to_string(event.data.data8[ 1])
8147 +
", 0x" + std::to_string(event.data.data8[ 2])
8148 +
", 0x" + std::to_string(event.data.data8[ 3])
8149 +
", 0x" + std::to_string(event.data.data8[ 4])
8150 +
", 0x" + std::to_string(event.data.data8[ 5])
8151 +
", 0x" + std::to_string(event.data.data8[ 6])
8152 +
", 0x" + std::to_string(event.data.data8[ 7])
8153 +
", 0x" + std::to_string(event.data.data8[ 8])
8154 +
", 0x" + std::to_string(event.data.data8[ 9])
8155 +
", 0x" + std::to_string(event.data.data8[10])
8156 +
", 0x" + std::to_string(event.data.data8[11])
8157 +
", 0x" + std::to_string(event.data.data8[12])
8158 +
", 0x" + std::to_string(event.data.data8[13])
8159 +
", 0x" + std::to_string(event.data.data8[14])
8160 +
", 0x" + std::to_string(event.data.data8[15])
8161 +
", 0x" + std::to_string(event.data.data8[16])
8162 +
", 0x" + std::to_string(event.data.data8[17])
8163 +
", 0x" + std::to_string(event.data.data8[18])
8164 +
", 0x" + std::to_string(event.data.data8[19])
8175 std::string
to_string(
const xcb_configure_notify_event_t& event
8178 return std::string()
8179 +
"{ \"response_type\": " + std::to_string(event.response_type)
8180 +
", \"pad0\": " + std::to_string(event.pad0)
8181 +
", \"sequence\": " + std::to_string(event.sequence)
8182 +
", \"event\": " + std::to_string(event.event)
8183 +
", \"window\": " + std::to_string(event.window)
8184 +
", \"above_sibling\": " + std::to_string(event.above_sibling)
8185 +
", \"x\": " + std::to_string(event.x)
8186 +
", \"y\": " + std::to_string(event.y)
8187 +
", \"width\": " + std::to_string(event.width)
8188 +
", \"height\": " + std::to_string(event.height)
8189 +
", \"border_width\": " + std::to_string(event.border_width)
8190 +
", \"override_redirect\": " + std::to_string(event.override_redirect)
8191 +
", \"pad1\": " + std::to_string(event.pad1)
8204 return std::string()
8205 +
"{ \"response_type\": " + std::to_string(event.response_type)
8206 +
", \"detail\": " + std::to_string(event.detail)
8207 +
", \"sequence\": " + std::to_string(event.sequence)
8208 +
", \"time\": " + std::to_string(event.time)
8209 +
", \"root\": " + std::to_string(event.root)
8210 +
", \"event\": " + std::to_string(event.event)
8211 +
", \"root_x\": " + std::to_string(event.root_x)
8212 +
", \"root_y\": " + std::to_string(event.root_y)
8213 +
", \"event_x\": " + std::to_string(event.event_x)
8214 +
", \"event_y\": " + std::to_string(event.event_y)
8215 +
", \"state\": " + std::to_string(event.state)
8216 +
", \"mode\": " + std::to_string(event.mode)
8217 +
", \"same_screen_focus\": " + std::to_string(event.same_screen_focus)
8230 return std::string()
8231 +
"{ \"response_type\": " + std::to_string(event.response_type)
8232 +
", \"pad0\": " + std::to_string(event.pad0)
8233 +
", \"sequence\": " + std::to_string(event.sequence)
8234 +
", \"window\": " + std::to_string(event.window)
8235 +
", \"x\": " + std::to_string(event.x)
8236 +
", \"y\": " + std::to_string(event.y)
8237 +
", \"width\": " + std::to_string(event.width)
8238 +
", \"height\": " + std::to_string(event.height)
8239 +
", \"count\": " + std::to_string(event.count)
8240 +
", \"pad1\": [ 0x" + std::to_string(event.pad1[0])
8241 +
", 0x" + std::to_string(event.pad1[1])
8255 return std::string()
8256 +
"{ \"response_type\": " + std::to_string(event.response_type)
8257 +
", \"detail\": " + std::to_string(event.detail)
8258 +
", \"sequence\": " + std::to_string(event.sequence)
8259 +
", \"event\": " + std::to_string(event.event)
8260 +
", \"mode\": " + std::to_string(event.mode)
8261 +
", \"pad0\": [ 0x" + std::to_string(event.pad0[0])
8262 +
", 0x" + std::to_string(event.pad0[1])
8263 +
", 0x" + std::to_string(event.pad0[2])
8277 return std::string()
8278 +
"{ \"response_type\": " + std::to_string(event.response_type)
8279 +
", \"pad0\": " + std::to_string(event.pad0)
8280 +
", \"sequence\": " + std::to_string(event.sequence)
8281 +
", \"pad\": [ 0x" + std::to_string(event.pad[0])
8282 +
", 0x" + std::to_string(event.pad[1])
8283 +
", 0x" + std::to_string(event.pad[2])
8284 +
", 0x" + std::to_string(event.pad[3])
8285 +
", 0x" + std::to_string(event.pad[4])
8286 +
", 0x" + std::to_string(event.pad[5])
8287 +
", 0x" + std::to_string(event.pad[6])
8289 +
", \"full_sequence\": " + std::to_string(event.full_sequence)
8299 std::string
to_string(
const xcb_gravity_notify_event_t& event
8302 return std::string()
8303 +
"{ \"response_type\": " + std::to_string(event.response_type)
8304 +
", \"pad0\": " + std::to_string(event.pad0)
8305 +
", \"sequence\": " + std::to_string(event.sequence)
8306 +
", \"event\": " + std::to_string(event.event)
8307 +
", \"window\": " + std::to_string(event.window)
8308 +
", \"x\": " + std::to_string(event.x)
8309 +
", \"y\": " + std::to_string(event.y)
8322 return std::string()
8323 +
"{ \"response_type\": " + std::to_string(event.response_type)
8324 +
", \"detail\": " + std::to_string(event.detail)
8325 +
", \"sequence\": " + std::to_string(event.sequence)
8326 +
", \"time\": " + std::to_string(event.time)
8327 +
", \"root\": " + std::to_string(event.root)
8328 +
", \"event\": " + std::to_string(event.event)
8329 +
", \"child\": " + std::to_string(event.child)
8330 +
", \"root_x\": " + std::to_string(event.root_x)
8331 +
", \"root_y\": " + std::to_string(event.root_y)
8332 +
", \"event_x\": " + std::to_string(event.event_x)
8333 +
", \"event_y\": " + std::to_string(event.event_y)
8334 +
", \"state\": " + std::to_string(event.state)
8335 +
", \"same_screen\": " + std::to_string(event.same_screen)
8336 +
", \"pad0\": " + std::to_string(event.pad0)
8349 return std::string()
8350 +
"{ \"response_type\": " + std::to_string(event.response_type)
8351 +
", \"pad0\": " + std::to_string(event.pad0)
8352 +
", \"sequence\": " + std::to_string(event.sequence)
8353 +
", \"event\": " + std::to_string(event.event)
8354 +
", \"window\": " + std::to_string(event.window)
8355 +
", \"override_redirect\": " + std::to_string(event.override_redirect)
8356 +
", \"pad1\": [ 0x" + std::to_string(event.pad1[0])
8357 +
", 0x" + std::to_string(event.pad1[1])
8358 +
", 0x" + std::to_string(event.pad1[2])
8369 std::string
to_string(
const xcb_motion_notify_event_t& event
8372 return std::string()
8373 +
"{ \"response_type\": " + std::to_string(event.response_type)
8374 +
", \"detail\": " + std::to_string(event.detail)
8375 +
", \"sequence\": " + std::to_string(event.sequence)
8376 +
", \"time\": " + std::to_string(event.time)
8377 +
", \"root\": " + std::to_string(event.root)
8378 +
", \"event\": " + std::to_string(event.event)
8379 +
", \"child\": " + std::to_string(event.child)
8380 +
", \"root_x\": " + std::to_string(event.root_x)
8381 +
", \"root_y\": " + std::to_string(event.root_y)
8382 +
", \"event_x\": " + std::to_string(event.event_x)
8383 +
", \"event_y\": " + std::to_string(event.event_y)
8384 +
", \"state\": " + std::to_string(event.state)
8385 +
", \"same_screen\": " + std::to_string(event.same_screen)
8386 +
", \"pad0\": " + std::to_string(event.pad0)
8396 std::string
to_string(
const xcb_property_notify_event_t& event
8399 return std::string()
8400 +
"{ \"response_type\": " + std::to_string(event.response_type)
8401 +
", \"pad0\": " + std::to_string(event.pad0)
8402 +
", \"sequence\": " + std::to_string(event.sequence)
8403 +
", \"window\": " + std::to_string(event.window)
8404 +
", \"atom\": " + std::to_string(event.atom)
8405 +
", \"time\": " + std::to_string(event.time)
8406 +
", \"state\": " + std::to_string(event.state)
8407 +
", \"pad1\": [ 0x" + std::to_string(event.pad1[0])
8408 +
", 0x" + std::to_string(event.pad1[1])
8409 +
", 0x" + std::to_string(event.pad1[2])
8420 std::string
to_string(
const xcb_reparent_notify_event_t& event
8423 return std::string()
8424 +
"{ \"response_type\": " + std::to_string(event.response_type)
8425 +
", \"pad0\": " + std::to_string(event.pad0)
8426 +
", \"sequence\": " + std::to_string(event.sequence)
8427 +
", \"event\": " + std::to_string(event.event)
8428 +
", \"window\": " + std::to_string(event.window)
8429 +
", \"parent\": " + std::to_string(event.parent)
8430 +
", \"x\": " + std::to_string(event.x)
8431 +
", \"y\": " + std::to_string(event.y)
8432 +
", \"override_redirect\": " + std::to_string(event.override_redirect)
8433 +
", \"pad1\": [ 0x" + std::to_string(event.pad1[0])
8434 +
", 0x" + std::to_string(event.pad1[1])
8435 +
", 0x" + std::to_string(event.pad1[2])
8449 return std::string()
8450 +
"{ \"response_type\": " + std::to_string(event.response_type)
8451 +
", \"pad0\": " + std::to_string(event.pad0)
8452 +
", \"sequence\": " + std::to_string(event.sequence)
8453 +
", \"event\": " + std::to_string(event.event)
8454 +
", \"window\": " + std::to_string(event.window)
8455 +
", \"from_configure\": " + std::to_string(event.from_configure)
8456 +
", \"pad1\": [ 0x" + std::to_string(event.pad1[0])
8457 +
", 0x" + std::to_string(event.pad1[1])
8458 +
", 0x" + std::to_string(event.pad1[2])
8472 return std::string()
8473 +
"{ \"depth\": " + std::to_string(format.depth)
8474 +
", \"bits_per_pixel\": " + std::to_string(format.bits_per_pixel)
8475 +
", \"scanline_pad\": " + std::to_string(format.scanline_pad)
8476 +
", \"pad0\": [ 0x" + std::to_string(format.pad0[0])
8477 +
", 0x" + std::to_string(format.pad0[1])
8478 +
", 0x" + std::to_string(format.pad0[2])
8479 +
", 0x" + std::to_string(format.pad0[3])
8480 +
", 0x" + std::to_string(format.pad0[4])
8494 return std::string()
8495 +
"{ \"root\": " + std::to_string(screen.root)
8496 +
", \"default_colormap\": " + std::to_string(screen.default_colormap)
8497 +
", \"white_pixel\": " + std::to_string(screen.white_pixel)
8498 +
", \"black_pixel\": " + std::to_string(screen.black_pixel)
8499 +
", \"current_input_masks\": " + std::to_string(screen.current_input_masks)
8500 +
", \"width_in_pixels\": " + std::to_string(screen.width_in_pixels)
8501 +
", \"height_in_pixels\": " + std::to_string(screen.height_in_pixels)
8502 +
", \"width_in_millimeters\": " + std::to_string(screen.width_in_millimeters)
8503 +
", \"height_in_millimeters\": " + std::to_string(screen.height_in_millimeters)
8504 +
", \"min_installed_maps\": " + std::to_string(screen.min_installed_maps)
8505 +
", \"max_installed_maps\": " + std::to_string(screen.max_installed_maps)
8506 +
", \"root_visual\": " + std::to_string(screen.root_visual)
8507 +
", \"backing_stores\": " + std::to_string(screen.backing_stores)
8508 +
", \"save_unders\": " + std::to_string(screen.save_unders)
8509 +
", \"root_depth\": " + std::to_string(screen.root_depth)
8510 +
", \"allowed_depths_len\": " + std::to_string(screen.allowed_depths_len)
8523 std::string
string =
"[ ";
8524 std::string delim =
"";
8526 for(
const auto& atom : vector)
8528 string += delim +
' ' + std::to_string(atom);
8547 std::string
string =
"[ ";
8548 std::string delim =
"";
8550 for(
const int32_t& value : vector)
8552 string += delim +
' ' + std::to_string(value);
8571 return std::string()
8572 +
"{ \"status\": " + std::to_string(setup.status)
8573 +
", \"pad0\": " + std::to_string(setup.pad0)
8574 +
", \"protocol_major_version\": " + std::to_string(setup.protocol_major_version)
8575 +
", \"protocol_minor_version\": " + std::to_string(setup.protocol_minor_version)
8576 +
", \"length\": " + std::to_string(setup.length)
8577 +
", \"release_number\": " + std::to_string(setup.release_number)
8578 +
", \"resource_id_base\": " + std::to_string(setup.resource_id_base)
8579 +
", \"resource_id_mask\": " + std::to_string(setup.resource_id_mask)
8580 +
", \"motion_buffer_size\": " + std::to_string(setup.motion_buffer_size)
8581 +
", \"vendor_len\": " + std::to_string(setup.vendor_len)
8582 +
", \"maximum_request_length\": " + std::to_string(setup.maximum_request_length)
8583 +
", \"roots_len\": " + std::to_string(setup.roots_len)
8584 +
", \"pixmap_formats_len\": " + std::to_string(setup.pixmap_formats_len)
8585 +
", \"image_byte_order\": " + std::to_string(setup.image_byte_order)
8586 +
", \"bitmap_format_bit_order\": " + std::to_string(setup.bitmap_format_bit_order)
8587 +
", \"bitmap_format_scanline_unit\": " + std::to_string(setup.bitmap_format_scanline_unit)
8588 +
", \"bitmap_format_scanline_pad\": " + std::to_string(setup.bitmap_format_scanline_pad)
8589 +
", \"min_keycode\": " + std::to_string(setup.min_keycode)
8590 +
", \"max_keycode\": " + std::to_string(setup.max_keycode)
8591 +
", \"pad1\": [ 0x" + std::to_string(setup.pad1[0])
8592 +
", 0x" + std::to_string(setup.pad1[1])
8593 +
", 0x" + std::to_string(setup.pad1[2])
8594 +
", 0x" + std::to_string(setup.pad1[3])
8610 return std::string()
8611 +
"{ \"time\": " + std::to_string(key.time)
8612 +
", \"code\": " + std::to_string(key.code)
8630 auto mod_to_str = [](std::string& s, uint32_t m)
8633 std::string delim =
"";
8637 s += delim +
"\"Shift\"";
8643 s += delim +
"\"CapsLock\"";
8649 s += delim +
"\"Control\"";
8655 s += delim +
"\"Alt\"";
8661 s += delim +
"\"Meta\"";
8666 s += delim +
"\"NumLock\"";
8672 std::string str =
"{ \"pressed\": ";
8673 mod_to_str(str, key_modifier.pressed);
8675 str +=
", \"latched\": ";
8676 mod_to_str(str, key_modifier.latched);
8678 str +=
", \"locked\": ";
8679 mod_to_str(str, key_modifier.locked);
8699 case Xenium::KeyState::Pressed:
return "Pressed";
8700 case Xenium::KeyState::Released:
return "Released";
8701 case Xenium::KeyState::Repeat:
return "Repeat";
8717 return std::string()
8719 +
", \"x\": " + std::to_string(
output.
x)
8720 +
", \"y\": " + std::to_string(
output.
y)
8747 return std::string()
8748 +
"{ \"time\": " + std::to_string(point.time)
8749 +
", \"x\": " + std::to_string(point.x)
8750 +
", \"y\": " + std::to_string(point.y)
8766 return std::string()
8767 +
"{ \"time\": " + std::to_string(point.time)
8768 +
", \"x\": " + std::to_string(point.x)
8769 +
", \"y\": " + std::to_string(point.y)
8785 return std::string()
8786 +
"{ \"time\": " + std::to_string(point.time)
8787 +
", \"x\": " + std::to_string(point.x)
8788 +
", \"y\": " + std::to_string(point.y)
8804 return std::string()
8805 +
"{ \"time\": " + std::to_string(pointer_axis.time)
8806 +
", \"steps\": " + std::to_string(pointer_axis.steps)
8807 +
", \"distance\": " + std::to_string(pointer_axis.distance)
8827 case Xenium::PointerAxisSource::Continuous:
return "Continuous";
8828 case Xenium::PointerAxisSource::Finger:
return "Finger";
8829 case Xenium::PointerAxisSource::Wheel:
return "Wheel";
8830 case Xenium::PointerAxisSource::Wheel_Tilt:
return "Wheel Tilt";
8831 case Xenium::PointerAxisSource::Unknown: [[fallthrough]];
8849 case Xenium::PointerAxisType::Horizontal:
return "Horizontal";
8850 case Xenium::PointerAxisType::Vertical:
return "Vertical";
8851 case Xenium::PointerAxisType::Unknown: [[fallthrough]];
8867 std::string str = std::string()
8868 +
"{ \"code\": " + std::to_string(button.code)
8887 switch(button_state)
8889 case Xenium::PointerButtonState::Pressed:
return "Pressed";
8890 case Xenium::PointerButtonState::Released:
return "Released";
8906 return std::string()
8907 +
"{ \"width\": " + std::to_string(size.width)
8908 +
", \"height\": " + std::to_string(size.height)
8923 return std::string()
8924 +
"{ \"width\": " + std::to_string(size.width)
8925 +
", \"height\": " + std::to_string(size.height)
8940 return std::string()
8941 +
"{ \"width\": " + std::to_string(size.width)
8942 +
", \"height\": " + std::to_string(size.height)
8957 switch(window_decorations)
8959 case Xenium::WindowDecorations::Client_Side:
return "Client Side";
8960 case Xenium::WindowDecorations::Server_Side:
return "Server Side";
8978 case Xenium::WindowMode::Fullscreen:
return "Fullscreen";
8979 case Xenium::WindowMode::Maximized:
return "Maximized";
8980 case Xenium::WindowMode::Normal:
return "Normal";
9046 return (lhs.x == rhs.x) && (lhs.y == rhs.y);
9104 return (lhs.width == rhs.width) && (lhs.height == rhs.height);
std::string to_string(const bool value) noexcept
Convert a bool into a string.
Definition: Zakero_Base.h:561
#define ZAKERO_STEADY_TIME_NOW(unit_)
Get the current time.
Definition: Zakero_Base.h:231
#define ZAKERO_FREE(ptr_)
Free memory.
Definition: Zakero_Base.h:144
bool equalish(const float a, const float b, const float delta) noexcept
Compare two floats.
Definition: Zakero_Base.h:375
bool operator==(const zakero::messagepack::Object &lhs, const zakero::messagepack::Object &rhs) noexcept
Compare two Objects for equality.
Definition: Zakero_MessagePack.h:8964
#define _NET_WM_STATE_REMOVE
A NET-WM Macro (that may not be defined).
Definition: Zakero_Xenium.h:1072
#define _NET_WM_STATE_ADD
A NET-WM Macro (that may not be defined).
Definition: Zakero_Xenium.h:1079
A Window.
Definition: Zakero_Xenium.h:507
void keyboardOnKey(Xenium::LambdaKey) noexcept
Respond to "Keyboard Key" events.
Definition: Zakero_Xenium.h:7619
void decorationsOnChange(Xenium::LambdaWindowDecorations) noexcept
Respond to "Decoration Change" events.
Definition: Zakero_Xenium.h:6871
void pointerOnEnter(Xenium::LambdaPointMm) noexcept
Respond to "Pointer Enter" events.
Definition: Zakero_Xenium.h:7735
void titleSet(const std::string &) noexcept
Change the window title.
Definition: Zakero_Xenium.h:6745
void pointerOnAxis(Xenium::LambdaAxis) noexcept
Respond to "Pointer Axis" events.
Definition: Zakero_Xenium.h:7641
std::error_code sizeSetMinMax(const Xenium::SizeMm &, const Xenium::SizeMm &) noexcept
Set the minimum window size.
Definition: Zakero_Xenium.h:7071
void sizeOnChange(Xenium::LambdaSizeMm) noexcept
Respond to "Resize" events.
Definition: Zakero_Xenium.h:7217
std::error_code sizeSet(const Xenium::SizeMm &) noexcept
Set the window size.
Definition: Zakero_Xenium.h:6906
void onCloseRequest(Xenium::Lambda) noexcept
Respond to "Close Request" events.
Definition: Zakero_Xenium.h:6777
virtual ~Window()
Destroy a Window.
Definition: Zakero_Xenium.h:6681
Xenium::PointPercent convertToPercent(const Xenium::PointPixel &) const noexcept
Unit conversion.
Definition: Zakero_Xenium.h:7320
void pointerOnButton(Xenium::LambdaButtonMm) noexcept
Respond to "Pointer Button" events.
Definition: Zakero_Xenium.h:7662
uint8_t bytesPerPixel() const noexcept
Get the number of bytes per pixel.
Definition: Zakero_Xenium.h:8051
void keyboardOnLeave(Xenium::Lambda) noexcept
Respond to "Keyboard Leave" events.
Definition: Zakero_Xenium.h:7598
bool windowModeIs(const Xenium::WindowMode) const noexcept
Check the WindowMode.
Definition: Zakero_Xenium.h:7478
std::error_code minimize() noexcept
Minimize the window.
Definition: Zakero_Xenium.h:7554
std::error_code decorationsSet(const Xenium::WindowDecorations) noexcept
Use the Desktop Environment borders.
Definition: Zakero_Xenium.h:6837
Window(Xenium *, void *)
Construct a Window.
Definition: Zakero_Xenium.h:6664
Xenium::PointPixel convertToPixel(const Xenium::PointMm &) const noexcept
Unit conversion.
Definition: Zakero_Xenium.h:7340
void pointerOnMotion(Xenium::LambdaPointMm) noexcept
Respond to "Pointer Motion" events.
Definition: Zakero_Xenium.h:7831
uint32_t time() const noexcept
When the last frame was rendered.
Definition: Zakero_Xenium.h:8037
void keyboardOnEnter(Xenium::Lambda) noexcept
Respond to "Keyboard Enter" events.
Definition: Zakero_Xenium.h:7579
void imagePresent() noexcept
Render the image.
Definition: Zakero_Xenium.h:7996
Xenium::WindowMode windowMode() const noexcept
Get the current WindowMode.
Definition: Zakero_Xenium.h:7463
std::error_code imageNext(uint8_t *&, Xenium::SizePixel &) noexcept
Get an image buffer.
Definition: Zakero_Xenium.h:7970
Xenium::PointMm convertToMm(const Xenium::PointPixel &) const noexcept
Unit conversion.
Definition: Zakero_Xenium.h:7300
std::error_code windowModeSet(const Xenium::WindowMode) noexcept
Change the window mode.
Definition: Zakero_Xenium.h:7495
void pointerOnLeave(Xenium::Lambda) noexcept
Respond to "Pointer Leave" events.
Definition: Zakero_Xenium.h:7810
void onFocusChange(Xenium::LambdaBool) noexcept
Respond to "Active" change events.
Definition: Zakero_Xenium.h:6806
void classSet(const std::string &) noexcept
Change the window class.
Definition: Zakero_Xenium.h:6720
void windowModeOnChange(Xenium::LambdaWindowMode) noexcept
Respond to "Window Mode" events.
Definition: Zakero_Xenium.h:7529
A wrapper class for X11/XCB.
Definition: Zakero_Xenium.h:264
static constexpr uint32_t KeyModifier_Shift
Key Modifier flag.
Definition: Zakero_Xenium.h:290
uint32_t locked
A collection of locked modifiers.
Definition: Zakero_Xenium.h:301
uint32_t physical_height_mm
The height of the device in millimeters.
Definition: Zakero_Xenium.h:430
Xenium::Output output(const Xenium::OutputId) const noexcept
Get a copy of the Output information.
Definition: Zakero_Xenium.h:2904
uint32_t latched
A collection of latched modifiers.
Definition: Zakero_Xenium.h:300
int32_t x
The X position within the global compositor.
Definition: Zakero_Xenium.h:425
int32_t steps
The number of rotation steps.
Definition: Zakero_Xenium.h:355
int32_t keyRepeatRate() const noexcept
The key repeat rate.
Definition: Zakero_Xenium.h:2884
void outputOnRemove(Xenium::LambdaOutputId) noexcept
Notification of removing an Output device.
Definition: Zakero_Xenium.h:3257
Xenium::PointMm outputConvertToMm(const Xenium::OutputId, const Xenium::PointPixel &) const noexcept
Convert Pixel to Millimeter.
Definition: Zakero_Xenium.h:3002
std::function< void(Xenium::WindowMode)> LambdaWindowMode
A Lambda that has a parameter: WindowMode.
Definition: Zakero_Xenium.h:500
static std::string outputSubpixelName(int32_t) noexcept
Get a human readable string.
Definition: Zakero_Xenium.h:2957
Xenium::PointerAxisType type
The type of Axis.
Definition: Zakero_Xenium.h:358
std::function< void(const Xenium::PointerButton &, const Xenium::PointMm &, const Xenium::KeyModifier &)> LambdaButtonMm
A Lambda that has parameters: PointerButton, PointMm and KeyModifier.
Definition: Zakero_Xenium.h:489
int32_t y
The Y position within the global compositor.
Definition: Zakero_Xenium.h:426
std::function< void(const Xenium::SizePercent &)> LambdaSizePercent
A Lambda that has a parameter: SizePercent.
Definition: Zakero_Xenium.h:497
static constexpr uint32_t KeyModifier_Control
Key Modifier flag.
Definition: Zakero_Xenium.h:292
float distance
The distance traveled.
Definition: Zakero_Xenium.h:356
PointerButtonState
Mouse button state.
Definition: Zakero_Xenium.h:365
std::function< void(const Xenium::PointerButton &, const Xenium::PointPercent &, const Xenium::KeyModifier &)> LambdaButtonPercent
A Lambda that has parameters: PointerButton, PointPercent and KeyModifier.
Definition: Zakero_Xenium.h:490
WindowMode
All the available window modes.
Definition: Zakero_Xenium.h:479
uint32_t physical_width_mm
The width of the device in millimeters.
Definition: Zakero_Xenium.h:429
PointerAxisSource
Where the axis information came from.
Definition: Zakero_Xenium.h:339
std::function< void(const Xenium::PointPercent &, const Xenium::KeyModifier &)> LambdaPointPercent
A Lambda that has parameters: PointPercent and KeyModifier.
Definition: Zakero_Xenium.h:494
float pixels_per_mm_horizontal
A pre-calculated value.
Definition: Zakero_Xenium.h:433
std::function< void(const Xenium::SizeMm &)> LambdaSizeMm
A Lambda that has a parameter: SizeMm.
Definition: Zakero_Xenium.h:496
int32_t height
The height of the device in hardware units.
Definition: Zakero_Xenium.h:428
std::function< void(const Xenium::PointerButton &, const Xenium::PointPixel &, const Xenium::KeyModifier &)> LambdaButtonPixel
A Lambda that has parameters: PointerButton, PointPixel and KeyModifier.
Definition: Zakero_Xenium.h:491
Xenium::VectorOutputId outputVector() const noexcept
Get a list of the Output Id's.
Definition: Zakero_Xenium.h:2932
std::string name
The name of the output.
Definition: Zakero_Xenium.h:424
std::function< void(const Xenium::Key &, const Xenium::KeyModifier &)> LambdaKey
A Lambda that has parameters: Key and KeyModifier.
Definition: Zakero_Xenium.h:492
std::function< void()> Lambda
A Lambda that has no parameters.
Definition: Zakero_Xenium.h:486
Xenium::PointerButtonState state
The button state.
Definition: Zakero_Xenium.h:372
std::function< void(bool)> LambdaBool
A Lambda that has a parameter: bool.
Definition: Zakero_Xenium.h:488
uint32_t WindowId
A type for better readablity.
Definition: Zakero_Xenium.h:502
Xenium::PointPixel outputConvertToPixel(const Xenium::OutputId, const Xenium::PointMm &) const noexcept
Convert Millimeter to Pixel.
Definition: Zakero_Xenium.h:3056
int32_t transform
Transform that maps framebuffer to output.
Definition: Zakero_Xenium.h:432
Xenium::Window * windowCreate(const Xenium::SizeMm &, std::error_code &) noexcept
Create a window.
Definition: Zakero_Xenium.h:3707
KeyState
Keyboard key state
Definition: Zakero_Xenium.h:278
static constexpr uint32_t KeyModifier_Meta
Key Modifier flag.
Definition: Zakero_Xenium.h:295
WindowDecorations
Who is responsible for rendering the decorations.
Definition: Zakero_Xenium.h:474
void outputOnChange(Xenium::LambdaOutputId) noexcept
Notification that an Output device has changed.
Definition: Zakero_Xenium.h:3236
static Xenium * connect() noexcept
Establish a connection with the X11 server.
Definition: Zakero_Xenium.h:2396
virtual ~Xenium() noexcept
Destructor.
Definition: Zakero_Xenium.h:2363
std::function< void(Xenium::WindowDecorations)> LambdaWindowDecorations
A Lambda that has a parameter: WindowDecorations.
Definition: Zakero_Xenium.h:499
int32_t subpixel
The device's subpixel orientation.
Definition: Zakero_Xenium.h:431
uint32_t pressed
A collection of pressed modifiers.
Definition: Zakero_Xenium.h:299
int32_t keyRepeatDelay() const noexcept
The key repeat delay.
Definition: Zakero_Xenium.h:2871
int32_t width
The width of the device in hardware units.
Definition: Zakero_Xenium.h:427
uint32_t code
The key code of the event.
Definition: Zakero_Xenium.h:286
std::function< void(const Xenium::PointPixel &, const Xenium::KeyModifier &)> LambdaPointPixel
A Lambda that has parameters: PointPixel and KeyModifier.
Definition: Zakero_Xenium.h:495
static constexpr uint32_t KeyModifier_Alt
Key Modifier flag.
Definition: Zakero_Xenium.h:293
std::function< void(const Xenium::SizePixel &)> LambdaSizePixel
A Lambda that has a parameter: SizePixel.
Definition: Zakero_Xenium.h:498
Xenium::KeyState state
The state of the key.
Definition: Zakero_Xenium.h:287
Xenium::PointPercent outputConvertToPercent(const Xenium::OutputId, const Xenium::PointPixel &) const noexcept
Convert Pixel to a Percentage.
Definition: Zakero_Xenium.h:3029
void outputOnAdd(Xenium::LambdaOutputId) noexcept
Notification of adding an Output device.
Definition: Zakero_Xenium.h:3215
uint32_t time
When the event occurred.
Definition: Zakero_Xenium.h:354
std::function< void(const Xenium::PointerAxis &, const Xenium::KeyModifier &)> LambdaAxis
A Lambda that has parameters: PointerAxis and KeyModifier.
Definition: Zakero_Xenium.h:487
static constexpr uint32_t KeyModifier_CapsLock
Key Modifier flag.
Definition: Zakero_Xenium.h:291
std::function< void(const Xenium::PointMm &, const Xenium::KeyModifier &)> LambdaPointMm
A Lambda that has parameters: PointMm and KeyModifier.
Definition: Zakero_Xenium.h:493
uint32_t code
The event code.
Definition: Zakero_Xenium.h:371
uint32_t time
When the key event happened.
Definition: Zakero_Xenium.h:285
static constexpr uint32_t KeyModifier_NumLock
Key Modifier flag.
Definition: Zakero_Xenium.h:294
Xenium::PointerAxisSource source
The source of the event.
Definition: Zakero_Xenium.h:357
uint32_t group
The keyboard layout.
Definition: Zakero_Xenium.h:302
float pixels_per_mm_vertical
A pre-calculated value.
Definition: Zakero_Xenium.h:434
PointerAxisType
The direction of the axis movement.
Definition: Zakero_Xenium.h:347
static std::string outputTransformName(int32_t) noexcept
Get a human readable string.
Definition: Zakero_Xenium.h:2980
Key event information.
Definition: Zakero_Xenium.h:284
A collection modifier flags.
Definition: Zakero_Xenium.h:298
Information about a output device.
Definition: Zakero_Xenium.h:423
Information about an Axis event.
Definition: Zakero_Xenium.h:353
A location that uses millimeters.
Definition: Zakero_Xenium.h:309
float y
Where in the Y-Axis the point is.
Definition: Zakero_Xenium.h:312
float x
Where in the X-Axis the point is.
Definition: Zakero_Xenium.h:311
uint32_t time
Where in time the point is (if > 0).
Definition: Zakero_Xenium.h:310
friend bool operator==(Xenium::PointMm &, Xenium::PointMm &) noexcept
Compare two Point objects.
Definition: Zakero_Xenium.h:8999
A location that uses percentages.
Definition: Zakero_Xenium.h:318
float x
Where in the X-Axis the point is.
Definition: Zakero_Xenium.h:320
uint32_t time
Where in time the point is (if > 0).
Definition: Zakero_Xenium.h:319
float y
Where in the Y-Axis the point is.
Definition: Zakero_Xenium.h:321
friend bool operator==(Xenium::PointPercent &, Xenium::PointPercent &) noexcept
Compare two Point objects.
Definition: Zakero_Xenium.h:9022
A location that uses pixels.
Definition: Zakero_Xenium.h:327
friend bool operator==(Xenium::PointPixel &, Xenium::PointPixel &) noexcept
Compare two Point objects.
Definition: Zakero_Xenium.h:9042
uint32_t time
Where in time the point is (if > 0).
Definition: Zakero_Xenium.h:328
int32_t y
Where in the Y-Axis the point is.
Definition: Zakero_Xenium.h:330
int32_t x
Where in the X-Axis the point is.
Definition: Zakero_Xenium.h:329
Size measured in millimeters.
Definition: Zakero_Xenium.h:379
friend bool operator==(Xenium::SizeMm &, Xenium::SizeMm &) noexcept
Compare two Point objects.
Definition: Zakero_Xenium.h:9061
Size measured as a percentage of the Output (Monitor) resolution.
Definition: Zakero_Xenium.h:387
friend bool operator==(Xenium::SizePercent &, Xenium::SizePercent &) noexcept
Compare two Point objects.
Definition: Zakero_Xenium.h:9082
Size measured in pixels.
Definition: Zakero_Xenium.h:395
friend bool operator==(Xenium::SizePixel &, Xenium::SizePixel &) noexcept
Compare two Size objects.
Definition: Zakero_Xenium.h:9100