2

私は libX11 を使用して単純なテキスト ユーザー インターフェイスを作成しており、基本的なライブラリの抽象化のために機能する一連のコードを用意しています。

問題は、テキストを描画しようとすると、タイトル バーが最初の行をブロックすることです。そのため、垂直方向の印刷を約 20 ピクセルオフセットする必要があります。テキストの各行を適切にオフセットできるように、タイトル バーの正確なサイズを決定する方法はありますか?

これが私がこれまでに持っているコードであり、これtui_putsを行うために必要な機能です:

#include "tui.h"

#include <X11/Xlib.h>
#include <unistd.h>

#include <stdlib.h>
#include <string.h>

struct tui_data {

    Display * display;
    Window id_window;
    GC context_graphics;

    XIM method_input;
    XIC context_input;

    XWindowAttributes spec_window;
    XFontStruct * spec_font;

    size_t offset_y;
    size_t offset_x;
};

int tui_init (struct tui_session * ptr_tui){
    memset (ptr_tui, 0, sizeof (struct tui_session));

    ptr_tui->ptr_data = calloc (sizeof (struct tui_data), 1);
    if (!ptr_tui->ptr_data) return -1;

    ptr_tui->ptr_data->display = XOpenDisplay (0);
    if (!ptr_tui->ptr_data->display) return -1;

    int color_black = BlackPixel(ptr_tui->ptr_data->display, DefaultScreen(ptr_tui->ptr_data->display));
    int color_white = WhitePixel(ptr_tui->ptr_data->display, DefaultScreen(ptr_tui->ptr_data->display));

    ptr_tui->ptr_data->id_window = XCreateSimpleWindow(ptr_tui->ptr_data->display,
                                                       DefaultRootWindow(ptr_tui->ptr_data->display),
                                                       0, 0, 640, 480, 0, color_black, color_black);

    XSelectInput (ptr_tui->ptr_data->display,
                  ptr_tui->ptr_data->id_window,
                  StructureNotifyMask);

    XMapWindow (ptr_tui->ptr_data->display,
                ptr_tui->ptr_data->id_window);

    ptr_tui->ptr_data->context_graphics = XCreateGC(ptr_tui->ptr_data->display,
                                                    ptr_tui->ptr_data->id_window, 0, 0);

    for (;;){
        XEvent e;
        XNextEvent (ptr_tui->ptr_data->display, &e);
        if (e.type == MapNotify) break;
    }

    XSetForeground (ptr_tui->ptr_data->display,
                    ptr_tui->ptr_data->context_graphics,
                    color_white);

    XGetWindowAttributes (ptr_tui->ptr_data->display,
                          ptr_tui->ptr_data->id_window,
                         &ptr_tui->ptr_data->spec_window);

    XSelectInput (ptr_tui->ptr_data->display,
                  ptr_tui->ptr_data->id_window,
                  ExposureMask | KeyPressMask | ResizeRedirectMask);

    ptr_tui->ptr_data->method_input = XOpenIM (ptr_tui->ptr_data->display, 0, 0, 0);

    if (!ptr_tui->ptr_data->method_input){
        return -1;
    }

    ptr_tui->ptr_data->context_input = XCreateIC (ptr_tui->ptr_data->method_input,
                                                  XNInputStyle, XIMPreeditNothing
                                                | XIMStatusNothing, XNClientWindow,
                                                  ptr_tui->ptr_data->id_window, NULL);

    if (!ptr_tui->ptr_data->context_input){
        return -1;
    }

    XSetICFocus (ptr_tui->ptr_data->context_input);

    ptr_tui->ptr_data->spec_font = XLoadQueryFont (ptr_tui->ptr_data->display,
                                                 "-misc-fixed-medium-"
                                                 "r-normal-*-*-120-*-*");

    if (!ptr_tui->ptr_data->spec_font){
        return -1;
    }

    XSetFont (ptr_tui->ptr_data->display,
              ptr_tui->ptr_data->context_graphics,
              ptr_tui->ptr_data->spec_font->fid);

    ptr_tui->max_x = ptr_tui->ptr_data->spec_window.width
                   / ptr_tui->ptr_data->spec_font->max_bounds.width;
    ptr_tui->max_y = ptr_tui->ptr_data->spec_window.height
                  / (ptr_tui->ptr_data->spec_font->max_bounds.ascent
                  +  ptr_tui->ptr_data->spec_font->max_bounds.descent);
    return 0;
}

