简体   繁体   中英

xcb correct window size

I have a question regarding xcb Window size I create a window using xcb_create_window function

    xcb_create_window(mScreen->connection(),
                  XCB_COPY_FROM_PARENT,
                  mWindow,
                  mScreen->screen()->root,
                  x, // left corner of the window client area
                  y, // upper corner of the window client area
                  width, // width of the client area
                  height, // height of the client area
                  0,
                  XCB_WINDOW_CLASS_INPUT_OUTPUT,
                  mScreen->screen()->root_visual,
                  value_mask,
                  value_list);
    auto reply = XCB_REPLY(xcb_intern_atom, mScreen->connection(), true, strlen("WM_PROTOCOLS"), "WM_PROTOCOLS");
    auto atomDelete = XCB_REPLY(xcb_intern_atom, mScreen->connection(), false, strlen("WM_DELETE_WINDOW"), "WM_DELETE_WINDOW");

    xcb_change_property(mScreen->connection(), XCB_PROP_MODE_REPLACE, mWindow, reply->atom, 4, 32, 1, &atomDelete->atom);
    xcb_change_property(mScreen->connection(), XCB_PROP_MODE_REPLACE, mWindow, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, strlen(windowName), windowName);
    xcb_flush(mScreen->connection());

On Win32 API I have the possibilty to adjust a window rect by using AdjustWindowRect function which basically adds border and caption size to ensure client window does have the expected size.

My question how do I achieve this with xcb? Is there any way to compute the additonal size that is needed to ensure client window das have the expected size?

Extended Window Manager Hints

_NET_REQUEST_FRAME_EXTENTS (Other Root Window Messages)

Rationale: A client cannot calculate the dimensions of its window's frame before the window is mapped, but some toolkits need this information. Asking the window manager for an estimate of the extents is a workable solution. The estimate may depend on the current theme, font sizes or other window properties. The client can track changes to the frame's dimensions by listening for _NET_FRAME_EXTENTS PropertyNotify events.

_NET_FRAME_EXTENTS (Application Window Properties)

The Window Manager MUST set _NET_FRAME_EXTENTS to the extents of the window's frame. left, right, top and bottom are widths of the respective borders added by the Window Manager.

The following code gets margins of a window followed suggestion from Erdal Küçük:

  • create window

  • configure stuff (like title or close button)

  • wait for property message

  • in case .NET_FRAME_EXTENTS read data

     uint32_t value_mask, value_list[32]{}; auto windowHandle = xcb_generate_id(xcb_connection()); value_mask = XCB_CW_EVENT_MASK; value_list[0] = XCB_EVENT_MASK_PROPERTY_CHANGE; xcb_create_window(screen->connection(), XCB_COPY_FROM_PARENT, windowHandle, screen->root, 100, 100, 100, 100, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, value_mask, value_list); auto protocols = XCB_REPLY(xcb_intern_atom, screen->connection(), true, strlen("WM_PROTOCOLS"), "WM_PROTOCOLS"); auto atomDelete = XCB_REPLY(xcb_intern_atom, screen->connection(), false, strlen("WM_DELETE_WINDOW"), "WM_DELETE_WINDOW"); auto atomExtents = XCB_REPLY(xcb_intern_atom, screen->connection(), false, strlen(".NET_FRAME_EXTENTS"), ".NET_FRAME_EXTENTS"); xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, windowHandle, protocols->atom, XCB_ATOM_ATOM, 32, 1, &atomDelete->atom); xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, windowHandle, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, strlen(""), ""); xcb_map_window(xcb_connection(), windowHandle); xcb_flush(xcb_connection()); xcb_generic_event_t* event; for (;;) { while ((event = xcb_poll_for_event(screen->connection()))) { switch (event->response_type & 0x7f) { case XCB_PROPERTY_NOTIFY: { auto propertyNotify = (const xcb_property_notify_event_t*)event; if (propertyNotify->atom == atomExtents->atom) { free(event); goto end; } break; } default: break; } free(event); } } end: auto extends = XCB_REPLY(xcb_get_property, xcb_connection(), false, windowHandle, atomExtents->atom, XCB_ATOM_CARDINAL, 0, 4); if (extends && extends->type == XCB_ATOM_CARDINAL && extends->format == 32 && extends->value_len == 4) { uint32_t* data = std::pointer_cast<uint32_t*>(xcb_get_property_value(extends.get())); windowMargins.l = -data[0]; windowMargins.r = data[1]; windowMargins.t = -data[2]; windowMargins.b = data[3]; } xcb_destroy_window(xcb_connection(), windowHandle);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM