Creare una finestra mediante le funzioni del API di XCB

Da Gambas-it.org - Wikipedia.

Il protocollo XCB (X C-language Binding) è stato realizzato con lo scopo di sostituire Xlib presentando rispetto a quest'ultimo ad esempio dimensioni ridotte, un accesso diretto al protocollo, migliorando il threading e la estensibilità.
XCB consente una compatibilità con Xlib che con XCB, anche attraverso l'uso combinato di risorse presenti in entrambe le librerie.

Per poter fruire delle risorse di XCB in Gambas, bisognerà utilizzare la libreria attualmente alla versione: "libxcb.so.1.1.0 ".

Mostriamo di seguito il codice per creare una semplice finestra di colore bianco che presenta al suo interno alcuni disegni di elementi geometrici:

Library "libxcb:1.1.0"

Public Struct xcb_screen_t
  root As Integer
  default_colormap As Integer
  white_pixel As Integer
  black_pixel As Integer
  current_input_masks As Integer
  width_in_pixels As Short
  height_in_pixels As Short
  width_in_millimeters As Short
  height_in_millimeters As Short
  min_installed_maps As Short
  max_installed_maps As Short
  root_visual As Integer
  backing_stores As Byte
  save_unders As Byte
  root_depth As Byte
  allowed_depths_len As Byte
End Struct


Public Struct xcb_generic_event_t
  response_type As Byte
  pad0 As Byte
  sequence As Short
  pad[7] As Integer
  full_sequence As Integer
End Struct

Private Const XCB_COPY_FROM_PARENT As Byte = 0
Private Enum XCB_CW_BACK_PIXEL = 2, XCB_GC_FOREGROUND = 4, XCB_CW_EVENT_MASK = 2048, XCB_GC_GRAPHICS_EXPOSURES = 65536
Private Enum XCB_WINDOW_CLASS_COPY_FROM_PARENT = 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_WINDOW_CLASS_INPUT_ONLY
Private Enum XCB_EVENT_MASK_NO_EVENT = 0, XCB_EVENT_MASK_KEY_PRESS, XCB_EVENT_MASK_BUTTON_PRESS = 4, XCB_EVENT_MASK_EXPOSURE = 32768
Private Enum XCB_KEY_PRESS = 2, XCB_BUTTON_PRESS = 4, XCB_EXPOSE = 12
Private Enum XCB_COORD_MODE_ORIGIN = 0, XCB_COORD_MODE_PREVIOUS

' xcb_connection_t * xcb_connect (const char *display, int *screen)
' Connects to the X server specified by display.
Private Extern xcb_connect(display As String, screenPo As Pointer) As Pointer

' const xcb_setup_t * xcb_get_setup (xcb_connection_t *c)
' Accessor for the data returned by the server when the xcb_connection_t was initialized.
Private Extern xcb_get_setup(c As Pointer) As Pointer

' xcb_screen_iterator_t xcb_setup_roots_iterator (const xcb_setup_t *R)
' Get the next element of the iterator.
Private Extern xcb_setup_roots_iterator(R As Pointer) As Pointer

' uint32_t xcb_generate_id (xcb_connection *c)
' Allocates an XID prior to creating a new X object.
Private Extern xcb_generate_id(c As Pointer) As Integer

' xcb_void_cookie_t xcb_create_window (xcb_connection_t *c, uint8_t depth, xcb_window_t wid, xcb_window_t parent, int16_t x, int16_t y, uint16_t width, uint16_t height, uint16_t border_width,
' uint16_t _class, xcb_visualid_t visual, uint32_t value_mask, const uint32_t *value_list)
' Creates a window.
Private Extern xcb_create_window(c As Pointer, depth As Byte, wid As Integer, parent As Integer, xs As Short, ys As Short, width As Short, height As Short, border_width As Short, _class As Short, visual As Integer, value_mask As Integer, value_list As Integer[]) As Integer

' xcb_void_cookie_t xcb_map_window (xcb_connection_t *c, xcb_window_t window)
' Makes a window visible.
Private Extern xcb_map_window(c As Pointer, wid As Integer) As Integer

' int xcb_flush(xcb_connection_t *c)
' Forces any buffered output to be written to the server.
Private Extern xcb_flush(c As Pointer) As Integer