int tui_free (struct tui_session * ptr_tui){

    if (ptr_tui->ptr_data){

        XFreeFont (ptr_tui->ptr_data->display, ptr_tui->ptr_data->spec_font);
        XFreeGC (ptr_tui->ptr_data->display, ptr_tui->ptr_data->context_graphics);

        XSetCloseDownMode(ptr_tui->ptr_data->display, DestroyAll);
        XCloseDisplay (ptr_tui->ptr_data->display);

        free (ptr_tui->ptr_data);
    }

    memset (ptr_tui, 0, sizeof (struct tui_session));
    return 0;
}

int tui_refresh (struct tui_session * ptr_tui){
    XFlush (ptr_tui->ptr_data->display);
    return 0;
}

int tui_clear (struct tui_session * ptr_tui){
    XClearWindow (ptr_tui->ptr_data->display,
                  ptr_tui->ptr_data->id_window);
    return 0;
}

int tui_puts (struct tui_session * ptr_tui,
              const void * ptr_data, size_t len_data,
              size_t index_x, size_t index_y, uint32_t flags){

    if (((index_x + len_data) >= ptr_tui->max_x)
    ||  (index_y >= ptr_tui->max_y)) return -1;

    XDrawImageString (ptr_tui->ptr_data->display,
                      ptr_tui->ptr_data->id_window,
                      ptr_tui->ptr_data->context_graphics,
                      ptr_tui->ptr_data->spec_window.border_width
                    + ptr_tui->ptr_data->spec_font->max_bounds.width * index_x,
                     (ptr_tui->ptr_data->spec_font->max_bounds.ascent
                    + ptr_tui->ptr_data->spec_font->max_bounds.descent)
                    * index_y + 20, ptr_data, len_data);

    return 0;
}

int tui_message (struct tui_session * ptr_tui, const char * format, ...){
    return -1;
}

int tui_prompt (struct tui_session * ptr_tui, const char * format, ...){
    return -1;
}

int tui_input (struct tui_session * ptr_tui, tui_event * ptr_event){

    XEvent event;
    Status status = 0;
    KeySym keysym = 0;
    char buffer[4];
    int count = 0;

    XNextEvent(ptr_tui->ptr_data->display, &event);

    switch (event.type){

    case KeyPress:

        count = Xutf8LookupString (ptr_tui->ptr_data->context_input,
                                  (XKeyPressedEvent*) &event, buffer,
                                   sizeof (buffer), &keysym, &status);

            if (count){
                ptr_event->type = TUI_EVENT_KEYPRESS;
                ptr_event->value = buffer[0];
            }

            break;

    case Expose:
        ptr_event->type = TUI_EVENT_REPRINT;
        ptr_event->value = 0;
        break;

    case ResizeRequest:
        XGetWindowAttributes (ptr_tui->ptr_data->display,
                              ptr_tui->ptr_data->id_window,
                             &ptr_tui->ptr_data->spec_window);
        ptr_event->type = TUI_EVENT_REPRINT;
        ptr_event->value = 0;
        break;

    default:
        ptr_event->type = 0;
        ptr_event->value = 0;
    }

    return 0;
}

int tui_scroll (struct tui_session * ptr_tui, int offset){
    return -1;
}

また、ここに重要な構造があります。

typedef struct {
    int x, y;                        /* location of window */
    int width, height;               /* width and height of window */
    int border_width;                /* border width of window */
    int depth;                       /* depth of window */
    Visual *visual;                  /* the associated visual structure */
    Window root;                     /* root of screen containing window */
    int class;                       /* InputOutput, InputOnly*/
    int bit_gravity;                 /* one of the bit gravity values */
    int win_gravity;                 /* one of the window gravity values */
    int backing_store;               /* NotUseful, WhenMapped, Always */
    unsigned long backing_planes;    /* planes to be preserved if possible */
    unsigned long backing_pixel;     /* value to be used when restoring planes */
    Bool save_under;                 /* boolean, should bits under be saved? */
    Colormap colormap;               /* color map to be associated with window */
    Bool map_installed;              /* boolean, is color map currently installed*/
    int map_state;                   /* IsUnmapped, IsUnviewable, IsViewable */
    long all_event_masks;            /* set of events all people have interest in*/
    long your_event_mask;            /* my event mask */
    long do_not_propagate_mask;      /* set of events that should not propagate */
    Bool override_redirect;          /* boolean value for override-redirect */
    Screen *screen;                  /* back pointer to correct screen */
} XWindowAttributes;

これは、クライアント領域の水平オフセットを取得するのに役立ちましたが、垂直オフセットを取得するのに役立つものは何もありません。

4

1 に答える 1