KWin
Loading...
Searching...
No Matches
normalhintsbasesizetest.cpp
Go to the documentation of this file.
1/*
2 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
5*/
6#include <cstdlib>
7#include <iostream>
8#include <xcb/xcb.h>
9#include <xcb/xcb_icccm.h>
10
11/*
12 * This is a small test app to ensure that KWin calculates the size of a window correctly
13 * according to ICCCM section 4.1.2.3
14 *
15 * The application creates a window and specifies the normal hints with:
16 * * min size
17 * * base size
18 * * size increment
19 *
20 * With these normal flags the size should be calculated as:
21 * width = base_width + (i * width_inc)
22 * height = base_height + (j * height_inc)
23 *
24 * With i and j being non-negative integers!
25 *
26 * This application waits for configure notify events and calculates the i and j and
27 * tries to calculate the size it expects. If it doesn't match it exits with a non-zero
28 * exit code and prints the mismatching i and/or j value to stderr.
29 *
30 * To simply quit the application just click into the window. This will return with exit code 0.
31 */
32int main(int, char **)
33{
34 int screenNumber;
35 xcb_connection_t *c = xcb_connect(nullptr, &screenNumber);
36
37 auto getScreen = [=]() {
38 const xcb_setup_t *setup = xcb_get_setup(c);
39 auto it = xcb_setup_roots_iterator(setup);
40 for (int i = 0; i < screenNumber; ++i) {
41 xcb_screen_next(&it);
42 }
43 return it.data;
44 };
45 xcb_screen_t *screen = getScreen();
46
47 xcb_window_t w = xcb_generate_id(c);
48 const uint32_t values[2] = {
49 screen->white_pixel,
50 XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_STRUCTURE_NOTIFY};
51
52 xcb_create_window(c, 0, w, screen->root, 0, 0, 365, 104, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
53 screen->root_visual, XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, values);
54
55 // set the normal hints
56 xcb_size_hints_t hints;
57 hints.flags = XCB_ICCCM_SIZE_HINT_P_MIN_SIZE | XCB_ICCCM_SIZE_HINT_BASE_SIZE | XCB_ICCCM_SIZE_HINT_P_RESIZE_INC;
58 hints.min_width = 365;
59 hints.min_height = 104;
60 hints.base_width = 15;
61 hints.base_height = 64;
62 hints.width_inc = 9;
63 hints.height_inc = 18;
64 xcb_icccm_set_wm_normal_hints(c, w, &hints);
65
66 // and map the window
67 xcb_map_window(c, w);
68 xcb_flush(c);
69
70 bool error = false;
71 while (xcb_generic_event_t *event = xcb_wait_for_event(c)) {
72 bool exit = false;
73 if ((event->response_type & ~0x80) == XCB_BUTTON_RELEASE) {
74 exit = true;
75 } else if ((event->response_type & ~0x80) == XCB_CONFIGURE_NOTIFY) {
76 auto *ce = reinterpret_cast<xcb_configure_notify_event_t *>(event);
77 const double i = (ce->width - hints.base_width) / (double)hints.width_inc;
78 const double j = (ce->height - hints.base_height) / (double)hints.height_inc;
79 // according to ICCCM the size should be:
80 // width = base_width + (i * width_inc)
81 // height = base_height + (j * height_inc)
82 // thus if the window manager configured correctly we get the same result
83 if (hints.base_width + (int(i) * hints.width_inc) != ce->width) {
84 std::cerr << "Incorrect width - i factor is " << i << std::endl;
85 exit = true;
86 error = true;
87 }
88 if (hints.base_height + (int(j) * hints.height_inc) != ce->height) {
89 std::cerr << "Incorrect height - j factor is " << i << std::endl;
90 exit = true;
91 error = true;
92 }
93 }
94 free(event);
95 if (exit) {
96 break;
97 }
98 }
99
100 xcb_disconnect(c);
101 return error ? 1 : 0;
102}