File indexing completed on 2024-11-10 10:57:02
0001 /* 0002 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 #include <cstdlib> 0007 #include <iostream> 0008 #include <xcb/xcb.h> 0009 #include <xcb/xcb_icccm.h> 0010 0011 /* 0012 * This is a small test app to ensure that KWin calculates the size of a window correctly 0013 * according to ICCCM section 4.1.2.3 0014 * 0015 * The application creates a window and specifies the normal hints with: 0016 * * min size 0017 * * base size 0018 * * size increment 0019 * 0020 * With these normal flags the size should be calculated as: 0021 * width = base_width + (i * width_inc) 0022 * height = base_height + (j * height_inc) 0023 * 0024 * With i and j being non-negative integers! 0025 * 0026 * This application waits for configure notify events and calculates the i and j and 0027 * tries to calculate the size it expects. If it doesn't match it exits with a non-zero 0028 * exit code and prints the mismatching i and/or j value to stderr. 0029 * 0030 * To simply quit the application just click into the window. This will return with exit code 0. 0031 */ 0032 int main(int, char **) 0033 { 0034 int screenNumber; 0035 xcb_connection_t *c = xcb_connect(nullptr, &screenNumber); 0036 0037 auto getScreen = [=]() { 0038 const xcb_setup_t *setup = xcb_get_setup(c); 0039 auto it = xcb_setup_roots_iterator(setup); 0040 for (int i = 0; i < screenNumber; ++i) { 0041 xcb_screen_next(&it); 0042 } 0043 return it.data; 0044 }; 0045 xcb_screen_t *screen = getScreen(); 0046 0047 xcb_window_t w = xcb_generate_id(c); 0048 const uint32_t values[2] = { 0049 screen->white_pixel, 0050 XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_STRUCTURE_NOTIFY}; 0051 0052 xcb_create_window(c, 0, w, screen->root, 0, 0, 365, 104, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, 0053 screen->root_visual, XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, values); 0054 0055 // set the normal hints 0056 xcb_size_hints_t hints; 0057 hints.flags = XCB_ICCCM_SIZE_HINT_P_MIN_SIZE | XCB_ICCCM_SIZE_HINT_BASE_SIZE | XCB_ICCCM_SIZE_HINT_P_RESIZE_INC; 0058 hints.min_width = 365; 0059 hints.min_height = 104; 0060 hints.base_width = 15; 0061 hints.base_height = 64; 0062 hints.width_inc = 9; 0063 hints.height_inc = 18; 0064 xcb_icccm_set_wm_normal_hints(c, w, &hints); 0065 0066 // and map the window 0067 xcb_map_window(c, w); 0068 xcb_flush(c); 0069 0070 bool error = false; 0071 while (xcb_generic_event_t *event = xcb_wait_for_event(c)) { 0072 bool exit = false; 0073 if ((event->response_type & ~0x80) == XCB_BUTTON_RELEASE) { 0074 exit = true; 0075 } else if ((event->response_type & ~0x80) == XCB_CONFIGURE_NOTIFY) { 0076 auto *ce = reinterpret_cast<xcb_configure_notify_event_t *>(event); 0077 const double i = (ce->width - hints.base_width) / (double)hints.width_inc; 0078 const double j = (ce->height - hints.base_height) / (double)hints.height_inc; 0079 // according to ICCCM the size should be: 0080 // width = base_width + (i * width_inc) 0081 // height = base_height + (j * height_inc) 0082 // thus if the window manager configured correctly we get the same result 0083 if (hints.base_width + (int(i) * hints.width_inc) != ce->width) { 0084 std::cerr << "Incorrect width - i factor is " << i << std::endl; 0085 exit = true; 0086 error = true; 0087 } 0088 if (hints.base_height + (int(j) * hints.height_inc) != ce->height) { 0089 std::cerr << "Incorrect height - j factor is " << i << std::endl; 0090 exit = true; 0091 error = true; 0092 } 0093 } 0094 free(event); 0095 if (exit) { 0096 break; 0097 } 0098 } 0099 0100 xcb_disconnect(c); 0101 return error ? 1 : 0; 0102 }