' xcb_void_cookie_t xcb_create_gc (xcb_connection_t *c, xcb_gcontext_t cid, xcb_drawable_t drawable, uint32_t value_mask, const uint32_t *value_list)
' Creates a graphics context.
Private Extern xcb_create_gc(c As Pointer, cid As Integer, drawable As Integer, value_mask As Integer, value_list As Integer[]) As Integer

' xcb_generic_event_t *xcb_wait_for_event(xcb_connection_t *c)
' Returns the next event or error from the server.
Private Extern xcb_wait_for_event(c As Pointer) As Xcb_generic_event_t

' xcb_void_cookie_t xcb_poly_point (xcb_connection_t  *c, uint8_t coordinate_mode, xcb_drawable_t drawable, xcb_gcontext_t gc, uint32_t points_len, const xcb_point_t *points)
' Draw points.
Private Extern xcb_poly_point(c As Pointer, coordinate_mode As Byte, drawable As Integer, gc_I As Integer, points_len As Integer, points As Short[]) As Integer

' xcb_void_cookie_t xcb_poly_line (xcb_connection_t  *c, uint8_t coordinate_mode, xcb_drawable_t drawable, xcb_gcontext_t gc, uint32_t points_len, const xcb_point_t *points)
' Draw lines.
Private Extern xcb_poly_line(c As Pointer, coordinate_mode As Byte, drawable As Integer, gc_I As Integer, points_len As Integer, points As Short[]) As Integer

' xcb_void_cookie_t xcb_poly_segment (xcb_connection_t  *c, xcb_drawable_t drawable, xcb_gcontext_t gc, uint32_t segments_len, const xcb_segment_t *segments)
' Draw lines.
Private Extern xcb_poly_segment(c As Pointer, drawable As Integer, gc_I As Integer, segments_len As Integer, segments As Short[]) As Integer

' xcb_void_cookie_t xcb_poly_rectangle (xcb_connection_t  *c, uint8_t coordinate_mode, xcb_drawable_t drawable, xcb_gcontext_t gc, uint32_t rectangles_len, const xcb_rectangle_t *rectangles)
' Draw rectangles.
Private Extern xcb_poly_rectangle(c As Pointer, drawable As Integer, gc_I As Integer, rectangles_len As Integer, rectangles As Short[]) As Integer

' xcb_void_cookie_t xcb_poly_arc (xcb_connection_t  *c, uint8_t coordinate_mode, xcb_drawable_t drawable, xcb_gcontext_t gc, uint32_t arcs_len, const xcb_arc_t *arcs)
' Draw arcs.
Private Extern xcb_poly_arc(c As Pointer, drawable As Integer, gc_I As Integer, arcs_len As Integer, arcs As Short[]) As Integer

' xcb_void_cookie_t xcb_poly_fill_rectangle (xcb_connection_t  *c, uint8_t coordinate_mode, xcb_drawable_t drawable, xcb_gcontext_t gc, uint32_t rectangles_len, const xcb_rectangle_t *rectangles)
' Fills rectangles.
Private Extern xcb_poly_fill_rectangle(c As Pointer, drawable As Integer, gc_I As Integer, rectangles_len As Integer, rectangles As Short[]) As Integer

' xcb_void_cookie_t xcb_poly_fill_arc (xcb_connection_t  *c, uint8_t coordinate_mode, xcb_drawable_t drawable, xcb_gcontext_t gc, uint32_t arcs_len, const xcb_arc_t *arcs)
' Fills arcs.
Private Extern xcb_poly_fill_arc(c As Pointer, drawable As Integer, gc_I As Integer, arcs_len As Integer, arcs As Short[]) As Integer

' void xcb_disconnect (xcb_connection *c)
' Closes the file descriptor and frees all memory associated with the connection.
Private Extern xcb_disconnect(c As Pointer)


Public Sub Main()

  Dim disp, xcb_setup As Pointer
  Dim screen As New Xcb_screen_t
  Dim win, primopiano, mask As Integer
  Dim vv As New Integer[]
  Dim points, polyline, segments, rectangles, arcs, fillrect, fillarc As Short[]
  Dim evento As New Xcb_generic_event_t

' Apre una connessione con il server X:
  disp = xcb_connect(Null, 0)
 
' Ottiene il primo schermo:
  xcb_setup = xcb_get_setup(disp)
 
  screen = xcb_setup_roots_iterator(xcb_setup)
 
' Mostra in console alcune informazioni sullo schermo utilizzato:
  With screen
    Print "Dimensioni dello schermo:\n"
    Print "Larghezza in pixel: ", Null, .width_in_pixels
    Print "Altezza in pixel: ", Null, .height_in_pixels
    Print "Larghezza in millimetri: "; Null, .width_in_millimeters
    Print "Altezza in millimetri: ", Null, .height_in_millimeters
  End With
 
' Crea un contesto grafico nero per disegnare in primo piano:
  mask = XCB_GC_FOREGROUND Or XCB_GC_GRAPHICS_EXPOSURES
  vv = [screen.black_pixel, 0]
  primopiano = xcb_generate_id(disp)
  xcb_create_gc(disp, primopiano, screen.root, mask, vv)
 
' Crea una finestra bianca:
  win = xcb_generate_id(disp)
  mask = XCB_CW_BACK_PIXEL Or XCB_CW_EVENT_MASK
' Impone il colore della finestra:
  vv[0] = screen.white_pixel
' Si impostano i tipi di eventi che dovranno essere visti:
  vv[1] = XCB_EVENT_MASK_EXPOSURE Or XCB_EVENT_MASK_KEY_PRESS Or XCB_EVENT_MASK_BUTTON_PRESS

  xcb_create_window(disp, XCB_COPY_FROM_PARENT, win, screen.root, 0, 0, 1000, 800, 10, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen.root_visual, mask, vv)

' Mappa la finestra sullo schermo:
  xcb_map_window(disp, win)
       
' Ci si assicura che le istruzioni siano inviate al server X:
  xcb_flush(disp)

' Vengono definiti i valori per disegnare gli elementi geometrici sulla finestra:
  points = [50, 50, 50, 100, 100, 50, 100, 100]
  polyline = [250, 50, 25, 100, 125, -100, 50, 50]
  segments = [500, 50, 700, 150, 550, 125, 650, 300]
  rectangles = [50, 250, 200, 100, 400, 250, 50, 200]
  arcs = [50, 500, 300, 200, 0, 90 * CInt(2 ^ 6), 450, 500, 275, 200, 0, 360 * CInt(2 ^ 6)]
  fillrect = [100, 450, 140, 30, 20, 300, 100, 100]
  fillarc = [5, 500, 300, 200, 0, 90 * CInt(2 ^ 6), 450, 500, 275, 200, 0, 270 * CInt(2 ^ 6)]
  fillarc = [650, 400, 100, 100, 0, 180 * CInt(2 ^ 6), 550, 500, 100, 100, 0, 360 * CInt(2 ^ 6)]

  Do
    evento = xcb_wait_for_event(disp)
    Select evento.response_type
      Case XCB_EXPOSE
' Disegna gli elementi geometrici:
        xcb_poly_point(disp, XCB_COORD_MODE_ORIGIN, win, primopiano, 4, points)
        xcb_poly_line(disp, XCB_COORD_MODE_PREVIOUS, win, primopiano, 4, polyline)
        xcb_poly_segment(disp, win, primopiano, 2, segments)
        xcb_poly_rectangle(disp, win, primopiano, 2, rectangles)
        xcb_poly_arc(disp, win, primopiano, 2, arcs)
        xcb_poly_fill_rectangle(disp, win, primopiano, 2, fillrect)
        xcb_poly_fill_arc(disp, win, primopiano, 2, fillarc)
        xcb_flush(disp)
' Se viene premuto un tasto della tastiera, la finestra si chiude:
      Case XCB_KEY_PRESS
        Print "\nPremuto un tasto della tastiera."
        Break
' Se viene premuto un qualsiasi tasto del mouse stando con il puntatore al di sopra della finestra, questa si chiude:
      Case XCB_BUTTON_PRESS
        Print "\nPremuto un tasto del mouse."
        Break
    End Select
  Loop
 
' Va in chiusura:
  xcb_disconnect(disp)

End



Riferimenti